Showing preview only (3,522K chars total). Download the full file or copy to clipboard to get everything.
Repository: mountain-loop/yaak
Branch: main
Commit: b4a1c418bb3f
Files: 1118
Total size: 3.2 MB
Directory structure:
gitextract_zes9y_de/
├── .claude/
│ ├── commands/
│ │ └── release/
│ │ └── generate-release-notes.md
│ └── rules.md
├── .claude-context.md
├── .codex/
│ └── skills/
│ └── release-generate-release-notes/
│ └── SKILL.md
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── config.yml
│ ├── pull_request_template.md
│ └── workflows/
│ ├── ci.yml
│ ├── claude.yml
│ ├── flathub.yml
│ ├── release-api-npm.yml
│ ├── release-app.yml
│ ├── release-cli-npm.yml
│ └── sponsors.yml
├── .gitignore
├── .node-version
├── .npmrc
├── .nvmrc
├── .oxfmtignore
├── .vite-hooks/
│ ├── post-checkout
│ └── pre-commit
├── .vscode/
│ ├── extensions.json
│ ├── launch.json
│ └── settings.json
├── AGENTS.md
├── CONTRIBUTING.md
├── Cargo.toml
├── DEVELOPMENT.md
├── LICENSE
├── README.md
├── crates/
│ ├── yaak/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── error.rs
│ │ ├── lib.rs
│ │ ├── plugin_events.rs
│ │ ├── render.rs
│ │ └── send.rs
│ ├── yaak-api/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── error.rs
│ │ └── lib.rs
│ ├── yaak-common/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── command.rs
│ │ ├── lib.rs
│ │ ├── platform.rs
│ │ └── serde.rs
│ ├── yaak-core/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── context.rs
│ │ ├── error.rs
│ │ └── lib.rs
│ ├── yaak-crypto/
│ │ ├── Cargo.toml
│ │ ├── index.ts
│ │ ├── package.json
│ │ └── src/
│ │ ├── encryption.rs
│ │ ├── error.rs
│ │ ├── lib.rs
│ │ ├── manager.rs
│ │ ├── master_key.rs
│ │ └── workspace_key.rs
│ ├── yaak-git/
│ │ ├── Cargo.toml
│ │ ├── bindings/
│ │ │ ├── gen_git.ts
│ │ │ └── gen_models.ts
│ │ ├── index.ts
│ │ ├── package.json
│ │ └── src/
│ │ ├── add.rs
│ │ ├── binary.rs
│ │ ├── branch.rs
│ │ ├── clone.rs
│ │ ├── commit.rs
│ │ ├── credential.rs
│ │ ├── error.rs
│ │ ├── fetch.rs
│ │ ├── init.rs
│ │ ├── lib.rs
│ │ ├── log.rs
│ │ ├── pull.rs
│ │ ├── push.rs
│ │ ├── remotes.rs
│ │ ├── repository.rs
│ │ ├── reset.rs
│ │ ├── status.rs
│ │ ├── unstage.rs
│ │ └── util.rs
│ ├── yaak-grpc/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── any.rs
│ │ ├── client.rs
│ │ ├── codec.rs
│ │ ├── error.rs
│ │ ├── json_schema.rs
│ │ ├── lib.rs
│ │ ├── manager.rs
│ │ ├── reflection.rs
│ │ └── transport.rs
│ ├── yaak-http/
│ │ ├── Cargo.toml
│ │ ├── src/
│ │ │ ├── chained_reader.rs
│ │ │ ├── client.rs
│ │ │ ├── cookies.rs
│ │ │ ├── decompress.rs
│ │ │ ├── dns.rs
│ │ │ ├── error.rs
│ │ │ ├── lib.rs
│ │ │ ├── manager.rs
│ │ │ ├── path_placeholders.rs
│ │ │ ├── proto.rs
│ │ │ ├── sender.rs
│ │ │ ├── tee_reader.rs
│ │ │ ├── transaction.rs
│ │ │ └── types.rs
│ │ └── tests/
│ │ └── test.txt
│ ├── yaak-models/
│ │ ├── Cargo.toml
│ │ ├── bindings/
│ │ │ ├── gen_models.ts
│ │ │ └── gen_util.ts
│ │ ├── blob_migrations/
│ │ │ └── 00000000000000_init.sql
│ │ ├── build.rs
│ │ ├── guest-js/
│ │ │ ├── atoms.ts
│ │ │ ├── index.ts
│ │ │ ├── store.ts
│ │ │ ├── types.ts
│ │ │ └── util.ts
│ │ ├── migrations/
│ │ │ ├── 20230225181302_init.sql
│ │ │ ├── 20230319042610_sort-priority.sql
│ │ │ ├── 20230330143214_request-auth.sql
│ │ │ ├── 20230413232435_response-body-blob.sql
│ │ │ ├── 20231022205109_environments.sql
│ │ │ ├── 20231028161007_variables.sql
│ │ │ ├── 20231103004111_workspace-variables.sql
│ │ │ ├── 20231103142807_folders.sql
│ │ │ ├── 20231112180500_body_object.sql
│ │ │ ├── 20231113183810_url_params.sql
│ │ │ ├── 20231122055216_remove_body.sql
│ │ │ ├── 20240111221224_settings.sql
│ │ │ ├── 20240115193751_workspace_settings.sql
│ │ │ ├── 20240118181105_channel_setting.sql
│ │ │ ├── 20240127013915_cookies.sql
│ │ │ ├── 20240128230717_more_response_attrs.sql
│ │ │ ├── 20240203164833_grpc.sql
│ │ │ ├── 20240522031045_theme-settings.sql
│ │ │ ├── 20240529143147_more-settings.sql
│ │ │ ├── 20240607151115_open-workspace-setting.sql
│ │ │ ├── 20240814013812_fix-env-model.sql
│ │ │ ├── 20240826184943_disable-telemetry.sql
│ │ │ ├── 20240829131004_plugins.sql
│ │ │ ├── 20241003134208_response-state.sql
│ │ │ ├── 20241012181547_proxy-setting.sql
│ │ │ ├── 20241217204951_docs.sql
│ │ │ ├── 20241219140051_base-environments.sql
│ │ │ ├── 20250102141937_sync.sql
│ │ │ ├── 20250108035425_editor-keymap.sql
│ │ │ ├── 20250108205117_workspace-meta.sql
│ │ │ ├── 20250114160022_remove-workspace-sync-setting.sql
│ │ │ ├── 20250123192023_plugin-kv.sql
│ │ │ ├── 20250128155623_websockets.sql
│ │ │ ├── 20250302041707_hide-window-controls.sql
│ │ │ ├── 20250326193143_key-value-id.sql
│ │ │ ├── 20250401122407_encrypted-key.sql
│ │ │ ├── 20250402144842_encryption-key-challenge.sql
│ │ │ ├── 20250424152740_remove-fks.sql
│ │ │ ├── 20250507140702_remove-ev-sync-states.sql
│ │ │ ├── 20250508161145_public-environments.sql
│ │ │ ├── 20250516182745_default-attrs.sql
│ │ │ ├── 20250530174021_graphql-introspection.sql
│ │ │ ├── 20250531193722_sync-state-index.sql
│ │ │ ├── 20250604102922_colored-methods-setting.sql
│ │ │ ├── 20250608150053_font-settings.sql
│ │ │ ├── 20250611120000_environment-color.sql
│ │ │ ├── 20250727190746_autoupdate_setting.sql
│ │ │ ├── 20250918141129_request-folder-environments.sql
│ │ │ ├── 20250929132954_dismiss-license-badge.sql
│ │ │ ├── 20251001082054_auto-download.sql
│ │ │ ├── 20251028060300_check_notifications_setting.sql
│ │ │ ├── 20251029062024_aws-auth-name.sql
│ │ │ ├── 20251031070515_environment-sort-priority.sql
│ │ │ ├── 20251202080000_use-native-titlebar.sql
│ │ │ ├── 20251209000000_client-certificates.sql
│ │ │ ├── 20251219074602_default-workspace-headers.sql
│ │ │ ├── 20251220000000_response-request-headers.sql
│ │ │ ├── 20251221000000_http-response-events.sql
│ │ │ ├── 20251221100000_request-content-length.sql
│ │ │ ├── 20260104000000_hotkeys.sql
│ │ │ ├── 20260111000000_dns-timing.sql
│ │ │ ├── 20260112000000_dns-overrides.sql
│ │ │ ├── 20260119045146_remove-default-workspace-headers.sql
│ │ │ ├── 20260216000000_model-changes.sql
│ │ │ ├── 20260217000000_remove-legacy-faker-plugin.sql
│ │ │ └── 20260301000000_plugin-source-and-unique-directory.sql
│ │ ├── package.json
│ │ └── src/
│ │ ├── blob_manager.rs
│ │ ├── connection_or_tx.rs
│ │ ├── db_context.rs
│ │ ├── error.rs
│ │ ├── lib.rs
│ │ ├── migrate.rs
│ │ ├── models.rs
│ │ ├── queries/
│ │ │ ├── any_request.rs
│ │ │ ├── batch.rs
│ │ │ ├── cookie_jars.rs
│ │ │ ├── environments.rs
│ │ │ ├── folders.rs
│ │ │ ├── graphql_introspections.rs
│ │ │ ├── grpc_connections.rs
│ │ │ ├── grpc_events.rs
│ │ │ ├── grpc_requests.rs
│ │ │ ├── http_requests.rs
│ │ │ ├── http_response_events.rs
│ │ │ ├── http_responses.rs
│ │ │ ├── key_values.rs
│ │ │ ├── mod.rs
│ │ │ ├── model_changes.rs
│ │ │ ├── plugin_key_values.rs
│ │ │ ├── plugins.rs
│ │ │ ├── settings.rs
│ │ │ ├── sync_states.rs
│ │ │ ├── websocket_connections.rs
│ │ │ ├── websocket_events.rs
│ │ │ ├── websocket_requests.rs
│ │ │ ├── workspace_metas.rs
│ │ │ └── workspaces.rs
│ │ ├── query_manager.rs
│ │ ├── render.rs
│ │ └── util.rs
│ ├── yaak-plugins/
│ │ ├── Cargo.toml
│ │ ├── bindings/
│ │ │ ├── gen_api.ts
│ │ │ ├── gen_events.ts
│ │ │ ├── gen_models.ts
│ │ │ ├── gen_search.ts
│ │ │ └── serde_json/
│ │ │ └── JsonValue.ts
│ │ ├── index.ts
│ │ ├── package.json
│ │ └── src/
│ │ ├── api.rs
│ │ ├── checksum.rs
│ │ ├── error.rs
│ │ ├── events.rs
│ │ ├── install.rs
│ │ ├── lib.rs
│ │ ├── manager.rs
│ │ ├── native_template_functions.rs
│ │ ├── nodejs.rs
│ │ ├── plugin_handle.rs
│ │ ├── plugin_meta.rs
│ │ ├── server_ws.rs
│ │ ├── template_callback.rs
│ │ └── util.rs
│ ├── yaak-sse/
│ │ ├── Cargo.toml
│ │ ├── bindings/
│ │ │ └── sse.ts
│ │ ├── index.ts
│ │ ├── package.json
│ │ └── src/
│ │ ├── lib.rs
│ │ └── sse.rs
│ ├── yaak-sync/
│ │ ├── Cargo.toml
│ │ ├── bindings/
│ │ │ ├── gen_models.ts
│ │ │ ├── gen_sync.ts
│ │ │ ├── gen_watch.ts
│ │ │ └── git.ts
│ │ ├── index.ts
│ │ ├── package.json
│ │ └── src/
│ │ ├── error.rs
│ │ ├── lib.rs
│ │ ├── models.rs
│ │ ├── sync.rs
│ │ └── watch.rs
│ ├── yaak-templates/
│ │ ├── Cargo.toml
│ │ ├── bindings/
│ │ │ └── parser.ts
│ │ ├── build-wasm.cjs
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── pkg/
│ │ │ ├── package.json
│ │ │ ├── yaak_templates.d.ts
│ │ │ ├── yaak_templates.js
│ │ │ ├── yaak_templates_bg.js
│ │ │ ├── yaak_templates_bg.wasm
│ │ │ └── yaak_templates_bg.wasm.d.ts
│ │ └── src/
│ │ ├── error.rs
│ │ ├── escape.rs
│ │ ├── format_json.rs
│ │ ├── lib.rs
│ │ ├── parser.rs
│ │ ├── renderer.rs
│ │ ├── strip_json_comments.rs
│ │ └── wasm.rs
│ ├── yaak-tls/
│ │ ├── Cargo.toml
│ │ └── src/
│ │ ├── error.rs
│ │ └── lib.rs
│ └── yaak-ws/
│ ├── Cargo.toml
│ ├── index.ts
│ ├── package.json
│ └── src/
│ ├── connect.rs
│ ├── error.rs
│ ├── lib.rs
│ ├── manager.rs
│ └── render.rs
├── crates-cli/
│ └── yaak-cli/
│ ├── Cargo.toml
│ ├── README.md
│ ├── src/
│ │ ├── cli.rs
│ │ ├── commands/
│ │ │ ├── auth.rs
│ │ │ ├── cookie_jar.rs
│ │ │ ├── environment.rs
│ │ │ ├── folder.rs
│ │ │ ├── mod.rs
│ │ │ ├── plugin.rs
│ │ │ ├── request.rs
│ │ │ ├── send.rs
│ │ │ └── workspace.rs
│ │ ├── context.rs
│ │ ├── main.rs
│ │ ├── plugin_events.rs
│ │ ├── ui.rs
│ │ ├── utils/
│ │ │ ├── confirm.rs
│ │ │ ├── http.rs
│ │ │ ├── json.rs
│ │ │ ├── mod.rs
│ │ │ ├── schema.rs
│ │ │ └── workspace.rs
│ │ ├── version.rs
│ │ └── version_check.rs
│ └── tests/
│ ├── common/
│ │ ├── http_server.rs
│ │ └── mod.rs
│ ├── environment_commands.rs
│ ├── folder_commands.rs
│ ├── request_commands.rs
│ ├── send_commands.rs
│ └── workspace_commands.rs
├── crates-tauri/
│ ├── yaak-app/
│ │ ├── .gitignore
│ │ ├── Cargo.toml
│ │ ├── bindings/
│ │ │ ├── gen_watch.ts
│ │ │ ├── index.ts
│ │ │ └── plugins_ext.ts
│ │ ├── build.rs
│ │ ├── capabilities/
│ │ │ └── default.json
│ │ ├── icons/
│ │ │ ├── dev/
│ │ │ │ └── icon.icns
│ │ │ └── release/
│ │ │ └── icon.icns
│ │ ├── macos/
│ │ │ ├── entitlements.plist
│ │ │ ├── entitlements.yaaknode.plist
│ │ │ └── entitlements.yaakprotoc.plist
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── commands.rs
│ │ │ ├── encoding.rs
│ │ │ ├── error.rs
│ │ │ ├── git_ext.rs
│ │ │ ├── grpc.rs
│ │ │ ├── history.rs
│ │ │ ├── http_request.rs
│ │ │ ├── import.rs
│ │ │ ├── lib.rs
│ │ │ ├── main.rs
│ │ │ ├── models_ext.rs
│ │ │ ├── notifications.rs
│ │ │ ├── plugin_events.rs
│ │ │ ├── plugins_ext.rs
│ │ │ ├── render.rs
│ │ │ ├── sync_ext.rs
│ │ │ ├── updates.rs
│ │ │ ├── uri_scheme.rs
│ │ │ ├── window.rs
│ │ │ ├── window_menu.rs
│ │ │ └── ws_ext.rs
│ │ ├── tauri.conf.json
│ │ ├── tauri.development.conf.json
│ │ ├── tauri.linux.conf.json
│ │ ├── tauri.release.conf.json
│ │ └── template.desktop
│ ├── yaak-fonts/
│ │ ├── Cargo.toml
│ │ ├── bindings/
│ │ │ └── gen_fonts.ts
│ │ ├── build.rs
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── permissions/
│ │ │ └── default.toml
│ │ └── src/
│ │ ├── commands.rs
│ │ ├── error.rs
│ │ └── lib.rs
│ ├── yaak-license/
│ │ ├── Cargo.toml
│ │ ├── bindings/
│ │ │ ├── gen_models.ts
│ │ │ ├── license.ts
│ │ │ └── models.ts
│ │ ├── build.rs
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── permissions/
│ │ │ └── default.toml
│ │ └── src/
│ │ ├── commands.rs
│ │ ├── error.rs
│ │ ├── lib.rs
│ │ └── license.rs
│ ├── yaak-mac-window/
│ │ ├── Cargo.toml
│ │ ├── build.rs
│ │ ├── index.ts
│ │ ├── package.json
│ │ ├── permissions/
│ │ │ └── default.toml
│ │ └── src/
│ │ ├── commands.rs
│ │ ├── lib.rs
│ │ └── mac.rs
│ └── yaak-tauri-utils/
│ ├── Cargo.toml
│ └── src/
│ ├── lib.rs
│ └── window.rs
├── flatpak/
│ ├── app.yaak.Yaak.metainfo.xml
│ ├── fix-lockfile.mjs
│ ├── generate-sources.sh
│ └── update-manifest.sh
├── npm/
│ ├── cli/
│ │ ├── .gitignore
│ │ ├── bin/
│ │ │ └── cli.js
│ │ ├── common.js
│ │ ├── index.js
│ │ ├── install.js
│ │ ├── package.json
│ │ └── prepublish.js
│ ├── cli-darwin-arm64/
│ │ ├── bin/
│ │ │ └── .gitkeep
│ │ └── package.json
│ ├── cli-darwin-x64/
│ │ ├── bin/
│ │ │ └── .gitkeep
│ │ └── package.json
│ ├── cli-linux-arm64/
│ │ ├── bin/
│ │ │ └── .gitkeep
│ │ └── package.json
│ ├── cli-linux-x64/
│ │ ├── bin/
│ │ │ └── .gitkeep
│ │ └── package.json
│ ├── cli-win32-arm64/
│ │ ├── bin/
│ │ │ └── .gitkeep
│ │ └── package.json
│ ├── cli-win32-x64/
│ │ ├── bin/
│ │ │ └── .gitkeep
│ │ └── package.json
│ └── prepare-publish.js
├── package.json
├── packages/
│ ├── common-lib/
│ │ ├── debounce.ts
│ │ ├── formatSize.ts
│ │ ├── index.ts
│ │ ├── package.json
│ │ └── templateFunction.ts
│ ├── plugin-runtime/
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── EventChannel.ts
│ │ │ ├── PluginHandle.ts
│ │ │ ├── PluginInstance.ts
│ │ │ ├── common.ts
│ │ │ ├── index.ts
│ │ │ ├── interceptStdout.ts
│ │ │ └── migrations.ts
│ │ ├── tests/
│ │ │ └── common.test.ts
│ │ └── tsconfig.json
│ └── plugin-runtime-types/
│ ├── .gitignore
│ ├── README.md
│ ├── package.json
│ ├── src/
│ │ ├── bindings/
│ │ │ ├── gen_api.ts
│ │ │ ├── gen_events.ts
│ │ │ ├── gen_models.ts
│ │ │ ├── gen_search.ts
│ │ │ └── serde_json/
│ │ │ └── JsonValue.ts
│ │ ├── helpers.ts
│ │ ├── index.ts
│ │ ├── plugins/
│ │ │ ├── AuthenticationPlugin.ts
│ │ │ ├── Context.ts
│ │ │ ├── FilterPlugin.ts
│ │ │ ├── FolderActionPlugin.ts
│ │ │ ├── GrpcRequestActionPlugin.ts
│ │ │ ├── HttpRequestActionPlugin.ts
│ │ │ ├── ImporterPlugin.ts
│ │ │ ├── TemplateFunctionPlugin.ts
│ │ │ ├── ThemePlugin.ts
│ │ │ ├── WebsocketRequestActionPlugin.ts
│ │ │ ├── WorkspaceActionPlugin.ts
│ │ │ └── index.ts
│ │ └── themes/
│ │ └── index.ts
│ └── tsconfig.json
├── plugins/
│ ├── .gitignore
│ ├── action-copy-curl/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ └── index.test.ts
│ │ └── tsconfig.json
│ ├── action-copy-grpcurl/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ └── index.test.ts
│ │ └── tsconfig.json
│ ├── action-send-folder/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── auth-apikey/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── auth-aws/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── auth-basic/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ └── index.test.ts
│ │ └── tsconfig.json
│ ├── auth-bearer/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ └── index.test.ts
│ │ └── tsconfig.json
│ ├── auth-jwt/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── auth-ntlm/
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── index.ts
│ │ │ └── modules.d.ts
│ │ ├── tests/
│ │ │ └── index.test.ts
│ │ └── tsconfig.json
│ ├── auth-oauth1/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── auth-oauth2/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── callbackServer.ts
│ │ │ ├── fetchAccessToken.ts
│ │ │ ├── getOrRefreshAccessToken.ts
│ │ │ ├── grants/
│ │ │ │ ├── authorizationCode.ts
│ │ │ │ ├── clientCredentials.ts
│ │ │ │ ├── implicit.ts
│ │ │ │ └── password.ts
│ │ │ ├── index.ts
│ │ │ ├── store.ts
│ │ │ └── util.ts
│ │ ├── tests/
│ │ │ └── util.test.ts
│ │ └── tsconfig.json
│ ├── filter-jsonpath/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── filter-xpath/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── importer-curl/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ └── index.test.ts
│ │ └── tsconfig.json
│ ├── importer-insomnia/
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── common.ts
│ │ │ ├── index.ts
│ │ │ ├── v4.ts
│ │ │ └── v5.ts
│ │ ├── tests/
│ │ │ ├── fixtures/
│ │ │ │ ├── basic.input.json
│ │ │ │ ├── basic.output.json
│ │ │ │ ├── version-5-minimal.input.yaml
│ │ │ │ ├── version-5-minimal.output.json
│ │ │ │ ├── version-5.input.yaml
│ │ │ │ └── version-5.output.json
│ │ │ └── index.test.ts
│ │ └── tsconfig.json
│ ├── importer-openapi/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ ├── fixtures/
│ │ │ │ └── petstore.yaml
│ │ │ └── index.test.ts
│ │ └── tsconfig.json
│ ├── importer-postman/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ ├── fixtures/
│ │ │ │ ├── auth.input.json
│ │ │ │ ├── auth.output.json
│ │ │ │ ├── nested.input.json
│ │ │ │ ├── nested.output.json
│ │ │ │ ├── params.input.json
│ │ │ │ └── params.output.json
│ │ │ └── index.test.ts
│ │ └── tsconfig.json
│ ├── importer-postman-environment/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ ├── fixtures/
│ │ │ │ ├── environment.input.json
│ │ │ │ └── environment.output.json
│ │ │ └── index.test.ts
│ │ └── tsconfig.json
│ ├── importer-yaak/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ └── index.test.ts
│ │ └── tsconfig.json
│ ├── template-function-1password/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── template-function-cookie/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── template-function-ctx/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── template-function-encode/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── template-function-fs/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── template-function-hash/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── template-function-json/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── template-function-prompt/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── template-function-random/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── template-function-regex/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ └── regex.test.ts
│ │ └── tsconfig.json
│ ├── template-function-request/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── template-function-response/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── template-function-timestamp/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ └── formatDatetime.test.ts
│ │ └── tsconfig.json
│ ├── template-function-uuid/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ ├── template-function-xml/
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ └── tsconfig.json
│ └── themes-yaak/
│ ├── package.json
│ ├── src/
│ │ ├── index.ts
│ │ └── themes/
│ │ ├── andromeda.ts
│ │ ├── atom-one-dark.ts
│ │ ├── ayu.ts
│ │ ├── bluloco.ts
│ │ ├── catppuccin.ts
│ │ ├── cobalt2.ts
│ │ ├── dracula.ts
│ │ ├── everforest.ts
│ │ ├── fleet.ts
│ │ ├── github-dimmed.ts
│ │ ├── github.ts
│ │ ├── gruvbox.ts
│ │ ├── high-contrast.ts
│ │ ├── horizon.ts
│ │ ├── hotdog-stand.ts
│ │ ├── material-darker.ts
│ │ ├── material-ocean.ts
│ │ ├── material-palenight.ts
│ │ ├── monokai-pro.ts
│ │ ├── moonlight.ts
│ │ ├── night-owl.ts
│ │ ├── noctis.ts
│ │ ├── nord.ts
│ │ ├── one-dark-pro.ts
│ │ ├── panda.ts
│ │ ├── relaxing.ts
│ │ ├── rose-pine.ts
│ │ ├── shades-of-purple.ts
│ │ ├── slack.ts
│ │ ├── solarized.ts
│ │ ├── synthwave-84.ts
│ │ ├── tokyo-night.ts
│ │ ├── triangle.ts
│ │ ├── vitesse.ts
│ │ └── winter-is-coming.ts
│ └── tsconfig.json
├── plugins-external/
│ ├── .gitignore
│ ├── faker/
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── src/
│ │ │ └── index.ts
│ │ ├── tests/
│ │ │ ├── __snapshots__/
│ │ │ │ └── init.test.ts.snap
│ │ │ └── init.test.ts
│ │ └── tsconfig.json
│ ├── httpsnippet/
│ │ ├── README.md
│ │ ├── package.json
│ │ └── src/
│ │ └── index.ts
│ └── mcp-server/
│ ├── README.md
│ ├── package.json
│ ├── src/
│ │ ├── index.ts
│ │ ├── server.ts
│ │ ├── tools/
│ │ │ ├── folder.ts
│ │ │ ├── helpers.ts
│ │ │ ├── httpRequest.ts
│ │ │ ├── schemas.ts
│ │ │ ├── toast.ts
│ │ │ ├── window.ts
│ │ │ └── workspace.ts
│ │ └── types.ts
│ └── tsconfig.json
├── rustfmt.toml
├── scripts/
│ ├── .gitignore
│ ├── create-migration.cjs
│ ├── git-hooks/
│ │ └── post-checkout.mjs
│ ├── install-wasm-pack.cjs
│ ├── publish-core-plugins.cjs
│ ├── replace-version.cjs
│ ├── run-dev.mjs
│ ├── run-workspaces-dev.mjs
│ ├── vendor-node.cjs
│ ├── vendor-plugins.cjs
│ └── vendor-protoc.cjs
├── src-web/
│ ├── .gitignore
│ ├── commands/
│ │ ├── commands.tsx
│ │ ├── createEnvironment.tsx
│ │ ├── deleteWebsocketConnections.ts
│ │ ├── moveToWorkspace.tsx
│ │ ├── openFolderSettings.tsx
│ │ ├── openSettings.tsx
│ │ ├── openWorkspaceFromSyncDir.tsx
│ │ ├── openWorkspaceSettings.tsx
│ │ └── switchWorkspace.tsx
│ ├── components/
│ │ ├── BinaryFileEditor.tsx
│ │ ├── CargoFeature.tsx
│ │ ├── CloneGitRepositoryDialog.tsx
│ │ ├── ColorIndicator.tsx
│ │ ├── CommandPaletteDialog.tsx
│ │ ├── ConfirmLargeRequestBody.tsx
│ │ ├── ConfirmLargeResponse.tsx
│ │ ├── ConfirmLargeResponseRequest.tsx
│ │ ├── CookieDialog.tsx
│ │ ├── CookieDropdown.tsx
│ │ ├── CopyButton.tsx
│ │ ├── CopyIconButton.tsx
│ │ ├── CreateDropdown.tsx
│ │ ├── CreateEnvironmentDialog.tsx
│ │ ├── CreateWorkspaceDialog.tsx
│ │ ├── Dialogs.tsx
│ │ ├── DnsOverridesEditor.tsx
│ │ ├── DropMarker.tsx
│ │ ├── DynamicForm.tsx
│ │ ├── EmptyStateText.tsx
│ │ ├── EncryptionHelp.tsx
│ │ ├── EnvironmentActionsDropdown.tsx
│ │ ├── EnvironmentColorIndicator.tsx
│ │ ├── EnvironmentColorPicker.tsx
│ │ ├── EnvironmentEditDialog.tsx
│ │ ├── EnvironmentEditor.tsx
│ │ ├── EnvironmentSharableTooltip.tsx
│ │ ├── ErrorBoundary.tsx
│ │ ├── ExportDataDialog.tsx
│ │ ├── FolderLayout.tsx
│ │ ├── FolderSettingsDialog.tsx
│ │ ├── FormMultipartEditor.tsx
│ │ ├── FormUrlencodedEditor.tsx
│ │ ├── GlobalHooks.tsx
│ │ ├── GrpcConnectionLayout.tsx
│ │ ├── GrpcEditor.tsx
│ │ ├── GrpcProtoSelectionDialog.tsx
│ │ ├── GrpcRequestPane.tsx
│ │ ├── GrpcResponsePane.tsx
│ │ ├── HeaderSize.tsx
│ │ ├── HeadersEditor.tsx
│ │ ├── HttpAuthenticationEditor.tsx
│ │ ├── HttpRequestLayout.tsx
│ │ ├── HttpRequestPane.tsx
│ │ ├── HttpResponsePane.tsx
│ │ ├── HttpResponseTimeline.tsx
│ │ ├── ImportCurlButton.tsx
│ │ ├── ImportDataDialog.tsx
│ │ ├── IsDev.tsx
│ │ ├── JsonBodyEditor.tsx
│ │ ├── KeyboardShortcutsDialog.tsx
│ │ ├── LicenseBadge.tsx
│ │ ├── LocalImage.tsx
│ │ ├── Markdown.tsx
│ │ ├── MarkdownEditor.tsx
│ │ ├── MoveToWorkspaceDialog.tsx
│ │ ├── Overlay.tsx
│ │ ├── Portal.tsx
│ │ ├── Prose.css
│ │ ├── Prose.tsx
│ │ ├── RecentGrpcConnectionsDropdown.tsx
│ │ ├── RecentHttpResponsesDropdown.tsx
│ │ ├── RecentRequestsDropdown.tsx
│ │ ├── RecentWebsocketConnectionsDropdown.tsx
│ │ ├── RedirectToLatestWorkspace.tsx
│ │ ├── RequestBodyViewer.tsx
│ │ ├── RequestMethodDropdown.tsx
│ │ ├── ResizeHandle.tsx
│ │ ├── ResponseCookies.tsx
│ │ ├── ResponseHeaders.tsx
│ │ ├── ResponseInfo.tsx
│ │ ├── RouteError.tsx
│ │ ├── SelectFile.tsx
│ │ ├── Settings/
│ │ │ ├── Settings.tsx
│ │ │ ├── SettingsCertificates.tsx
│ │ │ ├── SettingsGeneral.tsx
│ │ │ ├── SettingsHotkeys.tsx
│ │ │ ├── SettingsInterface.tsx
│ │ │ ├── SettingsLicense.tsx
│ │ │ ├── SettingsPlugins.tsx
│ │ │ ├── SettingsProxy.tsx
│ │ │ └── SettingsTheme.tsx
│ │ ├── SettingsDropdown.tsx
│ │ ├── Sidebar.tsx
│ │ ├── SidebarActions.tsx
│ │ ├── SwitchWorkspaceDialog.tsx
│ │ ├── SyncToFilesystemSetting.tsx
│ │ ├── TemplateFunctionDialog.tsx
│ │ ├── Toasts.tsx
│ │ ├── UrlBar.tsx
│ │ ├── UrlParameterEditor.tsx
│ │ ├── WebsocketRequestLayout.tsx
│ │ ├── WebsocketRequestPane.tsx
│ │ ├── WebsocketResponsePane.tsx
│ │ ├── WindowControls.tsx
│ │ ├── Workspace.tsx
│ │ ├── WorkspaceActionsDropdown.tsx
│ │ ├── WorkspaceEncryptionSetting.tsx
│ │ ├── WorkspaceHeader.tsx
│ │ ├── WorkspaceSettingsDialog.tsx
│ │ ├── core/
│ │ │ ├── Alert.tsx
│ │ │ ├── AutoScroller.tsx
│ │ │ ├── Banner.tsx
│ │ │ ├── BulkPairEditor.tsx
│ │ │ ├── Button.tsx
│ │ │ ├── ButtonInfiniteLoading.tsx
│ │ │ ├── Checkbox.tsx
│ │ │ ├── ColorPicker.tsx
│ │ │ ├── Confirm.tsx
│ │ │ ├── CountBadge.tsx
│ │ │ ├── DetailsBanner.tsx
│ │ │ ├── Dialog.tsx
│ │ │ ├── DismissibleBanner.tsx
│ │ │ ├── Dropdown.tsx
│ │ │ ├── Editor/
│ │ │ │ ├── BetterMatchDecorator.ts
│ │ │ │ ├── DiffViewer.css
│ │ │ │ ├── DiffViewer.tsx
│ │ │ │ ├── Editor.css
│ │ │ │ ├── Editor.tsx
│ │ │ │ ├── LazyEditor.tsx
│ │ │ │ ├── extensions.ts
│ │ │ │ ├── filter/
│ │ │ │ │ ├── extension.ts
│ │ │ │ │ ├── filter.grammar
│ │ │ │ │ ├── filter.ts
│ │ │ │ │ ├── highlight.ts
│ │ │ │ │ └── query.ts
│ │ │ │ ├── genericCompletion.ts
│ │ │ │ ├── hyperlink/
│ │ │ │ │ └── extension.ts
│ │ │ │ ├── json-lint.ts
│ │ │ │ ├── pairs/
│ │ │ │ │ ├── extension.ts
│ │ │ │ │ ├── highlight.ts
│ │ │ │ │ ├── pairs.grammar
│ │ │ │ │ ├── pairs.terms.ts
│ │ │ │ │ └── pairs.ts
│ │ │ │ ├── searchMatchCount.ts
│ │ │ │ ├── singleLine.ts
│ │ │ │ ├── text/
│ │ │ │ │ ├── extension.ts
│ │ │ │ │ ├── text.grammar
│ │ │ │ │ ├── text.terms.ts
│ │ │ │ │ └── text.ts
│ │ │ │ ├── timeline/
│ │ │ │ │ ├── extension.ts
│ │ │ │ │ ├── highlight.ts
│ │ │ │ │ ├── timeline.grammar
│ │ │ │ │ ├── timeline.terms.ts
│ │ │ │ │ └── timeline.ts
│ │ │ │ ├── twig/
│ │ │ │ │ ├── completion.ts
│ │ │ │ │ ├── extension.ts
│ │ │ │ │ ├── highlight.ts
│ │ │ │ │ ├── pathParameters.ts
│ │ │ │ │ ├── templateTags.ts
│ │ │ │ │ ├── twig.grammar
│ │ │ │ │ ├── twig.terms.ts
│ │ │ │ │ ├── twig.test.ts
│ │ │ │ │ ├── twig.ts
│ │ │ │ │ └── util.ts
│ │ │ │ └── url/
│ │ │ │ ├── completion.ts
│ │ │ │ ├── extension.ts
│ │ │ │ ├── highlight.ts
│ │ │ │ ├── url.grammar
│ │ │ │ ├── url.terms.ts
│ │ │ │ └── url.ts
│ │ │ ├── EventViewer.tsx
│ │ │ ├── EventViewerRow.tsx
│ │ │ ├── FormattedError.tsx
│ │ │ ├── Heading.tsx
│ │ │ ├── Hotkey.tsx
│ │ │ ├── HotkeyLabel.tsx
│ │ │ ├── HotkeyList.tsx
│ │ │ ├── HttpMethodTag.tsx
│ │ │ ├── HttpResponseDurationTag.tsx
│ │ │ ├── HttpStatusTag.tsx
│ │ │ ├── Icon.tsx
│ │ │ ├── IconButton.tsx
│ │ │ ├── IconTooltip.tsx
│ │ │ ├── InlineCode.tsx
│ │ │ ├── Input.tsx
│ │ │ ├── JsonAttributeTree.tsx
│ │ │ ├── KeyValueRow.tsx
│ │ │ ├── Label.tsx
│ │ │ ├── Link.tsx
│ │ │ ├── LoadingIcon.tsx
│ │ │ ├── PairEditor.tsx
│ │ │ ├── PairEditor.util.tsx
│ │ │ ├── PairOrBulkEditor.tsx
│ │ │ ├── PillButton.tsx
│ │ │ ├── PlainInput.tsx
│ │ │ ├── Prompt.tsx
│ │ │ ├── RadioCards.tsx
│ │ │ ├── RadioDropdown.tsx
│ │ │ ├── SegmentedControl.tsx
│ │ │ ├── Select.tsx
│ │ │ ├── Separator.tsx
│ │ │ ├── SizeTag.tsx
│ │ │ ├── SplitLayout.tsx
│ │ │ ├── Stacks.tsx
│ │ │ ├── Table.tsx
│ │ │ ├── Tabs/
│ │ │ │ └── Tabs.tsx
│ │ │ ├── Toast.tsx
│ │ │ ├── Tooltip.tsx
│ │ │ ├── WebsocketStatusTag.tsx
│ │ │ └── tree/
│ │ │ ├── Tree.tsx
│ │ │ ├── TreeDragOverlay.tsx
│ │ │ ├── TreeDropMarker.tsx
│ │ │ ├── TreeIndentGuide.tsx
│ │ │ ├── TreeItem.tsx
│ │ │ ├── TreeItemList.tsx
│ │ │ ├── atoms.ts
│ │ │ ├── common.ts
│ │ │ └── useSelectableItems.ts
│ │ ├── git/
│ │ │ ├── BranchSelectionDialog.tsx
│ │ │ ├── GitCommitDialog.tsx
│ │ │ ├── GitDropdown.tsx
│ │ │ ├── GitRemotesDialog.tsx
│ │ │ ├── HistoryDialog.tsx
│ │ │ ├── callbacks.tsx
│ │ │ ├── credentials.tsx
│ │ │ ├── diverged.tsx
│ │ │ ├── git-util.ts
│ │ │ ├── showAddRemoteDialog.tsx
│ │ │ └── uncommitted.tsx
│ │ ├── graphql/
│ │ │ ├── GraphQLDocsExplorer.tsx
│ │ │ ├── GraphQLEditor.tsx
│ │ │ └── graphqlAtoms.ts
│ │ └── responseViewers/
│ │ ├── AudioViewer.tsx
│ │ ├── BinaryViewer.tsx
│ │ ├── CsvViewer.tsx
│ │ ├── EventStreamViewer.tsx
│ │ ├── HTMLOrTextViewer.tsx
│ │ ├── ImageViewer.tsx
│ │ ├── JsonViewer.tsx
│ │ ├── MultipartViewer.tsx
│ │ ├── PdfViewer.css
│ │ ├── PdfViewer.tsx
│ │ ├── SvgViewer.tsx
│ │ ├── TextViewer.tsx
│ │ ├── VideoViewer.tsx
│ │ └── WebPageViewer.tsx
│ ├── font-size.ts
│ ├── font.ts
│ ├── hooks/
│ │ ├── useActiveCookieJar.ts
│ │ ├── useActiveEnvironment.ts
│ │ ├── useActiveEnvironmentVariables.ts
│ │ ├── useActiveFolder.ts
│ │ ├── useActiveFolderId.ts
│ │ ├── useActiveRequest.ts
│ │ ├── useActiveRequestId.ts
│ │ ├── useActiveWorkspace.ts
│ │ ├── useActiveWorkspaceChangedToast.tsx
│ │ ├── useAllRequests.ts
│ │ ├── useAuthTab.tsx
│ │ ├── useCancelHttpResponse.ts
│ │ ├── useCheckForUpdates.tsx
│ │ ├── useClickOutside.ts
│ │ ├── useContainerQuery.ts
│ │ ├── useCopyHttpResponse.ts
│ │ ├── useCreateCookieJar.ts
│ │ ├── useCreateDropdownItems.tsx
│ │ ├── useCreateWorkspace.tsx
│ │ ├── useDebouncedState.ts
│ │ ├── useDebouncedValue.ts
│ │ ├── useDeleteGrpcConnections.ts
│ │ ├── useDeleteHttpResponses.ts
│ │ ├── useDeleteSendHistory.tsx
│ │ ├── useEnvironmentValueVisibility.ts
│ │ ├── useEnvironmentVariables.ts
│ │ ├── useEnvironmentsBreakdown.ts
│ │ ├── useEventViewerKeyboard.ts
│ │ ├── useExportData.tsx
│ │ ├── useFastMutation.ts
│ │ ├── useFloatingSidebarHidden.ts
│ │ ├── useFolderActions.ts
│ │ ├── useFormatText.ts
│ │ ├── useGrpc.ts
│ │ ├── useGrpcProtoFiles.ts
│ │ ├── useGrpcRequestActions.ts
│ │ ├── useHeadersTab.tsx
│ │ ├── useHotKey.ts
│ │ ├── useHttpAuthentication.ts
│ │ ├── useHttpAuthenticationConfig.ts
│ │ ├── useHttpRequestActions.ts
│ │ ├── useHttpRequestBody.ts
│ │ ├── useHttpResponseEvents.ts
│ │ ├── useImportCurl.ts
│ │ ├── useInheritedAuthentication.ts
│ │ ├── useInheritedHeaders.ts
│ │ ├── useInstallPlugin.ts
│ │ ├── useIntrospectGraphQL.ts
│ │ ├── useIsEncryptionEnabled.ts
│ │ ├── useIsFullscreen.ts
│ │ ├── useKeyValue.ts
│ │ ├── useKeyboardEvent.ts
│ │ ├── useLatestGrpcConnection.ts
│ │ ├── useLatestHttpResponse.ts
│ │ ├── useListenToTauriEvent.ts
│ │ ├── useModelAncestors.ts
│ │ ├── useParentFolders.ts
│ │ ├── usePinnedGrpcConnection.ts
│ │ ├── usePinnedHttpResponse.ts
│ │ ├── usePinnedWebsocketConnection.ts
│ │ ├── usePluginInfo.ts
│ │ ├── usePlugins.ts
│ │ ├── usePortal.ts
│ │ ├── usePreferredAppearance.ts
│ │ ├── useRandomKey.ts
│ │ ├── useRecentCookieJars.ts
│ │ ├── useRecentEnvironments.ts
│ │ ├── useRecentRequests.ts
│ │ ├── useRecentWorkspaces.ts
│ │ ├── useRenderTemplate.ts
│ │ ├── useRequestEditor.tsx
│ │ ├── useRequestUpdateKey.ts
│ │ ├── useResolvedAppearance.ts
│ │ ├── useResolvedTheme.ts
│ │ ├── useResponseBodyEventSource.ts
│ │ ├── useResponseBodyText.ts
│ │ ├── useResponseViewMode.ts
│ │ ├── useSaveResponse.tsx
│ │ ├── useScrollIntoView.ts
│ │ ├── useSendAnyHttpRequest.ts
│ │ ├── useSendManyRequests.ts
│ │ ├── useShouldFloatSidebar.ts
│ │ ├── useSidebarHidden.ts
│ │ ├── useSidebarItemCollapsed.ts
│ │ ├── useSidebarWidth.ts
│ │ ├── useStateWithDeps.ts
│ │ ├── useStoplightsVisible.ts
│ │ ├── useSyncFontSizeSetting.ts
│ │ ├── useSyncWorkspaceChildModels.ts
│ │ ├── useSyncWorkspaceRequestTitle.ts
│ │ ├── useSyncZoomSetting.ts
│ │ ├── useTemplateFunctionConfig.ts
│ │ ├── useTemplateFunctions.tsx
│ │ ├── useTemplateTokensToString.ts
│ │ ├── useTimedBoolean.ts
│ │ ├── useTimelineViewMode.ts
│ │ ├── useToggle.ts
│ │ ├── useToggleCommandPalette.tsx
│ │ ├── useWebsocketRequestActions.ts
│ │ ├── useWindowFocus.ts
│ │ ├── useWorkspaceActions.ts
│ │ └── useZoom.ts
│ ├── index.html
│ ├── init/
│ │ └── sync.ts
│ ├── lib/
│ │ ├── alert.ts
│ │ ├── appInfo.ts
│ │ ├── atoms/
│ │ │ └── atomWithKVStorage.ts
│ │ ├── atoms.ts
│ │ ├── capitalize.ts
│ │ ├── clamp.ts
│ │ ├── color.ts
│ │ ├── confirm.ts
│ │ ├── constants.ts
│ │ ├── contentType.ts
│ │ ├── copy.ts
│ │ ├── createRequestAndNavigate.tsx
│ │ ├── data/
│ │ │ ├── charsets.ts
│ │ │ ├── connections.ts
│ │ │ ├── encodings.ts
│ │ │ ├── headerNames.ts
│ │ │ └── mimetypes.ts
│ │ ├── defaultHeaders.ts
│ │ ├── deleteModelWithConfirm.tsx
│ │ ├── dialog.ts
│ │ ├── diffYaml.ts
│ │ ├── dnd.ts
│ │ ├── duplicateRequestOrFolderAndNavigate.tsx
│ │ ├── editEnvironment.tsx
│ │ ├── encryption.ts
│ │ ├── fireAndForget.ts
│ │ ├── formatters.ts
│ │ ├── generateId.ts
│ │ ├── getNodeText.ts
│ │ ├── importData.tsx
│ │ ├── initGlobalListeners.tsx
│ │ ├── jotai.ts
│ │ ├── jsonComments.ts
│ │ ├── keyValueStore.ts
│ │ ├── markdown.ts
│ │ ├── minPromiseMillis.ts
│ │ ├── model_util.test.ts
│ │ ├── model_util.ts
│ │ ├── pluralize.ts
│ │ ├── prepareImportQuerystring.ts
│ │ ├── prompt-form.tsx
│ │ ├── prompt.ts
│ │ ├── queryClient.ts
│ │ ├── renameModelWithPrompt.tsx
│ │ ├── resolvedModelName.ts
│ │ ├── responseBody.ts
│ │ ├── reveal.ts
│ │ ├── router.ts
│ │ ├── scopes.ts
│ │ ├── sendEphemeralRequest.ts
│ │ ├── setWorkspaceSearchParams.ts
│ │ ├── settings.ts
│ │ ├── setupOrConfigureEncryption.tsx
│ │ ├── showColorPicker.tsx
│ │ ├── sleep.ts
│ │ ├── tauri.ts
│ │ ├── theme/
│ │ │ ├── appearance.ts
│ │ │ ├── themes.ts
│ │ │ ├── window.ts
│ │ │ └── yaakColor.ts
│ │ ├── toast.tsx
│ │ └── truncate.ts
│ ├── main.css
│ ├── main.tsx
│ ├── modules.d.ts
│ ├── package.json
│ ├── postcss.config.cjs
│ ├── routeTree.gen.ts
│ ├── routes/
│ │ ├── __root.tsx
│ │ ├── index.tsx
│ │ └── workspaces/
│ │ ├── $workspaceId/
│ │ │ ├── index.tsx
│ │ │ ├── requests/
│ │ │ │ └── $requestId.tsx
│ │ │ └── settings.tsx
│ │ └── index.tsx
│ ├── tailwind.config.cjs
│ ├── theme.ts
│ ├── tsconfig.json
│ ├── tsconfig.node.json
│ ├── tsr.config.json
│ ├── vite-env.d.ts
│ └── vite.config.ts
├── tsconfig.json
└── vite.config.ts
================================================
FILE CONTENTS
================================================
================================================
FILE: .claude/commands/release/generate-release-notes.md
================================================
---
description: Generate formatted release notes for Yaak releases
allowed-tools: Bash(git tag:*)
---
Generate formatted release notes for Yaak releases by analyzing git history and pull request descriptions.
## What to do
1. Identifies the version tag and previous version
2. Retrieves all commits between versions
- If the version is a beta version, it retrieves commits between the beta version and previous beta version
- If the version is a stable version, it retrieves commits between the stable version and the previous stable version
3. Fetches PR descriptions for linked issues to find:
- Feedback URLs (feedback.yaak.app)
- Additional context and descriptions
- Installation links for plugins
4. Formats the release notes using the standard Yaak format:
- Changelog badge at the top
- Bulleted list of changes with PR links
- Feedback links where available
- Full changelog comparison link at the bottom
## Output Format
The skill generates markdown-formatted release notes following this structure:
```markdown
[](https://yaak.app/changelog/VERSION)
- Feature/fix description in by @username [#123](https://github.com/mountain-loop/yaak/pull/123)
- [Linked feedback item](https://feedback.yaak.app/p/item) by @username in [#456](https://github.com/mountain-loop/yaak/pull/456)
- A simple item that doesn't have a feedback or PR link
**Full Changelog**: https://github.com/mountain-loop/yaak/compare/vPREV...vCURRENT
```
**IMPORTANT**: Always add a blank lines around the markdown code fence and output the markdown code block last
**IMPORTANT**: PRs by `@gschier` should not mention the @username
**IMPORTANT**: These are app release notes. Exclude CLI-only changes (commits prefixed with `cli:` or only touching `crates-cli/`) since the CLI has its own release process.
## After Generating Release Notes
After outputting the release notes, ask the user if they would like to create a draft GitHub release with these notes. If they confirm, create the release using:
```bash
gh release create <tag> --draft --prerelease --title "Release <version>" --notes '<release notes>'
```
**IMPORTANT**: The release title format is "Release XXXX" where XXXX is the version WITHOUT the `v` prefix. For example, tag `v2026.2.1-beta.1` gets title "Release 2026.2.1-beta.1".
================================================
FILE: .claude/rules.md
================================================
# Project Rules
## General Development
- **NEVER** commit or push without explicit confirmation
## Build and Lint
- **ALWAYS** run `npm run lint` after modifying TypeScript or JavaScript files
- Run `npm run bootstrap` after changing plugin runtime or MCP server code
## Plugin System
### Backend Constraints
- Always use `UpdateSource::Plugin` when calling database methods from plugin events
- Never send timestamps (`createdAt`, `updatedAt`) from TypeScript - Rust backend controls these
- Backend uses `NaiveDateTime` (no timezone) so avoid sending ISO timestamp strings
### MCP Server
- MCP server has **no active window context** - cannot call `window.workspaceId()`
- Get workspace ID from `workspaceCtx.yaak.workspace.list()` instead
## Rust Type Generation
- Run `cargo test --package yaak-plugins` (and for other crates) to regenerate TypeScript bindings after modifying Rust event types
================================================
FILE: .claude-context.md
================================================
# Claude Context: Detaching Tauri from Yaak
## Goal
Make Yaak runnable as a standalone CLI without Tauri as a dependency. The core Rust crates in `crates/` should be usable independently, while Tauri-specific code lives in `crates-tauri/`.
## Project Structure
```
crates/ # Core crates - should NOT depend on Tauri
crates-tauri/ # Tauri-specific crates (yaak-app, yaak-tauri-utils, etc.)
crates-cli/ # CLI crate (yaak-cli)
```
## Completed Work
### 1. Folder Restructure
- Moved Tauri-dependent app code to `crates-tauri/yaak-app/`
- Created `crates-tauri/yaak-tauri-utils/` for shared Tauri utilities (window traits, api_client, error handling)
- Created `crates-cli/yaak-cli/` for the standalone CLI
### 2. Decoupled Crates (no longer depend on Tauri)
- **yaak-models**: Uses `init_standalone()` pattern for CLI database access
- **yaak-http**: Removed Tauri plugin, HttpConnectionManager initialized in yaak-app setup
- **yaak-common**: Only contains Tauri-free utilities (serde, platform)
- **yaak-crypto**: Removed Tauri plugin, EncryptionManager initialized in yaak-app setup, commands moved to yaak-app
- **yaak-grpc**: Replaced AppHandle with GrpcConfig struct, uses tokio::process::Command instead of Tauri sidecar
### 3. CLI Implementation
- Basic CLI at `crates-cli/yaak-cli/src/main.rs`
- Commands: workspaces, requests, send (by ID), get (ad-hoc URL), create
- Uses same database as Tauri app via `yaak_models::init_standalone()`
## Remaining Work
### Crates Still Depending on Tauri (in `crates/`)
1. **yaak-git** (3 files) - Moderate complexity
2. **yaak-plugins** (13 files) - **Hardest** - deeply integrated with Tauri for plugin-to-window communication
3. **yaak-sync** (4 files) - Moderate complexity
4. **yaak-ws** (5 files) - Moderate complexity
### Pattern for Decoupling
1. Remove Tauri plugin `init()` function from the crate
2. Move commands to `yaak-app/src/commands.rs` or keep inline in `lib.rs`
3. Move extension traits (e.g., `SomethingManagerExt`) to yaak-app or yaak-tauri-utils
4. Initialize managers in yaak-app's `.setup()` block
5. Remove `tauri` from Cargo.toml dependencies
6. Update `crates-tauri/yaak-app/capabilities/default.json` to remove the plugin permission
7. Replace `tauri::async_runtime::block_on` with `tokio::runtime::Handle::current().block_on()`
## Key Files
- `crates-tauri/yaak-app/src/lib.rs` - Main Tauri app, setup block initializes managers
- `crates-tauri/yaak-app/src/commands.rs` - Migrated Tauri commands
- `crates-tauri/yaak-app/src/models_ext.rs` - Database plugin and extension traits
- `crates-tauri/yaak-tauri-utils/src/window.rs` - WorkspaceWindowTrait for window state
- `crates/yaak-models/src/lib.rs` - Contains `init_standalone()` for CLI usage
## Git Branch
Working on `detach-tauri` branch.
## Recent Commits
```
c40cff40 Remove Tauri dependencies from yaak-crypto and yaak-grpc
df495f1d Move Tauri utilities from yaak-common to yaak-tauri-utils
481e0273 Remove Tauri dependencies from yaak-http and yaak-common
10568ac3 Add HTTP request sending to yaak-cli
bcb7d600 Add yaak-cli stub with basic database access
e718a5f1 Refactor models_ext to use init_standalone from yaak-models
```
## Testing
- Run `cargo check -p <crate>` to verify a crate builds without Tauri
- Run `npm run app-dev` to test the Tauri app still works
- Run `cargo run -p yaak-cli -- --help` to test the CLI
================================================
FILE: .codex/skills/release-generate-release-notes/SKILL.md
================================================
---
name: release-generate-release-notes
description: Generate Yaak release notes from git history and PR metadata, including feedback links and full changelog compare links. Use when asked to run or replace the old Claude generate-release-notes command.
---
# Generate Release Notes
Generate formatted markdown release notes for a Yaak tag.
## Workflow
1. Determine target tag.
2. Determine previous comparable tag:
- Beta tag: compare against previous beta (if the root version is the same) or stable tag.
- Stable tag: compare against previous stable tag.
3. Collect commits in range:
- `git log --oneline <prev_tag>..<target_tag>`
4. For linked PRs, fetch metadata:
- `gh pr view <PR_NUMBER> --json number,title,body,author,url`
5. Extract useful details:
- Feedback URLs (`feedback.yaak.app`)
- Plugin install links or other notable context
6. Format notes using Yaak style:
- Changelog badge at top
- Bulleted items with PR links where available
- Feedback links where available
- Full changelog compare link at bottom
## Formatting Rules
- Wrap final notes in a markdown code fence.
- Keep a blank line before and after the code fence.
- Output the markdown code block last.
- Do not append `by @gschier` for PRs authored by `@gschier`.
- These are app release notes. Exclude CLI-only changes (commits prefixed with `cli:` or only touching `crates-cli/`) since the CLI has its own release process.
## Release Creation Prompt
After producing notes, ask whether to create a draft GitHub release.
If confirmed and release does not yet exist, run:
`gh release create <tag> --draft --prerelease --title "Release <version_without_v>" --notes '<release notes>'`
If a draft release for the tag already exists, update it instead:
`gh release edit <tag> --title "Release <version_without_v>" --notes-file <path_to_notes>`
Use title format `Release <version_without_v>`, e.g. `v2026.2.1-beta.1` -> `Release 2026.2.1-beta.1`.
================================================
FILE: .gitattributes
================================================
crates-tauri/yaak-app/vendored/**/* linguist-generated=true
crates-tauri/yaak-app/gen/schemas/**/* linguist-generated=true
**/bindings/* linguist-generated=true
crates/yaak-templates/pkg/* linguist-generated=true
# Ensure consistent line endings for test files that check exact content
crates/yaak-http/tests/test.txt text eol=lf
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: gschier
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
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.
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
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."
================================================
FILE: .github/pull_request_template.md
================================================
## Summary
<!-- Describe the bug and the fix in 1-3 sentences. -->
## Submission
- [ ] This PR is a bug fix or small-scope improvement.
- [ ] If this PR is not a bug fix or small-scope improvement, I linked an approved feedback item below.
- [ ] I have read and followed [`CONTRIBUTING.md`](CONTRIBUTING.md).
- [ ] I tested this change locally.
- [ ] I added or updated tests when reasonable.
Approved feedback item (required if not a bug fix or small-scope improvement):
<!-- https://yaak.app/feedback/... -->
## Related
<!-- Link related issues, discussions, or feedback items. -->
================================================
FILE: .github/workflows/ci.yml
================================================
on:
pull_request:
push:
branches:
- main
name: Lint and Test
permissions:
contents: read
jobs:
test:
name: Lint/Test
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: voidzero-dev/setup-vp@v1
with:
node-version: "24"
cache: true
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
shared-key: ci
cache-on-failure: true
- run: vp install
- run: npm run bootstrap
- run: npm run lint
- name: Run JS Tests
run: vp test
- name: Run Rust Tests
run: cargo test --all
================================================
FILE: .github/workflows/claude.yml
================================================
name: Claude Code
on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
issues:
types: [opened, assigned]
pull_request_review:
types: [submitted]
jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: read
issues: read
id-token: write
actions: read # Required for Claude to read CI results on PRs
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 1
- name: Run Claude Code
id: claude
uses: anthropics/claude-code-action@v1
with:
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
# This is an optional setting that allows Claude to read CI results on PRs
additional_permissions: |
actions: read
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
# prompt: 'Update the pull request description to include a summary of changes.'
# Optional: Add claude_args to customize behavior and configuration
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
# or https://code.claude.com/docs/en/cli-reference for available options
# claude_args: '--allowed-tools Bash(gh pr:*)'
================================================
FILE: .github/workflows/flathub.yml
================================================
name: Update Flathub
on:
release:
types: [published]
permissions:
contents: read
jobs:
update-flathub:
name: Update Flathub manifest
runs-on: ubuntu-latest
# Only run for stable releases (skip betas/pre-releases)
if: ${{ !github.event.release.prerelease }}
steps:
- name: Checkout app repo
uses: actions/checkout@v4
- name: Checkout Flathub repo
uses: actions/checkout@v4
with:
repository: flathub/app.yaak.Yaak
token: ${{ secrets.FLATHUB_TOKEN }}
path: flathub-repo
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: "22"
- name: Install source generators
run: |
pip install flatpak-node-generator tomlkit aiohttp
git clone --depth 1 https://github.com/flatpak/flatpak-builder-tools flatpak/flatpak-builder-tools
- name: Run update-manifest.sh
run: bash flatpak/update-manifest.sh "${{ github.event.release.tag_name }}" flathub-repo
- name: Commit and push to Flathub
working-directory: flathub-repo
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git add -A
git diff --cached --quiet && echo "No changes to commit" && exit 0
git commit -m "Update to ${{ github.event.release.tag_name }}"
git push
================================================
FILE: .github/workflows/release-api-npm.yml
================================================
name: Release API to NPM
on:
push:
tags: [yaak-api-*]
workflow_dispatch:
inputs:
version:
description: API version to publish (for example 0.9.0 or v0.9.0)
required: true
type: string
permissions:
contents: read
jobs:
publish-npm:
name: Publish @yaakapp/api
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: lts/*
registry-url: https://registry.npmjs.org
- name: Install dependencies
run: npm ci
- name: Set @yaakapp/api version
shell: bash
env:
WORKFLOW_VERSION: ${{ inputs.version }}
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="$WORKFLOW_VERSION"
else
VERSION="${GITHUB_REF_NAME#yaak-api-}"
fi
VERSION="${VERSION#v}"
echo "Preparing @yaakapp/api version: $VERSION"
cd packages/plugin-runtime-types
npm version "$VERSION" --no-git-tag-version --allow-same-version
- name: Build @yaakapp/api
working-directory: packages/plugin-runtime-types
run: npm run build
- name: Publish @yaakapp/api
working-directory: packages/plugin-runtime-types
run: npm publish --provenance --access public
================================================
FILE: .github/workflows/release-app.yml
================================================
name: Release App Artifacts
on:
push:
tags: [v*]
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"
os: "macos"
targets: "aarch64-apple-darwin"
- platform: "macos-latest" # for Intel-based Macs.
args: "--target x86_64-apple-darwin"
yaak_arch: "x64"
os: "macos"
targets: "x86_64-apple-darwin"
- platform: "ubuntu-22.04"
args: ""
yaak_arch: "x64"
os: "ubuntu"
targets: ""
- platform: "ubuntu-22.04-arm"
args: ""
yaak_arch: "arm64"
os: "ubuntu"
targets: ""
- platform: "windows-latest"
args: ""
yaak_arch: "x64"
os: "windows"
targets: ""
# Windows ARM64
- platform: "windows-latest"
args: "--target aarch64-pc-windows-msvc"
yaak_arch: "arm64"
os: "windows"
targets: "aarch64-pc-windows-msvc"
runs-on: ${{ matrix.platform }}
timeout-minutes: 40
steps:
- name: Checkout yaakapp/app
uses: actions/checkout@v4
- name: Setup Vite+
uses: voidzero-dev/setup-vp@v1
with:
node-version: "24"
cache: true
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.targets }}
- uses: Swatinem/rust-cache@v2
with:
shared-key: ci
cache-on-failure: true
- name: install dependencies (Linux only)
if: matrix.os == 'ubuntu'
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf xdg-utils
- name: Install Protoc for plugin-runtime
uses: arduino/setup-protoc@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install trusted-signing-cli (Windows only)
if: matrix.os == 'windows'
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$dir = "$env:USERPROFILE\trusted-signing"
New-Item -ItemType Directory -Force -Path $dir | Out-Null
$url = "https://github.com/Levminer/trusted-signing-cli/releases/download/0.8.0/trusted-signing-cli.exe"
$exe = Join-Path $dir "trusted-signing-cli.exe"
Invoke-WebRequest -Uri $url -OutFile $exe
echo $dir >> $env:GITHUB_PATH
& $exe --version
- run: vp install
- run: npm run bootstrap
env:
YAAK_TARGET_ARCH: ${{ matrix.yaak_arch }}
- run: npm run lint
- name: Run JS Tests
run: vp test
- name: Run Rust Tests
run: cargo test --all --exclude yaak-cli
- name: Set version
run: npm run replace-version
env:
YAAK_VERSION: ${{ github.ref_name }}
- name: Sign vendored binaries (macOS only)
if: matrix.os == 'macos'
env:
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
KEYCHAIN_PASSWORD: ${{ secrets.KEYCHAIN_PASSWORD }}
run: |
# Create keychain
KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db
security create-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
security set-keychain-settings -lut 21600 $KEYCHAIN_PATH
security unlock-keychain -p "$KEYCHAIN_PASSWORD" $KEYCHAIN_PATH
# Import certificate
echo "$APPLE_CERTIFICATE" | base64 --decode > certificate.p12
security import certificate.p12 -P "$APPLE_CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k $KEYCHAIN_PATH
security list-keychain -d user -s $KEYCHAIN_PATH
# Sign vendored binaries with hardened runtime and their specific entitlements
codesign --force --options runtime --entitlements crates-tauri/yaak-app/macos/entitlements.yaakprotoc.plist --sign "$APPLE_SIGNING_IDENTITY" crates-tauri/yaak-app/vendored/protoc/yaakprotoc || true
codesign --force --options runtime --entitlements crates-tauri/yaak-app/macos/entitlements.yaaknode.plist --sign "$APPLE_SIGNING_IDENTITY" crates-tauri/yaak-app/vendored/node/yaaknode || true
- uses: tauri-apps/tauri-action@v0
env:
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.os == 'macos' && secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ matrix.os == 'macos' && secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_ID: ${{ matrix.os == 'macos' && secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ matrix.os == 'macos' && secrets.APPLE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ matrix.os == 'macos' && secrets.APPLE_SIGNING_IDENTITY }}
APPLE_TEAM_ID: ${{ matrix.os == 'macos' && secrets.APPLE_TEAM_ID }}
# Windows signing stuff
AZURE_CLIENT_ID: ${{ matrix.os == 'windows' && secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ matrix.os == 'windows' && secrets.AZURE_CLIENT_SECRET }}
AZURE_TENANT_ID: ${{ matrix.os == 'windows' && secrets.AZURE_TENANT_ID }}
with:
tagName: "v__VERSION__"
releaseName: "Release __VERSION__"
releaseBody: "[Changelog __VERSION__](https://yaak.app/blog/__VERSION__)"
releaseDraft: true
prerelease: true
args: "${{ matrix.args }} --config ./crates-tauri/yaak-app/tauri.release.conf.json"
# Build a per-machine NSIS installer for enterprise deployment (PDQ, SCCM, Intune)
- name: Build and upload machine-wide installer (Windows only)
if: matrix.os == 'windows'
shell: pwsh
env:
YAAK_TARGET_ARCH: ${{ matrix.yaak_arch }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
run: |
Get-ChildItem -Recurse -Path target -File -Filter "*.exe.sig" | Remove-Item -Force
npx tauri bundle ${{ matrix.args }} --bundles nsis --config ./crates-tauri/yaak-app/tauri.release.conf.json --config '{"bundle":{"createUpdaterArtifacts":true,"windows":{"nsis":{"installMode":"perMachine"}}}}'
$setup = Get-ChildItem -Recurse -Path target -Filter "*setup*.exe" | Select-Object -First 1
$setupSig = "$($setup.FullName).sig"
$dest = $setup.FullName -replace '-setup\.exe$', '-setup-machine.exe'
$destSig = "$dest.sig"
Copy-Item $setup.FullName $dest
Copy-Item $setupSig $destSig
gh release upload "${{ github.ref_name }}" "$dest" --clobber
gh release upload "${{ github.ref_name }}" "$destSig" --clobber
================================================
FILE: .github/workflows/release-cli-npm.yml
================================================
name: Release CLI to NPM
on:
push:
tags: [yaak-cli-*]
workflow_dispatch:
inputs:
version:
description: CLI version to publish (for example 0.4.0 or v0.4.0)
required: true
type: string
permissions:
contents: read
jobs:
prepare-vendored-assets:
name: Prepare vendored plugin assets
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: lts/*
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
- name: Install dependencies
run: npm ci
- name: Build plugin assets
env:
SKIP_WASM_BUILD: "1"
run: |
npm run build
npm run vendor:vendor-plugins
- name: Upload vendored assets
uses: actions/upload-artifact@v4
with:
name: vendored-assets
path: |
crates-tauri/yaak-app/vendored/plugin-runtime/index.cjs
crates-tauri/yaak-app/vendored/plugins
if-no-files-found: error
build-binaries:
name: Build ${{ matrix.pkg }}
needs: prepare-vendored-assets
runs-on: ${{ matrix.runner }}
strategy:
fail-fast: false
matrix:
include:
- pkg: cli-darwin-arm64
runner: macos-latest
target: aarch64-apple-darwin
binary: yaak
- pkg: cli-darwin-x64
runner: macos-latest
target: x86_64-apple-darwin
binary: yaak
- pkg: cli-linux-arm64
runner: ubuntu-22.04-arm
target: aarch64-unknown-linux-gnu
binary: yaak
- pkg: cli-linux-x64
runner: ubuntu-22.04
target: x86_64-unknown-linux-gnu
binary: yaak
- pkg: cli-win32-arm64
runner: windows-latest
target: aarch64-pc-windows-msvc
binary: yaak.exe
- pkg: cli-win32-x64
runner: windows-latest
target: x86_64-pc-windows-msvc
binary: yaak.exe
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Restore Rust cache
uses: Swatinem/rust-cache@v2
with:
shared-key: release-cli-npm
cache-on-failure: true
- name: Install Linux build dependencies
if: startsWith(matrix.runner, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get install -y pkg-config libdbus-1-dev
- name: Download vendored assets
uses: actions/download-artifact@v4
with:
name: vendored-assets
path: crates-tauri/yaak-app/vendored
- name: Set CLI build version
shell: bash
env:
WORKFLOW_VERSION: ${{ inputs.version }}
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="$WORKFLOW_VERSION"
else
VERSION="${GITHUB_REF_NAME#yaak-cli-}"
fi
VERSION="${VERSION#v}"
echo "Building yaak version: $VERSION"
echo "YAAK_CLI_VERSION=$VERSION" >> "$GITHUB_ENV"
- name: Build yaak
run: cargo build --locked --release -p yaak-cli --bin yaak --target ${{ matrix.target }}
- name: Stage binary artifact
shell: bash
run: |
set -euo pipefail
mkdir -p "npm/dist/${{ matrix.pkg }}"
cp "target/${{ matrix.target }}/release/${{ matrix.binary }}" "npm/dist/${{ matrix.pkg }}/${{ matrix.binary }}"
- name: Upload binary artifact
uses: actions/upload-artifact@v4
with:
name: ${{ matrix.pkg }}
path: npm/dist/${{ matrix.pkg }}/${{ matrix.binary }}
if-no-files-found: error
publish-npm:
name: Publish @yaakapp/cli packages
needs: build-binaries
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: lts/*
registry-url: https://registry.npmjs.org
- name: Download binary artifacts
uses: actions/download-artifact@v4
with:
pattern: cli-*
path: npm/dist
merge-multiple: false
- name: Prepare npm packages
shell: bash
env:
WORKFLOW_VERSION: ${{ inputs.version }}
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
VERSION="$WORKFLOW_VERSION"
else
VERSION="${GITHUB_REF_NAME#yaak-cli-}"
fi
VERSION="${VERSION#v}"
if [[ "$VERSION" == *-* ]]; then
PRERELEASE="${VERSION#*-}"
NPM_TAG="${PRERELEASE%%.*}"
else
NPM_TAG="latest"
fi
echo "Preparing CLI npm packages for version: $VERSION"
echo "Publishing with npm dist-tag: $NPM_TAG"
echo "NPM_TAG=$NPM_TAG" >> "$GITHUB_ENV"
YAAK_CLI_VERSION="$VERSION" node npm/prepare-publish.js
- name: Publish @yaakapp/cli-darwin-arm64
run: npm publish --provenance --access public --tag "$NPM_TAG"
working-directory: npm/cli-darwin-arm64
- name: Publish @yaakapp/cli-darwin-x64
run: npm publish --provenance --access public --tag "$NPM_TAG"
working-directory: npm/cli-darwin-x64
- name: Publish @yaakapp/cli-linux-arm64
run: npm publish --provenance --access public --tag "$NPM_TAG"
working-directory: npm/cli-linux-arm64
- name: Publish @yaakapp/cli-linux-x64
run: npm publish --provenance --access public --tag "$NPM_TAG"
working-directory: npm/cli-linux-x64
- name: Publish @yaakapp/cli-win32-arm64
run: npm publish --provenance --access public --tag "$NPM_TAG"
working-directory: npm/cli-win32-arm64
- name: Publish @yaakapp/cli-win32-x64
run: npm publish --provenance --access public --tag "$NPM_TAG"
working-directory: npm/cli-win32-x64
- name: Publish @yaakapp/cli
run: npm publish --provenance --access public --tag "$NPM_TAG"
working-directory: npm/cli
================================================
FILE: .github/workflows/sponsors.yml
================================================
name: Generate Sponsors README
on:
workflow_dispatch:
schedule:
- cron: 30 15 * * 0-6
permissions:
contents: write
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout 🛎️
uses: actions/checkout@v2
- name: Generate Sponsors
uses: JamesIves/github-sponsors-readme-action@v1
with:
token: ${{ secrets.SPONSORS_PAT }}
file: "README.md"
maximum: 1999
template: '<a href="https://github.com/{{{ login }}}"><img src="{{{ avatarUrl }}}" width="50px" alt="User avatar: {{{ login }}}" /></a> '
active-only: false
include-private: true
marker: "sponsors-base"
- name: Generate Sponsors
uses: JamesIves/github-sponsors-readme-action@v1
with:
token: ${{ secrets.SPONSORS_PAT }}
file: "README.md"
minimum: 2000
template: '<a href="https://github.com/{{{ login }}}"><img src="{{{ avatarUrl }}}" width="80px" alt="User avatar: {{{ login }}}" /></a> '
active-only: false
include-private: true
marker: "sponsors-premium"
# ⚠️ Note: You can use any deployment step here to automatically push the README
# changes back to your branch.
- name: Commit Changes
uses: JamesIves/github-pages-deploy-action@v4
with:
branch: main
force: false
folder: "."
================================================
FILE: .gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
!.vscode/settings.json
!.vscode/launch.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
.eslintcache
out
*.sqlite
*.sqlite-*
.cargo
.tmp
tmp
.zed
codebook.toml
target
# Per-worktree Tauri config (generated by post-checkout hook)
crates-tauri/yaak-app/tauri.worktree.conf.json
# Tauri auto-generated permission files
**/permissions/autogenerated
**/permissions/schemas
# Flatpak build artifacts
flatpak-repo/
.flatpak-builder/
flatpak/flatpak-builder-tools/
flatpak/cargo-sources.json
flatpak/node-sources.json
# Local Codex desktop env state
.codex/environments/environment.toml
# Claude Code local settings
.claude/settings.local.json
================================================
FILE: .node-version
================================================
24.14.0
================================================
FILE: .npmrc
================================================
# vite-plugin-wasm has not yet declared Vite 8 in its peerDependencies
legacy-peer-deps=true
================================================
FILE: .nvmrc
================================================
20
================================================
FILE: .oxfmtignore
================================================
**/bindings/**
crates/yaak-templates/pkg/**
================================================
FILE: .vite-hooks/post-checkout
================================================
node scripts/git-hooks/post-checkout.mjs "$@"
================================================
FILE: .vite-hooks/pre-commit
================================================
vp lint
================================================
FILE: .vscode/extensions.json
================================================
{
"recommendations": [
"rust-lang.rust-analyzer",
"bradlc.vscode-tailwindcss",
"VoidZero.vite-plus-extension-pack"
]
}
================================================
FILE: .vscode/launch.json
================================================
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Dev App",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "start"]
},
{
"type": "node",
"request": "launch",
"name": "Build App",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "start"]
},
{
"type": "node",
"request": "launch",
"name": "Bootstrap",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "bootstrap"]
}
]
}
================================================
FILE: .vscode/settings.json
================================================
{
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.formatOnSave": true,
"editor.formatOnSaveMode": "file",
"editor.codeActionsOnSave": {
"source.fixAll.oxc": "explicit"
}
}
================================================
FILE: AGENTS.md
================================================
- Tag safety: app releases use `v*` tags and CLI releases use `yaak-cli-*` tags; always confirm which one is requested before retagging.
- Do not commit, push, or tag without explicit approval
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to Yaak
Yaak accepts community pull requests for:
- Bug fixes
- Small-scope improvements directly tied to existing behavior
Pull requests that introduce broad new features, major redesigns, or large refactors are out of scope unless explicitly approved first.
## Approval for Non-Bugfix Changes
If your PR is not a bug fix or small-scope improvement, include a link to the approved [feedback item](https://yaak.app/feedback) where contribution approval was explicitly stated.
## Development Setup
For local setup and development workflows, see [`DEVELOPMENT.md`](DEVELOPMENT.md).
================================================
FILE: Cargo.toml
================================================
[workspace]
resolver = "2"
members = [
"crates/yaak",
# Shared crates (no Tauri dependency)
"crates/yaak-core",
"crates/yaak-common",
"crates/yaak-crypto",
"crates/yaak-git",
"crates/yaak-grpc",
"crates/yaak-http",
"crates/yaak-models",
"crates/yaak-plugins",
"crates/yaak-sse",
"crates/yaak-sync",
"crates/yaak-templates",
"crates/yaak-tls",
"crates/yaak-ws",
"crates/yaak-api",
# CLI crates
"crates-cli/yaak-cli",
# Tauri-specific crates
"crates-tauri/yaak-app",
"crates-tauri/yaak-fonts",
"crates-tauri/yaak-license",
"crates-tauri/yaak-mac-window",
"crates-tauri/yaak-tauri-utils",
]
[workspace.dependencies]
chrono = "0.4.42"
hex = "0.4.3"
keyring = "3.6.3"
log = "0.4.29"
reqwest = "0.12.20"
rustls = { version = "0.23.34", default-features = false }
rustls-platform-verifier = "0.6.2"
schemars = { version = "0.8.22", features = ["chrono"] }
serde = "1.0.228"
serde_json = "1.0.145"
sha2 = "0.10.9"
tauri = "2.9.5"
tauri-plugin = "2.5.2"
tauri-plugin-dialog = "2.4.2"
tauri-plugin-shell = "2.3.3"
thiserror = "2.0.17"
tokio = "1.48.0"
ts-rs = "11.1.0"
# Internal crates - shared
yaak-core = { path = "crates/yaak-core" }
yaak = { path = "crates/yaak" }
yaak-common = { path = "crates/yaak-common" }
yaak-crypto = { path = "crates/yaak-crypto" }
yaak-git = { path = "crates/yaak-git" }
yaak-grpc = { path = "crates/yaak-grpc" }
yaak-http = { path = "crates/yaak-http" }
yaak-models = { path = "crates/yaak-models" }
yaak-plugins = { path = "crates/yaak-plugins" }
yaak-sse = { path = "crates/yaak-sse" }
yaak-sync = { path = "crates/yaak-sync" }
yaak-templates = { path = "crates/yaak-templates" }
yaak-tls = { path = "crates/yaak-tls" }
yaak-ws = { path = "crates/yaak-ws" }
yaak-api = { path = "crates/yaak-api" }
# Internal crates - Tauri-specific
yaak-fonts = { path = "crates-tauri/yaak-fonts" }
yaak-license = { path = "crates-tauri/yaak-license" }
yaak-mac-window = { path = "crates-tauri/yaak-mac-window" }
yaak-tauri-utils = { path = "crates-tauri/yaak-tauri-utils" }
[profile.release]
strip = false
================================================
FILE: DEVELOPMENT.md
================================================
# 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) (v24+)
- [Rust](https://www.rust-lang.org/tools/install)
- [Vite+](https://vite.dev/guide/vite-plus) (`vp` CLI)
Check the installations with the following commands:
```shell
node -v
npm -v
vp --version
rustc --version
```
Install the NPM dependencies:
```shell
npm install
```
Run the `bootstrap` command to do some initial setup:
```shell
npm run bootstrap
```
## Run the App
After bootstrapping, start the app in development mode:
```shell
npm start
```
## SQLite Migrations
New migrations can be created from the `src-tauri/` directory:
```shell
npm run migration
```
Rerun the app to apply the migrations.
_Note: For safety, development builds use a separate database location from production builds._
## Lezer Grammar Generation
```sh
# Example
lezer-generator components/core/Editor/<LANG>/<LANG>.grammar > components/core/Editor/<LANG>/<LANG>.ts
```
## Linting and Formatting
This repo uses [Vite+](https://vite.dev/guide/vite-plus) for linting (oxlint) and formatting (oxfmt).
- Lint the entire repo:
```sh
npm run lint
```
- Format code:
```sh
npm run format
```
Notes:
- A pre-commit hook runs `vp lint` automatically on commit.
- Some workspace packages also run `tsc --noEmit` for type-checking.
- VS Code users should install the recommended extensions for format-on-save support.
================================================
FILE: LICENSE
================================================
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.
================================================
FILE: README.md
================================================
<p align="center">
<a href="https://github.com/JamesIves/github-sponsors-readme-action">
<img width="200px" src="https://github.com/mountain-loop/yaak/raw/main/crates-tauri/yaak-app/icons/icon.png">
</a>
</p>
<h1 align="center">
💫 Yaak ➟ Desktop API Client 💫
</h1>
<p align="center">
A fast, privacy-first API client for REST, GraphQL, SSE, WebSocket, and gRPC – built with Tauri, Rust, and React.
</p>
<p align="center">
Development is funded by community-purchased <a href="https://yaak.app/pricing">licenses</a>. You can also <a href="https://github.com/sponsors/gschier">become a sponsor</a> to have your logo appear below. 💖
</p>
<br>
<p align="center">
<!-- sponsors-premium --><a href="https://github.com/MVST-Solutions"><img src="https://github.com/MVST-Solutions.png" width="80px" alt="User avatar: MVST-Solutions" /></a> <a href="https://github.com/dharsanb"><img src="https://github.com/dharsanb.png" width="80px" alt="User avatar: dharsanb" /></a> <a href="https://github.com/railwayapp"><img src="https://github.com/railwayapp.png" width="80px" alt="User avatar: railwayapp" /></a> <a href="https://github.com/caseyamcl"><img src="https://github.com/caseyamcl.png" width="80px" alt="User avatar: caseyamcl" /></a> <a href="https://github.com/bytebase"><img src="https://github.com/bytebase.png" width="80px" alt="User avatar: bytebase" /></a> <a href="https://github.com/"><img src="https://raw.githubusercontent.com/JamesIves/github-sponsors-readme-action/dev/.github/assets/placeholder.png" width="80px" alt="User avatar: " /></a> <!-- sponsors-premium -->
</p>
<p align="center">
<!-- sponsors-base --><a href="https://github.com/seanwash"><img src="https://github.com/seanwash.png" width="50px" alt="User avatar: seanwash" /></a> <a href="https://github.com/jerath"><img src="https://github.com/jerath.png" width="50px" alt="User avatar: jerath" /></a> <a href="https://github.com/itsa-sh"><img src="https://github.com/itsa-sh.png" width="50px" alt="User avatar: itsa-sh" /></a> <a href="https://github.com/dmmulroy"><img src="https://github.com/dmmulroy.png" width="50px" alt="User avatar: dmmulroy" /></a> <a href="https://github.com/timcole"><img src="https://github.com/timcole.png" width="50px" alt="User avatar: timcole" /></a> <a href="https://github.com/VLZH"><img src="https://github.com/VLZH.png" width="50px" alt="User avatar: VLZH" /></a> <a href="https://github.com/terasaka2k"><img src="https://github.com/terasaka2k.png" width="50px" alt="User avatar: terasaka2k" /></a> <a href="https://github.com/andriyor"><img src="https://github.com/andriyor.png" width="50px" alt="User avatar: andriyor" /></a> <a href="https://github.com/majudhu"><img src="https://github.com/majudhu.png" width="50px" alt="User avatar: majudhu" /></a> <a href="https://github.com/axelrindle"><img src="https://github.com/axelrindle.png" width="50px" alt="User avatar: axelrindle" /></a> <a href="https://github.com/jirizverina"><img src="https://github.com/jirizverina.png" width="50px" alt="User avatar: jirizverina" /></a> <a href="https://github.com/chip-well"><img src="https://github.com/chip-well.png" width="50px" alt="User avatar: chip-well" /></a> <a href="https://github.com/GRAYAH"><img src="https://github.com/GRAYAH.png" width="50px" alt="User avatar: GRAYAH" /></a> <a href="https://github.com/flashblaze"><img src="https://github.com/flashblaze.png" width="50px" alt="User avatar: flashblaze" /></a> <a href="https://github.com/Frostist"><img src="https://github.com/Frostist.png" width="50px" alt="User avatar: Frostist" /></a> <!-- sponsors-base -->
</p>

## Features
Yaak is an offline-first API client designed to stay out of your way while giving you everything you need when you need it.
Built with [Tauri](https://tauri.app), Rust, and React, it’s fast, lightweight, and private. No telemetry, no VC funding, and no cloud lock-in.
### 🌐 Work with any API
- Import collections from Postman, Insomnia, OpenAPI, Swagger, or Curl.
- Send requests via REST, GraphQL, gRPC, WebSocket, or Server-Sent Events.
- Filter and inspect responses with JSONPath or XPath.
### 🔐 Stay secure
- Use OAuth 2.0, JWT, Basic Auth, or custom plugins for authentication.
- Secure sensitive values with encrypted secrets.
- Store secrets in your OS keychain.
### ☁️ Organize & collaborate
- Group requests into workspaces and nested folders.
- Use environment variables to switch between dev, staging, and prod.
- Mirror workspaces to your filesystem for versioning in Git or syncing with Dropbox.
### 🧩 Extend & customize
- Insert dynamic values like UUIDs or timestamps with template tags.
- Pick from built-in themes or build your own.
- Create plugins to extend authentication, template tags, or the UI.
## Contribution Policy
> [!IMPORTANT]
> Community PRs are currently limited to bug fixes and small-scope improvements.
> If your PR is out of scope, link an approved feedback item from [yaak.app/feedback](https://yaak.app/feedback).
> See [`CONTRIBUTING.md`](CONTRIBUTING.md) for policy details and [`DEVELOPMENT.md`](DEVELOPMENT.md) for local setup.
## Useful Resources
- [Feedback and Bug Reports](https://feedback.yaak.app)
- [Documentation](https://yaak.app/docs)
- [Yaak vs Postman](https://yaak.app/alternatives/postman)
- [Yaak vs Bruno](https://yaak.app/alternatives/bruno)
- [Yaak vs Insomnia](https://yaak.app/alternatives/insomnia)
================================================
FILE: crates/yaak/Cargo.toml
================================================
[package]
name = "yaak"
version = "0.1.0"
edition = "2024"
publish = false
[dependencies]
async-trait = "0.1"
log = { workspace = true }
md5 = "0.8.0"
serde_json = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["sync", "rt"] }
yaak-http = { workspace = true }
yaak-crypto = { workspace = true }
yaak-models = { workspace = true }
yaak-plugins = { workspace = true }
yaak-templates = { workspace = true }
yaak-tls = { workspace = true }
[dev-dependencies]
tempfile = "3"
================================================
FILE: crates/yaak/src/error.rs
================================================
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error(transparent)]
Send(#[from] crate::send::SendHttpRequestError),
}
pub type Result<T> = std::result::Result<T, Error>;
================================================
FILE: crates/yaak/src/lib.rs
================================================
pub mod error;
pub mod plugin_events;
pub mod render;
pub mod send;
pub use error::Error;
pub type Result<T> = error::Result<T>;
================================================
FILE: crates/yaak/src/plugin_events.rs
================================================
use yaak_models::models::AnyModel;
use yaak_models::query_manager::QueryManager;
use yaak_models::util::UpdateSource;
use yaak_plugins::events::{
CloseWindowRequest, CopyTextRequest, DeleteKeyValueRequest, DeleteKeyValueResponse,
DeleteModelRequest, DeleteModelResponse, ErrorResponse, FindHttpResponsesRequest,
FindHttpResponsesResponse, GetCookieValueRequest, GetHttpRequestByIdRequest,
GetHttpRequestByIdResponse, GetKeyValueRequest, GetKeyValueResponse, InternalEventPayload,
ListCookieNamesRequest, ListFoldersRequest, ListFoldersResponse, ListHttpRequestsRequest,
ListHttpRequestsResponse, ListOpenWorkspacesRequest, OpenExternalUrlRequest, OpenWindowRequest,
PromptFormRequest, PromptTextRequest, ReloadResponse, RenderGrpcRequestRequest,
RenderHttpRequestRequest, SendHttpRequestRequest, SetKeyValueRequest, ShowToastRequest,
TemplateRenderRequest, UpsertModelRequest, UpsertModelResponse, WindowInfoRequest,
};
pub struct SharedPluginEventContext<'a> {
pub plugin_name: &'a str,
pub workspace_id: Option<&'a str>,
}
#[derive(Debug)]
pub enum GroupedPluginEvent<'a> {
Handled(Option<InternalEventPayload>),
ToHandle(HostRequest<'a>),
}
#[derive(Debug)]
pub enum GroupedPluginRequest<'a> {
Shared(SharedRequest<'a>),
Host(HostRequest<'a>),
Ignore,
}
#[derive(Debug)]
pub enum SharedRequest<'a> {
GetKeyValue(&'a GetKeyValueRequest),
SetKeyValue(&'a SetKeyValueRequest),
DeleteKeyValue(&'a DeleteKeyValueRequest),
GetHttpRequestById(&'a GetHttpRequestByIdRequest),
ListFolders(&'a ListFoldersRequest),
ListHttpRequests(&'a ListHttpRequestsRequest),
FindHttpResponses(&'a FindHttpResponsesRequest),
UpsertModel(&'a UpsertModelRequest),
DeleteModel(&'a DeleteModelRequest),
}
#[derive(Debug)]
pub enum HostRequest<'a> {
ShowToast(&'a ShowToastRequest),
CopyText(&'a CopyTextRequest),
PromptText(&'a PromptTextRequest),
PromptForm(&'a PromptFormRequest),
RenderGrpcRequest(&'a RenderGrpcRequestRequest),
RenderHttpRequest(&'a RenderHttpRequestRequest),
TemplateRender(&'a TemplateRenderRequest),
SendHttpRequest(&'a SendHttpRequestRequest),
OpenWindow(&'a OpenWindowRequest),
CloseWindow(&'a CloseWindowRequest),
OpenExternalUrl(&'a OpenExternalUrlRequest),
ListOpenWorkspaces(&'a ListOpenWorkspacesRequest),
ListCookieNames(&'a ListCookieNamesRequest),
GetCookieValue(&'a GetCookieValueRequest),
WindowInfo(&'a WindowInfoRequest),
ErrorResponse(&'a ErrorResponse),
ReloadResponse(&'a ReloadResponse),
OtherRequest(&'a InternalEventPayload),
}
impl HostRequest<'_> {
pub fn type_name(&self) -> String {
match self {
HostRequest::ShowToast(_) => "show_toast_request".to_string(),
HostRequest::CopyText(_) => "copy_text_request".to_string(),
HostRequest::PromptText(_) => "prompt_text_request".to_string(),
HostRequest::PromptForm(_) => "prompt_form_request".to_string(),
HostRequest::RenderGrpcRequest(_) => "render_grpc_request_request".to_string(),
HostRequest::RenderHttpRequest(_) => "render_http_request_request".to_string(),
HostRequest::TemplateRender(_) => "template_render_request".to_string(),
HostRequest::SendHttpRequest(_) => "send_http_request_request".to_string(),
HostRequest::OpenWindow(_) => "open_window_request".to_string(),
HostRequest::CloseWindow(_) => "close_window_request".to_string(),
HostRequest::OpenExternalUrl(_) => "open_external_url_request".to_string(),
HostRequest::ListOpenWorkspaces(_) => "list_open_workspaces_request".to_string(),
HostRequest::ListCookieNames(_) => "list_cookie_names_request".to_string(),
HostRequest::GetCookieValue(_) => "get_cookie_value_request".to_string(),
HostRequest::WindowInfo(_) => "window_info_request".to_string(),
HostRequest::ErrorResponse(_) => "error_response".to_string(),
HostRequest::ReloadResponse(_) => "reload_response".to_string(),
HostRequest::OtherRequest(payload) => payload.type_name(),
}
}
}
impl<'a> From<&'a InternalEventPayload> for GroupedPluginRequest<'a> {
fn from(payload: &'a InternalEventPayload) -> Self {
match payload {
InternalEventPayload::GetKeyValueRequest(req) => {
GroupedPluginRequest::Shared(SharedRequest::GetKeyValue(req))
}
InternalEventPayload::SetKeyValueRequest(req) => {
GroupedPluginRequest::Shared(SharedRequest::SetKeyValue(req))
}
InternalEventPayload::DeleteKeyValueRequest(req) => {
GroupedPluginRequest::Shared(SharedRequest::DeleteKeyValue(req))
}
InternalEventPayload::GetHttpRequestByIdRequest(req) => {
GroupedPluginRequest::Shared(SharedRequest::GetHttpRequestById(req))
}
InternalEventPayload::ErrorResponse(resp) => {
GroupedPluginRequest::Host(HostRequest::ErrorResponse(resp))
}
InternalEventPayload::ReloadResponse(req) => {
GroupedPluginRequest::Host(HostRequest::ReloadResponse(req))
}
InternalEventPayload::ListOpenWorkspacesRequest(req) => {
GroupedPluginRequest::Host(HostRequest::ListOpenWorkspaces(req))
}
InternalEventPayload::ListFoldersRequest(req) => {
GroupedPluginRequest::Shared(SharedRequest::ListFolders(req))
}
InternalEventPayload::ListHttpRequestsRequest(req) => {
GroupedPluginRequest::Shared(SharedRequest::ListHttpRequests(req))
}
InternalEventPayload::ShowToastRequest(req) => {
GroupedPluginRequest::Host(HostRequest::ShowToast(req))
}
InternalEventPayload::CopyTextRequest(req) => {
GroupedPluginRequest::Host(HostRequest::CopyText(req))
}
InternalEventPayload::PromptTextRequest(req) => {
GroupedPluginRequest::Host(HostRequest::PromptText(req))
}
InternalEventPayload::PromptFormRequest(req) => {
GroupedPluginRequest::Host(HostRequest::PromptForm(req))
}
InternalEventPayload::FindHttpResponsesRequest(req) => {
GroupedPluginRequest::Shared(SharedRequest::FindHttpResponses(req))
}
InternalEventPayload::UpsertModelRequest(req) => {
GroupedPluginRequest::Shared(SharedRequest::UpsertModel(req))
}
InternalEventPayload::DeleteModelRequest(req) => {
GroupedPluginRequest::Shared(SharedRequest::DeleteModel(req))
}
InternalEventPayload::RenderGrpcRequestRequest(req) => {
GroupedPluginRequest::Host(HostRequest::RenderGrpcRequest(req))
}
InternalEventPayload::RenderHttpRequestRequest(req) => {
GroupedPluginRequest::Host(HostRequest::RenderHttpRequest(req))
}
InternalEventPayload::TemplateRenderRequest(req) => {
GroupedPluginRequest::Host(HostRequest::TemplateRender(req))
}
InternalEventPayload::SendHttpRequestRequest(req) => {
GroupedPluginRequest::Host(HostRequest::SendHttpRequest(req))
}
InternalEventPayload::OpenWindowRequest(req) => {
GroupedPluginRequest::Host(HostRequest::OpenWindow(req))
}
InternalEventPayload::CloseWindowRequest(req) => {
GroupedPluginRequest::Host(HostRequest::CloseWindow(req))
}
InternalEventPayload::OpenExternalUrlRequest(req) => {
GroupedPluginRequest::Host(HostRequest::OpenExternalUrl(req))
}
InternalEventPayload::ListCookieNamesRequest(req) => {
GroupedPluginRequest::Host(HostRequest::ListCookieNames(req))
}
InternalEventPayload::GetCookieValueRequest(req) => {
GroupedPluginRequest::Host(HostRequest::GetCookieValue(req))
}
InternalEventPayload::WindowInfoRequest(req) => {
GroupedPluginRequest::Host(HostRequest::WindowInfo(req))
}
payload if payload.type_name().ends_with("_request") => {
GroupedPluginRequest::Host(HostRequest::OtherRequest(payload))
}
_ => GroupedPluginRequest::Ignore,
}
}
}
pub fn handle_shared_plugin_event<'a>(
query_manager: &QueryManager,
payload: &'a InternalEventPayload,
context: SharedPluginEventContext<'_>,
) -> GroupedPluginEvent<'a> {
match GroupedPluginRequest::from(payload) {
GroupedPluginRequest::Shared(req) => {
GroupedPluginEvent::Handled(Some(build_shared_reply(query_manager, req, context)))
}
GroupedPluginRequest::Host(req) => GroupedPluginEvent::ToHandle(req),
GroupedPluginRequest::Ignore => GroupedPluginEvent::Handled(None),
}
}
fn build_shared_reply(
query_manager: &QueryManager,
request: SharedRequest<'_>,
context: SharedPluginEventContext<'_>,
) -> InternalEventPayload {
match request {
SharedRequest::GetKeyValue(req) => {
let value = query_manager
.connect()
.get_plugin_key_value(context.plugin_name, &req.key)
.map(|v| v.value);
InternalEventPayload::GetKeyValueResponse(GetKeyValueResponse { value })
}
SharedRequest::SetKeyValue(req) => {
query_manager.connect().set_plugin_key_value(context.plugin_name, &req.key, &req.value);
InternalEventPayload::SetKeyValueResponse(yaak_plugins::events::SetKeyValueResponse {})
}
SharedRequest::DeleteKeyValue(req) => {
match query_manager.connect().delete_plugin_key_value(context.plugin_name, &req.key) {
Ok(deleted) => {
InternalEventPayload::DeleteKeyValueResponse(DeleteKeyValueResponse { deleted })
}
Err(err) => InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to delete plugin key '{}' : {err}", req.key),
}),
}
}
SharedRequest::GetHttpRequestById(req) => {
let http_request = query_manager.connect().get_http_request(&req.id).ok();
InternalEventPayload::GetHttpRequestByIdResponse(GetHttpRequestByIdResponse {
http_request,
})
}
SharedRequest::ListFolders(_) => {
let Some(workspace_id) = context.workspace_id else {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: "workspace_id is required for list_folders_request".to_string(),
});
};
let folders = match query_manager.connect().list_folders(workspace_id) {
Ok(folders) => folders,
Err(err) => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to list folders: {err}"),
});
}
};
InternalEventPayload::ListFoldersResponse(ListFoldersResponse { folders })
}
SharedRequest::ListHttpRequests(req) => {
let http_requests = if let Some(folder_id) = req.folder_id.as_deref() {
match query_manager.connect().list_http_requests_for_folder_recursive(folder_id) {
Ok(http_requests) => http_requests,
Err(err) => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to list HTTP requests for folder: {err}"),
});
}
}
} else {
let Some(workspace_id) = context.workspace_id else {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error:
"workspace_id is required for list_http_requests_request without folder_id"
.to_string(),
});
};
match query_manager.connect().list_http_requests(workspace_id) {
Ok(http_requests) => http_requests,
Err(err) => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to list HTTP requests: {err}"),
});
}
}
};
InternalEventPayload::ListHttpRequestsResponse(ListHttpRequestsResponse {
http_requests,
})
}
SharedRequest::FindHttpResponses(req) => {
let http_responses = query_manager
.connect()
.list_http_responses_for_request(&req.request_id, req.limit.map(|l| l as u64))
.unwrap_or_default();
InternalEventPayload::FindHttpResponsesResponse(FindHttpResponsesResponse {
http_responses,
})
}
SharedRequest::UpsertModel(req) => {
use AnyModel::*;
let model = match &req.model {
HttpRequest(m) => {
match query_manager.connect().upsert_http_request(m, &UpdateSource::Plugin) {
Ok(model) => HttpRequest(model),
Err(err) => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to upsert HTTP request: {err}"),
});
}
}
}
GrpcRequest(m) => {
match query_manager.connect().upsert_grpc_request(m, &UpdateSource::Plugin) {
Ok(model) => GrpcRequest(model),
Err(err) => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to upsert gRPC request: {err}"),
});
}
}
}
WebsocketRequest(m) => {
match query_manager.connect().upsert_websocket_request(m, &UpdateSource::Plugin)
{
Ok(model) => WebsocketRequest(model),
Err(err) => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to upsert WebSocket request: {err}"),
});
}
}
}
Folder(m) => {
match query_manager.connect().upsert_folder(m, &UpdateSource::Plugin) {
Ok(model) => Folder(model),
Err(err) => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to upsert folder: {err}"),
});
}
}
}
Environment(m) => {
match query_manager.connect().upsert_environment(m, &UpdateSource::Plugin) {
Ok(model) => Environment(model),
Err(err) => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to upsert environment: {err}"),
});
}
}
}
Workspace(m) => {
match query_manager.connect().upsert_workspace(m, &UpdateSource::Plugin) {
Ok(model) => Workspace(model),
Err(err) => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to upsert workspace: {err}"),
});
}
}
}
_ => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: "Upsert not supported for this model type".to_string(),
});
}
};
InternalEventPayload::UpsertModelResponse(UpsertModelResponse { model })
}
SharedRequest::DeleteModel(req) => {
let model = match req.model.as_str() {
"http_request" => {
match query_manager
.connect()
.delete_http_request_by_id(&req.id, &UpdateSource::Plugin)
{
Ok(model) => AnyModel::HttpRequest(model),
Err(err) => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to delete HTTP request: {err}"),
});
}
}
}
"grpc_request" => {
match query_manager
.connect()
.delete_grpc_request_by_id(&req.id, &UpdateSource::Plugin)
{
Ok(model) => AnyModel::GrpcRequest(model),
Err(err) => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to delete gRPC request: {err}"),
});
}
}
}
"websocket_request" => {
match query_manager
.connect()
.delete_websocket_request_by_id(&req.id, &UpdateSource::Plugin)
{
Ok(model) => AnyModel::WebsocketRequest(model),
Err(err) => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to delete WebSocket request: {err}"),
});
}
}
}
"folder" => match query_manager
.connect()
.delete_folder_by_id(&req.id, &UpdateSource::Plugin)
{
Ok(model) => AnyModel::Folder(model),
Err(err) => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to delete folder: {err}"),
});
}
},
"environment" => {
match query_manager
.connect()
.delete_environment_by_id(&req.id, &UpdateSource::Plugin)
{
Ok(model) => AnyModel::Environment(model),
Err(err) => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: format!("Failed to delete environment: {err}"),
});
}
}
}
_ => {
return InternalEventPayload::ErrorResponse(ErrorResponse {
error: "Delete not supported for this model type".to_string(),
});
}
};
InternalEventPayload::DeleteModelResponse(DeleteModelResponse { model })
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use tempfile::TempDir;
use yaak_models::models::{AnyModel, Folder, HttpRequest, Workspace};
use yaak_models::util::UpdateSource;
fn seed_query_manager() -> (QueryManager, TempDir) {
let temp_dir = TempDir::new().expect("Failed to create temp dir");
let db_path = temp_dir.path().join("db.sqlite");
let blob_path = temp_dir.path().join("blobs.sqlite");
let (query_manager, _blob_manager, _rx) =
yaak_models::init_standalone(&db_path, &blob_path).expect("Failed to initialize DB");
query_manager
.connect()
.upsert_workspace(
&Workspace {
id: "wk_test".to_string(),
name: "Workspace".to_string(),
..Default::default()
},
&UpdateSource::Sync,
)
.expect("Failed to seed workspace");
query_manager
.connect()
.upsert_folder(
&Folder {
id: "fl_test".to_string(),
workspace_id: "wk_test".to_string(),
name: "Folder".to_string(),
..Default::default()
},
&UpdateSource::Sync,
)
.expect("Failed to seed folder");
query_manager
.connect()
.upsert_http_request(
&HttpRequest {
id: "rq_test".to_string(),
workspace_id: "wk_test".to_string(),
folder_id: Some("fl_test".to_string()),
name: "Request".to_string(),
method: "GET".to_string(),
url: "https://example.com".to_string(),
..Default::default()
},
&UpdateSource::Sync,
)
.expect("Failed to seed request");
(query_manager, temp_dir)
}
#[test]
fn list_requests_requires_workspace_when_folder_missing() {
let (query_manager, _temp_dir) = seed_query_manager();
let payload = InternalEventPayload::ListHttpRequestsRequest(
yaak_plugins::events::ListHttpRequestsRequest { folder_id: None },
);
let result = handle_shared_plugin_event(
&query_manager,
&payload,
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: None },
);
assert!(matches!(
result,
GroupedPluginEvent::Handled(Some(InternalEventPayload::ErrorResponse(_)))
));
}
#[test]
fn list_requests_by_workspace_and_folder() {
let (query_manager, _temp_dir) = seed_query_manager();
let by_workspace_payload = InternalEventPayload::ListHttpRequestsRequest(
yaak_plugins::events::ListHttpRequestsRequest { folder_id: None },
);
let by_workspace = handle_shared_plugin_event(
&query_manager,
&by_workspace_payload,
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: Some("wk_test") },
);
match by_workspace {
GroupedPluginEvent::Handled(Some(InternalEventPayload::ListHttpRequestsResponse(
resp,
))) => {
assert_eq!(resp.http_requests.len(), 1);
}
other => panic!("unexpected workspace response: {other:?}"),
}
let by_folder_payload = InternalEventPayload::ListHttpRequestsRequest(
yaak_plugins::events::ListHttpRequestsRequest {
folder_id: Some("fl_test".to_string()),
},
);
let by_folder = handle_shared_plugin_event(
&query_manager,
&by_folder_payload,
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: None },
);
match by_folder {
GroupedPluginEvent::Handled(Some(InternalEventPayload::ListHttpRequestsResponse(
resp,
))) => {
assert_eq!(resp.http_requests.len(), 1);
}
other => panic!("unexpected folder response: {other:?}"),
}
}
#[test]
fn find_http_responses_is_shared_handled() {
let (query_manager, _temp_dir) = seed_query_manager();
let payload = InternalEventPayload::FindHttpResponsesRequest(FindHttpResponsesRequest {
request_id: "rq_test".to_string(),
limit: Some(1),
});
let result = handle_shared_plugin_event(
&query_manager,
&payload,
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: Some("wk_test") },
);
match result {
GroupedPluginEvent::Handled(Some(InternalEventPayload::FindHttpResponsesResponse(
resp,
))) => {
assert!(resp.http_responses.is_empty());
}
other => panic!("unexpected find responses result: {other:?}"),
}
}
#[test]
fn upsert_and_delete_model_are_shared_handled() {
let (query_manager, _temp_dir) = seed_query_manager();
let existing = query_manager
.connect()
.get_http_request("rq_test")
.expect("Failed to load seeded request");
let upsert_payload = InternalEventPayload::UpsertModelRequest(UpsertModelRequest {
model: AnyModel::HttpRequest(HttpRequest {
name: "Request Updated".to_string(),
..existing
}),
});
let upsert_result = handle_shared_plugin_event(
&query_manager,
&upsert_payload,
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: Some("wk_test") },
);
match upsert_result {
GroupedPluginEvent::Handled(Some(InternalEventPayload::UpsertModelResponse(resp))) => {
match resp.model {
AnyModel::HttpRequest(r) => assert_eq!(r.name, "Request Updated"),
other => panic!("unexpected upsert model type: {other:?}"),
}
}
other => panic!("unexpected upsert result: {other:?}"),
}
let delete_payload = InternalEventPayload::DeleteModelRequest(DeleteModelRequest {
model: "http_request".to_string(),
id: "rq_test".to_string(),
});
let delete_result = handle_shared_plugin_event(
&query_manager,
&delete_payload,
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: Some("wk_test") },
);
match delete_result {
GroupedPluginEvent::Handled(Some(InternalEventPayload::DeleteModelResponse(resp))) => {
match resp.model {
AnyModel::HttpRequest(r) => assert_eq!(r.id, "rq_test"),
other => panic!("unexpected delete model type: {other:?}"),
}
}
other => panic!("unexpected delete result: {other:?}"),
}
}
#[test]
fn host_request_classification_works() {
let (query_manager, _temp_dir) = seed_query_manager();
let payload = InternalEventPayload::WindowInfoRequest(WindowInfoRequest {
label: "main".to_string(),
});
let result = handle_shared_plugin_event(
&query_manager,
&payload,
SharedPluginEventContext { plugin_name: "@yaak/test", workspace_id: None },
);
match result {
GroupedPluginEvent::ToHandle(HostRequest::WindowInfo(req)) => {
assert_eq!(req.label, "main")
}
other => panic!("unexpected host classification: {other:?}"),
}
}
}
================================================
FILE: crates/yaak/src/render.rs
================================================
use log::info;
use serde_json::Value;
use std::collections::BTreeMap;
use yaak_http::path_placeholders::apply_path_placeholders;
use yaak_models::models::{Environment, GrpcRequest, HttpRequest, HttpRequestHeader, HttpUrlParameter};
use yaak_models::render::make_vars_hashmap;
use yaak_templates::{RenderOptions, TemplateCallback, parse_and_render, render_json_value_raw};
pub async fn render_http_request<T: TemplateCallback>(
request: &HttpRequest,
environment_chain: Vec<Environment>,
callback: &T,
options: &RenderOptions,
) -> yaak_templates::error::Result<HttpRequest> {
let vars = &make_vars_hashmap(environment_chain);
let mut url_parameters = Vec::new();
for parameter in request.url_parameters.clone() {
if !parameter.enabled {
continue;
}
url_parameters.push(HttpUrlParameter {
enabled: parameter.enabled,
name: parse_and_render(parameter.name.as_str(), vars, callback, options).await?,
value: parse_and_render(parameter.value.as_str(), vars, callback, options).await?,
id: parameter.id,
})
}
let mut headers = Vec::new();
for header in request.headers.clone() {
if !header.enabled {
continue;
}
headers.push(HttpRequestHeader {
enabled: header.enabled,
name: parse_and_render(header.name.as_str(), vars, callback, options).await?,
value: parse_and_render(header.value.as_str(), vars, callback, options).await?,
id: header.id,
})
}
let mut body = BTreeMap::new();
for (key, value) in request.body.clone() {
let value = if key == "form" { strip_disabled_form_entries(value) } else { value };
body.insert(key, render_json_value_raw(value, vars, callback, options).await?);
}
let authentication = {
let mut disabled = false;
let mut auth = BTreeMap::new();
match request.authentication.get("disabled") {
Some(Value::Bool(true)) => {
disabled = true;
}
Some(Value::String(template)) => {
disabled = parse_and_render(template.as_str(), vars, callback, options)
.await
.unwrap_or_default()
.is_empty();
info!(
"Rendering authentication.disabled as a template: {disabled} from \"{template}\""
);
}
_ => {}
}
if disabled {
auth.insert("disabled".to_string(), Value::Bool(true));
} else {
for (key, value) in request.authentication.clone() {
if key == "disabled" {
auth.insert(key, Value::Bool(false));
} else {
auth.insert(key, render_json_value_raw(value, vars, callback, options).await?);
}
}
}
auth
};
let url = parse_and_render(request.url.clone().as_str(), vars, callback, options).await?;
let (url, url_parameters) = apply_path_placeholders(&url, &url_parameters);
Ok(HttpRequest { url, url_parameters, headers, body, authentication, ..request.to_owned() })
}
pub async fn render_grpc_request<T: TemplateCallback>(
r: &GrpcRequest,
environment_chain: Vec<Environment>,
cb: &T,
opt: &RenderOptions,
) -> yaak_templates::error::Result<GrpcRequest> {
let vars = &make_vars_hashmap(environment_chain);
let mut metadata = Vec::new();
for p in r.metadata.clone() {
if !p.enabled {
continue;
}
metadata.push(HttpRequestHeader {
enabled: p.enabled,
name: parse_and_render(p.name.as_str(), vars, cb, opt).await?,
value: parse_and_render(p.value.as_str(), vars, cb, opt).await?,
id: p.id,
})
}
let authentication = {
let mut disabled = false;
let mut auth = BTreeMap::new();
match r.authentication.get("disabled") {
Some(Value::Bool(true)) => {
disabled = true;
}
Some(Value::String(tmpl)) => {
disabled = parse_and_render(tmpl.as_str(), vars, cb, opt)
.await
.unwrap_or_default()
.is_empty();
info!(
"Rendering authentication.disabled as a template: {disabled} from \"{tmpl}\""
);
}
_ => {}
}
if disabled {
auth.insert("disabled".to_string(), Value::Bool(true));
} else {
for (k, v) in r.authentication.clone() {
if k == "disabled" {
auth.insert(k, Value::Bool(false));
} else {
auth.insert(k, render_json_value_raw(v, vars, cb, opt).await?);
}
}
}
auth
};
let url = parse_and_render(r.url.as_str(), vars, cb, opt).await?;
Ok(GrpcRequest { url, metadata, authentication, ..r.to_owned() })
}
fn strip_disabled_form_entries(v: Value) -> Value {
match v {
Value::Array(items) => Value::Array(
items
.into_iter()
.filter(|item| item.get("enabled").and_then(|e| e.as_bool()).unwrap_or(true))
.collect(),
),
v => v,
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_strip_disabled_form_entries() {
let input = json!([
{"enabled": true, "name": "foo", "value": "bar"},
{"enabled": false, "name": "disabled", "value": "gone"},
{"enabled": true, "name": "baz", "value": "qux"},
]);
let result = strip_disabled_form_entries(input);
assert_eq!(
result,
json!([
{"enabled": true, "name": "foo", "value": "bar"},
{"enabled": true, "name": "baz", "value": "qux"},
])
);
}
#[test]
fn test_strip_disabled_form_entries_all_disabled() {
let input = json!([
{"enabled": false, "name": "a", "value": "b"},
{"enabled": false, "name": "c", "value": "d"},
]);
let result = strip_disabled_form_entries(input);
assert_eq!(result, json!([]));
}
#[test]
fn test_strip_disabled_form_entries_missing_enabled_defaults_to_kept() {
let input = json!([
{"name": "no_enabled_field", "value": "kept"},
{"enabled": false, "name": "disabled", "value": "gone"},
]);
let result = strip_disabled_form_entries(input);
assert_eq!(
result,
json!([
{"name": "no_enabled_field", "value": "kept"},
])
);
}
#[test]
fn test_strip_disabled_form_entries_non_array_passthrough() {
let input = json!("just a string");
let result = strip_disabled_form_entries(input.clone());
assert_eq!(result, input);
}
}
================================================
FILE: crates/yaak/src/send.rs
================================================
use crate::render::render_http_request;
use async_trait::async_trait;
use log::warn;
use std::path::{Path, PathBuf};
use std::sync::Arc;
use std::sync::atomic::{AtomicI32, Ordering};
use std::time::Instant;
use thiserror::Error;
use tokio::fs::File;
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use tokio::sync::mpsc;
use tokio::sync::watch;
use yaak_crypto::manager::EncryptionManager;
use yaak_http::client::{
HttpConnectionOptions, HttpConnectionProxySetting, HttpConnectionProxySettingAuth,
};
use yaak_http::cookies::CookieStore;
use yaak_http::manager::HttpConnectionManager;
use yaak_http::sender::{HttpResponseEvent as SenderHttpResponseEvent, ReqwestSender};
use yaak_http::tee_reader::TeeReader;
use yaak_http::transaction::HttpTransaction;
use yaak_http::types::{
SendableBody, SendableHttpRequest, SendableHttpRequestOptions, append_query_params,
};
use yaak_models::blob_manager::{BlobManager, BodyChunk};
use yaak_models::models::{
ClientCertificate, CookieJar, DnsOverride, Environment, HttpRequest, HttpResponse,
HttpResponseEvent, HttpResponseHeader, HttpResponseState, ProxySetting, ProxySettingAuth,
};
use yaak_models::query_manager::QueryManager;
use yaak_models::util::{UpdateSource, generate_prefixed_id};
use yaak_plugins::events::{
CallHttpAuthenticationRequest, HttpHeader, PluginContext, RenderPurpose,
};
use yaak_plugins::manager::PluginManager;
use yaak_plugins::template_callback::PluginTemplateCallback;
use yaak_templates::{RenderOptions, TemplateCallback};
use yaak_tls::find_client_certificate;
const HTTP_EVENT_CHANNEL_CAPACITY: usize = 100;
const REQUEST_BODY_CHUNK_SIZE: usize = 1024 * 1024;
const RESPONSE_PROGRESS_UPDATE_INTERVAL_MS: u128 = 100;
#[derive(Debug, Error)]
pub enum SendHttpRequestError {
#[error("Failed to load request: {0}")]
LoadRequest(#[source] yaak_models::error::Error),
#[error("Failed to load workspace: {0}")]
LoadWorkspace(#[source] yaak_models::error::Error),
#[error("Failed to resolve environments: {0}")]
ResolveEnvironments(#[source] yaak_models::error::Error),
#[error("Failed to resolve inherited request settings: {0}")]
ResolveRequestInheritance(#[source] yaak_models::error::Error),
#[error("Failed to load cookie jar: {0}")]
LoadCookieJar(#[source] yaak_models::error::Error),
#[error("Failed to persist cookie jar: {0}")]
PersistCookieJar(#[source] yaak_models::error::Error),
#[error("Failed to render request templates: {0}")]
RenderRequest(#[source] yaak_templates::error::Error),
#[error("Failed to prepare request before send: {0}")]
PrepareSendableRequest(String),
#[error("Failed to persist response metadata: {0}")]
PersistResponse(#[source] yaak_models::error::Error),
#[error("Failed to create HTTP client: {0}")]
CreateHttpClient(#[source] yaak_http::error::Error),
#[error("Failed to build sendable request: {0}")]
BuildSendableRequest(#[source] yaak_http::error::Error),
#[error("Failed to send request: {0}")]
SendRequest(#[source] yaak_http::error::Error),
#[error("Failed to read response body: {0}")]
ReadResponseBody(#[source] yaak_http::error::Error),
#[error("Failed to create response directory {path:?}: {source}")]
CreateResponseDirectory {
path: PathBuf,
#[source]
source: std::io::Error,
},
#[error("Failed to write response body to {path:?}: {source}")]
WriteResponseBody {
path: PathBuf,
#[source]
source: std::io::Error,
},
}
pub type Result<T> = std::result::Result<T, SendHttpRequestError>;
#[async_trait]
pub trait PrepareSendableRequest: Send + Sync {
async fn prepare_sendable_request(
&self,
rendered_request: &HttpRequest,
auth_context_id: &str,
sendable_request: &mut SendableHttpRequest,
) -> std::result::Result<(), String>;
}
#[async_trait]
pub trait SendRequestExecutor: Send + Sync {
async fn send(
&self,
sendable_request: SendableHttpRequest,
event_tx: mpsc::Sender<SenderHttpResponseEvent>,
cookie_store: Option<CookieStore>,
) -> yaak_http::error::Result<yaak_http::sender::HttpResponse>;
}
struct DefaultSendRequestExecutor;
#[async_trait]
impl SendRequestExecutor for DefaultSendRequestExecutor {
async fn send(
&self,
sendable_request: SendableHttpRequest,
event_tx: mpsc::Sender<SenderHttpResponseEvent>,
cookie_store: Option<CookieStore>,
) -> yaak_http::error::Result<yaak_http::sender::HttpResponse> {
let sender = ReqwestSender::new()?;
let transaction = match cookie_store {
Some(store) => HttpTransaction::with_cookie_store(sender, store),
None => HttpTransaction::new(sender),
};
let (_cancel_tx, cancel_rx) = watch::channel(false);
transaction.execute_with_cancellation(sendable_request, cancel_rx, event_tx).await
}
}
struct PluginPrepareSendableRequest {
plugin_manager: Arc<PluginManager>,
plugin_context: PluginContext,
cancelled_rx: Option<watch::Receiver<bool>>,
}
#[async_trait]
impl PrepareSendableRequest for PluginPrepareSendableRequest {
async fn prepare_sendable_request(
&self,
rendered_request: &HttpRequest,
auth_context_id: &str,
sendable_request: &mut SendableHttpRequest,
) -> std::result::Result<(), String> {
if let Some(cancelled_rx) = &self.cancelled_rx {
let mut cancelled_rx = cancelled_rx.clone();
tokio::select! {
result = apply_plugin_authentication(
sendable_request,
rendered_request,
auth_context_id,
&self.plugin_manager,
&self.plugin_context,
) => result,
_ = cancelled_rx.changed() => Err("Request canceled".to_string()),
}
} else {
apply_plugin_authentication(
sendable_request,
rendered_request,
auth_context_id,
&self.plugin_manager,
&self.plugin_context,
)
.await
}
}
}
struct ConnectionManagerSendRequestExecutor<'a> {
connection_manager: &'a HttpConnectionManager,
plugin_context_id: String,
query_manager: QueryManager,
workspace_id: String,
cancelled_rx: Option<watch::Receiver<bool>>,
}
#[async_trait]
impl SendRequestExecutor for ConnectionManagerSendRequestExecutor<'_> {
async fn send(
&self,
sendable_request: SendableHttpRequest,
event_tx: mpsc::Sender<SenderHttpResponseEvent>,
cookie_store: Option<CookieStore>,
) -> yaak_http::error::Result<yaak_http::sender::HttpResponse> {
let runtime_config =
resolve_http_send_runtime_config(&self.query_manager, &self.workspace_id)
.map_err(|e| yaak_http::error::Error::RequestError(e.to_string()))?;
let client_certificate =
find_client_certificate(&sendable_request.url, &runtime_config.client_certificates);
let cached_client = self
.connection_manager
.get_client(&HttpConnectionOptions {
id: self.plugin_context_id.clone(),
validate_certificates: runtime_config.validate_certificates,
proxy: runtime_config.proxy,
client_certificate,
dns_overrides: runtime_config.dns_overrides,
})
.await?;
cached_client.resolver.set_event_sender(Some(event_tx.clone())).await;
let sender = ReqwestSender::with_client(cached_client.client);
let transaction = match cookie_store {
Some(cs) => HttpTransaction::with_cookie_store(sender, cs),
None => HttpTransaction::new(sender),
};
let result = if let Some(cancelled_rx) = self.cancelled_rx.clone() {
transaction.execute_with_cancellation(sendable_request, cancelled_rx, event_tx).await
} else {
let (_cancel_tx, cancel_rx) = watch::channel(false);
transaction.execute_with_cancellation(sendable_request, cancel_rx, event_tx).await
};
cached_client.resolver.set_event_sender(None).await;
result
}
}
pub struct SendHttpRequestByIdParams<'a, T: TemplateCallback> {
pub query_manager: &'a QueryManager,
pub blob_manager: &'a BlobManager,
pub request_id: &'a str,
pub environment_id: Option<&'a str>,
pub template_callback: &'a T,
pub update_source: UpdateSource,
pub cookie_jar_id: Option<String>,
pub response_dir: &'a Path,
pub emit_events_to: Option<mpsc::Sender<SenderHttpResponseEvent>>,
pub emit_response_body_chunks_to: Option<mpsc::UnboundedSender<Vec<u8>>>,
pub cancelled_rx: Option<watch::Receiver<bool>>,
pub prepare_sendable_request: Option<&'a dyn PrepareSendableRequest>,
pub executor: Option<&'a dyn SendRequestExecutor>,
}
pub struct SendHttpRequestParams<'a, T: TemplateCallback> {
pub query_manager: &'a QueryManager,
pub blob_manager: &'a BlobManager,
pub request: HttpRequest,
pub environment_id: Option<&'a str>,
pub template_callback: &'a T,
pub send_options: Option<SendableHttpRequestOptions>,
pub update_source: UpdateSource,
pub cookie_jar_id: Option<String>,
pub response_dir: &'a Path,
pub emit_events_to: Option<mpsc::Sender<SenderHttpResponseEvent>>,
pub emit_response_body_chunks_to: Option<mpsc::UnboundedSender<Vec<u8>>>,
pub cancelled_rx: Option<watch::Receiver<bool>>,
pub auth_context_id: Option<String>,
pub existing_response: Option<HttpResponse>,
pub prepare_sendable_request: Option<&'a dyn PrepareSendableRequest>,
pub executor: Option<&'a dyn SendRequestExecutor>,
}
pub struct SendHttpRequestWithPluginsParams<'a> {
pub query_manager: &'a QueryManager,
pub blob_manager: &'a BlobManager,
pub request: HttpRequest,
pub environment_id: Option<&'a str>,
pub update_source: UpdateSource,
pub cookie_jar_id: Option<String>,
pub response_dir: &'a Path,
pub emit_events_to: Option<mpsc::Sender<SenderHttpResponseEvent>>,
pub emit_response_body_chunks_to: Option<mpsc::UnboundedSender<Vec<u8>>>,
pub existing_response: Option<HttpResponse>,
pub plugin_manager: Arc<PluginManager>,
pub encryption_manager: Arc<EncryptionManager>,
pub plugin_context: &'a PluginContext,
pub cancelled_rx: Option<watch::Receiver<bool>>,
pub connection_manager: Option<&'a HttpConnectionManager>,
}
pub struct SendHttpRequestByIdWithPluginsParams<'a> {
pub query_manager: &'a QueryManager,
pub blob_manager: &'a BlobManager,
pub request_id: &'a str,
pub environment_id: Option<&'a str>,
pub update_source: UpdateSource,
pub cookie_jar_id: Option<String>,
pub response_dir: &'a Path,
pub emit_events_to: Option<mpsc::Sender<SenderHttpResponseEvent>>,
pub emit_response_body_chunks_to: Option<mpsc::UnboundedSender<Vec<u8>>>,
pub plugin_manager: Arc<PluginManager>,
pub encryption_manager: Arc<EncryptionManager>,
pub plugin_context: &'a PluginContext,
pub cancelled_rx: Option<watch::Receiver<bool>>,
pub connection_manager: Option<&'a HttpConnectionManager>,
}
pub struct SendHttpRequestResult {
pub rendered_request: HttpRequest,
pub response: HttpResponse,
pub response_body: Vec<u8>,
}
pub struct HttpSendRuntimeConfig {
pub send_options: SendableHttpRequestOptions,
pub validate_certificates: bool,
pub proxy: HttpConnectionProxySetting,
pub dns_overrides: Vec<DnsOverride>,
pub client_certificates: Vec<ClientCertificate>,
}
pub fn resolve_http_send_runtime_config(
query_manager: &QueryManager,
workspace_id: &str,
) -> Result<HttpSendRuntimeConfig> {
let db = query_manager.connect();
let workspace = db.get_workspace(workspace_id).map_err(SendHttpRequestError::LoadWorkspace)?;
let settings = db.get_settings();
Ok(HttpSendRuntimeConfig {
send_options: SendableHttpRequestOptions {
follow_redirects: workspace.setting_follow_redirects,
timeout: if workspace.setting_request_timeout > 0 {
Some(std::time::Duration::from_millis(
workspace.setting_request_timeout.unsigned_abs() as u64,
))
} else {
None
},
},
validate_certificates: workspace.setting_validate_certificates,
proxy: proxy_setting_from_settings(settings.proxy),
dns_overrides: workspace.setting_dns_overrides,
client_certificates: settings.client_certificates,
})
}
pub async fn send_http_request_by_id_with_plugins(
params: SendHttpRequestByIdWithPluginsParams<'_>,
) -> Result<SendHttpRequestResult> {
let request = params
.query_manager
.connect()
.get_http_request(params.request_id)
.map_err(SendHttpRequestError::LoadRequest)?;
send_http_request_with_plugins(SendHttpRequestWithPluginsParams {
query_manager: params.query_manager,
blob_manager: params.blob_manager,
request,
environment_id: params.environment_id,
update_source: params.update_source,
cookie_jar_id: params.cookie_jar_id,
response_dir: params.response_dir,
emit_events_to: params.emit_events_to,
emit_response_body_chunks_to: params.emit_response_body_chunks_to,
existing_response: None,
plugin_manager: params.plugin_manager,
encryption_manager: params.encryption_manager,
plugin_context: params.plugin_context,
cancelled_rx: params.cancelled_rx,
connection_manager: params.connection_manager,
})
.await
}
pub async fn send_http_request_with_plugins(
params: SendHttpRequestWithPluginsParams<'_>,
) -> Result<SendHttpRequestResult> {
let template_callback = PluginTemplateCallback::new(
params.plugin_manager.clone(),
params.encryption_manager.clone(),
params.plugin_context,
RenderPurpose::Send,
);
let auth_hook = PluginPrepareSendableRequest {
plugin_manager: params.plugin_manager,
plugin_context: params.plugin_context.clone(),
cancelled_rx: params.cancelled_rx.clone(),
};
let executor =
params.connection_manager.map(|connection_manager| ConnectionManagerSendRequestExecutor {
connection_manager,
plugin_context_id: params.plugin_context.id.clone(),
query_manager: params.query_manager.clone(),
workspace_id: params.request.workspace_id.clone(),
cancelled_rx: params.cancelled_rx.clone(),
});
send_http_request(SendHttpRequestParams {
query_manager: params.query_manager,
blob_manager: params.blob_manager,
request: params.request,
environment_id: params.environment_id,
template_callback: &template_callback,
send_options: None,
update_source: params.update_source,
cookie_jar_id: params.cookie_jar_id,
response_dir: params.response_dir,
emit_events_to: params.emit_events_to,
emit_response_body_chunks_to: params.emit_response_body_chunks_to,
cancelled_rx: params.cancelled_rx,
auth_context_id: None,
existing_response: params.existing_response,
prepare_sendable_request: Some(&auth_hook),
executor: executor.as_ref().map(|e| e as &dyn SendRequestExecutor),
})
.await
}
pub async fn send_http_request_by_id<T: TemplateCallback>(
params: SendHttpRequestByIdParams<'_, T>,
) -> Result<SendHttpRequestResult> {
let request = params
.query_manager
.connect()
.get_http_request(params.request_id)
.map_err(SendHttpRequestError::LoadRequest)?;
let (request, auth_context_id) = resolve_inherited_request(params.query_manager, &request)?;
send_http_request(SendHttpRequestParams {
query_manager: params.query_manager,
blob_manager: params.blob_manager,
request,
environment_id: params.environment_id,
template_callback: params.template_callback,
send_options: None,
update_source: params.update_source,
cookie_jar_id: params.cookie_jar_id,
response_dir: params.response_dir,
emit_events_to: params.emit_events_to,
emit_response_body_chunks_to: params.emit_response_body_chunks_to,
cancelled_rx: params.cancelled_rx,
existing_response: None,
prepare_sendable_request: params.prepare_sendable_request,
executor: params.executor,
auth_context_id: Some(auth_context_id),
})
.await
}
pub async fn send_http_request<T: TemplateCallback>(
params: SendHttpRequestParams<'_, T>,
) -> Result<SendHttpRequestResult> {
let environment_chain =
resolve_environment_chain(params.query_manager, ¶ms.request, params.environment_id)?;
let (resolved_request, auth_context_id) =
if let Some(auth_context_id) = params.auth_context_id.clone() {
(params.request.clone(), auth_context_id)
} else {
resolve_inherited_request(params.query_manager, ¶ms.request)?
};
let runtime_config =
resolve_http_send_runtime_config(params.query_manager, ¶ms.request.workspace_id)?;
let send_options = params.send_options.unwrap_or(runtime_config.send_options);
let mut cookie_jar = load_cookie_jar(params.query_manager, params.cookie_jar_id.as_deref())?;
let cookie_store =
cookie_jar.as_ref().map(|jar| CookieStore::from_cookies(jar.cookies.clone()));
let rendered_request = render_http_request(
&resolved_request,
environment_chain,
params.template_callback,
&RenderOptions::throw(),
)
.await
.map_err(SendHttpRequestError::RenderRequest)?;
let mut sendable_request =
SendableHttpRequest::from_http_request(&rendered_request, send_options)
.await
.map_err(SendHttpRequestError::BuildSendableRequest)?;
if let Some(hook) = params.prepare_sendable_request {
hook.prepare_sendable_request(&rendered_request, &auth_context_id, &mut sendable_request)
.await
.map_err(SendHttpRequestError::PrepareSendableRequest)?;
}
let request_content_length = sendable_body_length(sendable_request.body.as_ref());
let mut response = params.existing_response.unwrap_or_default();
response.request_id = params.request.id.clone();
response.workspace_id = params.request.workspace_id.clone();
response.request_content_length = request_content_length;
response.request_headers = sendable_request
.headers
.iter()
.map(|(name, value)| HttpResponseHeader { name: name.clone(), value: value.clone() })
.collect();
response.url = sendable_request.url.clone();
response.state = HttpResponseState::Initialized;
response.error = None;
response.content_length = None;
response.content_length_compressed = None;
response.body_path = None;
response.status = 0;
response.status_reason = None;
response.headers = Vec::new();
response.remote_addr = None;
response.version = None;
response.elapsed = 0;
response.elapsed_headers = 0;
response.elapsed_dns = 0;
let persist_response = !response.request_id.is_empty();
if persist_response {
response = params
.query_manager
.connect()
.upsert_http_response(&response, ¶ms.update_source, params.blob_manager)
.map_err(SendHttpRequestError::PersistResponse)?;
} else if response.id.is_empty() {
response.id = generate_prefixed_id("rs");
}
let request_body_id = format!("{}.request", response.id);
let mut request_body_capture_task = None;
let mut request_body_capture_error = None;
if persist_response {
match sendable_request.body.as_mut() {
Some(SendableBody::Bytes(bytes)) => {
if let Err(err) = persist_request_body_bytes(
params.blob_manager,
&request_body_id,
bytes.as_ref(),
) {
request_body_capture_error = Some(err);
}
}
Some(SendableBody::Stream { data, .. }) => {
let (tx, rx) = tokio::sync::mpsc::unbounded_channel::<Vec<u8>>();
let inner = std::mem::replace(data, Box::pin(tokio::io::empty()));
let tee_reader = TeeReader::new(inner, tx);
*data = Box::pin(tee_reader);
let blob_manager = params.blob_manager.clone();
let body_id = request_body_id.clone();
request_body_capture_task = Some(tokio::spawn(async move {
persist_request_body_stream(blob_manager, body_id, rx).await
}));
}
None => {}
}
}
let (event_tx, mut event_rx) =
mpsc::channel::<SenderHttpResponseEvent>(HTTP_EVENT_CHANNEL_CAPACITY);
let event_query_manager = params.query_manager.clone();
let event_response_id = response.id.clone();
let event_workspace_id = params.request.workspace_id.clone();
let event_update_source = params.update_source.clone();
let emit_events_to = params.emit_events_to.clone();
let dns_elapsed = Arc::new(AtomicI32::new(0));
let event_dns_elapsed = dns_elapsed.clone();
let event_handle = tokio::spawn(async move {
while let Some(event) = event_rx.recv().await {
if let SenderHttpResponseEvent::DnsResolved { duration, .. } = &event {
event_dns_elapsed.store(u64_to_i32(*duration), Ordering::Relaxed);
}
if persist_response {
let db_event = HttpResponseEvent::new(
&event_response_id,
&event_workspace_id,
event.clone().into(),
);
if let Err(err) = event_query_manager
.connect()
.upsert_http_response_event(&db_event, &event_update_source)
{
warn!("Failed to persist HTTP response event: {}", err);
}
}
if let Some(tx) = emit_events_to.as_ref() {
let _ = tx.try_send(event);
}
}
});
let default_executor = DefaultSendRequestExecutor;
let executor = params.executor.unwrap_or(&default_executor);
let started_at = Instant::now();
let request_started_url = sendable_request.url.clone();
let mut http_response = match executor
.send(sendable_request, event_tx, cookie_store.clone())
.await
{
Ok(response) => response,
Err(err) => {
persist_cookie_jar(params.query_manager, cookie_jar.as_mut(), cookie_store.as_ref())?;
if persist_response {
let _ = persist_response_error(
params.query_manager,
params.blob_manager,
¶ms.update_source,
&response,
started_at,
err.to_string(),
request_started_url,
);
}
if let Err(join_err) = event_handle.await {
warn!("Failed to join response event task: {}", join_err);
}
if let Some(task) = request_body_capture_task.take() {
let _ = task.await;
}
return Err(SendHttpRequestError::SendRequest(err));
}
};
let headers_elapsed = duration_to_i32(started_at.elapsed());
std::fs::create_dir_all(params.response_dir).map_err(|source| {
SendHttpRequestError::CreateResponseDirectory {
path: params.response_dir.to_path_buf(),
source,
}
})?;
let body_path = params.response_dir.join(&response.id);
let connected_response = HttpResponse {
state: HttpResponseState::Connected,
elapsed_headers: headers_elapsed,
status: i32::from(http_response.status),
status_reason: http_response.status_reason.clone(),
url: http_response.url.clone(),
remote_addr: http_response.remote_addr.clone(),
version: http_response.version.clone(),
elapsed_dns: dns_elapsed.load(Ordering::Relaxed),
body_path: Some(body_path.to_string_lossy().to_string()),
content_length: http_response.content_length.map(u64_to_i32),
headers: http_response
.headers
.iter()
.map(|(name, value)| HttpResponseHeader { name: name.clone(), value: value.clone() })
.collect(),
request_headers: http_response
.request_headers
.iter()
.map(|(name, value)| HttpResponseHeader { name: name.clone(), value: value.clone() })
.collect(),
..response
};
if persist_response {
response = params
.query_manager
.connect()
.upsert_http_response(&connected_response, ¶ms.update_source, params.blob_manager)
.map_err(SendHttpRequestError::PersistResponse)?;
} else {
response = connected_response;
}
let mut file =
File::options().create(true).truncate(true).write(true).open(&body_path).await.map_err(
|source| SendHttpRequestError::WriteResponseBody { path: body_path.clone(), source },
)?;
let mut body_stream =
http_response.into_body_stream().map_err(SendHttpRequestError::ReadResponseBody)?;
let mut response_body = Vec::new();
let mut body_read_error = None;
let mut written_bytes: usize = 0;
let mut last_progress_update = started_at;
let mut cancelled_rx = params.cancelled_rx.clone();
loop {
let read_result = if let Some(cancelled_rx) = cancelled_rx.as_mut() {
if *cancelled_rx.borrow() {
break;
}
tokio::select! {
biased;
_ = cancelled_rx.changed() => {
None
}
result = body_stream.read_buf(&mut response_body) => {
Some(result)
}
}
} else {
Some(body_stream.read_buf(&mut response_body).await)
};
let Some(read_result) = read_result else {
break;
};
match read_result {
Ok(0) => break,
Ok(n) => {
written_bytes += n;
let start_idx = response_body.len() - n;
let chunk = &response_body[start_idx..];
file.write_all(chunk).await.map_err(|source| {
SendHttpRequestError::WriteResponseBody { path: body_path.clone(), source }
})?;
file.flush().await.map_err(|source| SendHttpRequestError::WriteResponseBody {
path: body_path.clone(),
source,
})?;
if let Some(tx) = params.emit_response_body_chunks_to.as_ref() {
let _ = tx.send(chunk.to_vec());
}
let now = Instant::now();
let should_update = now.duration_since(last_progress_update).as_millis()
>= RESPONSE_PROGRESS_UPDATE_INTERVAL_MS;
if should_update {
let elapsed = duration_to_i32(started_at.elapsed());
let progress_response = HttpResponse {
elapsed,
content_length: Some(usize_to_i32(written_bytes)),
elapsed_dns: dns_elapsed.load(Ordering::Relaxed),
..response.clone()
};
if persist_response {
response = params
.query_manager
.connect()
.upsert_http_response(
&progress_response,
¶ms.update_source,
params.blob_manager,
)
.map_err(SendHttpRequestError::PersistResponse)?;
} else {
response = progress_response;
}
last_progress_update = now;
}
}
Err(err) => {
body_read_error = Some(SendHttpRequestError::ReadResponseBody(
yaak_http::error::Error::BodyReadError(err.to_string()),
));
break;
}
}
}
file.flush().await.map_err(|source| SendHttpRequestError::WriteResponseBody {
path: body_path.clone(),
source,
})?;
drop(body_stream);
if let Some(task) = request_body_capture_task.take() {
match task.await {
Ok(Ok(total)) => {
response.request_content_length = Some(usize_to_i32(total));
}
Ok(Err(err)) => request_body_capture_error = Some(err),
Err(err) => request_body_capture_error = Some(err.to_string()),
}
}
if let Some(err) = request_body_capture_error.take() {
response.error = Some(append_error_message(
response.error.take(),
format!("Request succeeded but failed to store request body: {err}"),
));
}
if let Err(join_err) = event_handle.await {
warn!("Failed to join response event task: {}", join_err);
}
if let Some(err) = body_read_error {
if persist_response {
let _ = persist_response_error(
params.query_manager,
params.blob_manager,
¶ms.update_source,
&response,
started_at,
err.to_string(),
request_started_url,
);
}
persist_cookie_jar(params.query_manager, cookie_jar.as_mut(), cookie_store.as_ref())?;
return Err(err);
}
let compressed_length = http_response.content_length.unwrap_or(written_bytes as u64);
let final_response = HttpResponse {
body_path: Some(body_path.to_string_lossy().to_string()),
content_length: Some(usize_to_i32(written_bytes)),
content_length_compressed: Some(u64_to_i32(compressed_length)),
elapsed: duration_to_i32(started_at.elapsed()),
elapsed_headers: headers_elapsed,
elapsed_dns: dns_elapsed.load(Ordering::Relaxed),
state: HttpResponseState::Closed,
..response
};
if persist_response {
response = params
.query_manager
.connect()
.upsert_http_response(&final_response, ¶ms.update_source, params.blob_manager)
.map_err(SendHttpRequestError::PersistResponse)?;
} else {
response = final_response;
}
persist_cookie_jar(params.query_manager, cookie_jar.as_mut(), cookie_store.as_ref())?;
Ok(SendHttpRequestResult { rendered_request, response, response_body })
}
fn persist_request_body_bytes(
blob_manager: &BlobManager,
body_id: &str,
bytes: &[u8],
) -> std::result::Result<(), String> {
if bytes.is_empty() {
return Ok(());
}
let blob_ctx = blob_manager.connect();
let mut offset = 0;
let mut chunk_index: i32 = 0;
while offset < bytes.len() {
let end = std::cmp::min(offset + REQUEST_BODY_CHUNK_SIZE, bytes.len());
let chunk = BodyChunk::new(body_id, chunk_index, bytes[offset..end].to_vec());
blob_ctx.insert_chunk(&chunk).map_err(|e| e.to_string())?;
chunk_index += 1;
offset = end;
}
Ok(())
}
async fn persist_request_body_stream(
blob_manager: BlobManager,
body_id: String,
mut rx: tokio::sync::mpsc::UnboundedReceiver<Vec<u8>>,
) -> std::result::Result<usize, String> {
let mut chunk_index: i32 = 0;
let mut total_bytes = 0usize;
while let Some(data) = rx.recv().await {
total_bytes += data.len();
if data.is_empty() {
continue;
}
let chunk = BodyChunk::new(&body_id, chunk_index, data);
blob_manager.connect().insert_chunk(&chunk).map_err(|e| e.to_string())?;
chunk_index += 1;
}
Ok(total_bytes)
}
fn append_error_message(existing_error: Option<String>, message: String) -> String {
match existing_error {
Some(existing) => format!("{existing}; {message}"),
None => message,
}
}
fn resolve_environment_chain(
query_manager: &QueryManager,
request: &HttpRequest,
environment_id: Option<&str>,
) -> Result<Vec<Environment>> {
let db = query_manager.connect();
db.resolve_environments(&request.workspace_id, request.folder_id.as_deref(), environment_id)
.map_err(SendHttpRequestError::ResolveEnvironments)
}
fn resolve_inherited_request(
query_manager: &QueryManager,
request: &HttpRequest,
) -> Result<(HttpRequest, String)> {
let db = query_manager.connect();
let (authentication_type, authentication, auth_context_id) = db
.resolve_auth_for_http_request(request)
.map_err(SendHttpRequestError::ResolveRequestInheritance)?;
let resolved_headers = db
.resolve_headers_for_http_request(request)
.map_err(SendHttpRequestError::ResolveRequestInheritance)?;
let mut request = request.clone();
request.authentication_type = authentication_type;
request.authentication = authentication;
request.headers = resolved_headers;
Ok((request, auth_context_id))
}
fn load_cookie_jar(
query_manager: &QueryManager,
cookie_jar_id: Option<&str>,
) -> Result<Option<CookieJar>> {
let Some(cookie_jar_id) = cookie_jar_id else {
return Ok(None);
};
query_manager
.connect()
.get_cookie_jar(cookie_jar_id)
.map(Some)
.map_err(SendHttpRequestError::LoadCookieJar)
}
fn persist_cookie_jar(
query_manager: &QueryManager,
cookie_jar: Option<&mut CookieJar>,
cookie_store: Option<&CookieStore>,
) -> Result<()> {
match (cookie_jar, cookie_store) {
(Some(cookie_jar), Some(cookie_store)) => {
cookie_jar.cookies = cookie_store.get_all_cookies();
query_manager
.connect()
.upsert_cookie_jar(cookie_jar, &UpdateSource::Background)
.map_err(SendHttpRequestError::PersistCookieJar)?;
Ok(())
}
_ => Ok(()),
}
}
fn proxy_setting_from_settings(proxy: Option<ProxySetting>) -> HttpConnectionProxySetting {
match proxy {
None => HttpConnectionProxySetting::System,
Some(ProxySetting::Disabled) => HttpConnectionProxySetting::Disabled,
Some(ProxySetting::Enabled { http, https, auth, bypass, disabled }) => {
if disabled {
HttpConnectionProxySetting::System
} else {
HttpConnectionProxySetting::Enabled {
http,
https,
bypass,
auth: auth.map(|ProxySettingAuth { user, password }| {
HttpConnectionProxySettingAuth { user, password }
}),
}
}
}
}
}
pub async fn apply_plugin_authentication(
sendable_request: &mut SendableHttpRequest,
request: &HttpRequest,
auth_context_id: &str,
plugin_manager: &PluginManager,
plugin_context: &PluginContext,
) -> std::result::Result<(), String> {
match &request.authentication_type {
None => {}
Some(authentication_type) if authentication_type == "none" => {}
Some(authentication_type) => {
let req = CallHttpAuthenticationRequest {
context_id: format!("{:x}", md5::compute(auth_context_id)),
values: serde_json::from_value(
serde_json::to_value(&request.authentication)
.map_err(|e| format!("Failed to serialize auth values: {e}"))?,
)
.map_err(|e| format!("Failed to parse auth values: {e}"))?,
url: sendable_request.url.clone(),
method: sendable_request.method.clone(),
headers: sendable_request
.headers
.iter()
.map(|(name, value)| HttpHeader {
name: name.to_string(),
value: value.to_string(),
})
.collect(),
};
let plugin_result = plugin_manager
.call_http_authentication(plugin_context, authentication_type, req)
.await
.map_err(|e| format!("Failed to apply authentication plugin: {e}"))?;
for header in plugin_result.set_headers.unwrap_or_default() {
sendable_request.insert_header((header.name, header.value));
}
if let Some(params) = plugin_result.set_query_parameters {
let params = params.into_iter().map(|p| (p.name, p.value)).collect::<Vec<_>>();
sendable_request.url = append_query_params(&sendable_request.url, params);
}
}
}
Ok(())
}
fn persist_response_error(
query_manager: &QueryManager,
blob_manager: &BlobManager,
update_source: &UpdateSource,
response: &HttpResponse,
started_at: Instant,
error: String,
fallback_url: String,
) -> Result<HttpResponse> {
let elapsed = duration_to_i32(started_at.elapsed());
query_manager
.connect()
.upsert_http_response(
&HttpResponse {
state: HttpResponseState::Closed,
elapsed,
elapsed_headers: if response.elapsed_headers == 0 {
elapsed
} else {
response.elapsed_headers
},
error: Some(error),
url: if response.url.is_empty() { fallback_url } else { response.url.clone() },
..response.clone()
},
update_source,
blob_manager,
)
.map_err(SendHttpRequestError::PersistResponse)
}
fn sendable_body_length(body: Option<&SendableBody>) -> Option<i32> {
match body {
Some(SendableBody::Bytes(bytes)) => Some(usize_to_i32(bytes.len())),
Some(SendableBody::Stream { content_length: Some(length), .. }) => {
Some(u64_to_i32(*length))
}
_ => None,
}
}
fn duration_to_i32(duration: std::time::Duration) -> i32 {
u128_to_i32(duration.as_millis())
}
fn usize_to_i32(value: usize) -> i32 {
if value > i32::MAX as usize { i32::MAX } else { value as i32 }
}
fn u64_to_i32(value: u64) -> i32 {
if value > i32::MAX as u64 { i32::MAX } else { value as i32 }
}
fn u128_to_i32(value: u128) -> i32 {
if value > i32::MAX as u128 { i32::MAX } else { value as i32 }
}
================================================
FILE: crates/yaak-api/Cargo.toml
================================================
[package]
name = "yaak-api"
version = "0.1.0"
edition = "2024"
publish = false
[dependencies]
log = { workspace = true }
reqwest = { workspace = true, features = ["gzip"] }
sysproxy = "0.3"
thiserror = { workspace = true }
yaak-common = { workspace = true }
================================================
FILE: crates/yaak-api/src/error.rs
================================================
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error(transparent)]
ReqwestError(#[from] reqwest::Error),
}
pub type Result<T> = std::result::Result<T, Error>;
================================================
FILE: crates/yaak-api/src/lib.rs
================================================
mod error;
pub use error::{Error, Result};
use log::{debug, warn};
use reqwest::Client;
use reqwest::header::{HeaderMap, HeaderValue};
use std::time::Duration;
use yaak_common::platform::{get_ua_arch, get_ua_platform};
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum ApiClientKind {
App,
Cli,
}
/// Build a reqwest Client configured for Yaak's own API calls.
///
/// Includes a custom User-Agent, JSON accept header, 20s timeout, gzip,
/// and automatic OS-level proxy detection via sysproxy.
pub fn yaak_api_client(kind: ApiClientKind, version: &str) -> Result<Client> {
let platform = get_ua_platform();
let arch = get_ua_arch();
let product = match kind {
ApiClientKind::App => "Yaak",
ApiClientKind::Cli => "YaakCli",
};
let ua = format!("{product}/{version} ({platform}; {arch})");
let mut default_headers = HeaderMap::new();
default_headers.insert("Accept", HeaderValue::from_str("application/json").unwrap());
let mut builder = reqwest::ClientBuilder::new()
.timeout(Duration::from_secs(20))
.default_headers(default_headers)
.gzip(true)
.user_agent(ua);
if let Some(sys) = get_enabled_system_proxy() {
let proxy_url = format!("http://{}:{}", sys.host, sys.port);
match reqwest::Proxy::all(&proxy_url) {
Ok(p) => {
let p = if !sys.bypass.is_empty() {
p.no_proxy(reqwest::NoProxy::from_string(&sys.bypass))
} else {
p
};
builder = builder.proxy(p);
}
Err(e) => {
warn!("Failed to configure system proxy: {e}");
}
}
}
Ok(builder.build()?)
}
/// Returns the system proxy URL if one is enabled, e.g. `http://host:port`.
pub fn get_system_proxy_url() -> Option<String> {
let sys = get_enabled_system_proxy()?;
Some(format!("http://{}:{}", sys.host, sys.port))
}
fn get_enabled_system_proxy() -> Option<sysproxy::Sysproxy> {
match sysproxy::Sysproxy::get_system_proxy() {
Ok(sys) if sys.enable => {
debug!("Detected system proxy: http://{}:{}", sys.host, sys.port);
Some(sys)
}
Ok(_) => {
debug!("System proxy detected but not enabled");
None
}
Err(e) => {
debug!("Could not detect system proxy: {e}");
None
}
}
}
================================================
FILE: crates/yaak-common/Cargo.toml
================================================
[package]
name = "yaak-common"
version = "0.1.0"
edition = "2024"
publish = false
[dependencies]
serde_json = { workspace = true }
tokio = { workspace = true, features = ["process"] }
================================================
FILE: crates/yaak-common/src/command.rs
================================================
use std::ffi::{OsStr, OsString};
use std::io::{self, ErrorKind};
use std::process::Stdio;
#[cfg(target_os = "windows")]
const CREATE_NO_WINDOW: u32 = 0x0800_0000;
/// Creates a new `tokio::process::Command` that won't spawn a console window on Windows.
pub fn new_xplatform_command<S: AsRef<OsStr>>(program: S) -> tokio::process::Command {
#[allow(unused_mut)]
let mut cmd = tokio::process::Command::new(program);
#[cfg(target_os = "windows")]
{
use std::os::windows::process::CommandExt;
cmd.creation_flags(CREATE_NO_WINDOW);
}
cmd
}
/// Creates a command only if the binary exists and can be invoked with the given probe argument.
pub async fn new_checked_command<S: AsRef<OsStr>>(
program: S,
probe_arg: &str,
) -> io::Result<tokio::process::Command> {
let program: OsString = program.as_ref().to_os_string();
let mut probe = new_xplatform_command(&program);
probe.arg(probe_arg).stdin(Stdio::null()).stdout(Stdio::null()).stderr(Stdio::null());
let status = probe.status().await?;
if !status.success() {
return Err(io::Error::new(
ErrorKind::NotFound,
format!(
"'{}' is not available on PATH or failed to execute",
program.to_string_lossy()
),
));
}
Ok(new_xplatform_command(&program))
}
================================================
FILE: crates/yaak-common/src/lib.rs
================================================
pub mod command;
pub mod platform;
pub mod serde;
================================================
FILE: crates/yaak-common/src/platform.rs
================================================
use crate::platform::OperatingSystem::{Linux, MacOS, Unknown, Windows};
pub enum OperatingSystem {
Windows,
MacOS,
Linux,
Unknown,
}
pub fn get_os() -> OperatingSystem {
if cfg!(target_os = "windows") {
Windows
} else if cfg!(target_os = "macos") {
MacOS
} else if cfg!(target_os = "linux") {
Linux
} else {
Unknown
}
}
pub fn get_os_str() -> &'static str {
match get_os() {
Windows => "windows",
MacOS => "macos",
Linux => "linux",
Unknown => "unknown",
}
}
pub fn get_ua_platform() -> &'static str {
if cfg!(target_os = "windows") {
"Win"
} else if cfg!(target_os = "macos") {
"Mac"
} else if cfg!(target_os = "linux") {
"Linux"
} else {
"Unknown"
}
}
pub fn get_ua_arch() -> &'static str {
if cfg!(target_arch = "x86_64") {
"x86_64"
} else if cfg!(target_arch = "x86") {
"i386"
} else if cfg!(target_arch = "arm") {
"ARM"
} else if cfg!(target_arch = "aarch64") {
"ARM64"
} else {
"Unknown"
}
}
================================================
FILE: crates/yaak-common/src/serde.rs
================================================
use serde_json::Value;
use std::collections::BTreeMap;
pub fn get_bool(v: &Value, key: &str, fallback: bool) -> bool {
match v.get(key) {
None => fallback,
Some(v) => v.as_bool().unwrap_or(fallback),
}
}
pub fn get_str<'a>(v: &'a Value, key: &str) -> &'a str {
match v.get(key) {
None => "",
Some(v) => v.as_str().unwrap_or_default(),
}
}
pub fn get_str_map<'a>(v: &'a BTreeMap<String, Value>, key: &str) -> &'a str {
match v.get(key) {
None => "",
Some(v) => v.as_str().unwrap_or_default(),
}
}
pub fn get_bool_map(v: &BTreeMap<String, Value>, key: &str, fallback: bool) -> bool {
match v.get(key) {
None => fallback,
Some(v) => v.as_bool().unwrap_or(fallback),
}
}
================================================
FILE: crates/yaak-core/Cargo.toml
================================================
[package]
name = "yaak-core"
version = "0.0.0"
edition = "2024"
authors = ["Gregory Schier"]
publish = false
[dependencies]
thiserror = { workspace = true }
================================================
FILE: crates/yaak-core/src/context.rs
================================================
use std::path::PathBuf;
/// Context for a workspace operation.
///
/// In Tauri, this is extracted from the WebviewWindow URL.
/// In CLI, this is constructed from command arguments or config.
#[derive(Debug, Clone, Default)]
pub struct WorkspaceContext {
pub workspace_id: Option<String>,
pub environment_id: Option<String>,
pub cookie_jar_id: Option<String>,
pub request_id: Option<String>,
}
impl WorkspaceContext {
pub fn new() -> Self {
Self::default()
}
pub fn with_workspace(mut self, workspace_id: impl Into<String>) -> Self {
self.workspace_id = Some(workspace_id.into());
self
}
pub fn with_environment(mut self, environment_id: impl Into<String>) -> Self {
self.environment_id = Some(environment_id.into());
self
}
pub fn with_cookie_jar(mut self, cookie_jar_id: impl Into<String>) -> Self {
self.cookie_jar_id = Some(cookie_jar_id.into());
self
}
pub fn with_request(mut self, request_id: impl Into<String>) -> Self {
self.request_id = Some(request_id.into());
self
}
}
/// Application context trait for accessing app-level resources.
///
/// This abstracts over Tauri's `AppHandle` for path resolution and app identity.
/// Implemented by Tauri's AppHandle and by CLI's own context struct.
pub trait AppContext: Send + Sync + Clone {
/// Returns the path to the application data directory.
/// This is where the database and other persistent data are stored.
fn app_data_dir(&self) -> PathBuf;
/// Returns the application identifier (e.g., "app.yaak.desktop").
/// Used for keyring access and other platform-specific features.
fn app_identifier(&self) -> &str;
/// Returns true if running in development mode.
fn is_dev(&self) -> bool;
}
================================================
FILE: crates/yaak-core/src/error.rs
================================================
use thiserror::Error;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Error, Debug)]
pub enum Error {
#[error("Missing required context: {0}")]
MissingContext(String),
#[error("Configuration error: {0}")]
Config(String),
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
}
================================================
FILE: crates/yaak-core/src/lib.rs
================================================
//! Core abstractions for Yaak that work without Tauri.
//!
//! This crate provides foundational types and traits that allow Yaak's
//! business logic to run in both Tauri (desktop app) and CLI contexts.
mod context;
mod error;
pub use context::{AppContext, WorkspaceContext};
pub use error::{Error, Result};
================================================
FILE: crates/yaak-crypto/Cargo.toml
================================================
[package]
name = "yaak-crypto"
version = "0.1.0"
edition = "2021"
publish = false
[dependencies]
base32 = "0.5.1" # For encoding human-readable key
base64 = "0.22.1" # For encoding in the database
chacha20poly1305 = "0.10.1"
keyring = { workspace = true, features = ["apple-native", "windows-native", "sync-secret-service"] }
log = { workspace = true }
serde = { workspace = true, features = ["derive"] }
thiserror = { workspace = true }
yaak-models = { workspace = true }
================================================
FILE: crates/yaak-crypto/index.ts
================================================
import { invoke } from "@tauri-apps/api/core";
export function enableEncryption(workspaceId: string) {
return invoke<void>("cmd_enable_encryption", { workspaceId });
}
export function revealWorkspaceKey(workspaceId: string) {
return invoke<string>("cmd_reveal_workspace_key", { workspaceId });
}
export function setWorkspaceKey(args: { workspaceId: string; key: string }) {
return invoke<void>("cmd_set_workspace_key", args);
}
export function disableEncryption(workspaceId: string) {
return invoke<void>("cmd_disable_encryption", { workspaceId });
}
================================================
FILE: crates/yaak-crypto/package.json
================================================
{
"name": "@yaakapp-internal/crypto",
"version": "1.0.0",
"private": true,
"main": "index.ts"
}
================================================
FILE: crates/yaak-crypto/src/encryption.rs
================================================
use crate::error::Error::{DecryptionError, EncryptionError, InvalidEncryptedData};
use crate::error::Result;
use chacha20poly1305::aead::generic_array::typenum::Unsigned;
use chacha20poly1305::aead::{Aead, AeadCore, Key, KeyInit, OsRng};
use chacha20poly1305::XChaCha20Poly1305;
const ENCRYPTION_TAG: &str = "yA4k3nC";
const ENCRYPTION_VERSION: u8 = 1;
pub(crate) fn encrypt_data(data: &[u8], key: &Key<XChaCha20Poly1305>) -> Result<Vec<u8>> {
let nonce = XChaCha20Poly1305::generate_nonce(&mut OsRng);
let cipher = XChaCha20Poly1305::new(&key);
let ciphered_data = cipher.encrypt(&nonce, data).map_err(|_| EncryptionError)?;
let mut data: Vec<u8> = Vec::new();
data.extend_from_slice(ENCRYPTION_TAG.as_bytes()); // Tag
data.push(ENCRYPTION_VERSION); // Version
data.extend_from_slice(&nonce.as_slice()); // Nonce
data.extend_from_slice(&ciphered_data); // Ciphertext
Ok(data)
}
pub(crate) fn decrypt_data(cipher_data: &[u8], key: &Key<XChaCha20Poly1305>) -> Result<Vec<u8>> {
// Yaak Tag + ID + Version + Nonce + ... ciphertext ...
let (tag, rest) =
cipher_data.split_at_checked(ENCRYPTION_TAG.len()).ok_or(InvalidEncryptedData)?;
if tag != ENCRYPTION_TAG.as_bytes() {
return Err(InvalidEncryptedData);
}
let (version, rest) = rest.split_at_checked(1).ok_or(InvalidEncryptedData)?;
if version[0] != ENCRYPTION_VERSION {
return Err(InvalidEncryptedData);
}
let nonce_bytes = <XChaCha20Poly1305 as AeadCore>::NonceSize::to_usize();
let (nonce, ciphered_data) = rest.split_at_checked(nonce_bytes).ok_or(InvalidEncryptedData)?;
let cipher = XChaCha20Poly1305::new(&key);
cipher.decrypt(nonce.into(), ciphered_data).map_err(|_e| DecryptionError)
}
#[cfg(test)]
mod test {
use crate::encryption::{decrypt_data, encrypt_data};
use crate::error::Error::InvalidEncryptedData;
use crate::error::Result;
use chacha20poly1305::aead::OsRng;
use chacha20poly1305::{KeyInit, XChaCha20Poly1305};
#[test]
fn test_encrypt_decrypt() -> Result<()> {
let key = XChaCha20Poly1305::generate_key(OsRng);
let encrypted = encrypt_data("hello world".as_bytes(), &key)?;
let decrypted = decrypt_data(encrypted.as_slice(), &key)?;
assert_eq!(String::from_utf8(decrypted).unwrap(), "hello world");
Ok(())
}
#[test]
fn test_decrypt_empty() -> Result<()> {
let key = XChaCha20Poly1305::generate_key(OsRng);
let encrypted = encrypt_data(&[], &key)?;
assert_eq!(encrypted.len(), 48);
let decrypted = decrypt_data(encrypted.as_slice(), &key)?;
assert_eq!(String::from_utf8(decrypted).unwrap(), "");
Ok(())
}
#[test]
fn test_decrypt_bad_version() -> Result<()> {
let key = XChaCha20Poly1305::generate_key(OsRng);
let mut encrypted = encrypt_data("hello world".as_bytes(), &key)?;
encrypted[7] = 0;
let decrypted = decrypt_data(encrypted.as_slice(), &key);
assert!(matches!(decrypted, Err(InvalidEncryptedData)));
Ok(())
}
#[test]
fn test_decrypt_bad_tag() -> Result<()> {
let key = XChaCha20Poly1305::generate_key(OsRng);
let mut encrypted = encrypt_data("hello world".as_bytes(), &key)?;
encrypted[0] = 2;
let decrypted = decrypt_data(encrypted.as_slice(), &key);
assert!(matches!(decrypted, Err(InvalidEncryptedData)));
Ok(())
}
#[test]
fn test_decrypt_unencrypted_data() -> Result<()> {
let key = XChaCha20Poly1305::generate_key(OsRng);
let decrypted = decrypt_data("123".as_bytes(), &key);
assert!(matches!(decrypted, Err(InvalidEncryptedData)));
Ok(())
}
}
================================================
FILE: crates/yaak-crypto/src/error.rs
================================================
use serde::{Serialize, Serializer};
use std::io;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error(transparent)]
DbError(#[from] yaak_models::error::Error),
#[error("Keyring error: {0}")]
KeyringError(#[from] keyring::Error),
#[error("Missing workspace encryption key")]
MissingWorkspaceKey,
#[error("Incorrect workspace key")]
IncorrectWorkspaceKey,
#[error("Failed to decrypt workspace key: {0}")]
WorkspaceKeyDecryptionError(String),
#[error("Crypto IO error: {0}")]
IoError(#[from] io::Error),
#[error("Failed to encrypt data")]
EncryptionError,
#[error("Failed to decrypt data")]
DecryptionError,
#[error("Invalid encrypted data")]
InvalidEncryptedData,
#[error("Invalid key provided")]
InvalidHumanKey,
#[error("Encryption error: {0}")]
GenericError(String),
}
impl Serialize for Error {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.to_string().as_ref())
}
}
pub type Result<T> = std::result::Result<T, Error>;
================================================
FILE: crates/yaak-crypto/src/lib.rs
================================================
extern crate core;
pub mod encryption;
pub mod error;
pub mod manager;
mod master_key;
mod workspace_key;
================================================
FILE: crates/yaak-crypto/src/manager.rs
================================================
use crate::error::Error::{
GenericError, IncorrectWorkspaceKey, MissingWorkspaceKey, WorkspaceKeyDecryptionError,
};
use crate::error::{Error, Result};
use crate::master_key::MasterKey;
use crate::workspace_key::WorkspaceKey;
use base64::prelude::BASE64_STANDARD;
use base64::Engine;
use log::{info, warn};
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use yaak_models::models::{EncryptedKey, Workspace, WorkspaceMeta};
use yaak_models::query_manager::QueryManager;
use yaak_models::util::{generate_id_of_length, UpdateSource};
const KEY_USER: &str = "encryption-key";
#[derive(Debug, Clone)]
pub struct EncryptionManager {
cached_master_key: Arc<Mutex<Option<MasterKey>>>,
cached_workspace_keys: Arc<Mutex<HashMap<String, WorkspaceKey>>>,
query_manager: QueryManager,
app_id: String,
}
impl EncryptionManager {
pub fn new(query_manager: QueryManager, app_id: impl Into<String>) -> Self {
Self {
cached_master_key: Default::default(),
cached_workspace_keys: Default::default(),
query_manager,
app_id: app_id.into(),
}
}
pub fn encrypt(&self, workspace_id: &str, data: &[u8]) -> Result<Vec<u8>> {
let workspace_secret = self.get_workspace_key(workspace_id)?;
workspace_secret.encrypt(data)
}
pub fn decrypt(&self, workspace_id: &str, data: &[u8]) -> Result<Vec<u8>> {
let workspace_secret = self.get_workspace_key(workspace_id)?;
workspace_secret.decrypt(data)
}
pub fn reveal_workspace_key(&self, workspace_id: &str) -> Result<String> {
let key = self.get_workspace_key(workspace_id)?;
key.to_human()
}
pub fn set_human_key(&self, workspace_id: &str, human_key: &str) -> Result<WorkspaceMeta> {
let wkey = WorkspaceKey::from_human(human_key)?;
let workspace = self.query_manager.connect().get_workspace(workspace_id)?;
let encryption_key_challenge = match workspace.encryption_key_challenge {
None => return self.set_workspace_key(workspace_id, &wkey),
Some(c) => c,
};
let encryption_key_challenge = match BASE64_STANDARD.decode(encryption_key_challenge) {
Ok(c) => c,
Err(_) => return Err(GenericError("Failed to decode workspace challenge".to_string())),
};
if let Err(_) = wkey.decrypt(encryption_key_challenge.as_slice()) {
return Err(IncorrectWorkspaceKey);
};
self.set_workspace_key(workspace_id, &wkey)
}
pub(crate) fn set_workspace_key(
&self,
workspace_id: &str,
wkey: &WorkspaceKey,
) -> Result<WorkspaceMeta> {
info!("Created workspace key for {workspace_id}");
let encrypted_key = BASE64_STANDARD.encode(self.get_master_key()?.encrypt(wkey.raw_key())?);
let encrypted_key = EncryptedKey { encrypted_key };
let encryption_key_challenge = wkey.encrypt(generate_id_of_length(50).as_bytes())?;
let encryption_key_challenge = Some(BASE64_STANDARD.encode(encryption_key_challenge));
let workspace_meta = self.query_manager.with_tx::<WorkspaceMeta, Error>(|tx| {
let workspace = tx.get_workspace(workspace_id)?;
let workspace_meta = tx.get_or_create_workspace_meta(workspace_id)?;
tx.upsert_workspace(
&Workspace { encryption_key_challenge, ..workspace },
&UpdateSource::Background,
)?;
Ok(tx.upsert_workspace_meta(
&WorkspaceMeta { encryption_key: Some(encrypted_key.clone()), ..workspace_meta },
&UpdateSource::Background,
)?)
})?;
let mut cache = self.cached_workspace_keys.lock().unwrap();
cache.insert(workspace_id.to_string(), wkey.clone());
Ok(workspace_meta)
}
pub fn ensure_workspace_key(&self, workspace_id: &str) -> Result<WorkspaceMeta> {
let workspace_meta =
self.query_manager.connect().get_or_create_workspace_meta(workspace_id)?;
// Already exists
if let Some(_) = workspace_meta.encryption_key {
warn!("Tried to create workspace key when one already exists for {workspace_id}");
return Ok(workspace_meta);
}
let wkey = WorkspaceKey::create()?;
self.set_workspace_key(workspace_id, &wkey)
}
pub fn disable_encryption(&self, workspace_id: &str) -> Result<()> {
info!("Disabling encryption for {workspace_id}");
self.query_manager.with_tx::<(), Error>(|tx| {
let workspace = tx.get_workspace(workspace_id)?;
let workspace_meta = tx.get_or_create_workspace_meta(workspace_id)?;
// Clear encryption challenge on workspace
tx.upsert_workspace(
&Workspace { encryption_key_challenge: None, ..workspace },
&UpdateSource::Background,
)?;
// Clear encryption key on workspace meta
tx.upsert_workspace_meta(
&WorkspaceMeta { encryption_key: None, ..workspace_meta },
&UpdateSource::Background,
)?;
Ok(())
})?;
// Remove from cache
let mut cache = self.cached_workspace_keys.lock().unwrap();
cache.remove(workspace_id);
Ok(())
}
fn get_workspace_key(&self, workspace_id: &str) -> Result<WorkspaceKey> {
{
let cache = self.cached_workspace_keys.lock().unwrap();
if let Some(k) = cache.get(workspace_id) {
return Ok(k.clone());
}
};
let db = self.query_manager.connect();
let workspace_meta = db.get_or_create_workspace_meta(workspace_id)?;
let key = match workspace_meta.encryption_key {
None => return Err(MissingWorkspaceKey),
Some(k) => k,
};
let mkey = self.get_master_key()?;
let decoded_key = BASE64_STANDARD
.decode(key.encrypted_key)
.map_err(|e| WorkspaceKeyDecryptionError(e.to_string()))?;
let raw_key = mkey
.decrypt(decoded_key.as_slice())
.map_err(|e| WorkspaceKeyDecryptionError(e.to_string()))?;
let wkey = WorkspaceKey::from_raw_key(raw_key.as_slice());
Ok(wkey)
}
fn get_master_key(&self) -> Result<MasterKey> {
// NOTE: This locks the key for the entire function which seems wrong, but this prevents
// concurrent access from prompting the user for a keychain password multiple times.
let mut master_secret = self.cached_master_key.lock().unwrap();
if let Some(k) = master_secret.as_ref() {
return Ok(k.to_owned());
}
let mkey = MasterKey::get_or_create(&self.app_id, KEY_USER)?;
*master_secret = Some(mkey.clone());
Ok(mkey)
}
}
================================================
FILE: crates/yaak-crypto/src/master_key.rs
================================================
use crate::encryption::{decrypt_data, encrypt_data};
use crate::error::Error::GenericError;
use crate::error::Result;
use base32::Alphabet;
use chacha20poly1305::aead::{Key, KeyInit, OsRng};
use chacha20poly1305::XChaCha20Poly1305;
use keyring::{Entry, Error};
use log::info;
const HUMAN_PREFIX: &str = "YKM_";
#[derive(Debug, Clone)]
pub(crate) struct MasterKey {
key: Key<XChaCha20Poly1305>,
}
impl MasterKey {
pub(crate) fn get_or_create(app_id: &str, user: &str) -> Result<Self> {
let id = format!("{app_id}.EncryptionKey");
let entry = Entry::new(&id, user)?;
let key = match entry.get_password() {
Ok(encoded) => {
let without_prefix = encoded.strip_prefix(HUMAN_PREFIX).unwrap_or(&encoded);
let key_bytes = base32::decode(Alphabet::Crockford {}, &without_prefix)
.ok_or(GenericError("Failed to decode master key".to_string()))?;
Key::<XChaCha20Poly1305>::clone_from_slice(key_bytes.as_slice())
}
Err(Error::NoEntry) => {
info!("Creating new master key");
let key = XChaCha20Poly1305::generate_key(OsRng);
let encoded = base32::encode(Alphabet::Crockford {}, key.as_slice());
let with_prefix = format!("{HUMAN_PREFIX}{encoded}");
entry.set_password(&with_prefix)?;
key
}
Err(e) => return Err(GenericError(e.to_string())),
};
Ok(Self { key })
}
pub(crate) fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
encrypt_data(data, &self.key)
}
pub(crate) fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
decrypt_data(data, &self.key)
}
#[cfg(test)]
pub(crate) fn test_key() -> Self {
let key: Key<XChaCha20Poly1305> = Key::<XChaCha20Poly1305>::clone_from_slice(
"00000000000000000000000000000000".as_bytes(),
);
Self { key }
}
}
#[cfg(test)]
mod tests {
use crate::error::Result;
use crate::master_key::MasterKey;
#[test]
fn test_master_key() -> Result<()> {
// Test out the master key
let mkey = MasterKey::test_key();
let encrypted = mkey.encrypt("hello".as_bytes())?;
let decrypted = mkey.decrypt(encrypted.as_slice()).unwrap();
assert_eq!(decrypted, "hello".as_bytes().to_vec());
let mkey = MasterKey::test_key();
let decrypted = mkey.decrypt(encrypted.as_slice()).unwrap();
assert_eq!(decrypted, "hello".as_bytes().to_vec());
Ok(())
}
}
================================================
FILE: crates/yaak-crypto/src/workspace_key.rs
================================================
use crate::encryption::{decrypt_data, encrypt_data};
use crate::error::Error::InvalidHumanKey;
use crate::error::Result;
use base32::Alphabet;
use chacha20poly1305::aead::{Key, KeyInit, OsRng};
use chacha20poly1305::{KeySizeUser, XChaCha20Poly1305};
#[derive(Debug, Clone)]
pub struct WorkspaceKey {
key: Key<XChaCha20Poly1305>,
}
const HUMAN_PREFIX: &str = "YK";
impl WorkspaceKey {
pub(crate) fn to_human(&self) -> Result<String> {
let encoded = base32::encode(Alphabet::Crockford {}, self.key.as_slice());
let with_prefix = format!("{HUMAN_PREFIX}{encoded}");
let with_separators = with_prefix
.chars()
.collect::<Vec<_>>()
.chunks(6)
.map(|chunk| chunk.iter().collect::<String>())
.collect::<Vec<_>>()
.join("-");
Ok(with_separators)
}
#[allow(dead_code)]
pub(crate) fn from_human(human_key: &str) -> Result<Self> {
let without_prefix = human_key.strip_prefix(HUMAN_PREFIX).unwrap_or(human_key);
let without_separators = without_prefix.replace("-", "");
let key =
base32::decode(Alphabet::Crockford {}, &without_separators).ok_or(InvalidHumanKey)?;
if key.len() != XChaCha20Poly1305::key_size() {
return Err(InvalidHumanKey);
}
Ok(Self::from_raw_key(key.as_slice()))
}
pub(crate) fn from_raw_key(key: &[u8]) -> Self {
Self { key: Key::<XChaCha20Poly1305>::clone_from_slice(key) }
}
pub(crate) fn raw_key(&self) -> &[u8] {
self.key.as_slice()
}
pub(crate) fn create() -> Result<Self> {
let key = XChaCha20Poly1305::generate_key(OsRng);
Ok(Self::from_raw_key(key.as_slice()))
}
pub(crate) fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
encrypt_data(data, &self.key)
}
pub(crate) fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
decrypt_data(data, &self.key)
}
#[cfg(test)]
pub(crate) fn test_key() -> Self {
Self::from_raw_key("f1a2d4b3c8e799af1456be3478a4c3f2".as_bytes())
}
}
#[cfg(test)]
mod tests {
use crate::error::Error::InvalidHumanKey;
use crate::error::Result;
use crate::workspace_key::WorkspaceKey;
#[test]
fn test_persisted_key() -> Result<()> {
let key = WorkspaceKey::test_key();
let encrypted = key.encrypt("hello".as_bytes())?;
assert_eq!(key.decrypt(encrypted.as_slice())?, "hello".as_bytes());
Ok(())
}
#[test]
fn test_human_format() -> Result<()> {
let key = WorkspaceKey::test_key();
let encrypted = key.encrypt("hello".as_bytes())?;
assert_eq!(key.decrypt(encrypted.as_slice())?, "hello".as_bytes());
let human = key.to_human()?;
assert_eq!(human, "YKCRRP-2CK46H-H36RSR-CMVKJE-B1CRRK-8D9PC9-JK6D1Q-71GK8R-SKCRS0");
assert_eq!(
WorkspaceKey::from_human(&human)?.decrypt(encrypted.as_slice())?,
"hello".as_bytes()
);
Ok(())
}
#[test]
fn test_from_human_invalid() -> Result<()> {
assert!(matches!(
WorkspaceKey::from_human(
"YKCRRP-2CK46H-H36RSR-CMVKJE-B1CRRK-8D9PC9-JK6D1Q-71GK8R-SKCRS0-H3X38D",
),
Err(InvalidHumanKey)
));
assert!(matches!(WorkspaceKey::from_human("bad-key",), Err(InvalidHumanKey)));
assert!(matches!(WorkspaceKey::from_human("",), Err(InvalidHumanKey)));
Ok(())
}
}
================================================
FILE: crates/yaak-git/Cargo.toml
================================================
[package]
name = "yaak-git"
version = "0.1.0"
edition = "2024"
publish = false
[dependencies]
chrono = { workspace = true, features = ["serde"] }
git2 = { version = "0.20.4", features = ["vendored-libgit2", "vendored-openssl"] }
log = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
serde_yaml = "0.9.34"
thiserror = { workspace = true }
tokio = { workspace = true, features = ["io-util"] }
ts-rs = { workspace = true, features = ["chrono-impl", "serde-json-impl"] }
url = "2"
yaak-common = { workspace = true }
yaak-models = { workspace = true }
yaak-sync = { workspace = true }
================================================
FILE: crates/yaak-git/bindings/gen_git.ts
================================================
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { SyncModel } from "./gen_models";
export type BranchDeleteResult = { "type": "success", message: string, } | { "type": "not_fully_merged" };
export type CloneResult = { "type": "success" } | { "type": "cancelled" } | { "type": "needs_credentials", url: string, error: string | null, };
export type GitAuthor = { name: string | null, email: string | null, };
export type GitCommit = { author: GitAuthor, when: string, message: string | null, };
export type GitRemote = { name: string, url: string | null, };
export type GitStatus = "untracked" | "conflict" | "current" | "modified" | "removed" | "renamed" | "type_change";
export type GitStatusEntry = { relaPath: string, status: GitStatus, staged: boolean, prev: SyncModel | null, next: SyncModel | null, };
export type GitStatusSummary = { path: string, headRef: string | null, headRefShorthand: string | null, entries: Array<GitStatusEntry>, origins: Array<string>, localBranches: Array<string>, remoteBranches: Array<string>, ahead: number, behind: number, };
export type PullResult = { "type": "success", message: string, } | { "type": "up_to_date" } | { "type": "needs_credentials", url: string, error: string | null, } | { "type": "diverged", remote: string, branch: string, } | { "type": "uncommitted_changes" };
export type PushResult = { "type": "success", message: string, } | { "type": "up_to_date" } | { "type": "needs_credentials", url: string, error: string | null, };
================================================
FILE: crates/yaak-git/bindings/gen_models.ts
================================================
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type DnsOverride = { hostname: string, ipv4: Array<string>, ipv6: Array<string>, enabled?: boolean, };
export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, public: boolean, parentModel: string, parentId: string | null, variables: Array<EnvironmentVariable>, color: string | null, sortPriority: number, };
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, authentication: Record<string, any>, authenticationType: string | null, description: string, headers: Array<HttpRequestHeader>, name: string, sortPriority: number, };
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<HttpRequestHeader>, 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 HttpUrlParameter = { enabled?: boolean, name: string, value: string, id?: string, };
export type SyncModel = { "type": "workspace" } & Workspace | { "type": "environment" } & Environment | { "type": "folder" } & Folder | { "type": "http_request" } & HttpRequest | { "type": "grpc_request" } & GrpcRequest | { "type": "websocket_request" } & WebsocketRequest;
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, authentication: Record<string, any>, authenticationType: string | null, description: string, headers: Array<HttpRequestHeader>, name: string, encryptionKeyChallenge: string | null, settingValidateCertificates: boolean, settingFollowRedirects: boolean, settingRequestTimeout: number, settingDnsOverrides: Array<DnsOverride>, };
================================================
FILE: crates/yaak-git/index.ts
================================================
import { useQuery } from "@tanstack/react-query";
import { invoke } from "@tauri-apps/api/core";
import { createFastMutation } from "@yaakapp/app/hooks/useFastMutation";
import { queryClient } from "@yaakapp/app/lib/queryClient";
import { useMemo } from "react";
import {
BranchDeleteResult,
CloneResult,
GitCommit,
GitRemote,
GitStatusSummary,
PullResult,
PushResult,
} from "./bindings/gen_git";
import { showToast } from "@yaakapp/app/lib/toast";
export * from "./bindings/gen_git";
export * from "./bindings/gen_models";
export interface GitCredentials {
username: string;
password: string;
}
export type DivergedStrategy = "force_reset" | "merge" | "cancel";
export type UncommittedChangesStrategy = "reset" | "cancel";
export interface GitCallbacks {
addRemote: () => Promise<GitRemote | null>;
promptCredentials: (
result: Extract<PushResult, { type: "needs_credentials" }>,
) => Promise<GitCredentials | null>;
promptDiverged: (result: Extract<PullResult, { type: "diverged" }>) => Promise<DivergedStrategy>;
promptUncommittedChanges: () => Promise<UncommittedChangesStrategy>;
forceSync: () => Promise<void>;
}
const onSuccess = () => queryClient.invalidateQueries({ queryKey: ["git"] });
export function useGit(dir: string, callbacks: GitCallbacks, refreshKey?: string) {
const mutations = useMemo(() => gitMutations(dir, callbacks), [dir, callbacks]);
const fetchAll = useQuery<void, string>({
queryKey: ["git", "fetch_all", dir, refreshKey],
queryFn: () => invoke("cmd_git_fetch_all", { dir }),
refetchInterval: 10 * 60_000,
});
return [
{
remotes: useQuery<GitRemote[], string>({
queryKey: ["git", "remotes", dir, refreshKey],
queryFn: () => getRemotes(dir),
placeholderData: (prev) => prev,
}),
log: useQuery<GitCommit[], string>({
queryKey: ["git", "log", dir, refreshKey],
queryFn: () => invoke("cmd_git_log", { dir }),
placeholderData: (prev) => prev,
}),
status: useQuery<GitStatusSummary, string>({
refetchOnMount: true,
queryKey: ["git", "status", dir, refreshKey, fetchAll.dataUpdatedAt],
queryFn: () => invoke("cmd_git_status", { dir }),
placeholderData: (prev) => prev,
}),
},
mutations,
] as const;
}
export const gitMutations = (dir: string, callbacks: GitCallbacks) => {
const push = async () => {
const remotes = await getRemotes(dir);
if (remotes.length === 0) {
const remote = await callbacks.addRemote();
if (remote == null) throw new Error("No remote found");
}
const result = await invoke<PushResult>("cmd_git_push", { dir });
if (result.type !== "needs_credentials") return result;
// Needs credentials, prompt for them
const creds = await callbacks.promptCredentials(result);
if (creds == null) throw new Error("Canceled");
await invoke("cmd_git_add_credential", {
remoteUrl: result.url,
username: creds.username,
password: creds.password,
});
// Push again
return invoke<PushResult>("cmd_git_push", { dir });
};
const handleError = (err: unknown) => {
showToast({
id: err instanceof Error ? err.message : String(err),
message: err instanceof Error ? err.message : String(err),
color: "danger",
timeout: 5000,
});
};
return {
init: createFastMutation<void, string, void>({
mutationKey: ["git", "init"],
mutationFn: () => invoke("cmd_git_initialize", { dir }),
onSuccess,
}),
add: createFastMutation<void, string, { relaPaths: string[] }>({
mutationKey: ["git", "add", dir],
mutationFn: (args) => invoke("cmd_git_add", { dir, ...args }),
onSuccess,
}),
addRemote: createFastMutation<GitRemote, string, GitRemote>({
mutationKey: ["git", "add-remote"],
mutationFn: (args) => invoke("cmd_git_add_remote", { dir, ...args }),
onSuccess,
}),
rmRemote: createFastMutation<void, string, { name: string }>({
mutationKey: ["git", "rm-remote", dir],
mutationFn: (args) => invoke("cmd_git_rm_remote", { dir, ...args }),
onSuccess,
}),
createBranch: createFastMutation<void, string, { branch: string; base?: string }>({
mutationKey: ["git", "branch", dir],
mutationFn: (args) => invoke("cmd_git_branch", { dir, ...args }),
onSuccess,
}),
mergeBranch: createFastMutation<void, string, { branch: string }>({
mutationKey: ["git", "merge", dir],
mutationFn: (args) => invoke("cmd_git_merge_branch", { dir, ...args }),
onSuccess,
}),
deleteBranch: createFastMutation<
BranchDeleteResult,
string,
{ branch: string; force?: boolean }
>({
mutationKey: ["git", "delete-branch", dir],
mutationFn: (args) => invoke("cmd_git_delete_branch", { dir, ...args }),
onSuccess,
}),
deleteRemoteBranch: createFastMutation<void, string, { branch: string }>({
mutationKey: ["git", "delete-remote-branch", dir],
mutationFn: (args) => invoke("cmd_git_delete_remote_branch", { dir, ...args }),
onSuccess,
}),
renameBranch: createFastMutation<void, string, { oldName: string; newName: string }>({
mutationKey: ["git", "rename-branch", dir],
mutationFn: (args) => invoke("cmd_git_rename_branch", { dir, ...args }),
onSuccess,
}),
checkout: createFastMutation<string, string, { branch: string; force: boolean }>({
mutationKey: ["git", "checkout", dir],
mutationFn: (args) => invoke("cmd_git_checkout", { dir, ...args }),
onSuccess,
}),
commit: createFastMutation<void, string, { message: string }>({
mutationKey: ["git", "commit", dir],
mutationFn: (args) => invoke("cmd_git_commit", { dir, ...args }),
onSuccess,
}),
commitAndPush: createFastMutation<PushResult, string, { message: string }>({
mutationKey: ["git", "commit_push", dir],
mutationFn: async (args) => {
await invoke("cmd_git_commit", { dir, ...args });
return push();
},
onSuccess,
}),
push: createFastMutation<PushResult, string, void>({
mutationKey: ["git", "push", dir],
mutationFn: push,
onSuccess,
}),
pull: createFastMutation<PullResult, string, void>({
mutationKey: ["git", "pull", dir],
async mutationFn() {
const result = await invoke<PullResult>("cmd_git_pull", { dir });
if (result.type === "needs_credentials") {
const creds = await callbacks.promptCredentials(result);
if (creds == null) throw new Error("Canceled");
await invoke("cmd_git_add_credential", {
remoteUrl: result.url,
username: creds.username,
password: creds.password,
});
// Pull again after credentials
return invoke<PullResult>("cmd_git_pull", { dir });
}
if (result.type === "uncommitted_changes") {
void callbacks
.promptUncommittedChanges()
.then(async (strategy) => {
if (strategy === "cancel") return;
await invoke("cmd_git_reset_changes", { dir });
return invoke<PullResult>("cmd_git_pull", { dir });
})
.then(async () => {
await onSuccess();
await callbacks.forceSync();
}, handleError);
}
if (result.type === "diverged") {
void callbacks
.promptDiverged(result)
.then((strategy) => {
if (strategy === "cancel") return;
if (strategy === "force_reset") {
return invoke<PullResult>("cmd_git_pull_force_reset", {
dir,
remote: result.remote,
branch: result.branch,
});
}
return invoke<PullResult>("cmd_git_pull_merge", {
dir,
remote: result.remote,
branch: result.branch,
});
})
.then(async () => {
await onSuccess();
await callbacks.forceSync();
}, handleError);
}
return result;
},
onSuccess,
}),
unstage: createFastMutation<void, string, { relaPaths: string[] }>({
mutationKey: ["git", "unstage", dir],
mutationFn: (args) => invoke("cmd_git_unstage", { dir, ...args }),
onSuccess,
}),
resetChanges: createFastMutation<void, string, void>({
mutationKey: ["git", "reset-changes", dir],
mutationFn: () => invoke("cmd_git_reset_changes", { dir }),
onSuccess,
}),
} as const;
};
async function getRemotes(dir: string) {
return invoke<GitRemote[]>("cmd_git_remotes", { dir });
}
/**
* Clone a git repository, prompting for credentials if needed.
*/
export async function gitClone(
url: string,
dir: string,
promptCredentials: (args: {
url: string;
error: string | null;
}) => Promise<GitCredentials | null>,
): Promise<CloneResult> {
const result = await invoke<CloneResult>("cmd_git_clone", { url, dir });
if (result.type !== "needs_credentials") return result;
// Prompt for credentials
const creds = await promptCredentials({ url: result.url, error: result.error });
if (creds == null) return { type: "cancelled" };
// Store credentials and retry
await invoke("cmd_git_add_credential", {
remoteUrl: result.url,
username: creds.username,
password: creds.password,
});
return invoke<CloneResult>("cmd_git_clone", { url, dir });
}
================================================
FILE: crates/yaak-git/package.json
================================================
{
"name": "@yaakapp-internal/git",
"version": "1.0.0",
"private": true,
"main": "index.ts"
}
================================================
FILE: crates/yaak-git/src/add.rs
================================================
use crate::error::Result;
use crate::repository::open_repo;
use git2::IndexAddOption;
use log::info;
use std::path::Path;
pub fn git_add(dir: &Path, rela_path: &Path) -> Result<()> {
let repo = open_repo(dir)?;
let mut index = repo.index()?;
info!("Staging file {rela_path:?} to {dir:?}");
index.add_all(&[rela_path], IndexAddOption::DEFAULT, None)?;
index.write()?;
Ok(())
}
================================================
FILE: crates/yaak-git/src/binary.rs
================================================
use crate::error::Error::GitNotFound;
use crate::error::Result;
use std::path::Path;
use tokio::process::Command;
use yaak_common::command::new_checked_command;
/// Create a git command that runs in the specified directory
pub(crate) async fn new_binary_command(dir: &Path) -> Result<Command> {
let mut cmd = new_binary_command_global().await?;
cmd.arg("-C").arg(dir);
Ok(cmd)
}
/// Create a git command without a specific directory (for global operations)
pub(crate) async fn new_binary_command_global() -> Result<Command> {
new_checked_command("git", "--version").await.map_err(|_| GitNotFound)
}
================================================
FILE: crates/yaak-git/src/branch.rs
================================================
use serde::{Deserialize, Serialize};
use ts_rs::TS;
use crate::binary::new_binary_command;
use crate::error::Error::GenericError;
use crate::error::Result;
use std::path::Path;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)]
#[serde(rename_all = "snake_case", tag = "type")]
#[ts(export, export_to = "gen_git.ts")]
pub enum BranchDeleteResult {
Success { message: String },
NotFullyMerged,
}
pub async fn git_checkout_branch(dir: &Path, branch_name: &str, force: bool) -> Result<String> {
let branch_name = branch_name.trim_start_matches("origin/");
let mut args = vec!["checkout"];
if force {
args.push("--force");
}
args.push(branch_name);
let out = new_binary_command(dir)
.await?
.args(&args)
.output()
.await
.map_err(|e| GenericError(format!("failed to run git checkout: {e}")))?;
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
let combined = format!("{}{}", stdout, stderr);
if !out.status.success() {
return Err(GenericError(format!("Failed to checkout: {}", combined.trim())));
}
Ok(branch_name.to_string())
}
pub async fn git_create_branch(dir: &Path, name: &str, base: Option<&str>) -> Result<()> {
let mut cmd = new_binary_command(dir).await?;
cmd.arg("branch").arg(name);
if let Some(base_branch) = base {
cmd.arg(base_branch);
}
let out =
cmd.output().await.map_err(|e| GenericError(format!("failed to run git branch: {e}")))?;
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
let combined = format!("{}{}", stdout, stderr);
if !out.status.success() {
return Err(GenericError(format!("Failed to create branch: {}", combined.trim())));
}
Ok(())
}
pub async fn git_delete_branch(dir: &Path, name: &str, force: bool) -> Result<BranchDeleteResult> {
let mut cmd = new_binary_command(dir).await?;
let out =
if force { cmd.args(["branch", "-D", name]) } else { cmd.args(["branch", "-d", name]) }
.output()
.await
.map_err(|e| GenericError(format!("failed to run git branch -d: {e}")))?;
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
let combined = format!("{}{}", stdout, stderr);
if !out.status.success() && stderr.to_lowercase().contains("not fully merged") {
return Ok(BranchDeleteResult::NotFullyMerged);
}
if !out.status.success() {
return Err(GenericError(format!("Failed to delete branch: {}", combined.trim())));
}
Ok(BranchDeleteResult::Success { message: combined })
}
pub async fn git_merge_branch(dir: &Path, name: &str) -> Result<()> {
let out = new_binary_command(dir)
.await?
.args(["merge", name])
.output()
.await
.map_err(|e| GenericError(format!("failed to run git merge: {e}")))?;
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
let combined = format!("{}{}", stdout, stderr);
if !out.status.success() {
// Check for merge conflicts
if combined.to_lowercase().contains("conflict") {
return Err(GenericError(
"Merge conflicts detected. Please resolve them manually.".to_string(),
));
}
return Err(GenericError(format!("Failed to merge: {}", combined.trim())));
}
Ok(())
}
pub async fn git_delete_remote_branch(dir: &Path, name: &str) -> Result<()> {
// Remote branch names come in as "origin/branch-name", extract the branch name
let branch_name = name.trim_start_matches("origin/");
let out = new_binary_command(dir)
.await?
.args(["push", "origin", "--delete", branch_name])
.output()
.await
.map_err(|e| GenericError(format!("failed to run git push --delete: {e}")))?;
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
let combined = format!("{}{}", stdout, stderr);
if !out.status.success() {
return Err(GenericError(format!("Failed to delete remote branch: {}", combined.trim())));
}
Ok(())
}
pub async fn git_rename_branch(dir: &Path, old_name: &str, new_name: &str) -> Result<()> {
let out = new_binary_command(dir)
.await?
.args(["branch", "-m", old_name, new_name])
.output()
.await
.map_err(|e| GenericError(format!("failed to run git branch -m: {e}")))?;
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
let combined = format!("{}{}", stdout, stderr);
if !out.status.success() {
return Err(GenericError(format!("Failed to rename branch: {}", combined.trim())));
}
Ok(())
}
================================================
FILE: crates/yaak-git/src/clone.rs
================================================
use crate::binary::new_binary_command;
use crate::error::Error::GenericError;
use crate::error::Result;
use log::info;
use serde::{Deserialize, Serialize};
use std::fs;
use std::path::Path;
use ts_rs::TS;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)]
#[serde(rename_all = "snake_case", tag = "type")]
#[ts(export, export_to = "gen_git.ts")]
pub enum CloneResult {
Success,
Cancelled,
NeedsCredentials { url: String, error: Option<String> },
}
pub async fn git_clone(url: &str, dir: &Path) -> Result<CloneResult> {
let parent = dir.parent().ok_or_else(|| GenericError("Invalid clone directory".to_string()))?;
fs::create_dir_all(parent)
.map_err(|e| GenericError(format!("Failed to create directory: {e}")))?;
let mut cmd = new_binary_command(parent).await?;
cmd.args(["clone", url]).arg(dir).env("GIT_TERMINAL_PROMPT", "0");
let out =
cmd.output().await.map_err(|e| GenericError(format!("failed to run git clone: {e}")))?;
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
let combined = format!("{}{}", stdout, stderr);
let combined_lower = combined.to_lowercase();
info!("Cloned status={}: {combined}", out.status);
if !out.status.success() {
// Check for credentials error
if combined_lower.contains("could not read") {
return Ok(CloneResult::NeedsCredentials { url: url.to_string(), error: None });
}
if combined_lower.contains("unable to access")
|| combined_lower.contains("authentication failed")
{
return Ok(CloneResult::NeedsCredentials {
url: url.to_string(),
error: Some(combined.to_string()),
});
}
return Err(GenericError(format!("Failed to clone: {}", combined.trim())));
}
Ok(CloneResult::Success)
}
================================================
FILE: crates/yaak-git/src/commit.rs
================================================
use crate::binary::new_binary_command;
use crate::error::Error::GenericError;
use log::info;
use std::path::Path;
pub async fn git_commit(dir: &Path, message: &str) -> crate::error::Result<()> {
let out =
new_binary_command(dir).await?.args(["commit", "--message", message]).output().await?;
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
let combined = stdout + stderr;
if !out.status.success() {
return Err(GenericError(format!("Failed to commit: {}", combined)));
}
info!("Committed to {dir:?}");
Ok(())
}
================================================
FILE: crates/yaak-git/src/credential.rs
================================================
use crate::binary::new_binary_command_global;
use crate::error::Error::GenericError;
use crate::error::Result;
use std::process::Stdio;
use tokio::io::AsyncWriteExt;
use url::Url;
pub async fn git_add_credential(remote_url: &str, username: &str, password: &str) -> Result<()> {
let url = Url::parse(remote_url)
.map_err(|e| GenericError(format!("Failed to parse remote url {remote_url}: {e:?}")))?;
let protocol = url.scheme();
let host = url.host_str().unwrap();
let path = Some(url.path());
let mut child = new_binary_command_global()
.await?
.args(["credential", "approve"])
.stdin(Stdio::piped())
.stdout(Stdio::null())
.spawn()?;
{
let stdin = child.stdin.as_mut().unwrap();
stdin.write_all(format!("protocol={}\n", protocol).as_bytes()).await?;
stdin.write_all(format!("host={}\n", host).as_bytes()).await?;
if let Some(path) = path {
if !path.is_empty() {
stdin
.write_all(format!("path={}\n", path.trim_start_matches('/')).as_bytes())
.await?;
}
}
stdin.write_all(format!("username={}\n", username).as_bytes()).await?;
stdin.write_all(format!("password={}\n", password).as_bytes()).await?;
stdin.write_all(b"\n").await?; // blank line terminator
}
let status = child.wait().await?;
if !status.success() {
return Err(GenericError("Failed to approve git credential".to_string()));
}
Ok(())
}
================================================
FILE: crates/yaak-git/src/error.rs
================================================
use serde::{Serialize, Serializer};
use std::io;
use std::path::PathBuf;
use std::string::FromUtf8Error;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum Error {
#[error("Git repo not found {0}")]
GitRepoNotFound(PathBuf),
#[error("Git error: {0}")]
GitUnknown(#[from] git2::Error),
#[error("Yaml error: {0}")]
YamlParseError(#[from] serde_yaml::Error),
#[error(transparent)]
ModelError(#[from] yaak_models::error::Error),
#[error("Sync error: {0}")]
SyncError(#[from] yaak_sync::error::Error),
#[error("I/o error: {0}")]
IoError(#[from] io::Error),
#[error("JSON error: {0}")]
JsonParseError(#[from] serde_json::Error),
#[error("UTF8 error: {0}")]
Utf8ConversionError(#[from] FromUtf8Error),
#[error("Git error: {0}")]
GenericError(String),
#[error("'git' not found. Please ensure it's installed and available in $PATH")]
GitNotFound,
#[error("Credentials required: {0}")]
CredentialsRequiredError(String),
#[error("No default remote found")]
NoDefaultRemoteFound,
#[error("No remotes found for repo")]
NoRemotesFound,
#[error("Merge failed due to conflicts")]
MergeConflicts,
#[error("No active branch")]
NoActiveBranch,
}
impl Serialize for Error {
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.to_string().as_ref())
}
}
pub type Result<T> = std::result::Result<T, Error>;
================================================
FILE: crates/yaak-git/src/fetch.rs
================================================
use crate::binary::new_binary_command;
use crate::error::Error::GenericError;
use crate::error::Result;
use std::path::Path;
pub async fn git_fetch_all(dir: &Path) -> Result<()> {
let out = new_binary_command(dir)
.await?
.args(["fetch", "--all", "--prune", "--tags"])
.output()
.await
.map_err(|e| GenericError(format!("failed to run git pull: {e}")))?;
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
let combined = stdout + stderr;
if !out.status.success() {
return Err(GenericError(format!("Failed to fetch: {}", combined)));
}
Ok(())
}
================================================
FILE: crates/yaak-git/src/init.rs
================================================
use crate::error::Result;
use crate::repository::open_repo;
use log::info;
use std::path::Path;
pub fn git_init(dir: &Path) -> Result<()> {
git2::Repository::init(dir)?;
let repo = open_repo(dir)?;
// Default to main instead of master, to align with
// the official Git and GitHub behavior
repo.set_head("refs/heads/main")?;
info!("Initialized {dir:?}");
Ok(())
}
================================================
FILE: crates/yaak-git/src/lib.rs
================================================
mod add;
mod binary;
mod branch;
mod clone;
mod commit;
mod credential;
pub mod error;
mod fetch;
mod init;
mod log;
mod pull;
mod push;
mod remotes;
mod repository;
mod reset;
mod status;
mod unstage;
mod util;
// Re-export all git functions for external use
pub use add::git_add;
pub use branch::{
BranchDeleteResult, git_checkout_branch, git_create_branch, git_delete_branch,
git_delete_remote_branch, git_merge_branch, git_rename_branch,
};
pub use clone::{CloneResult, git_clone};
pub use commit::git_commit;
pub use credential::git_add_credential;
pub use fetch::git_fetch_all;
pub use init::git_init;
pub use log::{GitCommit, git_log};
pub use pull::{PullResult, git_pull, git_pull_force_reset, git_pull_merge};
pub use push::{PushResult, git_push};
pub use remotes::{GitRemote, git_add_remote, git_remotes, git_rm_remote};
pub use reset::git_reset_changes;
pub use status::{GitStatusSummary, git_status};
pub use unstage::git_unstage;
================================================
FILE: crates/yaak-git/src/log.rs
================================================
use crate::repository::open_repo;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::path::Path;
use ts_rs::TS;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export, export_to = "gen_git.ts")]
pub struct GitCommit {
pub author: GitAuthor,
pub when: DateTime<Utc>,
pub message: Option<String>,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export, export_to = "gen_git.ts")]
pub struct GitAuthor {
pub name: Option<String>,
pub email: Option<String>,
}
pub fn git_log(dir: &Path) -> crate::error::Result<Vec<GitCommit>> {
let repo = open_repo(dir)?;
// Return empty if empty repo or no head (new repo)
if repo.is_empty()? || repo.head().is_err() {
return Ok(vec![]);
}
let mut revwalk = repo.revwalk()?;
revwalk.push_head()?;
revwalk.set_sorting(git2::Sort::TIME)?;
// Run git log
macro_rules! filter_try {
($e:expr) => {
match $e {
Ok(t) => t,
Err(_) => return None,
}
};
}
let log: Vec<GitCommit> = revwalk
.filter_map(|oid| {
let oid = filter_try!(oid);
let commit = filter_try!(repo.find_commit(oid));
let author = commit.author();
Some(GitCommit {
author: GitAuthor {
name: author.name().map(|s| s.to_string()),
email: author.email().map(|s| s.to_string()),
},
when: convert_git_time_to_date(author.when()),
message: commit.message().map(|m| m.to_string()),
})
})
.collect();
Ok(log)
}
#[cfg(test)]
fn convert_git_time_to_date(_git_time: git2::Time) -> DateTime<Utc> {
DateTime::from_timestamp(0, 0).unwrap()
}
#[cfg(not(test))]
fn convert_git_time_to_date(git_time: git2::Time) -> DateTime<Utc> {
let timestamp = git_time.seconds();
DateTime::from_timestamp(timestamp, 0).unwrap()
}
================================================
FILE: crates/yaak-git/src/pull.rs
================================================
use crate::binary::new_binary_command;
use crate::error::Error::GenericError;
use crate::error::Result;
use crate::repository::open_repo;
use crate::util::{get_current_branch_name, get_default_remote_in_repo};
use log::info;
use serde::{Deserialize, Serialize};
use std::path::Path;
use ts_rs::TS;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)]
#[serde(rename_all = "snake_case", tag = "type")]
#[ts(export, export_to = "gen_git.ts")]
pub enum PullResult {
Success { message: String },
UpToDate,
NeedsCredentials { url: String, error: Option<String> },
Diverged { remote: String, branch: String },
UncommittedChanges,
}
fn has_uncommitted_changes(dir: &Path) -> Result<bool> {
let repo = open_repo(dir)?;
let mut opts = git2::StatusOptions::new();
opts.include_ignored(false).include_untracked(false);
let statuses = repo.statuses(Some(&mut opts))?;
Ok(statuses.iter().any(|e| e.status() != git2::Status::CURRENT))
}
pub async fn git_pull(dir: &Path) -> Result<PullResult> {
if has_uncommitted_changes(dir)? {
return Ok(PullResult::UncommittedChanges);
}
// Extract all git2 data before any await points (git2 types are not Send)
let (branch_name, remote_name, remote_url) = {
let repo = open_repo(dir)?;
let branch_name = get_current_branch_name(&repo)?;
let remote = get_default_remote_in_repo(&repo)?;
let remote_name =
remote.name().ok_or(GenericError("Failed to get remote name".to_string()))?.to_string();
let remote_url =
remote.url().ok_or(GenericError("Failed to get remote url".to_string()))?.to_string();
(branch_name, remote_name, remote_url)
};
// Step 1: fetch the specific branch
// NOTE: We use fetch + merge instead of `git pull` to avoid conflicts with
// global git config (e.g. pull.ff=only) and the background fetch --all.
let fetch_out = new_binary_command(dir)
.await?
.args(["fetch", &remote_name, &branch_name])
.env("GIT_TERMINAL_PROMPT", "0")
.output()
.await
.map_err(|e| GenericError(format!("failed to run git fetch: {e}")))?;
let fetch_stdout = String::from_utf8_lossy(&fetch_out.stdout);
let fetch_stderr = String::from_utf8_lossy(&fetch_out.stderr);
let fetch_combined = format!("{fetch_stdout}{fetch_stderr}");
info!("Fetched status={} {fetch_combined}", fetch_out.status);
if fetch_combined.to_lowercase().contains("could not read") {
return Ok(PullResult::NeedsCredentials { url: remote_url.to_string(), error: None });
}
if fetch_combined.to_lowercase().contains("unable to access") {
return Ok(PullResult::NeedsCredentials {
url: remote_url.to_string(),
error: Some(fetch_combined.to_string()),
});
}
if !fetch_out.status.success() {
return Err(GenericError(format!("Failed to fetch: {fetch_combined}")));
}
// Step 2: merge the fetched branch
let ref_name = format!("{}/{}", remote_name, branch_name);
let merge_out = new_binary_command(dir)
.await?
.args(["merge", "--ff-only", &ref_name])
.output()
.await
.map_err(|e| GenericError(format!("failed to run git merge: {e}")))?;
let merge_stdout = String::from_utf8_lossy(&merge_out.stdout);
let merge_stderr = String::from_utf8_lossy(&merge_out.stderr);
let merge_combined = format!("{merge_stdout}{merge_stderr}");
info!("Merged status={} {merge_combined}", merge_out.status);
if !merge_out.status.success() {
let merge_lower = merge_combined.to_lowercase();
if merge_lower.contains("cannot fast-forward")
|| merge_lower.contains("not possible to fast-forward")
|| merge_lower.contains("diverged")
{
return Ok(PullResult::Diverged { remote: remote_name, branch: branch_name });
}
return Err(GenericError(format!("Failed to merge: {merge_combined}")));
}
if merge_combined.to_lowercase().contains("up to date") {
return Ok(PullResult::UpToDate);
}
Ok(PullResult::Success { message: format!("Pulled from {}/{}", remote_name, branch_name) })
}
pub async fn git_pull_force_reset(dir: &Path, remote: &str, branch: &str) -> Result<PullResult> {
// Step 1: fetch the remote
let fetch_out = new_binary_command(dir)
.await?
.args(["fetch", remote])
.env("GIT_TERMINAL_PROMPT", "0")
.output()
.await
.map_err(|e| GenericError(format!("failed to run git fetch: {e}")))?;
if !fetch_out.status.success() {
let stderr = String::from_utf8_lossy(&fetch_out.stderr);
return Err(GenericError(format!("Failed to fetch: {stderr}")));
}
// Step 2: reset --hard to remote/branch
let ref_name = format!("{}/{}", remote, branch);
let reset_out = new_binary_command(dir)
.await?
.args(["reset", "--hard", &ref_name])
.output()
.await
.map_err(|e| GenericError(format!("failed to run git reset: {e}")))?;
if !reset_out.status.success() {
let stderr = String::from_utf8_lossy(&reset_out.stderr);
return Err(GenericError(format!("Failed to reset: {}", stderr.trim())));
}
Ok(PullResult::Success { message: format!("Reset to {}/{}", remote, branch) })
}
pub async fn git_pull_merge(dir: &Path, remote: &str, branch: &str) -> Result<PullResult> {
let out = new_binary_command(dir)
.await?
.args(["pull", "--no-rebase", remote, branch])
.env("GIT_TERMINAL_PROMPT", "0")
.output()
.await
.map_err(|e| GenericError(format!("failed to run git pull --no-rebase: {e}")))?;
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
let combined = format!("{}{}", stdout, stderr);
info!("Pull merge status={} {combined}", out.status);
if !out.status.success() {
if combined.to_lowercase().contains("conflict") {
return Err(GenericError(
"Merge conflicts detected. Please resolve them manually.".to_string(),
));
}
return Err(GenericError(format!("Failed to merge pull: {}", combined.trim())));
}
Ok(PullResult::Success { message: format!("Merged from {}/{}", remote, branch) })
}
// pub(crate) fn git_pull_old(dir: &Path) -> Result<PullResult> {
// let repo = open_repo(dir)?;
//
// let branch = get_current_branch(&repo)?.ok_or(NoActiveBranch)?;
// let branch_ref = branch.get();
// let branch_ref = bytes_to_string(branch_ref.name_bytes())?;
//
// let remote_name = repo.branch_upstream_remote(&branch_ref)?;
// let remote_name = bytes_to_string(&remote_name)?;
// debug!("Pulling from {remote_name}");
//
// let mut remote = repo.find_remote(&remote_name)?;
//
// let mut options = FetchOptions::new();
// let callbacks = default_callbacks();
// options.remote_callbacks(callbacks);
//
// let mut proxy = ProxyOptions::new();
// proxy.auto();
// options.proxy_options(proxy);
//
// remote.fetch(&[&branch_ref], Some(&mut options), None)?;
//
// let stats = remote.stats();
//
// let fetch_head = repo.find_reference("FETCH_HEAD")?;
// let fetch_commit = repo.reference_to_annotated_commit(&fetch_head)?;
// do_merge(&repo, &branch, &fetch_commit)?;
//
// Ok(PullResult::Success {
// message: "Hello".to_string(),
// // received_bytes: stats.received_bytes(),
// // received_objects: stats.received_objects(),
// })
// }
================================================
FILE: crates/yaak-git/src/push.rs
================================================
use crate::binary::new_binary_command;
use crate::error::Error::GenericError;
use crate::error::Result;
use crate::repository::open_repo;
use crate::util::{get_current_branch_name, get_default_remote_for_push_in_repo};
use log::info;
use serde::{Deserialize, Serialize};
use std::path::Path;
use ts_rs::TS;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, TS)]
#[serde(rename_all = "snake_case", tag = "type")]
#[ts(export, export_to = "gen_git.ts")]
pub enum PushResult {
Success { message: String },
UpToDate,
NeedsCredentials { url: String, error: Option<String> },
}
pub async fn git_push(dir: &Path) -> Result<PushResult> {
// Extract all git2 data before any await points (git2 types are not Send)
let (branch_name, remote_name, remote_url) = {
let repo = open_repo(dir)?;
let branch_name = get_current_branch_name(&repo)?;
let remote = get_default_remote_for_push_in_repo(&repo)?;
let remote_name =
remote.name().ok_or(GenericError("Failed to get remote name".to_string()))?.to_string();
let remote_url =
remote.url().ok_or(GenericError("Failed to get remote url".to_string()))?.to_string();
(branch_name, remote_name, remote_url)
};
let out = new_binary_command(dir)
.await?
.args(["push", &remote_name, &branch_name])
.env("GIT_TERMINAL_PROMPT", "0")
.output()
.await
.map_err(|e| GenericError(format!("failed to run git push: {e}")))?;
let stdout = String::from_utf8_lossy(&out.stdout);
let stderr = String::from_utf8_lossy(&out.stderr);
let combined = stdout + stderr;
let combined_lower = combined.to_lowercase();
info!("Pushed to repo status={} {combined}", out.status);
// Helper to check if this is a credentials error
let is_credentials_error = || {
combined_lower.contains("could not read")
|| combined_lower.contains("unable to access")
|| combined_lower.contains("authentication failed")
};
// Check for explicit rejection indicators first (e.g., protected branch rejections)
// These can occur even if some git servers don't properly set exit codes
if combined_lower.contains("rejected") || combined_lower.contains("failed to push") {
if is_credentials_error() {
return Ok(PushResult::NeedsCredentials {
url: remote_url.to_string(),
gitextract_zes9y_de/ ├── .claude/ │ ├── commands/ │ │ └── release/ │ │ └── generate-release-notes.md │ └── rules.md ├── .claude-context.md ├── .codex/ │ └── skills/ │ └── release-generate-release-notes/ │ └── SKILL.md ├── .gitattributes ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ └── config.yml │ ├── pull_request_template.md │ └── workflows/ │ ├── ci.yml │ ├── claude.yml │ ├── flathub.yml │ ├── release-api-npm.yml │ ├── release-app.yml │ ├── release-cli-npm.yml │ └── sponsors.yml ├── .gitignore ├── .node-version ├── .npmrc ├── .nvmrc ├── .oxfmtignore ├── .vite-hooks/ │ ├── post-checkout │ └── pre-commit ├── .vscode/ │ ├── extensions.json │ ├── launch.json │ └── settings.json ├── AGENTS.md ├── CONTRIBUTING.md ├── Cargo.toml ├── DEVELOPMENT.md ├── LICENSE ├── README.md ├── crates/ │ ├── yaak/ │ │ ├── Cargo.toml │ │ └── src/ │ │ ├── error.rs │ │ ├── lib.rs │ │ ├── plugin_events.rs │ │ ├── render.rs │ │ └── send.rs │ ├── yaak-api/ │ │ ├── Cargo.toml │ │ └── src/ │ │ ├── error.rs │ │ └── lib.rs │ ├── yaak-common/ │ │ ├── Cargo.toml │ │ └── src/ │ │ ├── command.rs │ │ ├── lib.rs │ │ ├── platform.rs │ │ └── serde.rs │ ├── yaak-core/ │ │ ├── Cargo.toml │ │ └── src/ │ │ ├── context.rs │ │ ├── error.rs │ │ └── lib.rs │ ├── yaak-crypto/ │ │ ├── Cargo.toml │ │ ├── index.ts │ │ ├── package.json │ │ └── src/ │ │ ├── encryption.rs │ │ ├── error.rs │ │ ├── lib.rs │ │ ├── manager.rs │ │ ├── master_key.rs │ │ └── workspace_key.rs │ ├── yaak-git/ │ │ ├── Cargo.toml │ │ ├── bindings/ │ │ │ ├── gen_git.ts │ │ │ └── gen_models.ts │ │ ├── index.ts │ │ ├── package.json │ │ └── src/ │ │ ├── add.rs │ │ ├── binary.rs │ │ ├── branch.rs │ │ ├── clone.rs │ │ ├── commit.rs │ │ ├── credential.rs │ │ ├── error.rs │ │ ├── fetch.rs │ │ ├── init.rs │ │ ├── lib.rs │ │ ├── log.rs │ │ ├── pull.rs │ │ ├── push.rs │ │ ├── remotes.rs │ │ ├── repository.rs │ │ ├── reset.rs │ │ ├── status.rs │ │ ├── unstage.rs │ │ └── util.rs │ ├── yaak-grpc/ │ │ ├── Cargo.toml │ │ └── src/ │ │ ├── any.rs │ │ ├── client.rs │ │ ├── codec.rs │ │ ├── error.rs │ │ ├── json_schema.rs │ │ ├── lib.rs │ │ ├── manager.rs │ │ ├── reflection.rs │ │ └── transport.rs │ ├── yaak-http/ │ │ ├── Cargo.toml │ │ ├── src/ │ │ │ ├── chained_reader.rs │ │ │ ├── client.rs │ │ │ ├── cookies.rs │ │ │ ├── decompress.rs │ │ │ ├── dns.rs │ │ │ ├── error.rs │ │ │ ├── lib.rs │ │ │ ├── manager.rs │ │ │ ├── path_placeholders.rs │ │ │ ├── proto.rs │ │ │ ├── sender.rs │ │ │ ├── tee_reader.rs │ │ │ ├── transaction.rs │ │ │ └── types.rs │ │ └── tests/ │ │ └── test.txt │ ├── yaak-models/ │ │ ├── Cargo.toml │ │ ├── bindings/ │ │ │ ├── gen_models.ts │ │ │ └── gen_util.ts │ │ ├── blob_migrations/ │ │ │ └── 00000000000000_init.sql │ │ ├── build.rs │ │ ├── guest-js/ │ │ │ ├── atoms.ts │ │ │ ├── index.ts │ │ │ ├── store.ts │ │ │ ├── types.ts │ │ │ └── util.ts │ │ ├── migrations/ │ │ │ ├── 20230225181302_init.sql │ │ │ ├── 20230319042610_sort-priority.sql │ │ │ ├── 20230330143214_request-auth.sql │ │ │ ├── 20230413232435_response-body-blob.sql │ │ │ ├── 20231022205109_environments.sql │ │ │ ├── 20231028161007_variables.sql │ │ │ ├── 20231103004111_workspace-variables.sql │ │ │ ├── 20231103142807_folders.sql │ │ │ ├── 20231112180500_body_object.sql │ │ │ ├── 20231113183810_url_params.sql │ │ │ ├── 20231122055216_remove_body.sql │ │ │ ├── 20240111221224_settings.sql │ │ │ ├── 20240115193751_workspace_settings.sql │ │ │ ├── 20240118181105_channel_setting.sql │ │ │ ├── 20240127013915_cookies.sql │ │ │ ├── 20240128230717_more_response_attrs.sql │ │ │ ├── 20240203164833_grpc.sql │ │ │ ├── 20240522031045_theme-settings.sql │ │ │ ├── 20240529143147_more-settings.sql │ │ │ ├── 20240607151115_open-workspace-setting.sql │ │ │ ├── 20240814013812_fix-env-model.sql │ │ │ ├── 20240826184943_disable-telemetry.sql │ │ │ ├── 20240829131004_plugins.sql │ │ │ ├── 20241003134208_response-state.sql │ │ │ ├── 20241012181547_proxy-setting.sql │ │ │ ├── 20241217204951_docs.sql │ │ │ ├── 20241219140051_base-environments.sql │ │ │ ├── 20250102141937_sync.sql │ │ │ ├── 20250108035425_editor-keymap.sql │ │ │ ├── 20250108205117_workspace-meta.sql │ │ │ ├── 20250114160022_remove-workspace-sync-setting.sql │ │ │ ├── 20250123192023_plugin-kv.sql │ │ │ ├── 20250128155623_websockets.sql │ │ │ ├── 20250302041707_hide-window-controls.sql │ │ │ ├── 20250326193143_key-value-id.sql │ │ │ ├── 20250401122407_encrypted-key.sql │ │ │ ├── 20250402144842_encryption-key-challenge.sql │ │ │ ├── 20250424152740_remove-fks.sql │ │ │ ├── 20250507140702_remove-ev-sync-states.sql │ │ │ ├── 20250508161145_public-environments.sql │ │ │ ├── 20250516182745_default-attrs.sql │ │ │ ├── 20250530174021_graphql-introspection.sql │ │ │ ├── 20250531193722_sync-state-index.sql │ │ │ ├── 20250604102922_colored-methods-setting.sql │ │ │ ├── 20250608150053_font-settings.sql │ │ │ ├── 20250611120000_environment-color.sql │ │ │ ├── 20250727190746_autoupdate_setting.sql │ │ │ ├── 20250918141129_request-folder-environments.sql │ │ │ ├── 20250929132954_dismiss-license-badge.sql │ │ │ ├── 20251001082054_auto-download.sql │ │ │ ├── 20251028060300_check_notifications_setting.sql │ │ │ ├── 20251029062024_aws-auth-name.sql │ │ │ ├── 20251031070515_environment-sort-priority.sql │ │ │ ├── 20251202080000_use-native-titlebar.sql │ │ │ ├── 20251209000000_client-certificates.sql │ │ │ ├── 20251219074602_default-workspace-headers.sql │ │ │ ├── 20251220000000_response-request-headers.sql │ │ │ ├── 20251221000000_http-response-events.sql │ │ │ ├── 20251221100000_request-content-length.sql │ │ │ ├── 20260104000000_hotkeys.sql │ │ │ ├── 20260111000000_dns-timing.sql │ │ │ ├── 20260112000000_dns-overrides.sql │ │ │ ├── 20260119045146_remove-default-workspace-headers.sql │ │ │ ├── 20260216000000_model-changes.sql │ │ │ ├── 20260217000000_remove-legacy-faker-plugin.sql │ │ │ └── 20260301000000_plugin-source-and-unique-directory.sql │ │ ├── package.json │ │ └── src/ │ │ ├── blob_manager.rs │ │ ├── connection_or_tx.rs │ │ ├── db_context.rs │ │ ├── error.rs │ │ ├── lib.rs │ │ ├── migrate.rs │ │ ├── models.rs │ │ ├── queries/ │ │ │ ├── any_request.rs │ │ │ ├── batch.rs │ │ │ ├── cookie_jars.rs │ │ │ ├── environments.rs │ │ │ ├── folders.rs │ │ │ ├── graphql_introspections.rs │ │ │ ├── grpc_connections.rs │ │ │ ├── grpc_events.rs │ │ │ ├── grpc_requests.rs │ │ │ ├── http_requests.rs │ │ │ ├── http_response_events.rs │ │ │ ├── http_responses.rs │ │ │ ├── key_values.rs │ │ │ ├── mod.rs │ │ │ ├── model_changes.rs │ │ │ ├── plugin_key_values.rs │ │ │ ├── plugins.rs │ │ │ ├── settings.rs │ │ │ ├── sync_states.rs │ │ │ ├── websocket_connections.rs │ │ │ ├── websocket_events.rs │ │ │ ├── websocket_requests.rs │ │ │ ├── workspace_metas.rs │ │ │ └── workspaces.rs │ │ ├── query_manager.rs │ │ ├── render.rs │ │ └── util.rs │ ├── yaak-plugins/ │ │ ├── Cargo.toml │ │ ├── bindings/ │ │ │ ├── gen_api.ts │ │ │ ├── gen_events.ts │ │ │ ├── gen_models.ts │ │ │ ├── gen_search.ts │ │ │ └── serde_json/ │ │ │ └── JsonValue.ts │ │ ├── index.ts │ │ ├── package.json │ │ └── src/ │ │ ├── api.rs │ │ ├── checksum.rs │ │ ├── error.rs │ │ ├── events.rs │ │ ├── install.rs │ │ ├── lib.rs │ │ ├── manager.rs │ │ ├── native_template_functions.rs │ │ ├── nodejs.rs │ │ ├── plugin_handle.rs │ │ ├── plugin_meta.rs │ │ ├── server_ws.rs │ │ ├── template_callback.rs │ │ └── util.rs │ ├── yaak-sse/ │ │ ├── Cargo.toml │ │ ├── bindings/ │ │ │ └── sse.ts │ │ ├── index.ts │ │ ├── package.json │ │ └── src/ │ │ ├── lib.rs │ │ └── sse.rs │ ├── yaak-sync/ │ │ ├── Cargo.toml │ │ ├── bindings/ │ │ │ ├── gen_models.ts │ │ │ ├── gen_sync.ts │ │ │ ├── gen_watch.ts │ │ │ └── git.ts │ │ ├── index.ts │ │ ├── package.json │ │ └── src/ │ │ ├── error.rs │ │ ├── lib.rs │ │ ├── models.rs │ │ ├── sync.rs │ │ └── watch.rs │ ├── yaak-templates/ │ │ ├── Cargo.toml │ │ ├── bindings/ │ │ │ └── parser.ts │ │ ├── build-wasm.cjs │ │ ├── index.ts │ │ ├── package.json │ │ ├── pkg/ │ │ │ ├── package.json │ │ │ ├── yaak_templates.d.ts │ │ │ ├── yaak_templates.js │ │ │ ├── yaak_templates_bg.js │ │ │ ├── yaak_templates_bg.wasm │ │ │ └── yaak_templates_bg.wasm.d.ts │ │ └── src/ │ │ ├── error.rs │ │ ├── escape.rs │ │ ├── format_json.rs │ │ ├── lib.rs │ │ ├── parser.rs │ │ ├── renderer.rs │ │ ├── strip_json_comments.rs │ │ └── wasm.rs │ ├── yaak-tls/ │ │ ├── Cargo.toml │ │ └── src/ │ │ ├── error.rs │ │ └── lib.rs │ └── yaak-ws/ │ ├── Cargo.toml │ ├── index.ts │ ├── package.json │ └── src/ │ ├── connect.rs │ ├── error.rs │ ├── lib.rs │ ├── manager.rs │ └── render.rs ├── crates-cli/ │ └── yaak-cli/ │ ├── Cargo.toml │ ├── README.md │ ├── src/ │ │ ├── cli.rs │ │ ├── commands/ │ │ │ ├── auth.rs │ │ │ ├── cookie_jar.rs │ │ │ ├── environment.rs │ │ │ ├── folder.rs │ │ │ ├── mod.rs │ │ │ ├── plugin.rs │ │ │ ├── request.rs │ │ │ ├── send.rs │ │ │ └── workspace.rs │ │ ├── context.rs │ │ ├── main.rs │ │ ├── plugin_events.rs │ │ ├── ui.rs │ │ ├── utils/ │ │ │ ├── confirm.rs │ │ │ ├── http.rs │ │ │ ├── json.rs │ │ │ ├── mod.rs │ │ │ ├── schema.rs │ │ │ └── workspace.rs │ │ ├── version.rs │ │ └── version_check.rs │ └── tests/ │ ├── common/ │ │ ├── http_server.rs │ │ └── mod.rs │ ├── environment_commands.rs │ ├── folder_commands.rs │ ├── request_commands.rs │ ├── send_commands.rs │ └── workspace_commands.rs ├── crates-tauri/ │ ├── yaak-app/ │ │ ├── .gitignore │ │ ├── Cargo.toml │ │ ├── bindings/ │ │ │ ├── gen_watch.ts │ │ │ ├── index.ts │ │ │ └── plugins_ext.ts │ │ ├── build.rs │ │ ├── capabilities/ │ │ │ └── default.json │ │ ├── icons/ │ │ │ ├── dev/ │ │ │ │ └── icon.icns │ │ │ └── release/ │ │ │ └── icon.icns │ │ ├── macos/ │ │ │ ├── entitlements.plist │ │ │ ├── entitlements.yaaknode.plist │ │ │ └── entitlements.yaakprotoc.plist │ │ ├── package.json │ │ ├── src/ │ │ │ ├── commands.rs │ │ │ ├── encoding.rs │ │ │ ├── error.rs │ │ │ ├── git_ext.rs │ │ │ ├── grpc.rs │ │ │ ├── history.rs │ │ │ ├── http_request.rs │ │ │ ├── import.rs │ │ │ ├── lib.rs │ │ │ ├── main.rs │ │ │ ├── models_ext.rs │ │ │ ├── notifications.rs │ │ │ ├── plugin_events.rs │ │ │ ├── plugins_ext.rs │ │ │ ├── render.rs │ │ │ ├── sync_ext.rs │ │ │ ├── updates.rs │ │ │ ├── uri_scheme.rs │ │ │ ├── window.rs │ │ │ ├── window_menu.rs │ │ │ └── ws_ext.rs │ │ ├── tauri.conf.json │ │ ├── tauri.development.conf.json │ │ ├── tauri.linux.conf.json │ │ ├── tauri.release.conf.json │ │ └── template.desktop │ ├── yaak-fonts/ │ │ ├── Cargo.toml │ │ ├── bindings/ │ │ │ └── gen_fonts.ts │ │ ├── build.rs │ │ ├── index.ts │ │ ├── package.json │ │ ├── permissions/ │ │ │ └── default.toml │ │ └── src/ │ │ ├── commands.rs │ │ ├── error.rs │ │ └── lib.rs │ ├── yaak-license/ │ │ ├── Cargo.toml │ │ ├── bindings/ │ │ │ ├── gen_models.ts │ │ │ ├── license.ts │ │ │ └── models.ts │ │ ├── build.rs │ │ ├── index.ts │ │ ├── package.json │ │ ├── permissions/ │ │ │ └── default.toml │ │ └── src/ │ │ ├── commands.rs │ │ ├── error.rs │ │ ├── lib.rs │ │ └── license.rs │ ├── yaak-mac-window/ │ │ ├── Cargo.toml │ │ ├── build.rs │ │ ├── index.ts │ │ ├── package.json │ │ ├── permissions/ │ │ │ └── default.toml │ │ └── src/ │ │ ├── commands.rs │ │ ├── lib.rs │ │ └── mac.rs │ └── yaak-tauri-utils/ │ ├── Cargo.toml │ └── src/ │ ├── lib.rs │ └── window.rs ├── flatpak/ │ ├── app.yaak.Yaak.metainfo.xml │ ├── fix-lockfile.mjs │ ├── generate-sources.sh │ └── update-manifest.sh ├── npm/ │ ├── cli/ │ │ ├── .gitignore │ │ ├── bin/ │ │ │ └── cli.js │ │ ├── common.js │ │ ├── index.js │ │ ├── install.js │ │ ├── package.json │ │ └── prepublish.js │ ├── cli-darwin-arm64/ │ │ ├── bin/ │ │ │ └── .gitkeep │ │ └── package.json │ ├── cli-darwin-x64/ │ │ ├── bin/ │ │ │ └── .gitkeep │ │ └── package.json │ ├── cli-linux-arm64/ │ │ ├── bin/ │ │ │ └── .gitkeep │ │ └── package.json │ ├── cli-linux-x64/ │ │ ├── bin/ │ │ │ └── .gitkeep │ │ └── package.json │ ├── cli-win32-arm64/ │ │ ├── bin/ │ │ │ └── .gitkeep │ │ └── package.json │ ├── cli-win32-x64/ │ │ ├── bin/ │ │ │ └── .gitkeep │ │ └── package.json │ └── prepare-publish.js ├── package.json ├── packages/ │ ├── common-lib/ │ │ ├── debounce.ts │ │ ├── formatSize.ts │ │ ├── index.ts │ │ ├── package.json │ │ └── templateFunction.ts │ ├── plugin-runtime/ │ │ ├── package.json │ │ ├── src/ │ │ │ ├── EventChannel.ts │ │ │ ├── PluginHandle.ts │ │ │ ├── PluginInstance.ts │ │ │ ├── common.ts │ │ │ ├── index.ts │ │ │ ├── interceptStdout.ts │ │ │ └── migrations.ts │ │ ├── tests/ │ │ │ └── common.test.ts │ │ └── tsconfig.json │ └── plugin-runtime-types/ │ ├── .gitignore │ ├── README.md │ ├── package.json │ ├── src/ │ │ ├── bindings/ │ │ │ ├── gen_api.ts │ │ │ ├── gen_events.ts │ │ │ ├── gen_models.ts │ │ │ ├── gen_search.ts │ │ │ └── serde_json/ │ │ │ └── JsonValue.ts │ │ ├── helpers.ts │ │ ├── index.ts │ │ ├── plugins/ │ │ │ ├── AuthenticationPlugin.ts │ │ │ ├── Context.ts │ │ │ ├── FilterPlugin.ts │ │ │ ├── FolderActionPlugin.ts │ │ │ ├── GrpcRequestActionPlugin.ts │ │ │ ├── HttpRequestActionPlugin.ts │ │ │ ├── ImporterPlugin.ts │ │ │ ├── TemplateFunctionPlugin.ts │ │ │ ├── ThemePlugin.ts │ │ │ ├── WebsocketRequestActionPlugin.ts │ │ │ ├── WorkspaceActionPlugin.ts │ │ │ └── index.ts │ │ └── themes/ │ │ └── index.ts │ └── tsconfig.json ├── plugins/ │ ├── .gitignore │ ├── action-copy-curl/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ ├── tests/ │ │ │ └── index.test.ts │ │ └── tsconfig.json │ ├── action-copy-grpcurl/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ ├── tests/ │ │ │ └── index.test.ts │ │ └── tsconfig.json │ ├── action-send-folder/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── auth-apikey/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── auth-aws/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── auth-basic/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ ├── tests/ │ │ │ └── index.test.ts │ │ └── tsconfig.json │ ├── auth-bearer/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ ├── tests/ │ │ │ └── index.test.ts │ │ └── tsconfig.json │ ├── auth-jwt/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── auth-ntlm/ │ │ ├── package.json │ │ ├── src/ │ │ │ ├── index.ts │ │ │ └── modules.d.ts │ │ ├── tests/ │ │ │ └── index.test.ts │ │ └── tsconfig.json │ ├── auth-oauth1/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── auth-oauth2/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ ├── callbackServer.ts │ │ │ ├── fetchAccessToken.ts │ │ │ ├── getOrRefreshAccessToken.ts │ │ │ ├── grants/ │ │ │ │ ├── authorizationCode.ts │ │ │ │ ├── clientCredentials.ts │ │ │ │ ├── implicit.ts │ │ │ │ └── password.ts │ │ │ ├── index.ts │ │ │ ├── store.ts │ │ │ └── util.ts │ │ ├── tests/ │ │ │ └── util.test.ts │ │ └── tsconfig.json │ ├── filter-jsonpath/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── filter-xpath/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── importer-curl/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ ├── tests/ │ │ │ └── index.test.ts │ │ └── tsconfig.json │ ├── importer-insomnia/ │ │ ├── package.json │ │ ├── src/ │ │ │ ├── common.ts │ │ │ ├── index.ts │ │ │ ├── v4.ts │ │ │ └── v5.ts │ │ ├── tests/ │ │ │ ├── fixtures/ │ │ │ │ ├── basic.input.json │ │ │ │ ├── basic.output.json │ │ │ │ ├── version-5-minimal.input.yaml │ │ │ │ ├── version-5-minimal.output.json │ │ │ │ ├── version-5.input.yaml │ │ │ │ └── version-5.output.json │ │ │ └── index.test.ts │ │ └── tsconfig.json │ ├── importer-openapi/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ ├── tests/ │ │ │ ├── fixtures/ │ │ │ │ └── petstore.yaml │ │ │ └── index.test.ts │ │ └── tsconfig.json │ ├── importer-postman/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ ├── tests/ │ │ │ ├── fixtures/ │ │ │ │ ├── auth.input.json │ │ │ │ ├── auth.output.json │ │ │ │ ├── nested.input.json │ │ │ │ ├── nested.output.json │ │ │ │ ├── params.input.json │ │ │ │ └── params.output.json │ │ │ └── index.test.ts │ │ └── tsconfig.json │ ├── importer-postman-environment/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ ├── tests/ │ │ │ ├── fixtures/ │ │ │ │ ├── environment.input.json │ │ │ │ └── environment.output.json │ │ │ └── index.test.ts │ │ └── tsconfig.json │ ├── importer-yaak/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ ├── tests/ │ │ │ └── index.test.ts │ │ └── tsconfig.json │ ├── template-function-1password/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── template-function-cookie/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── template-function-ctx/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── template-function-encode/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── template-function-fs/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── template-function-hash/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── template-function-json/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── template-function-prompt/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── template-function-random/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── template-function-regex/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ ├── tests/ │ │ │ └── regex.test.ts │ │ └── tsconfig.json │ ├── template-function-request/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── template-function-response/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── template-function-timestamp/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ ├── tests/ │ │ │ └── formatDatetime.test.ts │ │ └── tsconfig.json │ ├── template-function-uuid/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ ├── template-function-xml/ │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ └── tsconfig.json │ └── themes-yaak/ │ ├── package.json │ ├── src/ │ │ ├── index.ts │ │ └── themes/ │ │ ├── andromeda.ts │ │ ├── atom-one-dark.ts │ │ ├── ayu.ts │ │ ├── bluloco.ts │ │ ├── catppuccin.ts │ │ ├── cobalt2.ts │ │ ├── dracula.ts │ │ ├── everforest.ts │ │ ├── fleet.ts │ │ ├── github-dimmed.ts │ │ ├── github.ts │ │ ├── gruvbox.ts │ │ ├── high-contrast.ts │ │ ├── horizon.ts │ │ ├── hotdog-stand.ts │ │ ├── material-darker.ts │ │ ├── material-ocean.ts │ │ ├── material-palenight.ts │ │ ├── monokai-pro.ts │ │ ├── moonlight.ts │ │ ├── night-owl.ts │ │ ├── noctis.ts │ │ ├── nord.ts │ │ ├── one-dark-pro.ts │ │ ├── panda.ts │ │ ├── relaxing.ts │ │ ├── rose-pine.ts │ │ ├── shades-of-purple.ts │ │ ├── slack.ts │ │ ├── solarized.ts │ │ ├── synthwave-84.ts │ │ ├── tokyo-night.ts │ │ ├── triangle.ts │ │ ├── vitesse.ts │ │ └── winter-is-coming.ts │ └── tsconfig.json ├── plugins-external/ │ ├── .gitignore │ ├── faker/ │ │ ├── README.md │ │ ├── package.json │ │ ├── src/ │ │ │ └── index.ts │ │ ├── tests/ │ │ │ ├── __snapshots__/ │ │ │ │ └── init.test.ts.snap │ │ │ └── init.test.ts │ │ └── tsconfig.json │ ├── httpsnippet/ │ │ ├── README.md │ │ ├── package.json │ │ └── src/ │ │ └── index.ts │ └── mcp-server/ │ ├── README.md │ ├── package.json │ ├── src/ │ │ ├── index.ts │ │ ├── server.ts │ │ ├── tools/ │ │ │ ├── folder.ts │ │ │ ├── helpers.ts │ │ │ ├── httpRequest.ts │ │ │ ├── schemas.ts │ │ │ ├── toast.ts │ │ │ ├── window.ts │ │ │ └── workspace.ts │ │ └── types.ts │ └── tsconfig.json ├── rustfmt.toml ├── scripts/ │ ├── .gitignore │ ├── create-migration.cjs │ ├── git-hooks/ │ │ └── post-checkout.mjs │ ├── install-wasm-pack.cjs │ ├── publish-core-plugins.cjs │ ├── replace-version.cjs │ ├── run-dev.mjs │ ├── run-workspaces-dev.mjs │ ├── vendor-node.cjs │ ├── vendor-plugins.cjs │ └── vendor-protoc.cjs ├── src-web/ │ ├── .gitignore │ ├── commands/ │ │ ├── commands.tsx │ │ ├── createEnvironment.tsx │ │ ├── deleteWebsocketConnections.ts │ │ ├── moveToWorkspace.tsx │ │ ├── openFolderSettings.tsx │ │ ├── openSettings.tsx │ │ ├── openWorkspaceFromSyncDir.tsx │ │ ├── openWorkspaceSettings.tsx │ │ └── switchWorkspace.tsx │ ├── components/ │ │ ├── BinaryFileEditor.tsx │ │ ├── CargoFeature.tsx │ │ ├── CloneGitRepositoryDialog.tsx │ │ ├── ColorIndicator.tsx │ │ ├── CommandPaletteDialog.tsx │ │ ├── ConfirmLargeRequestBody.tsx │ │ ├── ConfirmLargeResponse.tsx │ │ ├── ConfirmLargeResponseRequest.tsx │ │ ├── CookieDialog.tsx │ │ ├── CookieDropdown.tsx │ │ ├── CopyButton.tsx │ │ ├── CopyIconButton.tsx │ │ ├── CreateDropdown.tsx │ │ ├── CreateEnvironmentDialog.tsx │ │ ├── CreateWorkspaceDialog.tsx │ │ ├── Dialogs.tsx │ │ ├── DnsOverridesEditor.tsx │ │ ├── DropMarker.tsx │ │ ├── DynamicForm.tsx │ │ ├── EmptyStateText.tsx │ │ ├── EncryptionHelp.tsx │ │ ├── EnvironmentActionsDropdown.tsx │ │ ├── EnvironmentColorIndicator.tsx │ │ ├── EnvironmentColorPicker.tsx │ │ ├── EnvironmentEditDialog.tsx │ │ ├── EnvironmentEditor.tsx │ │ ├── EnvironmentSharableTooltip.tsx │ │ ├── ErrorBoundary.tsx │ │ ├── ExportDataDialog.tsx │ │ ├── FolderLayout.tsx │ │ ├── FolderSettingsDialog.tsx │ │ ├── FormMultipartEditor.tsx │ │ ├── FormUrlencodedEditor.tsx │ │ ├── GlobalHooks.tsx │ │ ├── GrpcConnectionLayout.tsx │ │ ├── GrpcEditor.tsx │ │ ├── GrpcProtoSelectionDialog.tsx │ │ ├── GrpcRequestPane.tsx │ │ ├── GrpcResponsePane.tsx │ │ ├── HeaderSize.tsx │ │ ├── HeadersEditor.tsx │ │ ├── HttpAuthenticationEditor.tsx │ │ ├── HttpRequestLayout.tsx │ │ ├── HttpRequestPane.tsx │ │ ├── HttpResponsePane.tsx │ │ ├── HttpResponseTimeline.tsx │ │ ├── ImportCurlButton.tsx │ │ ├── ImportDataDialog.tsx │ │ ├── IsDev.tsx │ │ ├── JsonBodyEditor.tsx │ │ ├── KeyboardShortcutsDialog.tsx │ │ ├── LicenseBadge.tsx │ │ ├── LocalImage.tsx │ │ ├── Markdown.tsx │ │ ├── MarkdownEditor.tsx │ │ ├── MoveToWorkspaceDialog.tsx │ │ ├── Overlay.tsx │ │ ├── Portal.tsx │ │ ├── Prose.css │ │ ├── Prose.tsx │ │ ├── RecentGrpcConnectionsDropdown.tsx │ │ ├── RecentHttpResponsesDropdown.tsx │ │ ├── RecentRequestsDropdown.tsx │ │ ├── RecentWebsocketConnectionsDropdown.tsx │ │ ├── RedirectToLatestWorkspace.tsx │ │ ├── RequestBodyViewer.tsx │ │ ├── RequestMethodDropdown.tsx │ │ ├── ResizeHandle.tsx │ │ ├── ResponseCookies.tsx │ │ ├── ResponseHeaders.tsx │ │ ├── ResponseInfo.tsx │ │ ├── RouteError.tsx │ │ ├── SelectFile.tsx │ │ ├── Settings/ │ │ │ ├── Settings.tsx │ │ │ ├── SettingsCertificates.tsx │ │ │ ├── SettingsGeneral.tsx │ │ │ ├── SettingsHotkeys.tsx │ │ │ ├── SettingsInterface.tsx │ │ │ ├── SettingsLicense.tsx │ │ │ ├── SettingsPlugins.tsx │ │ │ ├── SettingsProxy.tsx │ │ │ └── SettingsTheme.tsx │ │ ├── SettingsDropdown.tsx │ │ ├── Sidebar.tsx │ │ ├── SidebarActions.tsx │ │ ├── SwitchWorkspaceDialog.tsx │ │ ├── SyncToFilesystemSetting.tsx │ │ ├── TemplateFunctionDialog.tsx │ │ ├── Toasts.tsx │ │ ├── UrlBar.tsx │ │ ├── UrlParameterEditor.tsx │ │ ├── WebsocketRequestLayout.tsx │ │ ├── WebsocketRequestPane.tsx │ │ ├── WebsocketResponsePane.tsx │ │ ├── WindowControls.tsx │ │ ├── Workspace.tsx │ │ ├── WorkspaceActionsDropdown.tsx │ │ ├── WorkspaceEncryptionSetting.tsx │ │ ├── WorkspaceHeader.tsx │ │ ├── WorkspaceSettingsDialog.tsx │ │ ├── core/ │ │ │ ├── Alert.tsx │ │ │ ├── AutoScroller.tsx │ │ │ ├── Banner.tsx │ │ │ ├── BulkPairEditor.tsx │ │ │ ├── Button.tsx │ │ │ ├── ButtonInfiniteLoading.tsx │ │ │ ├── Checkbox.tsx │ │ │ ├── ColorPicker.tsx │ │ │ ├── Confirm.tsx │ │ │ ├── CountBadge.tsx │ │ │ ├── DetailsBanner.tsx │ │ │ ├── Dialog.tsx │ │ │ ├── DismissibleBanner.tsx │ │ │ ├── Dropdown.tsx │ │ │ ├── Editor/ │ │ │ │ ├── BetterMatchDecorator.ts │ │ │ │ ├── DiffViewer.css │ │ │ │ ├── DiffViewer.tsx │ │ │ │ ├── Editor.css │ │ │ │ ├── Editor.tsx │ │ │ │ ├── LazyEditor.tsx │ │ │ │ ├── extensions.ts │ │ │ │ ├── filter/ │ │ │ │ │ ├── extension.ts │ │ │ │ │ ├── filter.grammar │ │ │ │ │ ├── filter.ts │ │ │ │ │ ├── highlight.ts │ │ │ │ │ └── query.ts │ │ │ │ ├── genericCompletion.ts │ │ │ │ ├── hyperlink/ │ │ │ │ │ └── extension.ts │ │ │ │ ├── json-lint.ts │ │ │ │ ├── pairs/ │ │ │ │ │ ├── extension.ts │ │ │ │ │ ├── highlight.ts │ │ │ │ │ ├── pairs.grammar │ │ │ │ │ ├── pairs.terms.ts │ │ │ │ │ └── pairs.ts │ │ │ │ ├── searchMatchCount.ts │ │ │ │ ├── singleLine.ts │ │ │ │ ├── text/ │ │ │ │ │ ├── extension.ts │ │ │ │ │ ├── text.grammar │ │ │ │ │ ├── text.terms.ts │ │ │ │ │ └── text.ts │ │ │ │ ├── timeline/ │ │ │ │ │ ├── extension.ts │ │ │ │ │ ├── highlight.ts │ │ │ │ │ ├── timeline.grammar │ │ │ │ │ ├── timeline.terms.ts │ │ │ │ │ └── timeline.ts │ │ │ │ ├── twig/ │ │ │ │ │ ├── completion.ts │ │ │ │ │ ├── extension.ts │ │ │ │ │ ├── highlight.ts │ │ │ │ │ ├── pathParameters.ts │ │ │ │ │ ├── templateTags.ts │ │ │ │ │ ├── twig.grammar │ │ │ │ │ ├── twig.terms.ts │ │ │ │ │ ├── twig.test.ts │ │ │ │ │ ├── twig.ts │ │ │ │ │ └── util.ts │ │ │ │ └── url/ │ │ │ │ ├── completion.ts │ │ │ │ ├── extension.ts │ │ │ │ ├── highlight.ts │ │ │ │ ├── url.grammar │ │ │ │ ├── url.terms.ts │ │ │ │ └── url.ts │ │ │ ├── EventViewer.tsx │ │ │ ├── EventViewerRow.tsx │ │ │ ├── FormattedError.tsx │ │ │ ├── Heading.tsx │ │ │ ├── Hotkey.tsx │ │ │ ├── HotkeyLabel.tsx │ │ │ ├── HotkeyList.tsx │ │ │ ├── HttpMethodTag.tsx │ │ │ ├── HttpResponseDurationTag.tsx │ │ │ ├── HttpStatusTag.tsx │ │ │ ├── Icon.tsx │ │ │ ├── IconButton.tsx │ │ │ ├── IconTooltip.tsx │ │ │ ├── InlineCode.tsx │ │ │ ├── Input.tsx │ │ │ ├── JsonAttributeTree.tsx │ │ │ ├── KeyValueRow.tsx │ │ │ ├── Label.tsx │ │ │ ├── Link.tsx │ │ │ ├── LoadingIcon.tsx │ │ │ ├── PairEditor.tsx │ │ │ ├── PairEditor.util.tsx │ │ │ ├── PairOrBulkEditor.tsx │ │ │ ├── PillButton.tsx │ │ │ ├── PlainInput.tsx │ │ │ ├── Prompt.tsx │ │ │ ├── RadioCards.tsx │ │ │ ├── RadioDropdown.tsx │ │ │ ├── SegmentedControl.tsx │ │ │ ├── Select.tsx │ │ │ ├── Separator.tsx │ │ │ ├── SizeTag.tsx │ │ │ ├── SplitLayout.tsx │ │ │ ├── Stacks.tsx │ │ │ ├── Table.tsx │ │ │ ├── Tabs/ │ │ │ │ └── Tabs.tsx │ │ │ ├── Toast.tsx │ │ │ ├── Tooltip.tsx │ │ │ ├── WebsocketStatusTag.tsx │ │ │ └── tree/ │ │ │ ├── Tree.tsx │ │ │ ├── TreeDragOverlay.tsx │ │ │ ├── TreeDropMarker.tsx │ │ │ ├── TreeIndentGuide.tsx │ │ │ ├── TreeItem.tsx │ │ │ ├── TreeItemList.tsx │ │ │ ├── atoms.ts │ │ │ ├── common.ts │ │ │ └── useSelectableItems.ts │ │ ├── git/ │ │ │ ├── BranchSelectionDialog.tsx │ │ │ ├── GitCommitDialog.tsx │ │ │ ├── GitDropdown.tsx │ │ │ ├── GitRemotesDialog.tsx │ │ │ ├── HistoryDialog.tsx │ │ │ ├── callbacks.tsx │ │ │ ├── credentials.tsx │ │ │ ├── diverged.tsx │ │ │ ├── git-util.ts │ │ │ ├── showAddRemoteDialog.tsx │ │ │ └── uncommitted.tsx │ │ ├── graphql/ │ │ │ ├── GraphQLDocsExplorer.tsx │ │ │ ├── GraphQLEditor.tsx │ │ │ └── graphqlAtoms.ts │ │ └── responseViewers/ │ │ ├── AudioViewer.tsx │ │ ├── BinaryViewer.tsx │ │ ├── CsvViewer.tsx │ │ ├── EventStreamViewer.tsx │ │ ├── HTMLOrTextViewer.tsx │ │ ├── ImageViewer.tsx │ │ ├── JsonViewer.tsx │ │ ├── MultipartViewer.tsx │ │ ├── PdfViewer.css │ │ ├── PdfViewer.tsx │ │ ├── SvgViewer.tsx │ │ ├── TextViewer.tsx │ │ ├── VideoViewer.tsx │ │ └── WebPageViewer.tsx │ ├── font-size.ts │ ├── font.ts │ ├── hooks/ │ │ ├── useActiveCookieJar.ts │ │ ├── useActiveEnvironment.ts │ │ ├── useActiveEnvironmentVariables.ts │ │ ├── useActiveFolder.ts │ │ ├── useActiveFolderId.ts │ │ ├── useActiveRequest.ts │ │ ├── useActiveRequestId.ts │ │ ├── useActiveWorkspace.ts │ │ ├── useActiveWorkspaceChangedToast.tsx │ │ ├── useAllRequests.ts │ │ ├── useAuthTab.tsx │ │ ├── useCancelHttpResponse.ts │ │ ├── useCheckForUpdates.tsx │ │ ├── useClickOutside.ts │ │ ├── useContainerQuery.ts │ │ ├── useCopyHttpResponse.ts │ │ ├── useCreateCookieJar.ts │ │ ├── useCreateDropdownItems.tsx │ │ ├── useCreateWorkspace.tsx │ │ ├── useDebouncedState.ts │ │ ├── useDebouncedValue.ts │ │ ├── useDeleteGrpcConnections.ts │ │ ├── useDeleteHttpResponses.ts │ │ ├── useDeleteSendHistory.tsx │ │ ├── useEnvironmentValueVisibility.ts │ │ ├── useEnvironmentVariables.ts │ │ ├── useEnvironmentsBreakdown.ts │ │ ├── useEventViewerKeyboard.ts │ │ ├── useExportData.tsx │ │ ├── useFastMutation.ts │ │ ├── useFloatingSidebarHidden.ts │ │ ├── useFolderActions.ts │ │ ├── useFormatText.ts │ │ ├── useGrpc.ts │ │ ├── useGrpcProtoFiles.ts │ │ ├── useGrpcRequestActions.ts │ │ ├── useHeadersTab.tsx │ │ ├── useHotKey.ts │ │ ├── useHttpAuthentication.ts │ │ ├── useHttpAuthenticationConfig.ts │ │ ├── useHttpRequestActions.ts │ │ ├── useHttpRequestBody.ts │ │ ├── useHttpResponseEvents.ts │ │ ├── useImportCurl.ts │ │ ├── useInheritedAuthentication.ts │ │ ├── useInheritedHeaders.ts │ │ ├── useInstallPlugin.ts │ │ ├── useIntrospectGraphQL.ts │ │ ├── useIsEncryptionEnabled.ts │ │ ├── useIsFullscreen.ts │ │ ├── useKeyValue.ts │ │ ├── useKeyboardEvent.ts │ │ ├── useLatestGrpcConnection.ts │ │ ├── useLatestHttpResponse.ts │ │ ├── useListenToTauriEvent.ts │ │ ├── useModelAncestors.ts │ │ ├── useParentFolders.ts │ │ ├── usePinnedGrpcConnection.ts │ │ ├── usePinnedHttpResponse.ts │ │ ├── usePinnedWebsocketConnection.ts │ │ ├── usePluginInfo.ts │ │ ├── usePlugins.ts │ │ ├── usePortal.ts │ │ ├── usePreferredAppearance.ts │ │ ├── useRandomKey.ts │ │ ├── useRecentCookieJars.ts │ │ ├── useRecentEnvironments.ts │ │ ├── useRecentRequests.ts │ │ ├── useRecentWorkspaces.ts │ │ ├── useRenderTemplate.ts │ │ ├── useRequestEditor.tsx │ │ ├── useRequestUpdateKey.ts │ │ ├── useResolvedAppearance.ts │ │ ├── useResolvedTheme.ts │ │ ├── useResponseBodyEventSource.ts │ │ ├── useResponseBodyText.ts │ │ ├── useResponseViewMode.ts │ │ ├── useSaveResponse.tsx │ │ ├── useScrollIntoView.ts │ │ ├── useSendAnyHttpRequest.ts │ │ ├── useSendManyRequests.ts │ │ ├── useShouldFloatSidebar.ts │ │ ├── useSidebarHidden.ts │ │ ├── useSidebarItemCollapsed.ts │ │ ├── useSidebarWidth.ts │ │ ├── useStateWithDeps.ts │ │ ├── useStoplightsVisible.ts │ │ ├── useSyncFontSizeSetting.ts │ │ ├── useSyncWorkspaceChildModels.ts │ │ ├── useSyncWorkspaceRequestTitle.ts │ │ ├── useSyncZoomSetting.ts │ │ ├── useTemplateFunctionConfig.ts │ │ ├── useTemplateFunctions.tsx │ │ ├── useTemplateTokensToString.ts │ │ ├── useTimedBoolean.ts │ │ ├── useTimelineViewMode.ts │ │ ├── useToggle.ts │ │ ├── useToggleCommandPalette.tsx │ │ ├── useWebsocketRequestActions.ts │ │ ├── useWindowFocus.ts │ │ ├── useWorkspaceActions.ts │ │ └── useZoom.ts │ ├── index.html │ ├── init/ │ │ └── sync.ts │ ├── lib/ │ │ ├── alert.ts │ │ ├── appInfo.ts │ │ ├── atoms/ │ │ │ └── atomWithKVStorage.ts │ │ ├── atoms.ts │ │ ├── capitalize.ts │ │ ├── clamp.ts │ │ ├── color.ts │ │ ├── confirm.ts │ │ ├── constants.ts │ │ ├── contentType.ts │ │ ├── copy.ts │ │ ├── createRequestAndNavigate.tsx │ │ ├── data/ │ │ │ ├── charsets.ts │ │ │ ├── connections.ts │ │ │ ├── encodings.ts │ │ │ ├── headerNames.ts │ │ │ └── mimetypes.ts │ │ ├── defaultHeaders.ts │ │ ├── deleteModelWithConfirm.tsx │ │ ├── dialog.ts │ │ ├── diffYaml.ts │ │ ├── dnd.ts │ │ ├── duplicateRequestOrFolderAndNavigate.tsx │ │ ├── editEnvironment.tsx │ │ ├── encryption.ts │ │ ├── fireAndForget.ts │ │ ├── formatters.ts │ │ ├── generateId.ts │ │ ├── getNodeText.ts │ │ ├── importData.tsx │ │ ├── initGlobalListeners.tsx │ │ ├── jotai.ts │ │ ├── jsonComments.ts │ │ ├── keyValueStore.ts │ │ ├── markdown.ts │ │ ├── minPromiseMillis.ts │ │ ├── model_util.test.ts │ │ ├── model_util.ts │ │ ├── pluralize.ts │ │ ├── prepareImportQuerystring.ts │ │ ├── prompt-form.tsx │ │ ├── prompt.ts │ │ ├── queryClient.ts │ │ ├── renameModelWithPrompt.tsx │ │ ├── resolvedModelName.ts │ │ ├── responseBody.ts │ │ ├── reveal.ts │ │ ├── router.ts │ │ ├── scopes.ts │ │ ├── sendEphemeralRequest.ts │ │ ├── setWorkspaceSearchParams.ts │ │ ├── settings.ts │ │ ├── setupOrConfigureEncryption.tsx │ │ ├── showColorPicker.tsx │ │ ├── sleep.ts │ │ ├── tauri.ts │ │ ├── theme/ │ │ │ ├── appearance.ts │ │ │ ├── themes.ts │ │ │ ├── window.ts │ │ │ └── yaakColor.ts │ │ ├── toast.tsx │ │ └── truncate.ts │ ├── main.css │ ├── main.tsx │ ├── modules.d.ts │ ├── package.json │ ├── postcss.config.cjs │ ├── routeTree.gen.ts │ ├── routes/ │ │ ├── __root.tsx │ │ ├── index.tsx │ │ └── workspaces/ │ │ ├── $workspaceId/ │ │ │ ├── index.tsx │ │ │ ├── requests/ │ │ │ │ └── $requestId.tsx │ │ │ └── settings.tsx │ │ └── index.tsx │ ├── tailwind.config.cjs │ ├── theme.ts │ ├── tsconfig.json │ ├── tsconfig.node.json │ ├── tsr.config.json │ ├── vite-env.d.ts │ └── vite.config.ts ├── tsconfig.json └── vite.config.ts
Showing preview only (368K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3944 symbols across 715 files)
FILE: crates-cli/yaak-cli/src/cli.rs
type Cli (line 15) | pub struct Cli {
type Commands (line 41) | pub enum Commands {
type SendArgs (line 82) | pub struct SendArgs {
type CookieJarArgs (line 97) | pub struct CookieJarArgs {
type CookieJarCommands (line 103) | pub enum CookieJarCommands {
type WorkspaceArgs (line 113) | pub struct WorkspaceArgs {
type WorkspaceCommands (line 119) | pub enum WorkspaceCommands {
type RequestArgs (line 175) | pub struct RequestArgs {
type RequestCommands (line 181) | pub enum RequestCommands {
type RequestSchemaType (line 255) | pub enum RequestSchemaType {
type LogLevel (line 262) | pub enum LogLevel {
method as_filter (line 271) | pub fn as_filter(self) -> log::LevelFilter {
type FolderArgs (line 284) | pub struct FolderArgs {
type FolderCommands (line 290) | pub enum FolderCommands {
type EnvironmentArgs (line 341) | pub struct EnvironmentArgs {
type EnvironmentCommands (line 347) | pub enum EnvironmentCommands {
type AuthArgs (line 412) | pub struct AuthArgs {
type AuthCommands (line 418) | pub enum AuthCommands {
type PluginArgs (line 431) | pub struct PluginArgs {
type PluginCommands (line 437) | pub enum PluginCommands {
type PluginPathArg (line 455) | pub struct PluginPathArg {
type GenerateArgs (line 461) | pub struct GenerateArgs {
type InstallPluginArgs (line 472) | pub struct InstallPluginArgs {
FILE: crates-cli/yaak-cli/src/commands/auth.rs
constant OAUTH_CLIENT_ID (line 16) | const OAUTH_CLIENT_ID: &str = "a1fe44800c2d7e803cad1b4bf07a291c";
constant KEYRING_USER (line 17) | const KEYRING_USER: &str = "yaak";
constant AUTH_TIMEOUT (line 18) | const AUTH_TIMEOUT: Duration = Duration::from_secs(300);
constant MAX_REQUEST_BYTES (line 19) | const MAX_REQUEST_BYTES: usize = 16 * 1024;
type CommandResult (line 21) | type CommandResult<T = ()> = std::result::Result<T, String>;
type Environment (line 24) | enum Environment {
method app_base_url (line 31) | fn app_base_url(self) -> &'static str {
method api_base_url (line 39) | fn api_base_url(self) -> &'static str {
method keyring_service (line 47) | fn keyring_service(self) -> &'static str {
type OAuthFlow (line 56) | struct OAuthFlow {
function run (line 65) | pub async fn run(args: AuthArgs) -> i32 {
function login (line 81) | async fn login() -> CommandResult {
function logout (line 122) | fn logout() -> CommandResult {
function whoami (line 128) | async fn whoami() -> CommandResult {
function current_environment (line 165) | fn current_environment() -> Environment {
function parse_environment (line 170) | fn parse_environment(value: Option<&str>) -> Environment {
function build_oauth_flow (line 178) | fn build_oauth_flow(environment: Environment, callback_port: u16) -> Com...
function receive_oauth_code (line 207) | async fn receive_oauth_code(
function parse_callback_request (line 241) | async fn parse_callback_request(stream: &mut TcpStream) -> CommandResult...
function read_http_target (line 284) | async fn read_http_target(stream: &mut TcpStream) -> CommandResult<Strin...
function write_bad_request (line 324) | async fn write_bad_request(stream: &mut TcpStream, message: &str) -> std...
function write_redirect (line 335) | async fn write_redirect(stream: &mut TcpStream, location: &str) -> std::...
function exchange_access_token (line 343) | async fn exchange_access_token(oauth: &OAuthFlow, code: &str) -> Command...
function keyring_entry (line 380) | fn keyring_entry(environment: Environment) -> CommandResult<Entry> {
function get_auth_token (line 385) | fn get_auth_token(environment: Environment) -> CommandResult<Option<Stri...
function store_auth_token (line 394) | fn store_auth_token(environment: Environment, token: &str) -> CommandRes...
function delete_auth_token (line 399) | fn delete_auth_token(environment: Environment) -> CommandResult {
function random_hex (line 407) | fn random_hex(bytes: usize) -> String {
function confirm_open_browser (line 413) | fn confirm_open_browser() -> CommandResult<bool> {
function environment_mapping (line 438) | fn environment_mapping() {
function parses_callback_request (line 446) | async fn parses_callback_request() {
function parse_callback_request_oauth_error (line 469) | async fn parse_callback_request_oauth_error() {
function receive_oauth_code_fails_fast_on_provider_error (line 492) | async fn receive_oauth_code_fails_fast_on_provider_error() {
function builds_oauth_flow_with_pkce (line 517) | fn builds_oauth_flow_with_pkce() {
FILE: crates-cli/yaak-cli/src/commands/cookie_jar.rs
type CommandResult (line 5) | type CommandResult<T = ()> = std::result::Result<T, String>;
function run (line 7) | pub fn run(ctx: &CliContext, args: CookieJarArgs) -> i32 {
function list (line 21) | fn list(ctx: &CliContext, workspace_id: Option<&str>) -> CommandResult {
FILE: crates-cli/yaak-cli/src/commands/environment.rs
type CommandResult (line 14) | type CommandResult<T = ()> = std::result::Result<T, String>;
function run (line 16) | pub fn run(ctx: &CliContext, args: EnvironmentArgs) -> i32 {
function schema (line 37) | fn schema(pretty: bool) -> CommandResult {
function list (line 49) | fn list(ctx: &CliContext, workspace_id: Option<&str>) -> CommandResult {
function show (line 66) | fn show(ctx: &CliContext, environment_id: &str) -> CommandResult {
function create (line 77) | fn create(
function update (line 144) | fn update(ctx: &CliContext, json: Option<String>, json_input: Option<Str...
function delete (line 163) | fn delete(ctx: &CliContext, environment_id: &str, yes: bool) -> CommandR...
FILE: crates-cli/yaak-cli/src/commands/folder.rs
type CommandResult (line 12) | type CommandResult<T = ()> = std::result::Result<T, String>;
function run (line 14) | pub fn run(ctx: &CliContext, args: FolderArgs) -> i32 {
function list (line 34) | fn list(ctx: &CliContext, workspace_id: Option<&str>) -> CommandResult {
function show (line 48) | fn show(ctx: &CliContext, folder_id: &str) -> CommandResult {
function create (line 57) | fn create(
function update (line 114) | fn update(ctx: &CliContext, json: Option<String>, json_input: Option<Str...
function delete (line 131) | fn delete(ctx: &CliContext, folder_id: &str, yes: bool) -> CommandResult {
FILE: crates-cli/yaak-cli/src/commands/plugin.rs
type CommandResult (line 27) | type CommandResult<T = ()> = std::result::Result<T, String>;
constant KEYRING_USER (line 29) | const KEYRING_USER: &str = "yaak";
type Environment (line 32) | enum Environment {
method api_base_url (line 39) | fn api_base_url(self) -> &'static str {
method keyring_service (line 47) | fn keyring_service(self) -> &'static str {
function run_build (line 56) | pub async fn run_build(args: PluginPathArg) -> i32 {
function run_install (line 66) | pub async fn run_install(context: &CliContext, args: InstallPluginArgs) ...
function run_dev (line 76) | pub async fn run_dev(args: PluginPathArg) -> i32 {
function run_generate (line 86) | pub async fn run_generate(args: GenerateArgs) -> i32 {
function run_publish (line 96) | pub async fn run_publish(args: PluginPathArg) -> i32 {
function build (line 106) | async fn build(args: PluginPathArg) -> CommandResult {
function dev (line 119) | async fn dev(args: PluginPathArg) -> CommandResult {
function generate (line 176) | fn generate(args: GenerateArgs) -> CommandResult {
function publish (line 218) | async fn publish(args: PluginPathArg) -> CommandResult {
function install (line 260) | async fn install(context: &CliContext, args: InstallPluginArgs) -> Comma...
function install_from_registry (line 273) | async fn install_from_registry(
function install_from_directory (line 300) | async fn install_from_directory(context: &CliContext, source: &str) -> C...
function parse_registry_install_spec (line 335) | fn parse_registry_install_spec(source: &str) -> Option<(String, Option<S...
type PublishResponse (line 368) | struct PublishResponse {
function build_plugin_bundle (line 373) | async fn build_plugin_bundle(plugin_dir: &Path) -> CommandResult<Vec<Str...
function prepare_build_output_dir (line 382) | fn prepare_build_output_dir(plugin_dir: &Path) -> CommandResult {
function bundler_options (line 392) | fn bundler_options(plugin_dir: &Path, watch: bool) -> BundlerOptions {
function resolve_plugin_dir (line 407) | fn resolve_plugin_dir(path: Option<PathBuf>) -> CommandResult<PathBuf> {
function ensure_plugin_build_inputs (line 428) | fn ensure_plugin_build_inputs(plugin_dir: &Path) -> CommandResult {
function create_publish_archive (line 445) | fn create_publish_archive(plugin_dir: &Path) -> CommandResult<Vec<u8>> {
function write_file (line 500) | fn write_file(path: &Path, contents: &str) -> CommandResult {
function prompt_with_default (line 508) | fn prompt_with_default(label: &str, default: &str) -> CommandResult<Stri...
function current_environment (line 523) | fn current_environment() -> Environment {
function keyring_entry (line 531) | fn keyring_entry(environment: Environment) -> CommandResult<Entry> {
function get_auth_token (line 536) | fn get_auth_token(environment: Environment) -> CommandResult<Option<Stri...
function random_name (line 545) | fn random_name() -> String {
constant TEMPLATE_GITIGNORE (line 560) | const TEMPLATE_GITIGNORE: &str = "node_modules\n";
constant TEMPLATE_PACKAGE_JSON (line 562) | const TEMPLATE_PACKAGE_JSON: &str = r#"{
constant TEMPLATE_TSCONFIG (line 581) | const TEMPLATE_TSCONFIG: &str = r#"{
constant TEMPLATE_README (line 604) | const TEMPLATE_README: &str = r#"# yaak-plugin-name
constant TEMPLATE_INDEX_TS (line 609) | const TEMPLATE_INDEX_TS: &str = r#"import type { PluginDefinition } from...
constant TEMPLATE_INDEX_TEST_TS (line 627) | const TEMPLATE_INDEX_TEST_TS: &str = r#"import { describe, expect, test ...
function publish_archive_includes_required_and_optional_files (line 647) | fn publish_archive_includes_required_and_optional_files() {
FILE: crates-cli/yaak-cli/src/commands/request.rs
type CommandResult (line 22) | type CommandResult<T = ()> = std::result::Result<T, String>;
function run (line 24) | pub async fn run(
function list (line 70) | fn list(ctx: &CliContext, workspace_id: Option<&str>) -> CommandResult {
function schema (line 86) | async fn schema(ctx: &CliContext, request_type: RequestSchemaType, prett...
function enrich_schema_guidance (line 110) | fn enrich_schema_guidance(schema: &mut Value, request_type: RequestSchem...
function append_description (line 127) | fn append_description(schema: &mut Map<String, Value>, extra: &str) {
function merge_auth_schema_from_plugins (line 141) | async fn merge_auth_schema_from_plugins(
function auth_variant_schema (line 193) | fn auth_variant_schema(auth_name: &str, auth_label: &str, args: &[FormIn...
function add_input_schema (line 215) | fn add_input_schema(
function add_base_schema (line 309) | fn add_base_schema(
function create (line 336) | fn create(
function update (line 401) | fn update(ctx: &CliContext, json: Option<String>, json_input: Option<Str...
function show (line 420) | fn show(ctx: &CliContext, request_id: &str) -> CommandResult {
function delete (line 429) | fn delete(ctx: &CliContext, request_id: &str, yes: bool) -> CommandResult {
function send_request_by_id (line 444) | pub async fn send_request_by_id(
function send_http_request_by_id (line 474) | async fn send_http_request_by_id(
function resolve_cookie_jar_id (line 531) | pub(crate) fn resolve_cookie_jar_id(
FILE: crates-cli/yaak-cli/src/commands/send.rs
type ExecutionMode (line 7) | enum ExecutionMode {
function run (line 12) | pub async fn run(
function send_target (line 28) | async fn send_target(
function collect_folder_request_ids (line 101) | fn collect_folder_request_ids(ctx: &CliContext, folder_id: &str) -> Resu...
function collect_workspace_request_ids (line 134) | fn collect_workspace_request_ids(
function send_many (line 170) | async fn send_many(
FILE: crates-cli/yaak-cli/src/commands/workspace.rs
type CommandResult (line 12) | type CommandResult<T = ()> = std::result::Result<T, String>;
function run (line 14) | pub fn run(ctx: &CliContext, args: WorkspaceArgs) -> i32 {
function schema (line 33) | fn schema(pretty: bool) -> CommandResult {
function list (line 45) | fn list(ctx: &CliContext) -> CommandResult {
function show (line 58) | fn show(ctx: &CliContext, workspace_id: &str) -> CommandResult {
function create (line 69) | fn create(
function update (line 107) | fn update(ctx: &CliContext, json: Option<String>, json_input: Option<Str...
function delete (line 126) | fn delete(ctx: &CliContext, workspace_id: &str, yes: bool) -> CommandRes...
FILE: crates-cli/yaak-cli/src/context.rs
constant EMBEDDED_PLUGIN_RUNTIME (line 14) | const EMBEDDED_PLUGIN_RUNTIME: &str = include_str!(concat!(
type CliExecutionContext (line 22) | pub struct CliExecutionContext {
type CliContext (line 29) | pub struct CliContext {
method new (line 39) | pub fn new(data_dir: PathBuf, app_id: &str) -> Self {
method init_plugins (line 62) | pub async fn init_plugins(&mut self, execution_context: CliExecutionCo...
method data_dir (line 107) | pub fn data_dir(&self) -> &Path {
method db (line 111) | pub fn db(&self) -> DbContext<'_> {
method query_manager (line 115) | pub fn query_manager(&self) -> &QueryManager {
method blob_manager (line 119) | pub fn blob_manager(&self) -> &BlobManager {
method plugin_manager (line 123) | pub fn plugin_manager(&self) -> Arc<PluginManager> {
method shutdown (line 127) | pub async fn shutdown(&self) {
function prepare_embedded_plugin_runtime (line 137) | fn prepare_embedded_plugin_runtime(data_dir: &Path) -> std::io::Result<P...
function prepare_embedded_vendored_plugins (line 145) | fn prepare_embedded_vendored_plugins(vendored_plugin_dir: &Path) -> std:...
FILE: crates-cli/yaak-cli/src/main.rs
function main (line 17) | async fn main() {
function resolve_send_execution_context (line 152) | fn resolve_send_execution_context(
function resolve_request_execution_context (line 197) | fn resolve_request_execution_context(
function resolve_cookie_jar_id (line 223) | fn resolve_cookie_jar_id(
function resolve_data_dir (line 242) | fn resolve_data_dir(app_id: &str) -> PathBuf {
function wsl_data_dir (line 250) | fn wsl_data_dir(app_id: &str) -> Option<PathBuf> {
FILE: crates-cli/yaak-cli/src/plugin_events.rs
type CliPluginEventBridge (line 34) | pub struct CliPluginEventBridge {
method start (line 49) | pub async fn start(
method shutdown (line 111) | pub async fn shutdown(self, plugin_manager: &PluginManager) {
type CliHostContext (line 39) | struct CliHostContext {
function build_plugin_reply (line 118) | async fn build_plugin_reply(
function render_json_value_for_cli (line 525) | async fn render_json_value_for_cli<T: TemplateCallback>(
function parse_cookie_name_value (line 536) | fn parse_cookie_name_value(raw_cookie: &str) -> Option<(String, String)> {
function copy_text_to_clipboard (line 542) | fn copy_text_to_clipboard(text: &str) -> Result<(), String> {
function prompt_text_for_cli (line 547) | fn prompt_text_for_cli(req: &PromptTextRequest) -> Result<Option<String>...
function prompt_form_for_cli (line 581) | fn prompt_form_for_cli(
type PromptOutcome (line 605) | enum PromptOutcome {
function prompt_form_input_for_cli (line 610) | fn prompt_form_input_for_cli(
type PromptValue (line 821) | enum PromptValue {
function prompt_text_with_inquire (line 826) | fn prompt_text_with_inquire(
function prompt_password_with_inquire (line 874) | fn prompt_password_with_inquire(
function prompt_editor_with_inquire (line 917) | fn prompt_editor_with_inquire(
function prompt_select_with_inquire (line 949) | fn prompt_select_with_inquire(
function prompt_confirm_with_inquire (line 980) | fn prompt_confirm_with_inquire(label: &str, default: bool) -> Result<Pro...
function prompt_message (line 990) | fn prompt_message(label: &str) -> String {
function prompt_label_for_base (line 994) | fn prompt_label_for_base(base: &yaak_plugins::events::FormInputBase) -> ...
FILE: crates-cli/yaak-cli/src/ui.rs
function info (line 4) | pub fn info(message: &str) {
function warning (line 12) | pub fn warning(message: &str) {
function warning_stderr (line 20) | pub fn warning_stderr(message: &str) {
function success (line 28) | pub fn success(message: &str) {
function error (line 36) | pub fn error(message: &str) {
FILE: crates-cli/yaak-cli/src/utils/confirm.rs
function confirm_delete (line 3) | pub fn confirm_delete(resource_name: &str, resource_id: &str) -> bool {
FILE: crates-cli/yaak-cli/src/utils/http.rs
function build_client (line 5) | pub fn build_client(session_token: Option<&str>) -> Result<Client, Strin...
function parse_api_error (line 23) | pub fn parse_api_error(status: u16, body: &str) -> String {
function user_agent (line 36) | fn user_agent() -> String {
function ua_platform (line 40) | fn ua_platform() -> &'static str {
FILE: crates-cli/yaak-cli/src/utils/json.rs
type JsonResult (line 5) | type JsonResult<T> = std::result::Result<T, String>;
function is_json_shorthand (line 7) | pub fn is_json_shorthand(input: &str) -> bool {
function parse_json_object (line 11) | pub fn parse_json_object(raw: &str, context: &str) -> JsonResult<Value> {
function parse_optional_json (line 22) | pub fn parse_optional_json(
function parse_required_json (line 37) | pub fn parse_required_json(
function require_id (line 46) | pub fn require_id(payload: &Value, context: &str) -> JsonResult<String> {
function validate_create_id (line 55) | pub fn validate_create_id(payload: &Value, context: &str) -> JsonResult<...
function merge_workspace_id_arg (line 66) | pub fn merge_workspace_id_arg(
function apply_merge_patch (line 90) | pub fn apply_merge_patch<T>(existing: &T, patch: &Value, id: &str, conte...
function merge_patch (line 107) | fn merge_patch(target: &mut Value, patch: &Value) {
FILE: crates-cli/yaak-cli/src/utils/schema.rs
function append_agent_hints (line 3) | pub fn append_agent_hints(schema: &mut Value) {
FILE: crates-cli/yaak-cli/src/utils/workspace.rs
function resolve_workspace_id (line 3) | pub fn resolve_workspace_id(
FILE: crates-cli/yaak-cli/src/version.rs
function cli_version (line 1) | pub fn cli_version() -> &'static str {
FILE: crates-cli/yaak-cli/src/version_check.rs
constant CACHE_FILE_NAME (line 10) | const CACHE_FILE_NAME: &str = "cli-version-check.json";
constant CHECK_INTERVAL_SECS (line 11) | const CHECK_INTERVAL_SECS: u64 = 24 * 60 * 60;
constant REQUEST_TIMEOUT (line 12) | const REQUEST_TIMEOUT: Duration = Duration::from_millis(800);
type VersionCheckResponse (line 16) | struct VersionCheckResponse {
type CacheRecord (line 24) | struct CacheRecord {
method default (line 32) | fn default() -> Self {
type VersionCheckRequest (line 44) | struct VersionCheckRequest<'a> {
function maybe_check_for_updates (line 52) | pub async fn maybe_check_for_updates() {
function should_skip_check (line 98) | fn should_skip_check() -> bool {
function fetch_version_check (line 112) | async fn fetch_version_check() -> Option<VersionCheckResponse> {
function release_channel (line 134) | fn release_channel(version: &str) -> String {
function install_source (line 142) | fn install_source() -> String {
function update_base_url (line 149) | fn update_base_url() -> &'static str {
function maybe_warn_outdated (line 156) | fn maybe_warn_outdated(record: &mut CacheRecord, now: u64) {
function default_upgrade_hint (line 175) | fn default_upgrade_hint() -> String {
function cache_path (line 187) | fn cache_path() -> PathBuf {
function environment_name (line 191) | fn environment_name() -> &'static str {
function read_cache (line 199) | fn read_cache(path: &Path) -> Option<CacheRecord> {
function write_cache (line 204) | fn write_cache(path: &Path, record: &CacheRecord) {
function is_expired (line 217) | fn is_expired(checked_at_epoch_secs: u64, now: u64) -> bool {
function unix_epoch_secs (line 221) | fn unix_epoch_secs() -> u64 {
FILE: crates-cli/yaak-cli/tests/common/http_server.rs
type TestHttpServer (line 8) | pub struct TestHttpServer {
method spawn_ok (line 16) | pub fn spawn_ok(body: &'static str) -> Self {
method drop (line 56) | fn drop(&mut self) {
FILE: crates-cli/yaak-cli/tests/common/mod.rs
function cli_cmd (line 12) | pub fn cli_cmd(data_dir: &Path) -> Command {
function parse_created_id (line 18) | pub fn parse_created_id(stdout: &[u8], label: &str) -> String {
function query_manager (line 26) | pub fn query_manager(data_dir: &Path) -> QueryManager {
function seed_workspace (line 34) | pub fn seed_workspace(data_dir: &Path, workspace_id: &str) {
function seed_request (line 48) | pub fn seed_request(data_dir: &Path, workspace_id: &str, request_id: &st...
function seed_folder (line 64) | pub fn seed_folder(data_dir: &Path, workspace_id: &str, folder_id: &str) {
function seed_grpc_request (line 78) | pub fn seed_grpc_request(data_dir: &Path, workspace_id: &str, request_id...
function seed_websocket_request (line 93) | pub fn seed_websocket_request(data_dir: &Path, workspace_id: &str, reque...
FILE: crates-cli/yaak-cli/tests/environment_commands.rs
function create_list_show_delete_round_trip (line 8) | fn create_list_show_delete_round_trip() {
function json_create_and_update_merge_patch_round_trip (line 49) | fn json_create_and_update_merge_patch_round_trip() {
function create_merges_positional_workspace_id_into_json_payload (line 83) | fn create_merges_positional_workspace_id_into_json_payload() {
function create_rejects_conflicting_workspace_ids_between_arg_and_json (line 109) | fn create_rejects_conflicting_workspace_ids_between_arg_and_json() {
function environment_schema_outputs_json_schema (line 131) | fn environment_schema_outputs_json_schema() {
FILE: crates-cli/yaak-cli/tests/folder_commands.rs
function create_list_show_delete_round_trip (line 8) | fn create_list_show_delete_round_trip() {
function json_create_and_update_merge_patch_round_trip (line 43) | fn json_create_and_update_merge_patch_round_trip() {
function create_merges_positional_workspace_id_into_json_payload (line 77) | fn create_merges_positional_workspace_id_into_json_payload() {
function create_rejects_conflicting_workspace_ids_between_arg_and_json (line 103) | fn create_rejects_conflicting_workspace_ids_between_arg_and_json() {
FILE: crates-cli/yaak-cli/tests/request_commands.rs
function show_and_delete_yes_round_trip (line 13) | fn show_and_delete_yes_round_trip() {
function delete_without_yes_fails_in_non_interactive_mode (line 50) | fn delete_without_yes_fails_in_non_interactive_mode() {
function json_create_and_update_merge_patch_round_trip (line 69) | fn json_create_and_update_merge_patch_round_trip() {
function update_requires_id_in_json_payload (line 103) | fn update_requires_id_in_json_payload() {
function create_allows_workspace_only_with_empty_defaults (line 115) | fn create_allows_workspace_only_with_empty_defaults() {
function create_merges_positional_workspace_id_into_json_payload (line 134) | fn create_merges_positional_workspace_id_into_json_payload() {
function create_rejects_conflicting_workspace_ids_between_arg_and_json (line 160) | fn create_rejects_conflicting_workspace_ids_between_arg_and_json() {
function request_send_persists_response_body_and_events (line 182) | fn request_send_persists_response_body_and_events() {
function request_schema_http_outputs_json_schema (line 231) | fn request_schema_http_outputs_json_schema() {
function request_schema_http_pretty_prints_with_flag (line 251) | fn request_schema_http_pretty_prints_with_flag() {
function request_send_grpc_returns_explicit_nyi_error (line 264) | fn request_send_grpc_returns_explicit_nyi_error() {
function request_send_websocket_returns_explicit_nyi_error (line 279) | fn request_send_websocket_returns_explicit_nyi_error() {
FILE: crates-cli/yaak-cli/tests/send_commands.rs
function top_level_send_workspace_sends_http_requests_and_prints_summary (line 11) | fn top_level_send_workspace_sends_http_requests_and_prints_summary() {
function top_level_send_folder_sends_http_requests_and_prints_summary (line 39) | fn top_level_send_folder_sends_http_requests_and_prints_summary() {
function top_level_send_unknown_id_fails_with_clear_error (line 69) | fn top_level_send_unknown_id_fails_with_clear_error() {
FILE: crates-cli/yaak-cli/tests/workspace_commands.rs
function create_show_delete_round_trip (line 8) | fn create_show_delete_round_trip() {
function json_create_and_update_merge_patch_round_trip (line 33) | fn json_create_and_update_merge_patch_round_trip() {
function workspace_schema_outputs_json_schema (line 62) | fn workspace_schema_outputs_json_schema() {
FILE: crates-tauri/yaak-app/bindings/gen_watch.ts
type WatchResult (line 3) | type WatchResult = { unlistenEvent: string, };
FILE: crates-tauri/yaak-app/bindings/index.ts
type PluginUpdateInfo (line 3) | type PluginUpdateInfo = { name: string, currentVersion: string, latestVe...
type PluginUpdateNotification (line 5) | type PluginUpdateNotification = { updateCount: number, plugins: Array<Pl...
type UpdateInfo (line 7) | type UpdateInfo = { replyEventId: string, version: string, downloaded: b...
type UpdateResponse (line 9) | type UpdateResponse = { "type": "ack" } | { "type": "action", action: Up...
type UpdateResponseAction (line 11) | type UpdateResponseAction = "install" | "skip";
type WatchResult (line 13) | type WatchResult = { unlistenEvent: string, };
type YaakNotification (line 15) | type YaakNotification = { timestamp: string, timeout: number | null, id:...
type YaakNotificationAction (line 17) | type YaakNotificationAction = { label: string, url: string, };
FILE: crates-tauri/yaak-app/bindings/plugins_ext.ts
type PluginUpdateInfo (line 3) | type PluginUpdateInfo = { name: string, currentVersion: string, latestVe...
type PluginUpdateNotification (line 5) | type PluginUpdateNotification = { updateCount: number, plugins: Array<Pl...
FILE: crates-tauri/yaak-app/build.rs
function main (line 1) | fn main() {
FILE: crates-tauri/yaak-app/src/commands.rs
type EncryptionManagerExt (line 15) | pub trait EncryptionManagerExt<'a, R> {
method crypto (line 16) | fn crypto(&'a self) -> State<'a, EncryptionManager>;
method crypto (line 20) | fn crypto(&'a self) -> State<'a, EncryptionManager> {
function cmd_decrypt_template (line 26) | pub(crate) async fn cmd_decrypt_template<R: Runtime>(
function cmd_secure_template (line 36) | pub(crate) async fn cmd_secure_template<R: Runtime>(
function cmd_get_themes (line 53) | pub(crate) async fn cmd_get_themes<R: Runtime>(
function cmd_enable_encryption (line 61) | pub(crate) async fn cmd_enable_encryption<R: Runtime>(
function cmd_reveal_workspace_key (line 71) | pub(crate) async fn cmd_reveal_workspace_key<R: Runtime>(
function cmd_set_workspace_key (line 79) | pub(crate) async fn cmd_set_workspace_key<R: Runtime>(
function cmd_disable_encryption (line 89) | pub(crate) async fn cmd_disable_encryption<R: Runtime>(
function cmd_default_headers (line 98) | pub(crate) fn cmd_default_headers() -> Vec<HttpRequestHeader> {
FILE: crates-tauri/yaak-app/src/encoding.rs
function read_response_body (line 6) | pub async fn read_response_body(body_path: impl AsRef<Path>, content_typ...
function parse_charset (line 17) | fn parse_charset(content_type: &str) -> Option<String> {
FILE: crates-tauri/yaak-app/src/error.rs
type Error (line 6) | pub enum Error {
method serialize (line 70) | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::E...
type Result (line 78) | pub type Result<T> = std::result::Result<T, Error>;
FILE: crates-tauri/yaak-app/src/git_ext.rs
function cmd_git_checkout (line 19) | pub async fn cmd_git_checkout(dir: &Path, branch: &str, force: bool) -> ...
function cmd_git_branch (line 24) | pub async fn cmd_git_branch(dir: &Path, branch: &str, base: Option<&str>...
function cmd_git_delete_branch (line 29) | pub async fn cmd_git_delete_branch(
function cmd_git_delete_remote_branch (line 38) | pub async fn cmd_git_delete_remote_branch(dir: &Path, branch: &str) -> R...
function cmd_git_merge_branch (line 43) | pub async fn cmd_git_merge_branch(dir: &Path, branch: &str) -> Result<()> {
function cmd_git_rename_branch (line 48) | pub async fn cmd_git_rename_branch(dir: &Path, old_name: &str, new_name:...
function cmd_git_status (line 53) | pub async fn cmd_git_status(dir: &Path) -> Result<GitStatusSummary> {
function cmd_git_log (line 58) | pub async fn cmd_git_log(dir: &Path) -> Result<Vec<GitCommit>> {
function cmd_git_initialize (line 63) | pub async fn cmd_git_initialize(dir: &Path) -> Result<()> {
function cmd_git_clone (line 68) | pub async fn cmd_git_clone(url: &str, dir: &Path) -> Result<CloneResult> {
function cmd_git_commit (line 73) | pub async fn cmd_git_commit(dir: &Path, message: &str) -> Result<()> {
function cmd_git_fetch_all (line 78) | pub async fn cmd_git_fetch_all(dir: &Path) -> Result<()> {
function cmd_git_push (line 83) | pub async fn cmd_git_push(dir: &Path) -> Result<PushResult> {
function cmd_git_pull (line 88) | pub async fn cmd_git_pull(dir: &Path) -> Result<PullResult> {
function cmd_git_pull_force_reset (line 93) | pub async fn cmd_git_pull_force_reset(
function cmd_git_pull_merge (line 102) | pub async fn cmd_git_pull_merge(dir: &Path, remote: &str, branch: &str) ...
function cmd_git_add (line 107) | pub async fn cmd_git_add(dir: &Path, rela_paths: Vec<PathBuf>) -> Result...
function cmd_git_unstage (line 115) | pub async fn cmd_git_unstage(dir: &Path, rela_paths: Vec<PathBuf>) -> Re...
function cmd_git_reset_changes (line 123) | pub async fn cmd_git_reset_changes(dir: &Path) -> Result<()> {
function cmd_git_add_credential (line 128) | pub async fn cmd_git_add_credential(
function cmd_git_remotes (line 137) | pub async fn cmd_git_remotes(dir: &Path) -> Result<Vec<GitRemote>> {
function cmd_git_add_remote (line 142) | pub async fn cmd_git_add_remote(dir: &Path, name: &str, url: &str) -> Re...
function cmd_git_rm_remote (line 147) | pub async fn cmd_git_rm_remote(dir: &Path, name: &str) -> Result<()> {
FILE: crates-tauri/yaak-app/src/grpc.rs
function metadata_to_map (line 13) | pub(crate) fn metadata_to_map(metadata: MetadataMap) -> BTreeMap<String,...
function resolve_grpc_request (line 24) | pub(crate) fn resolve_grpc_request<R: Runtime>(
function build_metadata (line 41) | pub(crate) async fn build_metadata<R: Runtime>(
FILE: crates-tauri/yaak-app/src/history.rs
constant NAMESPACE (line 8) | const NAMESPACE: &str = "analytics";
constant NUM_LAUNCHES_KEY (line 9) | const NUM_LAUNCHES_KEY: &str = "num_launches";
constant LAST_VERSION_KEY (line 10) | const LAST_VERSION_KEY: &str = "last_tracked_version";
constant PREV_VERSION_KEY (line 11) | const PREV_VERSION_KEY: &str = "last_tracked_version_prev";
constant VERSION_SINCE_KEY (line 12) | const VERSION_SINCE_KEY: &str = "last_tracked_version_since";
type LaunchEventInfo (line 15) | pub struct LaunchEventInfo {
function get_or_upsert_launch_info (line 26) | pub fn get_or_upsert_launch_info<R: Runtime>(app_handle: &AppHandle<R>) ...
FILE: crates-tauri/yaak-app/src/http_request.rs
type ResponseContext (line 21) | struct ResponseContext<R: Runtime> {
function new (line 28) | fn new(app_handle: AppHandle<R>, response: HttpResponse, update_source: ...
function is_persisted (line 33) | fn is_persisted(&self) -> bool {
function update (line 40) | fn update<F>(&mut self, func: F) -> Result<()>
function response (line 60) | fn response(&self) -> &HttpResponse {
function send_http_request (line 65) | pub async fn send_http_request<R: Runtime>(
function send_http_request_with_context (line 85) | pub async fn send_http_request_with_context<R: Runtime>(
function send_http_request_inner (line 131) | async fn send_http_request_inner<R: Runtime>(
function resolve_http_request (line 171) | pub fn resolve_http_request<R: Runtime>(
FILE: crates-tauri/yaak-app/src/import.rs
function import_data (line 16) | pub(crate) async fn import_data<R: Runtime>(
FILE: crates-tauri/yaak-app/src/lib.rs
type PluginContextExt (line 87) | pub trait PluginContextExt<R: Runtime> {
method plugin_context (line 88) | fn plugin_context(&self) -> PluginContext;
function plugin_context (line 92) | fn plugin_context(&self) -> PluginContext {
type AppMetaData (line 99) | struct AppMetaData {
function cmd_metadata (line 113) | async fn cmd_metadata(app_handle: AppHandle) -> YaakResult<AppMetaData> {
function detect_cli_version (line 134) | async fn detect_cli_version() -> Option<String> {
function detect_cli_version_for_binary (line 138) | async fn detect_cli_version_for_binary(program: &str) -> Option<String> {
function cmd_template_tokens_to_string (line 153) | async fn cmd_template_tokens_to_string<R: Runtime>(
function cmd_render_template (line 171) | async fn cmd_render_template<R: Runtime>(
function cmd_dismiss_notification (line 205) | async fn cmd_dismiss_notification<R: Runtime>(
function cmd_grpc_reflect (line 214) | async fn cmd_grpc_reflect<R: Runtime>(
function cmd_grpc_go (line 273) | async fn cmd_grpc_go<R: Runtime>(
function cmd_restart (line 836) | async fn cmd_restart<R: Runtime>(app_handle: AppHandle<R>) -> YaakResult...
function cmd_send_ephemeral_request (line 842) | async fn cmd_send_ephemeral_request<R: Runtime>(
function cmd_format_json (line 871) | async fn cmd_format_json(text: &str) -> YaakResult<String> {
function cmd_format_graphql (line 876) | async fn cmd_format_graphql(text: &str) -> YaakResult<String> {
function cmd_http_response_body (line 884) | async fn cmd_http_response_body<R: Runtime>(
function cmd_http_request_body (line 918) | async fn cmd_http_request_body<R: Runtime>(
function cmd_get_sse_events (line 935) | async fn cmd_get_sse_events(file_path: &str) -> YaakResult<Vec<ServerSen...
function cmd_get_http_response_events (line 956) | async fn cmd_get_http_response_events<R: Runtime>(
function cmd_import_data (line 965) | async fn cmd_import_data<R: Runtime>(
function cmd_http_request_actions (line 973) | async fn cmd_http_request_actions<R: Runtime>(
function cmd_websocket_request_actions (line 981) | async fn cmd_websocket_request_actions<R: Runtime>(
function cmd_call_websocket_request_action (line 989) | async fn cmd_call_websocket_request_action<R: Runtime>(
function cmd_workspace_actions (line 1007) | async fn cmd_workspace_actions<R: Runtime>(
function cmd_call_workspace_action (line 1015) | async fn cmd_call_workspace_action<R: Runtime>(
function cmd_folder_actions (line 1030) | async fn cmd_folder_actions<R: Runtime>(
function cmd_call_folder_action (line 1038) | async fn cmd_call_folder_action<R: Runtime>(
function cmd_grpc_request_actions (line 1053) | async fn cmd_grpc_request_actions<R: Runtime>(
function cmd_template_function_summaries (line 1061) | async fn cmd_template_function_summaries<R: Runtime>(
function cmd_template_function_config (line 1070) | async fn cmd_template_function_config<R: Runtime>(
function cmd_get_http_authentication_summaries (line 1084) | async fn cmd_get_http_authentication_summaries<R: Runtime>(
function cmd_get_http_authentication_config (line 1094) | async fn cmd_get_http_authentication_config<R: Runtime>(
function cmd_call_http_request_action (line 1149) | async fn cmd_call_http_request_action<R: Runtime>(
function cmd_call_grpc_request_action (line 1169) | async fn cmd_call_grpc_request_action<R: Runtime>(
function cmd_call_http_authentication_action (line 1189) | async fn cmd_call_http_authentication_action<R: Runtime>(
function cmd_curl_to_request (line 1245) | async fn cmd_curl_to_request<R: Runtime>(
function cmd_export_data (line 1267) | async fn cmd_export_data<R: Runtime>(
function cmd_save_response (line 1294) | async fn cmd_save_response<R: Runtime>(
function cmd_send_http_request (line 1309) | async fn cmd_send_http_request<R: Runtime>(
function cmd_reload_plugins (line 1382) | async fn cmd_reload_plugins<R: Runtime>(
function cmd_plugin_info (line 1395) | async fn cmd_plugin_info<R: Runtime>(
function cmd_delete_all_grpc_connections (line 1409) | async fn cmd_delete_all_grpc_connections<R: Runtime>(
function cmd_delete_send_history (line 1421) | async fn cmd_delete_send_history<R: Runtime>(
function cmd_delete_all_http_responses (line 1436) | async fn cmd_delete_all_http_responses<R: Runtime>(
function cmd_get_workspace_meta (line 1448) | async fn cmd_get_workspace_meta<R: Runtime>(
function cmd_new_child_window (line 1458) | async fn cmd_new_child_window(
function cmd_new_main_window (line 1470) | async fn cmd_new_main_window(app_handle: AppHandle, url: &str) -> YaakRe...
function cmd_check_for_updates (line 1476) | async fn cmd_check_for_updates<R: Runtime>(
function run (line 1490) | pub fn run() {
function get_update_mode (line 1815) | async fn get_update_mode<R: Runtime>(window: &WebviewWindow<R>) -> YaakR...
function safe_uri (line 1820) | fn safe_uri(endpoint: &str) -> String {
function monitor_plugin_events (line 1828) | fn monitor_plugin_events<R: Runtime>(app_handle: &AppHandle<R>) {
function call_frontend (line 1878) | async fn call_frontend<R: Runtime>(
function get_window_from_plugin_context (line 1903) | fn get_window_from_plugin_context<R: Runtime>(
function workspace_from_window (line 1931) | fn workspace_from_window<R: Runtime>(window: &WebviewWindow<R>) -> Optio...
function environment_from_window (line 1935) | fn environment_from_window<R: Runtime>(window: &WebviewWindow<R>) -> Opt...
function cookie_jar_from_window (line 1939) | fn cookie_jar_from_window<R: Runtime>(window: &WebviewWindow<R>) -> Opti...
FILE: crates-tauri/yaak-app/src/main.rs
function main (line 3) | fn main() {
FILE: crates-tauri/yaak-app/src/models_ext.rs
constant MODEL_CHANGES_RETENTION_HOURS (line 20) | const MODEL_CHANGES_RETENTION_HOURS: i64 = 1;
constant MODEL_CHANGES_POLL_INTERVAL_MS (line 21) | const MODEL_CHANGES_POLL_INTERVAL_MS: u64 = 1000;
constant MODEL_CHANGES_POLL_BATCH_SIZE (line 22) | const MODEL_CHANGES_POLL_BATCH_SIZE: usize = 200;
type ModelChangeCursor (line 24) | struct ModelChangeCursor {
method from_launch_time (line 30) | fn from_launch_time() -> Self {
function drain_model_changes_batch (line 38) | fn drain_model_changes_batch<R: Runtime>(
function run_model_change_poller (line 77) | async fn run_model_change_poller<R: Runtime>(
type QueryManagerExt (line 89) | pub trait QueryManagerExt<'a, R> {
method db_manager (line 90) | fn db_manager(&'a self) -> State<'a, QueryManager>;
method db (line 91) | fn db(&'a self) -> DbContext<'a>;
method with_tx (line 92) | fn with_tx<F, T>(&'a self, func: F) -> Result<T>
method db_manager (line 98) | fn db_manager(&'a self) -> State<'a, QueryManager> {
method db (line 102) | fn db(&'a self) -> DbContext<'a> {
method with_tx (line 107) | fn with_tx<F, T>(&'a self, func: F) -> Result<T>
type BlobManagerExt (line 117) | pub trait BlobManagerExt<'a, R> {
method blob_manager (line 118) | fn blob_manager(&'a self) -> State<'a, BlobManager>;
method blobs (line 119) | fn blobs(&'a self) -> yaak_models::blob_manager::BlobContext;
method blob_manager (line 123) | fn blob_manager(&'a self) -> State<'a, BlobManager> {
method blobs (line 127) | fn blobs(&'a self) -> yaak_models::blob_manager::BlobContext {
function models_upsert (line 137) | pub(crate) fn models_upsert<R: Runtime>(
function models_delete (line 166) | pub(crate) fn models_delete<R: Runtime>(
function models_duplicate (line 195) | pub(crate) fn models_duplicate<R: Runtime>(
function models_websocket_events (line 218) | pub(crate) fn models_websocket_events<R: Runtime>(
function models_grpc_events (line 226) | pub(crate) fn models_grpc_events<R: Runtime>(
function models_get_settings (line 234) | pub(crate) fn models_get_settings<R: Runtime>(app_handle: tauri::AppHand...
function models_get_graphql_introspection (line 239) | pub(crate) fn models_get_graphql_introspection<R: Runtime>(
function models_upsert_graphql_introspection (line 247) | pub(crate) fn models_upsert_graphql_introspection<R: Runtime>(
function models_workspace_models (line 259) | pub(crate) async fn models_workspace_models<R: Runtime>(
function escape_str_for_webview (line 302) | fn escape_str_for_webview(input: &str) -> String {
function init (line 326) | pub fn init<R: Runtime>() -> TauriPlugin<R> {
FILE: crates-tauri/yaak-app/src/notifications.rs
constant MAX_UPDATE_CHECK_SECONDS (line 16) | const MAX_UPDATE_CHECK_SECONDS: u64 = 60 * 60;
constant KV_NAMESPACE (line 18) | const KV_NAMESPACE: &str = "notifications";
constant KV_KEY (line 19) | const KV_KEY: &str = "seen";
type YaakNotifier (line 22) | pub struct YaakNotifier {
method new (line 48) | pub fn new() -> Self {
method seen (line 52) | pub async fn seen<R: Runtime>(&mut self, window: &WebviewWindow<R>, id...
method maybe_check (line 67) | pub async fn maybe_check<R: Runtime>(&mut self, window: &WebviewWindow...
type YaakNotification (line 29) | pub struct YaakNotification {
type YaakNotificationAction (line 42) | pub struct YaakNotificationAction {
function get_kv (line 138) | async fn get_kv<R: Runtime>(app_handle: &AppHandle<R>) -> Result<Vec<Str...
function get_updater_status (line 146) | fn get_updater_status<R: Runtime>(app_handle: &AppHandle<R>) -> &'static...
FILE: crates-tauri/yaak-app/src/plugin_events.rs
function handle_plugin_event (line 39) | pub(crate) async fn handle_plugin_event<R: Runtime>(
function handle_host_plugin_request (line 77) | async fn handle_host_plugin_request<R: Runtime>(
FILE: crates-tauri/yaak-app/src/plugins_ext.rs
constant MAX_UPDATE_CHECK_HOURS (line 42) | const MAX_UPDATE_CHECK_HOURS: u64 = 12;
type PluginUpdater (line 44) | pub struct PluginUpdater {
method new (line 66) | pub fn new() -> Self {
method check_now (line 70) | pub async fn check_now<R: Runtime>(&mut self, window: &WebviewWindow<R...
method maybe_check (line 118) | pub async fn maybe_check<R: Runtime>(&mut self, window: &WebviewWindow...
type PluginUpdateNotification (line 51) | pub struct PluginUpdateNotification {
type PluginUpdateInfo (line 59) | pub struct PluginUpdateInfo {
function cmd_plugins_search (line 136) | pub async fn cmd_plugins_search<R: Runtime>(
function cmd_plugins_install (line 146) | pub async fn cmd_plugins_install<R: Runtime>(
function cmd_plugins_install_from_directory (line 169) | pub async fn cmd_plugins_install_from_directory<R: Runtime>(
function cmd_plugins_uninstall (line 191) | pub async fn cmd_plugins_uninstall<R: Runtime>(
function cmd_plugin_init_errors (line 202) | pub async fn cmd_plugin_init_errors(
function cmd_plugins_updates (line 209) | pub async fn cmd_plugins_updates<R: Runtime>(
function cmd_plugins_update_all (line 219) | pub async fn cmd_plugins_update_all<R: Runtime>(
function init (line 268) | pub fn init<R: Runtime>() -> TauriPlugin<R> {
FILE: crates-tauri/yaak-app/src/render.rs
function render_template (line 7) | pub async fn render_template<T: TemplateCallback>(
function render_json_value (line 17) | pub async fn render_json_value<T: TemplateCallback>(
FILE: crates-tauri/yaak-app/src/sync_ext.rs
function cmd_sync_calculate (line 23) | pub(crate) async fn cmd_sync_calculate<R: Runtime>(
function cmd_sync_calculate_fs (line 44) | pub(crate) async fn cmd_sync_calculate_fs(dir: &Path) -> Result<Vec<Sync...
function cmd_sync_apply (line 51) | pub(crate) async fn cmd_sync_apply<R: Runtime>(
type WatchResult (line 66) | pub(crate) struct WatchResult {
function cmd_sync_watch (line 71) | pub(crate) async fn cmd_sync_watch<R: Runtime>(
FILE: crates-tauri/yaak-app/src/updates.rs
constant MAX_UPDATE_CHECK_HOURS_STABLE (line 24) | const MAX_UPDATE_CHECK_HOURS_STABLE: u64 = 12;
constant MAX_UPDATE_CHECK_HOURS_BETA (line 25) | const MAX_UPDATE_CHECK_HOURS_BETA: u64 = 3;
constant MAX_UPDATE_CHECK_HOURS_ALPHA (line 26) | const MAX_UPDATE_CHECK_HOURS_ALPHA: u64 = 1;
type YaakUpdater (line 29) | pub struct YaakUpdater {
method new (line 67) | pub fn new() -> Self {
method check_now (line 71) | pub async fn check_now<R: Runtime>(
method maybe_check (line 175) | pub async fn maybe_check<R: Runtime>(
type UpdateMode (line 33) | pub enum UpdateMode {
method new (line 51) | pub fn new(mode: &str) -> UpdateMode {
method fmt (line 40) | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
type UpdateTrigger (line 61) | pub enum UpdateTrigger {
type UpdateInfo (line 205) | struct UpdateInfo {
type UpdateResponse (line 214) | enum UpdateResponse {
type UpdateResponseAction (line 222) | enum UpdateResponseAction {
function finish_integrated_update (line 227) | async fn finish_integrated_update<R: Runtime>(window: &WebviewWindow<R>,...
function start_integrated_update (line 233) | async fn start_integrated_update<R: Runtime>(
function start_native_update (line 308) | async fn start_native_update<R: Runtime>(window: &WebviewWindow<R>, upda...
function download_update_idempotent (line 344) | pub async fn download_update_idempotent<R: Runtime>(
function detect_install_mode (line 366) | fn detect_install_mode() -> Option<&'static str> {
function install_update_maybe_download (line 381) | pub async fn install_update_maybe_download<R: Runtime>(
function ensure_download_path (line 391) | pub fn ensure_download_path<R: Runtime>(
FILE: crates-tauri/yaak-app/src/uri_scheme.rs
function handle_deep_link (line 17) | pub(crate) async fn handle_deep_link<R: Runtime>(
FILE: crates-tauri/yaak-app/src/window.rs
constant DEFAULT_WINDOW_WIDTH (line 13) | const DEFAULT_WINDOW_WIDTH: f64 = 1100.0;
constant DEFAULT_WINDOW_HEIGHT (line 14) | const DEFAULT_WINDOW_HEIGHT: f64 = 600.0;
constant MIN_WINDOW_WIDTH (line 16) | const MIN_WINDOW_WIDTH: f64 = 300.0;
constant MIN_WINDOW_HEIGHT (line 17) | const MIN_WINDOW_HEIGHT: f64 = 300.0;
constant MAIN_WINDOW_PREFIX (line 19) | pub(crate) const MAIN_WINDOW_PREFIX: &str = "main_";
constant OTHER_WINDOW_PREFIX (line 20) | const OTHER_WINDOW_PREFIX: &str = "other_";
type CreateWindowConfig (line 23) | pub(crate) struct CreateWindowConfig<'s> {
function create_window (line 35) | pub(crate) fn create_window<R: Runtime>(
function create_main_window (line 193) | pub(crate) fn create_main_window(handle: &AppHandle, url: &str) -> Resul...
function create_child_window (line 221) | pub(crate) fn create_child_window(
FILE: crates-tauri/yaak-app/src/window_menu.rs
function app_menu (line 8) | pub fn app_menu<R: Runtime>(app_handle: &AppHandle<R>) -> tauri::Result<...
FILE: crates-tauri/yaak-app/src/ws_ext.rs
function cmd_ws_delete_connections (line 33) | pub async fn cmd_ws_delete_connections<R: Runtime>(
function cmd_ws_send (line 45) | pub async fn cmd_ws_send<R: Runtime>(
function cmd_ws_close (line 98) | pub async fn cmd_ws_close<R: Runtime>(
function cmd_ws_connect (line 122) | pub async fn cmd_ws_connect<R: Runtime>(
function resolve_websocket_request (line 415) | fn resolve_websocket_request<R: Runtime>(
function convert_ws_url_to_http (line 434) | fn convert_ws_url_to_http(ws_url: &Url) -> Url {
FILE: crates-tauri/yaak-fonts/bindings/gen_fonts.ts
type Fonts (line 3) | type Fonts = { editorFonts: Array<string>, uiFonts: Array<string>, };
FILE: crates-tauri/yaak-fonts/build.rs
constant COMMANDS (line 1) | const COMMANDS: &[&str] = &["list"];
function main (line 3) | fn main() {
FILE: crates-tauri/yaak-fonts/index.ts
function listFonts (line 5) | async function listFonts() {
function useFonts (line 9) | function useFonts() {
FILE: crates-tauri/yaak-fonts/src/commands.rs
type Fonts (line 11) | pub struct Fonts {
function list (line 17) | pub(crate) async fn list() -> Result<Fonts> {
FILE: crates-tauri/yaak-fonts/src/error.rs
type Error (line 4) | pub enum Error {}
method serialize (line 7) | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::E...
type Result (line 15) | pub type Result<T> = std::result::Result<T, Error>;
FILE: crates-tauri/yaak-fonts/src/lib.rs
function init (line 13) | pub fn init<R: Runtime>() -> TauriPlugin<R> {
FILE: crates-tauri/yaak-license/bindings/gen_models.ts
type CheckActivationRequestPayload (line 3) | type CheckActivationRequestPayload = { appVersion: string, appPlatform: ...
FILE: crates-tauri/yaak-license/bindings/license.ts
type APIErrorResponsePayload (line 3) | type APIErrorResponsePayload = { error: string, message: string, };
type ActivateLicenseRequestPayload (line 5) | type ActivateLicenseRequestPayload = { licenseKey: string, appVersion: s...
type ActivateLicenseResponsePayload (line 7) | type ActivateLicenseResponsePayload = { activationId: string, };
type DeactivateLicenseRequestPayload (line 9) | type DeactivateLicenseRequestPayload = { appVersion: string, appPlatform...
type LicenseCheckStatus (line 11) | type LicenseCheckStatus = { "status": "personal_use", "data": { trial_en...
FILE: crates-tauri/yaak-license/bindings/models.ts
type CheckActivationRequestPayload (line 3) | type CheckActivationRequestPayload = { activationId: string, };
FILE: crates-tauri/yaak-license/build.rs
constant COMMANDS (line 1) | const COMMANDS: &[&str] = &["activate", "deactivate", "check"];
function main (line 3) | fn main() {
FILE: crates-tauri/yaak-license/index.ts
constant CHECK_QUERY_KEY (line 10) | const CHECK_QUERY_KEY = ["license.check"];
function useLicense (line 12) | function useLicense() {
FILE: crates-tauri/yaak-license/src/commands.rs
function check (line 6) | pub async fn check<R: Runtime>(window: WebviewWindow<R>) -> Result<Licen...
function activate (line 11) | pub async fn activate<R: Runtime>(license_key: &str, window: WebviewWind...
function deactivate (line 16) | pub async fn deactivate<R: Runtime>(window: WebviewWindow<R>) -> Result<...
FILE: crates-tauri/yaak-license/src/error.rs
type Error (line 5) | pub enum Error {
method serialize (line 26) | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::E...
type Result (line 34) | pub type Result<T> = std::result::Result<T, Error>;
FILE: crates-tauri/yaak-license/src/lib.rs
function init (line 13) | pub fn init<R: Runtime>() -> TauriPlugin<R> {
FILE: crates-tauri/yaak-license/src/license.rs
type QueryManagerExt (line 18) | trait QueryManagerExt<'a, R> {
method db (line 19) | fn db(&'a self) -> DbContext<'a>;
method db (line 23) | fn db(&'a self) -> DbContext<'a> {
constant KV_NAMESPACE (line 29) | const KV_NAMESPACE: &str = "license";
constant KV_ACTIVATION_ID_KEY (line 30) | const KV_ACTIVATION_ID_KEY: &str = "activation_id";
constant TRIAL_SECONDS (line 31) | const TRIAL_SECONDS: u64 = 3600 * 24 * 30;
type CheckActivationRequestPayload (line 36) | pub struct CheckActivationRequestPayload {
type ActivateLicenseRequestPayload (line 44) | pub struct ActivateLicenseRequestPayload {
type DeactivateLicenseRequestPayload (line 53) | pub struct DeactivateLicenseRequestPayload {
type ActivateLicenseResponsePayload (line 61) | pub struct ActivateLicenseResponsePayload {
type APIErrorResponsePayload (line 68) | pub struct APIErrorResponsePayload {
type LicenseCheckStatus (line 76) | pub enum LicenseCheckStatus {
function activate_license (line 116) | pub async fn activate_license<R: Runtime>(
function deactivate_license (line 154) | pub async fn deactivate_license<R: Runtime>(window: &WebviewWindow<R>) -...
function check_license (line 188) | pub async fn check_license<R: Runtime>(window: &WebviewWindow<R>) -> Res...
function build_url (line 232) | fn build_url(path: &str) -> String {
function get_activation_id (line 240) | pub async fn get_activation_id<R: Runtime>(app_handle: &AppHandle<R>) ->...
FILE: crates-tauri/yaak-mac-window/build.rs
constant COMMANDS (line 1) | const COMMANDS: &[&str] = &["set_title", "set_theme"];
function main (line 3) | fn main() {
FILE: crates-tauri/yaak-mac-window/index.ts
function setWindowTitle (line 3) | function setWindowTitle(title: string) {
function setWindowTheme (line 7) | function setWindowTheme(bgColor: string) {
FILE: crates-tauri/yaak-mac-window/src/commands.rs
function set_title (line 4) | pub(crate) fn set_title<R: Runtime>(window: Window<R>, title: &str) {
function set_theme (line 18) | pub(crate) fn set_theme<R: Runtime>(window: Window<R>, bg_color: &str) {
FILE: crates-tauri/yaak-mac-window/src/lib.rs
type AppHandleMacWindowExt (line 10) | pub trait AppHandleMacWindowExt {
method set_native_titlebar (line 12) | fn set_native_titlebar(&self, enable: bool);
method set_native_titlebar (line 16) | fn set_native_titlebar(&self, enable: bool) {
type PluginState (line 23) | pub(crate) struct PluginState {
function init (line 27) | pub fn init<R: Runtime>() -> TauriPlugin<R> {
FILE: crates-tauri/yaak-mac-window/src/mac.rs
type UnsafeWindowHandle (line 7) | struct UnsafeWindowHandle(*mut std::ffi::c_void);
constant WINDOW_CONTROL_PAD_X (line 13) | const WINDOW_CONTROL_PAD_X: f64 = 13.0;
constant WINDOW_CONTROL_PAD_Y (line 14) | const WINDOW_CONTROL_PAD_Y: f64 = 18.0;
constant TITLEBAR_EXTRA_HEIGHT (line 19) | const TITLEBAR_EXTRA_HEIGHT: f64 = 4.0;
constant MAIN_WINDOW_PREFIX (line 20) | const MAIN_WINDOW_PREFIX: &str = "main_";
function update_window_title (line 22) | pub(crate) fn update_window_title<R: Runtime>(window: Window<R>, title: ...
function update_window_theme (line 50) | pub(crate) fn update_window_theme<R: Runtime>(window: Window<R>, color: ...
function position_traffic_lights (line 87) | fn position_traffic_lights(ns_window_handle: UnsafeWindowHandle, x: f64,...
type WindowState (line 143) | struct WindowState<R: Runtime> {
function setup_traffic_light_positioner (line 147) | pub fn setup_traffic_light_positioner<R: Runtime>(window: &Window<R>) {
FILE: crates-tauri/yaak-tauri-utils/src/window.rs
type WorkspaceWindowTrait (line 4) | pub trait WorkspaceWindowTrait {
method workspace_id (line 5) | fn workspace_id(&self) -> Option<String>;
method cookie_jar_id (line 6) | fn cookie_jar_id(&self) -> Option<String>;
method environment_id (line 7) | fn environment_id(&self) -> Option<String>;
method request_id (line 8) | fn request_id(&self) -> Option<String>;
method workspace_id (line 12) | fn workspace_id(&self) -> Option<String> {
method cookie_jar_id (line 21) | fn cookie_jar_id(&self) -> Option<String> {
method environment_id (line 27) | fn environment_id(&self) -> Option<String> {
method request_id (line 33) | fn request_id(&self) -> Option<String> {
FILE: crates/yaak-api/src/error.rs
type Error (line 4) | pub enum Error {
type Result (line 9) | pub type Result<T> = std::result::Result<T, Error>;
FILE: crates/yaak-api/src/lib.rs
type ApiClientKind (line 12) | pub enum ApiClientKind {
function yaak_api_client (line 21) | pub fn yaak_api_client(kind: ApiClientKind, version: &str) -> Result<Cli...
function get_system_proxy_url (line 60) | pub fn get_system_proxy_url() -> Option<String> {
function get_enabled_system_proxy (line 65) | fn get_enabled_system_proxy() -> Option<sysproxy::Sysproxy> {
FILE: crates/yaak-common/src/command.rs
constant CREATE_NO_WINDOW (line 6) | const CREATE_NO_WINDOW: u32 = 0x0800_0000;
function new_xplatform_command (line 9) | pub fn new_xplatform_command<S: AsRef<OsStr>>(program: S) -> tokio::proc...
function new_checked_command (line 21) | pub async fn new_checked_command<S: AsRef<OsStr>>(
FILE: crates/yaak-common/src/platform.rs
type OperatingSystem (line 3) | pub enum OperatingSystem {
function get_os (line 10) | pub fn get_os() -> OperatingSystem {
function get_os_str (line 22) | pub fn get_os_str() -> &'static str {
function get_ua_platform (line 31) | pub fn get_ua_platform() -> &'static str {
function get_ua_arch (line 43) | pub fn get_ua_arch() -> &'static str {
FILE: crates/yaak-common/src/serde.rs
function get_bool (line 4) | pub fn get_bool(v: &Value, key: &str, fallback: bool) -> bool {
function get_str (line 11) | pub fn get_str<'a>(v: &'a Value, key: &str) -> &'a str {
function get_str_map (line 18) | pub fn get_str_map<'a>(v: &'a BTreeMap<String, Value>, key: &str) -> &'a...
function get_bool_map (line 25) | pub fn get_bool_map(v: &BTreeMap<String, Value>, key: &str, fallback: bo...
FILE: crates/yaak-core/src/context.rs
type WorkspaceContext (line 8) | pub struct WorkspaceContext {
method new (line 16) | pub fn new() -> Self {
method with_workspace (line 20) | pub fn with_workspace(mut self, workspace_id: impl Into<String>) -> Se...
method with_environment (line 25) | pub fn with_environment(mut self, environment_id: impl Into<String>) -...
method with_cookie_jar (line 30) | pub fn with_cookie_jar(mut self, cookie_jar_id: impl Into<String>) -> ...
method with_request (line 35) | pub fn with_request(mut self, request_id: impl Into<String>) -> Self {
type AppContext (line 45) | pub trait AppContext: Send + Sync + Clone {
method app_data_dir (line 48) | fn app_data_dir(&self) -> PathBuf;
method app_identifier (line 52) | fn app_identifier(&self) -> &str;
method is_dev (line 55) | fn is_dev(&self) -> bool;
FILE: crates/yaak-core/src/error.rs
type Result (line 3) | pub type Result<T> = std::result::Result<T, Error>;
type Error (line 6) | pub enum Error {
FILE: crates/yaak-crypto/index.ts
function enableEncryption (line 3) | function enableEncryption(workspaceId: string) {
function revealWorkspaceKey (line 7) | function revealWorkspaceKey(workspaceId: string) {
function setWorkspaceKey (line 11) | function setWorkspaceKey(args: { workspaceId: string; key: string }) {
function disableEncryption (line 15) | function disableEncryption(workspaceId: string) {
FILE: crates/yaak-crypto/src/encryption.rs
constant ENCRYPTION_TAG (line 7) | const ENCRYPTION_TAG: &str = "yA4k3nC";
constant ENCRYPTION_VERSION (line 8) | const ENCRYPTION_VERSION: u8 = 1;
function encrypt_data (line 10) | pub(crate) fn encrypt_data(data: &[u8], key: &Key<XChaCha20Poly1305>) ->...
function decrypt_data (line 24) | pub(crate) fn decrypt_data(cipher_data: &[u8], key: &Key<XChaCha20Poly13...
function test_encrypt_decrypt (line 53) | fn test_encrypt_decrypt() -> Result<()> {
function test_decrypt_empty (line 62) | fn test_decrypt_empty() -> Result<()> {
function test_decrypt_bad_version (line 72) | fn test_decrypt_bad_version() -> Result<()> {
function test_decrypt_bad_tag (line 82) | fn test_decrypt_bad_tag() -> Result<()> {
function test_decrypt_unencrypted_data (line 92) | fn test_decrypt_unencrypted_data() -> Result<()> {
FILE: crates/yaak-crypto/src/error.rs
type Error (line 6) | pub enum Error {
method serialize (line 42) | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::E...
type Result (line 50) | pub type Result<T> = std::result::Result<T, Error>;
FILE: crates/yaak-crypto/src/manager.rs
constant KEY_USER (line 16) | const KEY_USER: &str = "encryption-key";
type EncryptionManager (line 19) | pub struct EncryptionManager {
method new (line 27) | pub fn new(query_manager: QueryManager, app_id: impl Into<String>) -> ...
method encrypt (line 36) | pub fn encrypt(&self, workspace_id: &str, data: &[u8]) -> Result<Vec<u...
method decrypt (line 41) | pub fn decrypt(&self, workspace_id: &str, data: &[u8]) -> Result<Vec<u...
method reveal_workspace_key (line 46) | pub fn reveal_workspace_key(&self, workspace_id: &str) -> Result<Strin...
method set_human_key (line 51) | pub fn set_human_key(&self, workspace_id: &str, human_key: &str) -> Re...
method set_workspace_key (line 72) | pub(crate) fn set_workspace_key(
method ensure_workspace_key (line 104) | pub fn ensure_workspace_key(&self, workspace_id: &str) -> Result<Works...
method disable_encryption (line 118) | pub fn disable_encryption(&self, workspace_id: &str) -> Result<()> {
method get_workspace_key (line 147) | fn get_workspace_key(&self, workspace_id: &str) -> Result<WorkspaceKey> {
method get_master_key (line 175) | fn get_master_key(&self) -> Result<MasterKey> {
FILE: crates/yaak-crypto/src/master_key.rs
constant HUMAN_PREFIX (line 10) | const HUMAN_PREFIX: &str = "YKM_";
type MasterKey (line 13) | pub(crate) struct MasterKey {
method get_or_create (line 18) | pub(crate) fn get_or_create(app_id: &str, user: &str) -> Result<Self> {
method encrypt (line 43) | pub(crate) fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
method decrypt (line 47) | pub(crate) fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
method test_key (line 52) | pub(crate) fn test_key() -> Self {
function test_master_key (line 66) | fn test_master_key() -> Result<()> {
FILE: crates/yaak-crypto/src/workspace_key.rs
type WorkspaceKey (line 9) | pub struct WorkspaceKey {
method to_human (line 16) | pub(crate) fn to_human(&self) -> Result<String> {
method from_human (line 30) | pub(crate) fn from_human(human_key: &str) -> Result<Self> {
method from_raw_key (line 41) | pub(crate) fn from_raw_key(key: &[u8]) -> Self {
method raw_key (line 45) | pub(crate) fn raw_key(&self) -> &[u8] {
method create (line 49) | pub(crate) fn create() -> Result<Self> {
method encrypt (line 54) | pub(crate) fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
method decrypt (line 58) | pub(crate) fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>> {
method test_key (line 63) | pub(crate) fn test_key() -> Self {
constant HUMAN_PREFIX (line 13) | const HUMAN_PREFIX: &str = "YK";
function test_persisted_key (line 75) | fn test_persisted_key() -> Result<()> {
function test_human_format (line 84) | fn test_human_format() -> Result<()> {
function test_from_human_invalid (line 101) | fn test_from_human_invalid() -> Result<()> {
FILE: crates/yaak-git/bindings/gen_git.ts
type BranchDeleteResult (line 4) | type BranchDeleteResult = { "type": "success", message: string, } | { "t...
type CloneResult (line 6) | type CloneResult = { "type": "success" } | { "type": "cancelled" } | { "...
type GitAuthor (line 8) | type GitAuthor = { name: string | null, email: string | null, };
type GitCommit (line 10) | type GitCommit = { author: GitAuthor, when: string, message: string | nu...
type GitRemote (line 12) | type GitRemote = { name: string, url: string | null, };
type GitStatus (line 14) | type GitStatus = "untracked" | "conflict" | "current" | "modified" | "re...
type GitStatusEntry (line 16) | type GitStatusEntry = { relaPath: string, status: GitStatus, staged: boo...
type GitStatusSummary (line 18) | type GitStatusSummary = { path: string, headRef: string | null, headRefS...
type PullResult (line 20) | type PullResult = { "type": "success", message: string, } | { "type": "u...
type PushResult (line 22) | type PushResult = { "type": "success", message: string, } | { "type": "u...
FILE: crates/yaak-git/bindings/gen_models.ts
type DnsOverride (line 3) | type DnsOverride = { hostname: string, ipv4: Array<string>, ipv6: Array<...
type Environment (line 5) | type Environment = { model: "environment", id: string, workspaceId: stri...
type EnvironmentVariable (line 7) | type EnvironmentVariable = { enabled?: boolean, name: string, value: str...
type Folder (line 9) | type Folder = { model: "folder", id: string, createdAt: string, updatedA...
type GrpcRequest (line 11) | type GrpcRequest = { model: "grpc_request", id: string, createdAt: strin...
type HttpRequest (line 13) | type HttpRequest = { model: "http_request", id: string, createdAt: strin...
type HttpRequestHeader (line 15) | type HttpRequestHeader = { enabled?: boolean, name: string, value: strin...
type HttpUrlParameter (line 17) | type HttpUrlParameter = { enabled?: boolean, name: string, value: string...
type SyncModel (line 19) | type SyncModel = { "type": "workspace" } & Workspace | { "type": "enviro...
type WebsocketRequest (line 21) | type WebsocketRequest = { model: "websocket_request", id: string, create...
type Workspace (line 23) | type Workspace = { model: "workspace", id: string, createdAt: string, up...
FILE: crates/yaak-git/index.ts
type GitCredentials (line 20) | interface GitCredentials {
type DivergedStrategy (line 25) | type DivergedStrategy = "force_reset" | "merge" | "cancel";
type UncommittedChangesStrategy (line 27) | type UncommittedChangesStrategy = "reset" | "cancel";
type GitCallbacks (line 29) | interface GitCallbacks {
function useGit (line 41) | function useGit(dir: string, callbacks: GitCallbacks, refreshKey?: strin...
method mutationFn (line 181) | async mutationFn() {
function getRemotes (line 256) | async function getRemotes(dir: string) {
function gitClone (line 263) | async function gitClone(
FILE: crates/yaak-git/src/add.rs
function git_add (line 7) | pub fn git_add(dir: &Path, rela_path: &Path) -> Result<()> {
FILE: crates/yaak-git/src/binary.rs
function new_binary_command (line 8) | pub(crate) async fn new_binary_command(dir: &Path) -> Result<Command> {
function new_binary_command_global (line 15) | pub(crate) async fn new_binary_command_global() -> Result<Command> {
FILE: crates/yaak-git/src/branch.rs
type BranchDeleteResult (line 12) | pub enum BranchDeleteResult {
function git_checkout_branch (line 17) | pub async fn git_checkout_branch(dir: &Path, branch_name: &str, force: b...
function git_create_branch (line 44) | pub async fn git_create_branch(dir: &Path, name: &str, base: Option<&str...
function git_delete_branch (line 65) | pub async fn git_delete_branch(dir: &Path, name: &str, force: bool) -> R...
function git_merge_branch (line 89) | pub async fn git_merge_branch(dir: &Path, name: &str) -> Result<()> {
function git_delete_remote_branch (line 114) | pub async fn git_delete_remote_branch(dir: &Path, name: &str) -> Result<...
function git_rename_branch (line 136) | pub async fn git_rename_branch(dir: &Path, old_name: &str, new_name: &st...
FILE: crates/yaak-git/src/clone.rs
type CloneResult (line 13) | pub enum CloneResult {
function git_clone (line 19) | pub async fn git_clone(url: &str, dir: &Path) -> Result<CloneResult> {
FILE: crates/yaak-git/src/commit.rs
function git_commit (line 6) | pub async fn git_commit(dir: &Path, message: &str) -> crate::error::Resu...
FILE: crates/yaak-git/src/credential.rs
function git_add_credential (line 8) | pub async fn git_add_credential(remote_url: &str, username: &str, passwo...
FILE: crates/yaak-git/src/error.rs
type Error (line 8) | pub enum Error {
method serialize (line 56) | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::E...
type Result (line 64) | pub type Result<T> = std::result::Result<T, Error>;
FILE: crates/yaak-git/src/fetch.rs
function git_fetch_all (line 6) | pub async fn git_fetch_all(dir: &Path) -> Result<()> {
FILE: crates/yaak-git/src/init.rs
function git_init (line 6) | pub fn git_init(dir: &Path) -> Result<()> {
FILE: crates/yaak-git/src/log.rs
type GitCommit (line 10) | pub struct GitCommit {
type GitAuthor (line 19) | pub struct GitAuthor {
function git_log (line 24) | pub fn git_log(dir: &Path) -> crate::error::Result<Vec<GitCommit>> {
function convert_git_time_to_date (line 65) | fn convert_git_time_to_date(_git_time: git2::Time) -> DateTime<Utc> {
function convert_git_time_to_date (line 70) | fn convert_git_time_to_date(git_time: git2::Time) -> DateTime<Utc> {
FILE: crates/yaak-git/src/pull.rs
type PullResult (line 14) | pub enum PullResult {
function has_uncommitted_changes (line 22) | fn has_uncommitted_changes(dir: &Path) -> Result<bool> {
function git_pull (line 30) | pub async fn git_pull(dir: &Path) -> Result<PullResult> {
function git_pull_force_reset (line 112) | pub async fn git_pull_force_reset(dir: &Path, remote: &str, branch: &str...
function git_pull_merge (line 144) | pub async fn git_pull_merge(dir: &Path, remote: &str, branch: &str) -> R...
FILE: crates/yaak-git/src/push.rs
type PushResult (line 14) | pub enum PushResult {
function git_push (line 20) | pub async fn git_push(dir: &Path) -> Result<PushResult> {
FILE: crates/yaak-git/src/remotes.rs
type GitRemote (line 10) | pub struct GitRemote {
function git_remotes (line 15) | pub fn git_remotes(dir: &Path) -> Result<Vec<GitRemote>> {
function git_add_remote (line 37) | pub fn git_add_remote(dir: &Path, name: &str, url: &str) -> Result<GitRe...
function git_rm_remote (line 43) | pub fn git_rm_remote(dir: &Path, name: &str) -> Result<()> {
FILE: crates/yaak-git/src/repository.rs
function open_repo (line 4) | pub(crate) fn open_repo(dir: &Path) -> crate::error::Result<git2::Reposi...
FILE: crates/yaak-git/src/reset.rs
function git_reset_changes (line 6) | pub async fn git_reset_changes(dir: &Path) -> Result<()> {
FILE: crates/yaak-git/src/status.rs
type GitStatusSummary (line 13) | pub struct GitStatusSummary {
type GitStatusEntry (line 28) | pub struct GitStatusEntry {
type GitStatus (line 39) | pub enum GitStatus {
function git_status (line 49) | pub fn git_status(dir: &Path) -> crate::error::Result<GitStatusSummary> {
FILE: crates/yaak-git/src/unstage.rs
function git_unstage (line 5) | pub fn git_unstage(dir: &Path, rela_path: &Path) -> crate::error::Result...
FILE: crates/yaak-git/src/util.rs
constant DEFAULT_REMOTE_NAME (line 5) | const DEFAULT_REMOTE_NAME: &str = "origin";
function get_current_branch (line 7) | pub(crate) fn get_current_branch(repo: &Repository) -> Result<Option<Bra...
function get_current_branch_name (line 17) | pub(crate) fn get_current_branch_name(repo: &Repository) -> Result<Strin...
function local_branch_names (line 25) | pub(crate) fn local_branch_names(repo: &Repository) -> Result<Vec<String...
function remote_branch_names (line 36) | pub(crate) fn remote_branch_names(repo: &Repository) -> Result<Vec<Strin...
function bytes_to_string (line 50) | pub(crate) fn bytes_to_string(bytes: &[u8]) -> Result<String> {
function get_default_remote_for_push_in_repo (line 54) | pub(crate) fn get_default_remote_for_push_in_repo(repo: &'_ Repository) ...
function get_default_remote_name_for_push_in_repo (line 60) | pub(crate) fn get_default_remote_name_for_push_in_repo(repo: &Repository...
function get_default_remote_in_repo (line 88) | pub(crate) fn get_default_remote_in_repo(repo: &'_ Repository) -> Result...
function get_default_remote_name_in_repo (line 94) | pub(crate) fn get_default_remote_name_in_repo(repo: &Repository) -> Resu...
FILE: crates/yaak-grpc/src/any.rs
function collect_any_types (line 3) | pub(crate) fn collect_any_types(json: &str, out: &mut Vec<String>) {
function collect_any_types_value (line 14) | fn collect_any_types_value(json: &serde_json::Value, out: &mut Vec<Strin...
function test_collect_any_types (line 40) | fn test_collect_any_types() {
FILE: crates/yaak-grpc/src/client.rs
type AutoReflectionClient (line 25) | pub struct AutoReflectionClient<T = Client<HttpsConnector<HttpConnector>...
method new (line 32) | pub fn new(
method send_reflection_request (line 49) | pub async fn send_reflection_request(
function to_v1_msg_response (line 119) | fn to_v1_msg_response(
function to_v1alpha_request (line 152) | fn to_v1alpha_request(request: ServerReflectionRequest) -> v1alpha::Serv...
function to_v1alpha_msg_request (line 159) | fn to_v1alpha_msg_request(
FILE: crates/yaak-grpc/src/codec.rs
type DynamicCodec (line 7) | pub struct DynamicCodec(MethodDescriptor);
method new (line 11) | pub fn new(md: MethodDescriptor) -> Self {
type Encode (line 17) | type Encode = DynamicMessage;
type Decode (line 18) | type Decode = DynamicMessage;
type Encoder (line 19) | type Encoder = Self;
type Decoder (line 20) | type Decoder = Self;
method encoder (line 22) | fn encoder(&mut self) -> Self::Encoder {
method decoder (line 26) | fn decoder(&mut self) -> Self::Decoder {
type Item (line 32) | type Item = DynamicMessage;
type Error (line 33) | type Error = Status;
method encode (line 35) | fn encode(&mut self, item: Self::Item, dst: &mut EncodeBuf<'_>) -> Resul...
type Item (line 42) | type Item = DynamicMessage;
type Error (line 43) | type Error = Status;
method decode (line 45) | fn decode(&mut self, src: &mut DecodeBuf<'_>) -> Result<Option<Self::Ite...
FILE: crates/yaak-grpc/src/error.rs
type Error (line 10) | pub enum Error {
method serialize (line 43) | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::E...
type Result (line 51) | pub type Result<T> = std::result::Result<T, Error>;
FILE: crates/yaak-grpc/src/json_schema.rs
function message_to_json_schema (line 4) | pub fn message_to_json_schema(_: &DescriptorPool, root_msg: MessageDescr...
type JsonSchemaGenerator (line 8) | struct JsonSchemaGenerator {
method new (line 13) | pub fn new() -> Self {
method generate_json_schema (line 17) | pub fn generate_json_schema(msg: MessageDescriptor) -> JsonSchemaEntry {
method add_message (line 22) | fn add_message(&mut self, msg: &MessageDescriptor) {
method scan_root (line 30) | pub fn scan_root(mut self, root_msg: MessageDescriptor) -> JsonSchemaE...
method fill_properties (line 42) | fn fill_properties(&mut self, root_msg: MessageDescriptor) {
method init_structure (line 130) | fn init_structure(&mut self, root_msg: MessageDescriptor) {
function field_to_type_or_ref (line 186) | fn field_to_type_or_ref(root_name: &str, field: FieldDescriptor) -> Json...
function is_message_field (line 234) | fn is_message_field(field: &FieldDescriptor) -> Option<MessageDescriptor> {
type JsonSchemaEntry (line 243) | pub struct JsonSchemaEntry {
method add_property (line 281) | pub fn add_property(&mut self, name: String, entry: JsonSchemaEntry) {
method add_required (line 288) | pub fn add_required(&mut self, name: String) {
method object (line 297) | pub fn object() -> Self {
method boolean (line 300) | pub fn boolean() -> Self {
method number (line 303) | pub fn number<S: Into<String>>(format: S) -> Self {
method string (line 310) | pub fn string() -> Self {
method string_with_format (line 314) | pub fn string_with_format<S: Into<String>>(format: S) -> Self {
method reference (line 321) | pub fn reference<S: AsRef<str>>(ref_: S) -> Self {
method root_reference (line 324) | pub fn root_reference() -> Self {
method array (line 327) | pub fn array(item: JsonSchemaEntry) -> Self {
method enums (line 334) | pub fn enums(enums: Vec<String>) -> Self {
method map (line 338) | pub fn map(value_type: JsonSchemaEntry) -> Self {
method null (line 346) | pub fn null() -> Self {
type JsonType (line 351) | enum JsonType {
method serialize (line 368) | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S:...
method default (line 362) | fn default() -> Self {
FILE: crates/yaak-grpc/src/lib.rs
function serialize_options (line 17) | pub fn serialize_options() -> SerializeOptions {
type ServiceDefinition (line 23) | pub struct ServiceDefinition {
type MethodDefinition (line 30) | pub struct MethodDefinition {
function serialize_message (line 40) | pub fn serialize_message(msg: &DynamicMessage) -> Result<String, String> {
function deserialize_message (line 48) | pub fn deserialize_message(msg: &str, method: MethodDescriptor) -> Resul...
FILE: crates/yaak-grpc/src/manager.rs
type GrpcConnection (line 33) | pub struct GrpcConnection {
method method (line 70) | pub async fn method(&self, service: &str, method: &str) -> Result<Meth...
method service (line 79) | async fn service(&self, service: &str) -> Result<ServiceDescriptor> {
method unary (line 87) | pub async fn unary(
method streaming (line 118) | pub async fn streaming<F>(
method client_streaming (line 184) | pub async fn client_streaming<F>(
method server_streaming (line 253) | pub async fn server_streaming(
type GrpcStreamError (line 41) | pub struct GrpcStreamError {
method from (line 58) | fn from(value: String) -> Self {
method from (line 64) | fn from(s: Status) -> Self {
method fmt (line 49) | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
type GrpcConfig (line 281) | pub struct GrpcConfig {
type GrpcHandle (line 288) | pub struct GrpcHandle {
method new (line 294) | pub fn new(config: GrpcConfig) -> Self {
method invalidate_pool (line 302) | pub fn invalidate_pool(&mut self, id: &str, uri: &str, proto_files: &V...
method reflect (line 307) | pub async fn reflect(
method services (line 335) | pub async fn services(
method services_from_pool (line 357) | fn services_from_pool(&self, pool: &DescriptorPool) -> Vec<ServiceDefi...
method connect (line 380) | pub async fn connect(
method get_pool (line 410) | fn get_pool(&self, id: &str, uri: &str, proto_files: &Vec<PathBuf>) ->...
function decorate_req (line 415) | pub(crate) fn decorate_req<T>(
function uri_from_str (line 426) | fn uri_from_str(uri_str: &str) -> Result<Uri> {
function make_pool_key (line 436) | fn make_pool_key(id: &str, uri: &str, proto_files: &Vec<PathBuf>) -> Str...
FILE: crates/yaak-grpc/src/reflection.rs
function fill_pool_from_files (line 27) | pub async fn fill_pool_from_files(
function fill_pool_from_reflection (line 117) | pub async fn fill_pool_from_reflection(
function list_services (line 140) | async fn list_services(
function file_descriptor_set_from_service_name (line 155) | async fn file_descriptor_set_from_service_name(
function reflect_types_for_message (line 189) | pub(crate) async fn reflect_types_for_message(
function add_file_descriptors_to_pool (line 237) | pub(crate) async fn add_file_descriptors_to_pool(
function file_descriptor_set_by_filename (line 267) | async fn file_descriptor_set_by_filename(
function method_desc_to_path (line 300) | pub fn method_desc_to_path(md: &MethodDescriptor) -> PathAndQuery {
type SimpleTopoSort (line 312) | pub struct SimpleTopoSort<T> {
function new (line 321) | pub fn new() -> Self {
function insert (line 325) | pub fn insert<I: IntoIterator<Item = T>>(&mut self, node: T, deps: I) {
type Item (line 338) | type Item = <SimpleTopoSortIter<T> as Iterator>::Item;
type IntoIter (line 339) | type IntoIter = SimpleTopoSortIter<T>;
method into_iter (line 341) | fn into_iter(self) -> Self::IntoIter {
type SimpleTopoSortIter (line 346) | pub struct SimpleTopoSortIter<T> {
function new (line 355) | pub fn new(data: SimpleTopoSort<T>) -> Self {
type Item (line 376) | type Item = Result<T, &'static str>;
method next (line 378) | fn next(&mut self) -> Option<Self::Item> {
function test_sort (line 403) | fn test_sort() {
function find_parent_proto_dir (line 435) | fn find_parent_proto_dir(start_path: impl AsRef<Path>) -> Option<PathBuf> {
FILE: crates/yaak-grpc/src/transport.rs
constant WITH_ALPN (line 11) | const WITH_ALPN: bool = false;
function get_transport (line 13) | pub(crate) fn get_transport(
FILE: crates/yaak-http/src/chained_reader.rs
type ChainedReader (line 7) | pub(crate) struct ChainedReader {
method new (line 20) | pub(crate) fn new(readers: Vec<ReaderType>) -> Self {
type ReaderType (line 14) | pub(crate) enum ReaderType {
method poll_read (line 26) | fn poll_read(
FILE: crates/yaak-http/src/client.rs
type HttpConnectionProxySettingAuth (line 10) | pub struct HttpConnectionProxySettingAuth {
type HttpConnectionProxySetting (line 16) | pub enum HttpConnectionProxySetting {
type HttpConnectionOptions (line 28) | pub struct HttpConnectionOptions {
method build_client (line 40) | pub(crate) fn build_client(&self) -> Result<(Client, Arc<LocalhostReso...
function build_enabled_proxy (line 86) | fn build_enabled_proxy(
FILE: crates/yaak-http/src/cookies.rs
type CookieStore (line 14) | pub struct CookieStore {
method new (line 26) | pub fn new() -> Self {
method from_cookies (line 31) | pub fn from_cookies(cookies: Vec<Cookie>) -> Self {
method get_all_cookies (line 36) | pub fn get_all_cookies(&self) -> Vec<Cookie> {
method get_cookie_header (line 41) | pub fn get_cookie_header(&self, url: &Url) -> Option<String> {
method store_cookies_from_response (line 68) | pub fn store_cookies_from_response(&self, url: &Url, set_cookie_header...
method cookie_matches (line 88) | fn cookie_matches(&self, cookie: &Cookie, url: &Url, now: &SystemTime)...
method default (line 19) | fn default() -> Self {
function parse_cookie_name_value (line 128) | fn parse_cookie_name_value(raw_cookie: &str) -> Option<(String, String)> {
function parse_set_cookie (line 139) | fn parse_set_cookie(header_value: &str, request_url: &Url) -> Option<Coo...
function default_cookie_path (line 192) | fn default_cookie_path(request_path: &str) -> String {
function path_matches (line 206) | fn path_matches(request_path: &str, cookie_path: &str) -> bool {
function cookies_match (line 225) | fn cookies_match(a: &Cookie, b: &Cookie) -> bool {
function parse_cookie_date (line 246) | fn parse_cookie_date(date_str: &str) -> Result<SystemTime, ()> {
function is_single_component_domain (line 254) | fn is_single_component_domain(domain: &str) -> bool {
function is_localhost (line 268) | fn is_localhost(domain: &str) -> bool {
function test_parse_cookie_name_value (line 282) | fn test_parse_cookie_name_value() {
function test_path_matches (line 296) | fn test_path_matches() {
function test_default_cookie_path (line 306) | fn test_default_cookie_path() {
function test_cookie_store_basic (line 315) | fn test_cookie_store_basic() {
function test_cookie_domain_matching (line 331) | fn test_cookie_domain_matching() {
function test_cookie_path_matching (line 354) | fn test_cookie_path_matching() {
function test_cookie_replacement (line 374) | fn test_cookie_replacement() {
function test_is_single_component_domain (line 391) | fn test_is_single_component_domain() {
function test_is_localhost (line 415) | fn test_is_localhost() {
function test_reject_tld_cookies (line 434) | fn test_reject_tld_cookies() {
function test_allow_localhost_cookies (line 447) | fn test_allow_localhost_cookies() {
function test_allow_127_0_0_1_cookies (line 460) | fn test_allow_127_0_0_1_cookies() {
function test_allow_normal_domain_cookies (line 473) | fn test_allow_normal_domain_cookies() {
FILE: crates/yaak-http/src/decompress.rs
type ContentEncoding (line 12) | pub enum ContentEncoding {
method from_header (line 23) | pub fn from_header(value: Option<&str>) -> Self {
type DecompressResult (line 36) | pub struct DecompressResult {
function decompress (line 44) | pub fn decompress(data: Vec<u8>, encoding: ContentEncoding) -> Result<De...
function decompress_gzip (line 60) | fn decompress_gzip(data: &[u8]) -> Result<Vec<u8>> {
function decompress_deflate (line 69) | fn decompress_deflate(data: &[u8]) -> Result<Vec<u8>> {
function decompress_brotli (line 78) | fn decompress_brotli(data: &[u8]) -> Result<Vec<u8>> {
function decompress_zstd (line 85) | fn decompress_zstd(data: &[u8]) -> Result<Vec<u8>> {
function streaming_decoder (line 92) | pub fn streaming_decoder<R: AsyncBufRead + Unpin + Send + 'static>(
function test_content_encoding_from_header (line 113) | fn test_content_encoding_from_header() {
function test_decompress_identity (line 126) | fn test_decompress_identity() {
function test_decompress_gzip (line 135) | fn test_decompress_gzip() {
function test_decompress_deflate (line 149) | fn test_decompress_deflate() {
function test_decompress_brotli (line 163) | fn test_decompress_brotli() {
function test_decompress_zstd (line 178) | fn test_decompress_zstd() {
FILE: crates/yaak-http/src/dns.rs
type ResolvedOverride (line 18) | pub struct ResolvedOverride {
type LocalhostResolver (line 24) | pub struct LocalhostResolver {
method new (line 31) | pub fn new(dns_overrides: Vec<DnsOverride>) -> Arc<Self> {
method set_event_sender (line 64) | pub async fn set_event_sender(&self, tx: Option<mpsc::Sender<HttpRespo...
method resolve (line 71) | fn resolve(&self, name: Name) -> Resolving {
FILE: crates/yaak-http/src/error.rs
type Error (line 5) | pub enum Error {
method serialize (line 29) | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::E...
type Result (line 37) | pub type Result<T> = std::result::Result<T, Error>;
FILE: crates/yaak-http/src/manager.rs
type CachedClient (line 12) | pub struct CachedClient {
type HttpConnectionManager (line 17) | pub struct HttpConnectionManager {
method new (line 23) | pub fn new() -> Self {
method get_client (line 30) | pub async fn get_client(&self, opt: &HttpConnectionOptions) -> Result<...
FILE: crates/yaak-http/src/path_placeholders.rs
function apply_path_placeholders (line 3) | pub fn apply_path_placeholders(
function replace_path_placeholder (line 28) | fn replace_path_placeholder(p: &HttpUrlParameter, url: &str) -> String {
function placeholder_middle (line 57) | fn placeholder_middle() {
function placeholder_end (line 67) | fn placeholder_end() {
function placeholder_query (line 77) | fn placeholder_query() {
function placeholder_missing (line 87) | fn placeholder_missing() {
function placeholder_disabled (line 101) | fn placeholder_disabled() {
function placeholder_prefix (line 115) | fn placeholder_prefix() {
function placeholder_encode (line 125) | fn placeholder_encode() {
function apply_placeholder (line 139) | fn apply_placeholder() {
FILE: crates/yaak-http/src/proto.rs
function ensure_proto (line 4) | pub(crate) fn ensure_proto(url_str: &str) -> String {
FILE: crates/yaak-http/src/sender.rs
type RedirectBehavior (line 18) | pub enum RedirectBehavior {
type HttpResponseEvent (line 26) | pub enum HttpResponseEvent {
method fmt (line 68) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
function from (line 146) | fn from(event: HttpResponseEvent) -> Self {
type BodyStats (line 196) | pub struct BodyStats {
type TrackingRead (line 204) | pub struct TrackingRead<R> {
function new (line 211) | pub fn new(inner: R, event_tx: mpsc::Sender<HttpResponseEvent>) -> Self {
method poll_read (line 217) | fn poll_read(
type BodyStream (line 239) | type BodyStream = Pin<Box<dyn AsyncRead + Send>>;
type HttpResponse (line 244) | pub struct HttpResponse {
method fmt (line 269) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method new (line 287) | pub fn new(
method bytes (line 315) | pub async fn bytes(mut self) -> Result<(Vec<u8>, BodyStats)> {
method text (line 352) | pub async fn text(self) -> Result<(String, BodyStats)> {
method into_body_stream (line 362) | pub fn into_body_stream(&mut self) -> Result<Box<dyn AsyncRead + Unpin...
method drain (line 374) | pub async fn drain(mut self) -> Result<()> {
type HttpSender (line 401) | pub trait HttpSender: Send + Sync {
method send (line 405) | async fn send(
method send (line 432) | async fn send(
type ReqwestSender (line 413) | pub struct ReqwestSender {
method new (line 419) | pub fn new() -> Result<Self> {
method with_client (line 425) | pub fn with_client(client: Client) -> Self {
type SizedBody (line 588) | struct SizedBody<S> {
function new (line 594) | fn new(stream: S, content_length: u64) -> Self {
type Data (line 606) | type Data = Bytes;
type Error (line 607) | type Error = std::io::Error;
method poll_frame (line 609) | fn poll_frame(
method size_hint (line 626) | fn size_hint(&self) -> SizeHint {
function version_to_str (line 631) | fn version_to_str(version: &Version) -> String {
FILE: crates/yaak-http/src/tee_reader.rs
type TeeReader (line 10) | pub struct TeeReader<R> {
function new (line 16) | pub fn new(inner: R, tx: mpsc::UnboundedSender<Vec<u8>>) -> Self {
method poll_read (line 22) | fn poll_read(
function test_tee_reader_captures_all_data (line 54) | async fn test_tee_reader_captures_all_data() {
function test_tee_reader_with_chunked_reads (line 75) | async fn test_tee_reader_with_chunked_reads() {
function test_tee_reader_empty_data (line 105) | async fn test_tee_reader_empty_data() {
function test_tee_reader_works_when_receiver_dropped (line 122) | async fn test_tee_reader_works_when_receiver_dropped() {
function test_tee_reader_large_data (line 139) | async fn test_tee_reader_large_data() {
FILE: crates/yaak-http/src/transaction.rs
type HttpTransaction (line 11) | pub struct HttpTransaction<S: HttpSender> {
function new (line 19) | pub fn new(sender: S) -> Self {
function with_max_redirects (line 24) | pub fn with_max_redirects(sender: S, max_redirects: usize) -> Self {
function with_cookie_store (line 29) | pub fn with_cookie_store(sender: S, cookie_store: CookieStore) -> Self {
function with_options (line 34) | pub fn with_options(
function execute_with_cancellation (line 45) | pub async fn execute_with_cancellation(
function remove_sensitive_headers (line 257) | fn remove_sensitive_headers(
function push_header_if_missing (line 286) | fn push_header_if_missing(headers: &mut Vec<String>, name: &str) {
function is_redirect (line 293) | fn is_redirect(status: u16) -> bool {
function extract_base_url (line 298) | fn extract_base_url(url: &str) -> Result<String> {
function extract_base_path (line 316) | fn extract_base_path(url: &str) -> Result<String> {
type CapturedRequest (line 344) | struct CapturedRequest {
type MockSender (line 351) | struct MockSender {
method new (line 364) | fn new(responses: Vec<MockResponse>) -> Self {
type MockResponse (line 357) | struct MockResponse {
method send (line 374) | async fn send(
function test_transaction_no_redirect (line 411) | async fn test_transaction_no_redirect() {
function test_transaction_single_redirect (line 434) | async fn test_transaction_single_redirect() {
function test_transaction_max_redirects_exceeded (line 466) | async fn test_transaction_max_redirects_exceeded() {
function test_is_redirect (line 499) | fn test_is_redirect() {
function test_extract_base_url (line 511) | fn test_extract_base_url() {
function test_extract_base_path (line 524) | fn test_extract_base_path() {
function test_cookie_injection (line 538) | async fn test_cookie_injection() {
function test_set_cookie_parsing (line 606) | async fn test_set_cookie_parsing() {
function test_multiple_set_cookie_headers (line 662) | async fn test_multiple_set_cookie_headers() {
function test_cookies_across_redirects (line 738) | async fn test_cookies_across_redirects() {
function test_cross_origin_redirect_strips_auth_headers (line 821) | async fn test_cross_origin_redirect_strips_auth_headers() {
function test_same_origin_redirect_preserves_auth_headers (line 881) | async fn test_same_origin_redirect_preserves_auth_headers() {
FILE: crates/yaak-http/src/types.rs
constant MULTIPART_BOUNDARY (line 16) | pub(crate) const MULTIPART_BOUNDARY: &str = "------YaakFormBoundary";
type SendableBody (line 18) | pub enum SendableBody {
method from (line 38) | fn from(value: SendableBodyWithMeta) -> Self {
type SendableBodyWithMeta (line 29) | enum SendableBodyWithMeta {
type SendableHttpRequest (line 49) | pub struct SendableHttpRequest {
method from_http_request (line 64) | pub async fn from_http_request(
method insert_header (line 80) | pub fn insert_header(&mut self, header: (String, String)) {
type SendableHttpRequestOptions (line 58) | pub struct SendableHttpRequestOptions {
function append_query_params (line 91) | pub fn append_query_params(url: &str, params: Vec<(String, String)>) -> ...
function strip_query_params (line 138) | fn strip_query_params(url: &str, names: &[&str]) -> String {
function build_url (line 172) | fn build_url(r: &HttpRequest) -> String {
function append_graphql_query_params (line 191) | fn append_graphql_query_params(url: &str, body: &BTreeMap<String, serde_...
function build_headers (line 203) | fn build_headers(r: &HttpRequest) -> Vec<(String, String)> {
function build_body (line 216) | async fn build_body(
function build_form_body (line 260) | fn build_form_body(body: &BTreeMap<String, serde_json::Value>) -> Option...
function build_binary_body (line 285) | async fn build_binary_body(
function build_text_body (line 309) | fn build_text_body(body: &BTreeMap<String, serde_json::Value>, body_type...
function build_graphql_body (line 325) | fn build_graphql_body(
function build_multipart_body (line 350) | async fn build_multipart_body(
function extract_boundary_from_headers (line 465) | fn extract_boundary_from_headers(headers: &Vec<(String, String)>) -> Str...
function test_build_url_no_params (line 488) | fn test_build_url_no_params() {
function test_build_url_with_params (line 500) | fn test_build_url_with_params() {
function test_build_url_with_disabled_params (line 525) | fn test_build_url_with_disabled_params() {
function test_build_url_with_existing_query (line 550) | fn test_build_url_with_existing_query() {
function test_build_url_with_empty_existing_query (line 567) | fn test_build_url_with_empty_existing_query() {
function test_build_url_with_special_chars (line 584) | fn test_build_url_with_special_chars() {
function test_build_url_adds_protocol (line 604) | fn test_build_url_adds_protocol() {
function test_build_url_adds_https_for_dev_domain (line 622) | fn test_build_url_adds_https_for_dev_domain() {
function test_build_url_with_fragment (line 640) | fn test_build_url_with_fragment() {
function test_build_url_with_existing_query_and_fragment (line 657) | fn test_build_url_with_existing_query_and_fragment() {
function test_build_url_with_empty_query_and_fragment (line 674) | fn test_build_url_with_empty_query_and_fragment() {
function test_build_url_with_fragment_containing_special_chars (line 691) | fn test_build_url_with_fragment_containing_special_chars() {
function test_build_url_preserves_empty_fragment (line 708) | fn test_build_url_preserves_empty_fragment() {
function test_build_url_with_multiple_fragments (line 725) | fn test_build_url_with_multiple_fragments() {
function test_text_body (line 744) | async fn test_text_body() {
function test_text_body_empty (line 758) | async fn test_text_body_empty() {
function test_text_body_missing (line 767) | async fn test_text_body_missing() {
function test_text_body_strips_json_comments_by_default (line 775) | async fn test_text_body_strips_json_comments_by_default() {
function test_text_body_send_json_comments_when_opted_in (line 791) | async fn test_text_body_send_json_comments_when_opted_in() {
function test_text_body_no_strip_for_non_json (line 807) | async fn test_text_body_no_strip_for_non_json() {
function test_form_urlencoded_body (line 822) | async fn test_form_urlencoded_body() -> Result<()> {
function test_form_urlencoded_body_missing_form (line 845) | async fn test_form_urlencoded_body_missing_form() {
function test_binary_body (line 852) | async fn test_binary_body() -> Result<()> {
function test_binary_body_file_not_found (line 862) | async fn test_binary_body_file_not_found() {
function test_graphql_body_with_variables (line 874) | async fn test_graphql_body_with_variables() {
function test_graphql_body_without_variables (line 891) | async fn test_graphql_body_without_variables() {
function test_graphql_body_get_method (line 907) | async fn test_graphql_body_get_method() {
function test_multipart_body_text_fields (line 916) | async fn test_multipart_body_text_fields() -> Result<()> {
function test_multipart_body_with_file (line 955) | async fn test_multipart_body_with_file() -> Result<()> {
function test_multipart_body_empty (line 992) | async fn test_multipart_body_empty() -> Result<()> {
function test_extract_boundary_from_headers_with_custom_boundary (line 1001) | fn test_extract_boundary_from_headers_with_custom_boundary() {
function test_extract_boundary_from_headers_default (line 1011) | fn test_extract_boundary_from_headers_default() {
function test_extract_boundary_from_headers_no_boundary_in_content_type (line 1018) | fn test_extract_boundary_from_headers_no_boundary_in_content_type() {
function test_extract_boundary_case_insensitive (line 1025) | fn test_extract_boundary_case_insensitive() {
function test_no_content_length_header_added_by_build_body (line 1035) | async fn test_no_content_length_header_added_by_build_body() -> Result<(...
function test_chunked_encoding_header_preserved (line 1055) | async fn test_chunked_encoding_header_preserved() -> Result<()> {
FILE: crates/yaak-models/bindings/gen_models.ts
type AnyModel (line 3) | type AnyModel = CookieJar | Environment | Folder | GraphQlIntrospection ...
type ClientCertificate (line 5) | type ClientCertificate = { host: string, port: number | null, crtFile: s...
type Cookie (line 7) | type Cookie = { raw_cookie: string, domain: CookieDomain, expires: Cooki...
type CookieDomain (line 9) | type CookieDomain = { "HostOnly": string } | { "Suffix": string } | "Not...
type CookieExpires (line 11) | type CookieExpires = { "AtUtc": string } | "SessionEnd";
type CookieJar (line 13) | type CookieJar = { model: "cookie_jar", id: string, createdAt: string, u...
type DnsOverride (line 15) | type DnsOverride = { hostname: string, ipv4: Array<string>, ipv6: Array<...
type EditorKeymap (line 17) | type EditorKeymap = "default" | "vim" | "vscode" | "emacs";
type EncryptedKey (line 19) | type EncryptedKey = { encryptedKey: string, };
type Environment (line 21) | type Environment = { model: "environment", id: string, workspaceId: stri...
type EnvironmentVariable (line 23) | type EnvironmentVariable = { enabled?: boolean, name: string, value: str...
type Folder (line 25) | type Folder = { model: "folder", id: string, createdAt: string, updatedA...
type GraphQlIntrospection (line 27) | type GraphQlIntrospection = { model: "graphql_introspection", id: string...
type GrpcConnection (line 29) | type GrpcConnection = { model: "grpc_connection", id: string, createdAt:...
type GrpcConnectionState (line 31) | type GrpcConnectionState = "initialized" | "connected" | "closed";
type GrpcEvent (line 33) | type GrpcEvent = { model: "grpc_event", id: string, createdAt: string, u...
type GrpcEventType (line 35) | type GrpcEventType = "info" | "error" | "client_message" | "server_messa...
type GrpcRequest (line 37) | type GrpcRequest = { model: "grpc_request", id: string, createdAt: strin...
type HttpRequest (line 39) | type HttpRequest = { model: "http_request", id: string, createdAt: strin...
type HttpRequestHeader (line 41) | type HttpRequestHeader = { enabled?: boolean, name: string, value: strin...
type HttpResponse (line 43) | type HttpResponse = { model: "http_response", id: string, createdAt: str...
type HttpResponseEvent (line 45) | type HttpResponseEvent = { model: "http_response_event", id: string, cre...
type HttpResponseEventData (line 52) | type HttpResponseEventData = { "type": "setting", name: string, value: s...
type HttpResponseHeader (line 54) | type HttpResponseHeader = { name: string, value: string, };
type HttpResponseState (line 56) | type HttpResponseState = "initialized" | "connected" | "closed";
type HttpUrlParameter (line 58) | type HttpUrlParameter = { enabled?: boolean, name: string, value: string...
type KeyValue (line 60) | type KeyValue = { model: "key_value", id: string, createdAt: string, upd...
type ModelChangeEvent (line 62) | type ModelChangeEvent = { "type": "upsert", created: boolean, } | { "typ...
type ModelPayload (line 64) | type ModelPayload = { model: AnyModel, updateSource: UpdateSource, chang...
type ParentAuthentication (line 66) | type ParentAuthentication = { authentication: Record<string, any>, authe...
type ParentHeaders (line 68) | type ParentHeaders = { headers: Array<HttpRequestHeader>, };
type Plugin (line 70) | type Plugin = { model: "plugin", id: string, createdAt: string, updatedA...
type PluginSource (line 72) | type PluginSource = "bundled" | "filesystem" | "registry";
type PluginKeyValue (line 74) | type PluginKeyValue = { model: "plugin_key_value", createdAt: string, up...
type ProxySetting (line 76) | type ProxySetting = { "type": "enabled", http: string, https: string, au...
type ProxySettingAuth (line 78) | type ProxySettingAuth = { user: string, password: string, };
type Settings (line 80) | type Settings = { model: "settings", id: string, createdAt: string, upda...
type SyncState (line 82) | type SyncState = { model: "sync_state", id: string, workspaceId: string,...
type UpdateSource (line 84) | type UpdateSource = { "type": "background" } | { "type": "import" } | { ...
type WebsocketConnection (line 86) | type WebsocketConnection = { model: "websocket_connection", id: string, ...
type WebsocketConnectionState (line 88) | type WebsocketConnectionState = "initialized" | "connected" | "closing" ...
type WebsocketEvent (line 90) | type WebsocketEvent = { model: "websocket_event", id: string, createdAt:...
type WebsocketEventType (line 92) | type WebsocketEventType = "binary" | "close" | "frame" | "open" | "ping"...
type WebsocketMessageType (line 94) | type WebsocketMessageType = "text" | "binary";
type WebsocketRequest (line 96) | type WebsocketRequest = { model: "websocket_request", id: string, create...
type Workspace (line 98) | type Workspace = { model: "workspace", id: string, createdAt: string, up...
type WorkspaceMeta (line 100) | type WorkspaceMeta = { model: "workspace_meta", id: string, workspaceId:...
FILE: crates/yaak-models/bindings/gen_util.ts
type BatchUpsertResult (line 4) | type BatchUpsertResult = { workspaces: Array<Workspace>, environments: A...
FILE: crates/yaak-models/blob_migrations/00000000000000_init.sql
type body_chunks (line 1) | CREATE TABLE body_chunks
type idx_body_chunks_body_id (line 12) | CREATE INDEX idx_body_chunks_body_id ON body_chunks (body_id, chunk_index)
FILE: crates/yaak-models/build.rs
function main (line 1) | fn main() {
FILE: crates/yaak-models/guest-js/atoms.ts
function createModelAtom (line 36) | function createModelAtom<M extends AnyModel["model"]>(modelType: M) {
function createSingularModelAtom (line 44) | function createSingularModelAtom<M extends AnyModel["model"]>(modelType:...
function createOrderedModelAtom (line 53) | function createOrderedModelAtom<M extends AnyModel["model"]>(
function shallowEqual (line 73) | function shallowEqual<T>(a: T[], b: T[]): boolean {
FILE: crates/yaak-models/guest-js/index.ts
function modelTypeLabel (line 8) | function modelTypeLabel(m: AnyModel): string {
FILE: crates/yaak-models/guest-js/store.ts
function initModelStore (line 11) | function initModelStore(store: JotaiStore) {
function mustStore (line 37) | function mustStore(): JotaiStore {
function changeModelStoreWorkspace (line 47) | async function changeModelStoreWorkspace(workspaceId: string | null) {
function listModels (line 65) | function listModels<M extends AnyModel["model"], T extends ExtractModel<...
function getModel (line 73) | function getModel<M extends AnyModel["model"], T extends ExtractModel<An...
function getAnyModel (line 86) | function getAnyModel(id: string): AnyModel | null {
function patchModelById (line 96) | function patchModelById<M extends AnyModel["model"], T extends ExtractMo...
function patchModel (line 110) | async function patchModel<M extends AnyModel["model"], T extends Extract...
function updateModel (line 117) | async function updateModel<M extends AnyModel["model"], T extends Extrac...
function deleteModelById (line 123) | async function deleteModelById<
function deleteModel (line 131) | async function deleteModel<M extends AnyModel["model"], T extends Extrac...
function duplicateModel (line 140) | function duplicateModel<M extends AnyModel["model"], T extends ExtractMo...
function createGlobalModel (line 179) | async function createGlobalModel<T extends Exclude<AnyModel, { workspace...
function createWorkspaceModel (line 185) | async function createWorkspaceModel<T extends Extract<AnyModel, { worksp...
function replaceModelsInStore (line 191) | function replaceModelsInStore<
function mergeModelsInStore (line 208) | function mergeModelsInStore<
function shouldIgnoreModel (line 236) | function shouldIgnoreModel({ model, updateSource }: ModelPayload) {
FILE: crates/yaak-models/guest-js/types.ts
type ExtractModel (line 4) | type ExtractModel<T, M> = T extends { model: M } ? T : never;
type ModelStoreData (line 5) | type ModelStoreData<T extends AnyModel = AnyModel> = {
type JotaiStore (line 8) | type JotaiStore = ReturnType<typeof createStore>;
FILE: crates/yaak-models/guest-js/util.ts
function newStoreData (line 3) | function newStoreData(): ModelStoreData {
FILE: crates/yaak-models/migrations/20230225181302_init.sql
type key_values (line 1) | CREATE TABLE key_values
type workspaces (line 13) | CREATE TABLE workspaces
type http_requests (line 25) | CREATE TABLE http_requests
type http_responses (line 44) | CREATE TABLE http_responses
FILE: crates/yaak-models/migrations/20231022205109_environments.sql
type environments (line 1) | CREATE TABLE environments
FILE: crates/yaak-models/migrations/20231103142807_folders.sql
type folders (line 1) | CREATE TABLE folders
FILE: crates/yaak-models/migrations/20240111221224_settings.sql
type settings (line 1) | CREATE TABLE settings
FILE: crates/yaak-models/migrations/20240127013915_cookies.sql
type cookie_jars (line 1) | CREATE TABLE cookie_jars
FILE: crates/yaak-models/migrations/20240203164833_grpc.sql
type grpc_requests (line 1) | CREATE TABLE grpc_requests
type grpc_connections (line 25) | CREATE TABLE grpc_connections
type grpc_events (line 47) | CREATE TABLE grpc_events
FILE: crates/yaak-models/migrations/20240829131004_plugins.sql
type plugins (line 1) | CREATE TABLE plugins
FILE: crates/yaak-models/migrations/20250102141937_sync.sql
type sync_states (line 4) | CREATE TABLE sync_states
FILE: crates/yaak-models/migrations/20250108205117_workspace-meta.sql
type workspace_metas (line 1) | CREATE TABLE workspace_metas
FILE: crates/yaak-models/migrations/20250123192023_plugin-kv.sql
type plugin_key_values (line 1) | CREATE TABLE plugin_key_values
FILE: crates/yaak-models/migrations/20250128155623_websockets.sql
type websocket_requests (line 1) | CREATE TABLE websocket_requests
type websocket_connections (line 26) | CREATE TABLE websocket_connections
type websocket_events (line 47) | CREATE TABLE websocket_events
FILE: crates/yaak-models/migrations/20250326193143_key-value-id.sql
type key_values_new (line 2) | CREATE TABLE key_values_new
FILE: crates/yaak-models/migrations/20250424152740_remove-fks.sql
type http_requests_dg_tmp (line 9) | CREATE TABLE http_requests_dg_tmp
type grpc_requests_dg_tmp (line 66) | CREATE TABLE grpc_requests_dg_tmp
type websocket_requests_dg_tmp (line 118) | CREATE TABLE websocket_requests_dg_tmp
type environments_dg_tmp (line 171) | CREATE TABLE environments_dg_tmp
type folders_dg_tmp (line 209) | CREATE TABLE folders_dg_tmp
FILE: crates/yaak-models/migrations/20250530174021_graphql-introspection.sql
type graphql_introspections (line 6) | CREATE TABLE graphql_introspections
FILE: crates/yaak-models/migrations/20250531193722_sync-state-index.sql
type sync_states (line 9) | CREATE TABLE sync_states
type idx_sync_states_unique (line 24) | CREATE UNIQUE INDEX idx_sync_states_unique
FILE: crates/yaak-models/migrations/20250918141129_request-folder-environments.sql
type environments__new (line 2) | CREATE TABLE environments__new
FILE: crates/yaak-models/migrations/20251221000000_http-response-events.sql
type http_response_events (line 1) | CREATE TABLE http_response_events
FILE: crates/yaak-models/migrations/20260216000000_model-changes.sql
type model_changes (line 1) | CREATE TABLE model_changes
type idx_model_changes_created_at (line 12) | CREATE INDEX idx_model_changes_created_at ON model_changes (created_at)
FILE: crates/yaak-models/migrations/20260301000000_plugin-source-and-unique-directory.sql
type idx_plugins_directory_unique (line 32) | CREATE UNIQUE INDEX IF NOT EXISTS idx_plugins_directory_unique
FILE: crates/yaak-models/src/blob_manager.rs
type BodyChunk (line 14) | pub struct BodyChunk {
method new (line 22) | pub fn new(body_id: impl Into<String>, chunk_index: i32, data: Vec<u8>...
type BlobManager (line 29) | pub struct BlobManager {
method new (line 34) | pub fn new(pool: Pool<SqliteConnectionManager>) -> Self {
method connect (line 38) | pub fn connect(&self) -> BlobContext {
type BlobContext (line 50) | pub struct BlobContext {
method insert_chunk (line 56) | pub fn insert_chunk(&self, chunk: &BodyChunk) -> Result<()> {
method get_chunks (line 65) | pub fn get_chunks(&self, body_id: &str) -> Result<Vec<BodyChunk>> {
method delete_chunks (line 86) | pub fn delete_chunks(&self, body_id: &str) -> Result<()> {
method delete_chunks_like (line 92) | pub fn delete_chunks_like(&self, body_id_prefix: &str) -> Result<()> {
method get_body_size (line 101) | pub fn get_body_size(&self, body_id: &str) -> Result<usize> {
method body_exists (line 114) | pub fn body_exists(&self, body_id: &str) -> Result<bool> {
function migrate_blob_db (line 128) | pub fn migrate_blob_db(pool: &Pool<SqliteConnectionManager>) -> Result<(...
function create_test_pool (line 195) | fn create_test_pool() -> Pool<SqliteConnectionManager> {
function test_insert_and_get_chunks (line 203) | fn test_insert_and_get_chunks() {
function test_get_chunks_ordered_by_index (line 224) | fn test_get_chunks_ordered_by_index() {
function test_delete_chunks (line 244) | fn test_delete_chunks() {
function test_delete_chunks_like (line 261) | fn test_delete_chunks_like() {
function test_get_body_size (line 283) | fn test_get_body_size() {
function test_get_body_size_empty (line 297) | fn test_get_body_size_empty() {
function test_body_exists (line 307) | fn test_body_exists() {
function test_multiple_bodies_isolated (line 320) | fn test_multiple_bodies_isolated() {
function test_large_chunk (line 338) | fn test_large_chunk() {
FILE: crates/yaak-models/src/connection_or_tx.rs
type ConnectionOrTx (line 5) | pub enum ConnectionOrTx<'a> {
function resolve (line 11) | pub(crate) fn resolve(&self) -> &Connection {
function prepare (line 18) | pub(crate) fn prepare(&self, sql: &str) -> rusqlite::Result<Statement<'_...
function execute (line 22) | pub(crate) fn execute(&self, sql: &str, params: &[&dyn ToSql]) -> rusqli...
FILE: crates/yaak-models/src/db_context.rs
type DbContext (line 15) | pub struct DbContext<'a> {
function find_one (line 21) | pub(crate) fn find_one<'s, M>(
function find_optional (line 50) | pub(crate) fn find_optional<'s, M>(
function find_all (line 69) | pub(crate) fn find_all<'s, M>(&self) -> Result<Vec<M>>
function find_many (line 84) | pub(crate) fn find_many<'s, M>(
function upsert (line 117) | pub(crate) fn upsert<M>(&self, model: &M, source: &UpdateSource) -> Resu...
function upsert_one (line 131) | fn upsert_one<M>(
function delete (line 188) | pub(crate) fn delete<'s, M>(&self, m: &M, source: &UpdateSource) -> Resu...
function record_model_change (line 210) | fn record_model_change(&self, payload: &ModelPayload) -> Result<()> {
FILE: crates/yaak-models/src/error.rs
type Error (line 5) | pub enum Error {
method serialize (line 44) | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::E...
type Result (line 52) | pub type Result<T> = std::result::Result<T, Error>;
FILE: crates/yaak-models/src/lib.rs
function init_standalone (line 29) | pub fn init_standalone(
function init_in_memory (line 76) | pub fn init_in_memory() -> Result<(QueryManager, BlobManager, mpsc::Rece...
FILE: crates/yaak-models/src/migrate.rs
function migrate_db (line 12) | pub fn migrate_db(pool: &Pool<SqliteConnectionManager>) -> Result<()> {
function run_migration (line 76) | fn run_migration(migration_path: &DirEntry, tx: &mut rusqlite::Transacti...
function split_migration_filename (line 112) | fn split_migration_filename(filename: &str) -> Option<(String, String)> {
function sha384_hex_prefixed (line 124) | fn sha384_hex_prefixed(input: &[u8]) -> String {
FILE: crates/yaak-models/src/models.rs
type ProxySetting (line 34) | pub enum ProxySetting {
type ProxySettingAuth (line 52) | pub struct ProxySettingAuth {
type ClientCertificate (line 60) | pub struct ClientCertificate {
type DnsOverride (line 80) | pub struct DnsOverride {
type EditorKeymap (line 94) | pub enum EditorKeymap {
type Err (line 102) | type Err = crate::error::Error;
method from_str (line 104) | fn from_str(s: &str) -> Result<Self> {
method fmt (line 116) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method default (line 128) | fn default() -> Self {
type Settings (line 137) | pub struct Settings {
type Workspace (line 300) | pub struct Workspace {
type EncryptedKey (line 413) | pub struct EncryptedKey {
type WorkspaceMeta (line 421) | pub struct WorkspaceMeta {
type CookieDomain (line 494) | pub enum CookieDomain {
type CookieExpires (line 503) | pub enum CookieExpires {
type Cookie (line 510) | pub struct Cookie {
type CookieJar (line 521) | pub struct CookieJar {
type Environment (line 597) | pub struct Environment {
type EnvironmentVariable (line 706) | pub struct EnvironmentVariable {
type ParentAuthentication (line 719) | pub struct ParentAuthentication {
type ParentHeaders (line 728) | pub struct ParentHeaders {
type Folder (line 736) | pub struct Folder {
type HttpRequestHeader (line 833) | pub struct HttpRequestHeader {
type HttpUrlParameter (line 846) | pub struct HttpUrlParameter {
type HttpRequest (line 862) | pub struct HttpRequest {
type WebsocketConnectionState (line 981) | pub enum WebsocketConnectionState {
method default (line 989) | fn default() -> Self {
type WebsocketConnection (line 998) | pub struct WebsocketConnection {
type WebsocketMessageType (line 1093) | pub enum WebsocketMessageType {
method default (line 1099) | fn default() -> Self {
type WebsocketRequest (line 1108) | pub struct WebsocketRequest {
type WebsocketEventType (line 1220) | pub enum WebsocketEventType {
method default (line 1231) | fn default() -> Self {
type WebsocketEvent (line 1240) | pub struct WebsocketEvent {
type HttpResponseHeader (line 1325) | pub struct HttpResponseHeader {
type HttpResponseState (line 1333) | pub enum HttpResponseState {
method default (line 1340) | fn default() -> Self {
type HttpResponse (line 1349) | pub struct HttpResponse {
type HttpResponseEventData (line 1490) | pub enum HttpResponseEventData {
method default (line 1552) | fn default() -> Self {
type HttpResponseEvent (line 1561) | pub struct HttpResponseEvent {
method new (line 1632) | pub fn new(response_id: &str, workspace_id: &str, event: HttpResponseE...
type GraphQlIntrospection (line 1649) | pub struct GraphQlIntrospection {
type GrpcRequest (line 1722) | pub struct GrpcRequest {
type GrpcConnectionState (line 1837) | pub enum GrpcConnectionState {
method default (line 1844) | fn default() -> Self {
type GrpcConnection (line 1853) | pub struct GrpcConnection {
type GrpcEventType (line 1956) | pub enum GrpcEventType {
method default (line 1966) | fn default() -> Self {
type GrpcEvent (line 1975) | pub struct GrpcEvent {
type Plugin (line 2070) | pub struct Plugin {
type PluginSource (line 2087) | pub enum PluginSource {
type Err (line 2094) | type Err = crate::error::Error;
method from_str (line 2096) | fn from_str(s: &str) -> Result<Self> {
method fmt (line 2107) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
method default (line 2118) | fn default() -> Self {
type SyncState (line 2193) | pub struct SyncState {
type KeyValue (line 2279) | pub struct KeyValue {
type PluginKeyValue (line 2350) | pub struct PluginKeyValue {
type Error (line 2362) | type Error = rusqlite::Error;
method try_from (line 2364) | fn try_from(r: &Row<'s>) -> std::result::Result<Self, Self::Error> {
function default_true (line 2376) | fn default_true() -> bool {
function default_http_method (line 2380) | fn default_http_method() -> String {
method deserialize (line 2461) | fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
method resolved_name (line 2506) | pub fn resolved_name(&self) -> String {
type UpsertModelInfo (line 2528) | pub trait UpsertModelInfo {
method table_name (line 170) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 174) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 178) | fn generate_id() -> String {
method order_by (line 182) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 186) | fn get_id(&self) -> String {
method insert_values (line 190) | fn insert_values(
method update_columns (line 229) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 257) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 326) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 330) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 334) | fn generate_id() -> String {
method order_by (line 338) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 342) | fn get_id(&self) -> String {
method insert_values (line 346) | fn insert_values(
method update_columns (line 367) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 384) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 433) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 437) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 441) | fn generate_id() -> String {
method order_by (line 445) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 449) | fn get_id(&self) -> String {
method insert_values (line 453) | fn insert_values(
method update_columns (line 467) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 475) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 534) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 538) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 542) | fn generate_id() -> String {
method order_by (line 546) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 550) | fn get_id(&self) -> String {
method insert_values (line 554) | fn insert_values(
method update_columns (line 568) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 576) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 622) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 626) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 630) | fn generate_id() -> String {
method order_by (line 634) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 638) | fn get_id(&self) -> String {
method insert_values (line 642) | fn insert_values(
method update_columns (line 661) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 674) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 755) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 759) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 763) | fn generate_id() -> String {
method order_by (line 767) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 771) | fn get_id(&self) -> String {
method insert_values (line 775) | fn insert_values(
method update_columns (line 794) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 807) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 889) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 893) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 897) | fn generate_id() -> String {
method order_by (line 901) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 905) | fn get_id(&self) -> String {
method insert_values (line 909) | fn insert_values(
method update_columns (line 932) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 951) | fn from_row(row: &Row) -> rusqlite::Result<Self> {
method table_name (line 1016) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 1020) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 1024) | fn generate_id() -> String {
method order_by (line 1028) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 1032) | fn get_id(&self) -> String {
method insert_values (line 1036) | fn insert_values(
method update_columns (line 1055) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 1067) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 1131) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 1135) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 1139) | fn generate_id() -> String {
method order_by (line 1143) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 1147) | fn get_id(&self) -> String {
method insert_values (line 1151) | fn insert_values(
method update_columns (line 1173) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 1190) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 1256) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 1260) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 1264) | fn generate_id() -> String {
method order_by (line 1268) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 1272) | fn get_id(&self) -> String {
method insert_values (line 1276) | fn insert_values(
method update_columns (line 1293) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 1302) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 1377) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 1381) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 1385) | fn generate_id() -> String {
method order_by (line 1389) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 1393) | fn get_id(&self) -> String {
method insert_values (line 1397) | fn insert_values(
method update_columns (line 1426) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 1448) | fn from_row(r: &Row) -> rusqlite::Result<Self>
method table_name (line 1573) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 1577) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 1581) | fn generate_id() -> String {
method order_by (line 1585) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 1589) | fn get_id(&self) -> String {
method insert_values (line 1593) | fn insert_values(
method update_columns (line 1607) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 1614) | fn from_row(r: &Row) -> rusqlite::Result<Self>
method table_name (line 1661) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 1665) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 1669) | fn generate_id() -> String {
method order_by (line 1673) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 1677) | fn get_id(&self) -> String {
method insert_values (line 1681) | fn insert_values(
method update_columns (line 1695) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 1702) | fn from_row(r: &Row) -> rusqlite::Result<Self>
method table_name (line 1746) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 1750) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 1754) | fn generate_id() -> String {
method order_by (line 1758) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 1762) | fn get_id(&self) -> String {
method insert_values (line 1766) | fn insert_values(
method update_columns (line 1789) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 1807) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 1873) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 1877) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 1881) | fn generate_id() -> String {
method order_by (line 1885) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 1889) | fn get_id(&self) -> String {
method insert_values (line 1893) | fn insert_values(
method update_columns (line 1914) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 1928) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 1993) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 1997) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 2001) | fn generate_id() -> String {
method order_by (line 2005) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 2009) | fn get_id(&self) -> String {
method insert_values (line 2013) | fn insert_values(
method update_columns (line 2032) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 2043) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 2124) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 2128) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 2132) | fn generate_id() -> String {
method order_by (line 2136) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 2140) | fn get_id(&self) -> String {
method insert_values (line 2144) | fn insert_values(
method update_columns (line 2160) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 2171) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 2209) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 2213) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 2217) | fn generate_id() -> String {
method order_by (line 2221) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 2225) | fn get_id(&self) -> String {
method insert_values (line 2229) | fn insert_values(
method update_columns (line 2246) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 2256) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 2292) | fn table_name() -> impl IntoTableRef + IntoIden {
method id_column (line 2296) | fn id_column() -> impl IntoIden + Eq + Clone {
method generate_id (line 2300) | fn generate_id() -> String {
method order_by (line 2304) | fn order_by() -> (impl IntoColumnRef, Order) {
method get_id (line 2308) | fn get_id(&self) -> String {
method insert_values (line 2312) | fn insert_values(
method update_columns (line 2326) | fn update_columns() -> Vec<impl IntoIden> {
method from_row (line 2330) | fn from_row(row: &Row) -> rusqlite::Result<Self>
method table_name (line 2529) | fn table_name() -> impl IntoTableRef + IntoIden;
method id_column (line 2530) | fn id_column() -> impl IntoIden + Eq + Clone;
method generate_id (line 2531) | fn generate_id() -> String;
method order_by (line 2532) | fn order_by() -> (impl IntoColumnRef, Order);
method get_id (line 2533) | fn get_id(&self) -> String;
method insert_values (line 2534) | fn insert_values(
method update_columns (line 2538) | fn update_columns() -> Vec<impl IntoIden>;
method from_row (line 2539) | fn from_row(row: &Row) -> rusqlite::Result<Self>
function upsert_date (line 2546) | fn upsert_date(update_source: &UpdateSource, dt: NaiveDateTime) -> Simpl...
FILE: crates/yaak-models/src/queries/any_request.rs
type AnyRequest (line 5) | pub enum AnyRequest {
function get_any_request (line 12) | pub fn get_any_request(&self, id: &str) -> Result<AnyRequest> {
FILE: crates/yaak-models/src/queries/batch.rs
function batch_upsert (line 8) | pub fn batch_upsert(
FILE: crates/yaak-models/src/queries/cookie_jars.rs
function get_cookie_jar (line 7) | pub fn get_cookie_jar(&self, id: &str) -> Result<CookieJar> {
function list_cookie_jars (line 11) | pub fn list_cookie_jars(&self, workspace_id: &str) -> Result<Vec<CookieJ...
function delete_cookie_jar (line 26) | pub fn delete_cookie_jar(
function delete_cookie_jar_by_id (line 34) | pub fn delete_cookie_jar_by_id(&self, id: &str, source: &UpdateSource) -...
function upsert_cookie_jar (line 39) | pub fn upsert_cookie_jar(
FILE: crates/yaak-models/src/queries/environments.rs
function get_environment (line 9) | pub fn get_environment(&self, id: &str) -> Result<Environment> {
function get_environment_by_folder_id (line 13) | pub fn get_environment_by_folder_id(&self, folder_id: &str) -> Result<Op...
function get_base_environment (line 21) | pub fn get_base_environment(&self, workspace_id: &str) -> Result<Environ...
function list_environments_ensure_base (line 39) | pub fn list_environments_ensure_base(&self, workspace_id: &str) -> Resul...
function list_environments_dangerous (line 62) | fn list_environments_dangerous(&self, workspace_id: &str) -> Result<Vec<...
function delete_environment (line 66) | pub fn delete_environment(
function delete_environment_by_id (line 79) | pub fn delete_environment_by_id(&self, id: &str, source: &UpdateSource) ...
function duplicate_environment (line 84) | pub fn duplicate_environment(
function list_duplicate_folder_environments (line 95) | fn list_duplicate_folder_environments(&self, environment: &Environment) ...
function upsert_environment (line 111) | pub fn upsert_environment(
function resolve_environments (line 151) | pub fn resolve_environments(
FILE: crates/yaak-models/src/queries/folders.rs
function get_folder (line 13) | pub fn get_folder(&self, id: &str) -> Result<Folder> {
function list_folders (line 17) | pub fn list_folders(&self, workspace_id: &str) -> Result<Vec<Folder>> {
function delete_folder (line 21) | pub fn delete_folder(&self, folder: &Folder, source: &UpdateSource) -> R...
function delete_folder_by_id (line 52) | pub fn delete_folder_by_id(&self, id: &str, source: &UpdateSource) -> Re...
function upsert_folder (line 57) | pub fn upsert_folder(&self, folder: &Folder, source: &UpdateSource) -> R...
function duplicate_folder (line 61) | pub fn duplicate_folder(&self, src_folder: &Folder, source: &UpdateSourc...
function resolve_auth_for_folder (line 109) | pub fn resolve_auth_for_folder(
function resolve_headers_for_folder (line 126) | pub fn resolve_headers_for_folder(&self, folder: &Folder) -> Result<Vec<...
FILE: crates/yaak-models/src/queries/graphql_introspections.rs
function get_graphql_introspection (line 10) | pub fn get_graphql_introspection(&self, request_id: &str) -> Option<Grap...
function upsert_graphql_introspection (line 14) | pub fn upsert_graphql_introspection(
function delete_expired_graphql_introspections (line 40) | pub fn delete_expired_graphql_introspections(&self) -> Result<()> {
FILE: crates/yaak-models/src/queries/grpc_connections.rs
function get_grpc_connection (line 11) | pub fn get_grpc_connection(&self, id: &str) -> Result<GrpcConnection> {
function delete_all_grpc_connections_for_request (line 15) | pub fn delete_all_grpc_connections_for_request(
function delete_all_grpc_connections_for_workspace (line 27) | pub fn delete_all_grpc_connections_for_workspace(
function delete_grpc_connection (line 38) | pub fn delete_grpc_connection(
function delete_grpc_connection_by_id (line 46) | pub fn delete_grpc_connection_by_id(
function list_grpc_connections_for_request (line 55) | pub fn list_grpc_connections_for_request(
function list_grpc_connections (line 63) | pub fn list_grpc_connections(&self, workspace_id: &str) -> Result<Vec<Gr...
function cancel_pending_grpc_connections (line 67) | pub fn cancel_pending_grpc_connections(&self) -> Result<()> {
function upsert_grpc_connection (line 79) | pub fn upsert_grpc_connection(
FILE: crates/yaak-models/src/queries/grpc_events.rs
function get_grpc_events (line 7) | pub fn get_grpc_events(&self, id: &str) -> Result<GrpcEvent> {
function list_grpc_events (line 11) | pub fn list_grpc_events(&self, connection_id: &str) -> Result<Vec<GrpcEv...
function upsert_grpc_event (line 15) | pub fn upsert_grpc_event(
FILE: crates/yaak-models/src/queries/grpc_requests.rs
function get_grpc_request (line 10) | pub fn get_grpc_request(&self, id: &str) -> Result<GrpcRequest> {
function list_grpc_requests (line 14) | pub fn list_grpc_requests(&self, workspace_id: &str) -> Result<Vec<GrpcR...
function list_grpc_requests_for_folder_recursive (line 18) | pub fn list_grpc_requests_for_folder_recursive(
function delete_grpc_request (line 32) | pub fn delete_grpc_request(
function delete_grpc_request_by_id (line 41) | pub fn delete_grpc_request_by_id(
function duplicate_grpc_request (line 50) | pub fn duplicate_grpc_request(
function upsert_grpc_request (line 61) | pub fn upsert_grpc_request(
function resolve_auth_for_grpc_request (line 69) | pub fn resolve_auth_for_grpc_request(
function resolve_metadata_for_grpc_request (line 86) | pub fn resolve_metadata_for_grpc_request(
FILE: crates/yaak-models/src/queries/http_requests.rs
function get_http_request (line 10) | pub fn get_http_request(&self, id: &str) -> Result<HttpRequest> {
function list_http_requests (line 14) | pub fn list_http_requests(&self, workspace_id: &str) -> Result<Vec<HttpR...
function delete_http_request (line 18) | pub fn delete_http_request(
function delete_http_request_by_id (line 27) | pub fn delete_http_request_by_id(
function duplicate_http_request (line 36) | pub fn duplicate_http_request(
function upsert_http_request (line 47) | pub fn upsert_http_request(
function resolve_auth_for_http_request (line 55) | pub fn resolve_auth_for_http_request(
function resolve_headers_for_http_request (line 72) | pub fn resolve_headers_for_http_request(
function list_http_requests_for_folder_recursive (line 94) | pub fn list_http_requests_for_folder_recursive(
FILE: crates/yaak-models/src/queries/http_response_events.rs
function list_http_response_events (line 7) | pub fn list_http_response_events(&self, response_id: &str) -> Result<Vec...
function upsert_http_response_event (line 11) | pub fn upsert_http_response_event(
FILE: crates/yaak-models/src/queries/http_responses.rs
function get_http_response (line 13) | pub fn get_http_response(&self, id: &str) -> Result<HttpResponse> {
function list_http_responses_for_request (line 17) | pub fn list_http_responses_for_request(
function list_http_responses (line 25) | pub fn list_http_responses(
function delete_all_http_responses_for_request (line 33) | pub fn delete_all_http_responses_for_request(
function delete_all_http_responses_for_workspace (line 45) | pub fn delete_all_http_responses_for_workspace(
function delete_http_response (line 58) | pub fn delete_http_response(
function upsert_http_response (line 81) | pub fn upsert_http_response(
function cancel_pending_http_responses (line 97) | pub fn cancel_pending_http_responses(&self) -> Result<()> {
function update_http_response_if_id (line 109) | pub fn update_http_response_if_id(
FILE: crates/yaak-models/src/queries/key_values.rs
function list_key_values (line 11) | pub fn list_key_values(&self) -> Result<Vec<KeyValue>> {
function get_key_value_str (line 26) | pub fn get_key_value_str(&self, namespace: &str, key: &str, default: &st...
function get_key_value_dte (line 42) | pub fn get_key_value_dte(
function get_key_value_int (line 63) | pub fn get_key_value_int(&self, namespace: &str, key: &str, default: i32...
function get_key_value_raw (line 79) | pub fn get_key_value_raw(&self, namespace: &str, key: &str) -> Option<Ke...
function set_key_value_dte (line 92) | pub fn set_key_value_dte(
function set_key_value_str (line 103) | pub fn set_key_value_str(
function set_key_value_int (line 114) | pub fn set_key_value_int(
function set_key_value_raw (line 125) | pub fn set_key_value_raw(
function upsert_key_value (line 154) | pub fn upsert_key_value(
function delete_key_value (line 162) | pub fn delete_key_value(
FILE: crates/yaak-models/src/queries/mod.rs
constant MAX_HISTORY_ITEMS (line 26) | const MAX_HISTORY_ITEMS: usize = 20;
function dedupe_headers (line 33) | pub(crate) fn dedupe_headers(headers: Vec<HttpRequestHeader>) -> Vec<Htt...
FILE: crates/yaak-models/src/queries/model_changes.rs
type PersistedModelChange (line 8) | pub struct PersistedModelChange {
function list_model_changes_after (line 15) | pub fn list_model_changes_after(
function list_model_changes_since (line 43) | pub fn list_model_changes_since(
function prune_model_changes_older_than_days (line 73) | pub fn prune_model_changes_older_than_days(&self, days: i64) -> Result<u...
function prune_model_changes_older_than_hours (line 84) | pub fn prune_model_changes_older_than_hours(&self, hours: i64) -> Result...
function records_model_changes_for_upsert_and_delete (line 105) | fn records_model_changes_for_upsert_and_delete() {
function prunes_old_model_changes (line 147) | fn prunes_old_model_changes() {
function list_model_changes_since_uses_timestamp_with_id_tiebreaker (line 180) | fn list_model_changes_since_uses_timestamp_with_id_tiebreaker() {
function prunes_old_model_changes_by_hours (line 214) | fn prunes_old_model_changes_by_hours() {
function list_model_changes_deserializes_http_response_event_payload (line 246) | fn list_model_changes_deserializes_http_response_event_payload() {
FILE: crates/yaak-models/src/queries/plugin_key_values.rs
function get_plugin_key_value (line 9) | pub fn get_plugin_key_value(&self, plugin_name: &str, key: &str) -> Opti...
function set_plugin_key_value (line 22) | pub fn set_plugin_key_value(
function delete_plugin_key_value (line 63) | pub fn delete_plugin_key_value(&self, namespace: &str, key: &str) -> Res...
FILE: crates/yaak-models/src/queries/plugins.rs
function get_plugin (line 7) | pub fn get_plugin(&self, id: &str) -> Result<Plugin> {
function get_plugin_by_directory (line 11) | pub fn get_plugin_by_directory(&self, directory: &str) -> Option<Plugin> {
function list_plugins (line 15) | pub fn list_plugins(&self) -> Result<Vec<Plugin>> {
function delete_plugin (line 19) | pub fn delete_plugin(&self, plugin: &Plugin, source: &UpdateSource) -> R...
function delete_plugin_by_id (line 23) | pub fn delete_plugin_by_id(&self, id: &str, source: &UpdateSource) -> Re...
function upsert_plugin (line 28) | pub fn upsert_plugin(&self, plugin: &Plugin, source: &UpdateSource) -> R...
FILE: crates/yaak-models/src/queries/settings.rs
function get_settings (line 9) | pub fn get_settings(&self) -> Settings {
function upsert_settings (line 48) | pub fn upsert_settings(&self, settings: &Settings, source: &UpdateSource...
FILE: crates/yaak-models/src/queries/sync_states.rs
function get_sync_state (line 10) | pub fn get_sync_state(&self, id: &str) -> Result<SyncState> {
function upsert_sync_state (line 14) | pub fn upsert_sync_state(&self, sync_state: &SyncState) -> Result<SyncSt...
function list_sync_states_for_workspace (line 18) | pub fn list_sync_states_for_workspace(
function delete_sync_state (line 37) | pub fn delete_sync_state(&self, sync_state: &SyncState) -> Result<SyncSt...
function delete_sync_state_by_id (line 41) | pub fn delete_sync_state_by_id(&self, id: &str) -> Result<SyncState> {
FILE: crates/yaak-models/src/queries/websocket_connections.rs
function get_websocket_connection (line 11) | pub fn get_websocket_connection(&self, id: &str) -> Result<WebsocketConn...
function delete_all_websocket_connections_for_request (line 15) | pub fn delete_all_websocket_connections_for_request(
function delete_all_websocket_connections_for_workspace (line 27) | pub fn delete_all_websocket_connections_for_workspace(
function list_websocket_connections (line 39) | pub fn list_websocket_connections(
function list_websocket_connections_for_request (line 46) | pub fn list_websocket_connections_for_request(
function delete_websocket_connection (line 53) | pub fn delete_websocket_connection(
function delete_websocket_connection_by_id (line 61) | pub fn delete_websocket_connection_by_id(
function upsert_websocket_connection (line 70) | pub fn upsert_websocket_connection(
function cancel_pending_websocket_connections (line 86) | pub fn cancel_pending_websocket_connections(&self) -> Result<()> {
FILE: crates/yaak-models/src/queries/websocket_events.rs
function get_websocket_event (line 7) | pub fn get_websocket_event(&self, id: &str) -> Result<WebsocketEvent> {
function list_websocket_events (line 11) | pub fn list_websocket_events(&self, connection_id: &str) -> Result<Vec<W...
function upsert_websocket_event (line 15) | pub fn upsert_websocket_event(
FILE: crates/yaak-models/src/queries/websocket_requests.rs
function get_websocket_request (line 12) | pub fn get_websocket_request(&self, id: &str) -> Result<WebsocketRequest> {
function list_websocket_requests (line 16) | pub fn list_websocket_requests(&self, workspace_id: &str) -> Result<Vec<...
function list_websocket_requests_for_folder_recursive (line 20) | pub fn list_websocket_requests_for_folder_recursive(
function delete_websocket_request (line 36) | pub fn delete_websocket_request(
function delete_websocket_request_by_id (line 45) | pub fn delete_websocket_request_by_id(
function duplicate_websocket_request (line 54) | pub fn duplicate_websocket_request(
function upsert_websocket_request (line 65) | pub fn upsert_websocket_request(
function resolve_auth_for_websocket_request (line 73) | pub fn resolve_auth_for_websocket_request(
function resolve_headers_for_websocket_request (line 94) | pub fn resolve_headers_for_websocket_request(
FILE: crates/yaak-models/src/queries/workspace_metas.rs
function get_workspace_meta (line 8) | pub fn get_workspace_meta(&self, workspace_id: &str) -> Option<Workspace...
function list_workspace_metas (line 12) | pub fn list_workspace_metas(&self, workspace_id: &str) -> Result<Vec<Wor...
function get_or_create_workspace_meta (line 24) | pub fn get_or_create_workspace_meta(&self, workspace_id: &str) -> Result...
function upsert_workspace_meta (line 38) | pub fn upsert_workspace_meta(
FILE: crates/yaak-models/src/queries/workspaces.rs
function get_workspace (line 12) | pub fn get_workspace(&self, id: &str) -> Result<Workspace> {
function list_workspaces (line 16) | pub fn list_workspaces(&self) -> Result<Vec<Workspace>> {
function delete_workspace (line 34) | pub fn delete_workspace(
function delete_workspace_by_id (line 62) | pub fn delete_workspace_by_id(&self, id: &str, source: &UpdateSource) ->...
function upsert_workspace (line 67) | pub fn upsert_workspace(&self, w: &Workspace, source: &UpdateSource) -> ...
function resolve_auth_for_workspace (line 71) | pub fn resolve_auth_for_workspace(
function resolve_headers_for_workspace (line 82) | pub fn resolve_headers_for_workspace(&self, workspace: &Workspace) -> Ve...
function default_headers (line 92) | pub fn default_headers() -> Vec<HttpRequestHeader> {
FILE: crates/yaak-models/src/query_manager.rs
type QueryManager (line 11) | pub struct QueryManager {
method new (line 17) | pub fn new(pool: Pool<SqliteConnectionManager>, events_tx: mpsc::Sende...
method connect (line 21) | pub fn connect(&self) -> DbContext<'_> {
method with_conn (line 31) | pub fn with_conn<F, T>(&self, func: F) -> T
method with_tx (line 50) | pub fn with_tx<T, E>(
FILE: crates/yaak-models/src/render.rs
function make_vars_hashmap (line 4) | pub fn make_vars_hashmap(environment_chain: Vec<Environment>) -> HashMap...
function add_variable_to_map (line 14) | fn add_variable_to_map(
FILE: crates/yaak-models/src/util.rs
function generate_prefixed_id (line 14) | pub fn generate_prefixed_id(prefix: &str) -> String {
function generate_id (line 18) | pub fn generate_id() -> String {
function generate_id_of_length (line 22) | pub fn generate_id_of_length(n: usize) -> String {
type ModelPayload (line 36) | pub struct ModelPayload {
type ModelChangeEvent (line 45) | pub enum ModelChangeEvent {
type UpdateSource (line 53) | pub enum UpdateSource {
method from_window_label (line 62) | pub fn from_window_label(label: impl Into<String>) -> Self {
type WorkspaceExport (line 69) | pub struct WorkspaceExport {
type BatchUpsertResult (line 79) | pub struct BatchUpsertResult {
function get_workspace_export_resources (line 88) | pub fn get_workspace_export_resources(
function maybe_gen_id (line 126) | pub fn maybe_gen_id<M: UpsertModelInfo>(
function maybe_gen_id_opt (line 151) | pub fn maybe_gen_id_opt<M: UpsertModelInfo>(
FILE: crates/yaak-plugins/bindings/gen_api.ts
type PluginNameVersion (line 4) | type PluginNameVersion = { name: string, version: string, };
type PluginSearchResponse (line 6) | type PluginSearchResponse = { plugins: Array<PluginVersion>, };
type PluginUpdatesResponse (line 8) | type PluginUpdatesResponse = { plugins: Array<PluginNameVersion>, };
FILE: crates/yaak-plugins/bindings/gen_events.ts
type BootRequest (line 5) | type BootRequest = { dir: string, watch: boolean, };
type CallFolderActionArgs (line 7) | type CallFolderActionArgs = { folder: Folder, };
type CallFolderActionRequest (line 9) | type CallFolderActionRequest = { index: number, pluginRefId: string, arg...
type CallGrpcRequestActionArgs (line 11) | type CallGrpcRequestActionArgs = { grpcRequest: GrpcRequest, protoFiles:...
type CallGrpcRequestActionRequest (line 13) | type CallGrpcRequestActionRequest = { index: number, pluginRefId: string...
type CallHttpAuthenticationActionArgs (line 15) | type CallHttpAuthenticationActionArgs = { contextId: string, values: { [...
type CallHttpAuthenticationActionRequest (line 17) | type CallHttpAuthenticationActionRequest = { index: number, pluginRefId:...
type CallHttpAuthenticationRequest (line 19) | type CallHttpAuthenticationRequest = { contextId: string, values: { [key...
type CallHttpAuthenticationResponse (line 21) | type CallHttpAuthenticationResponse = {
type CallHttpRequestActionArgs (line 33) | type CallHttpRequestActionArgs = { httpRequest: HttpRequest, };
type CallHttpRequestActionRequest (line 35) | type CallHttpRequestActionRequest = { index: number, pluginRefId: string...
type CallTemplateFunctionArgs (line 37) | type CallTemplateFunctionArgs = { purpose: RenderPurpose, values: { [key...
type CallTemplateFunctionRequest (line 39) | type CallTemplateFunctionRequest = { name: string, args: CallTemplateFun...
type CallTemplateFunctionResponse (line 41) | type CallTemplateFunctionResponse = { value: string | null, error?: stri...
type CallWebsocketRequestActionArgs (line 43) | type CallWebsocketRequestActionArgs = { websocketRequest: WebsocketReque...
type CallWebsocketRequestActionRequest (line 45) | type CallWebsocketRequestActionRequest = { index: number, pluginRefId: s...
type CallWorkspaceActionArgs (line 47) | type CallWorkspaceActionArgs = { workspace: Workspace, };
type CallWorkspaceActionRequest (line 49) | type CallWorkspaceActionRequest = { index: number, pluginRefId: string, ...
type CloseWindowRequest (line 51) | type CloseWindowRequest = { label: string, };
type Color (line 53) | type Color = "primary" | "secondary" | "info" | "success" | "notice" | "...
type CompletionOptionType (line 55) | type CompletionOptionType = "constant" | "variable";
type Content (line 57) | type Content = { "type": "text", content: string, } | { "type": "markdow...
type CopyTextRequest (line 59) | type CopyTextRequest = { text: string, };
type DeleteKeyValueRequest (line 61) | type DeleteKeyValueRequest = { key: string, };
type DeleteKeyValueResponse (line 63) | type DeleteKeyValueResponse = { deleted: boolean, };
type DeleteModelRequest (line 65) | type DeleteModelRequest = { model: string, id: string, };
type DeleteModelResponse (line 67) | type DeleteModelResponse = { model: AnyModel, };
type DialogSize (line 69) | type DialogSize = "sm" | "md" | "lg" | "full" | "dynamic";
type EditorLanguage (line 71) | type EditorLanguage = "text" | "javascript" | "json" | "html" | "xml" | ...
type EmptyPayload (line 73) | type EmptyPayload = {};
type ErrorResponse (line 75) | type ErrorResponse = { error: string, };
type ExportHttpRequestRequest (line 77) | type ExportHttpRequestRequest = { httpRequest: HttpRequest, };
type ExportHttpRequestResponse (line 79) | type ExportHttpRequestResponse = { content: string, };
type FileFilter (line 81) | type FileFilter = { name: string,
type FilterRequest (line 87) | type FilterRequest = { content: string, filter: string, };
type FilterResponse (line 89) | type FilterResponse = { content: string, error?: string, };
type FindHttpResponsesRequest (line 91) | type FindHttpResponsesRequest = { requestId: string, limit?: number, };
type FindHttpResponsesResponse (line 93) | type FindHttpResponsesResponse = { httpResponses: Array<HttpResponse>, };
type FolderAction (line 95) | type FolderAction = { label: string, icon?: Icon, };
type FormInput (line 97) | type FormInput = { "type": "text" } & FormInputText | { "type": "editor"...
type FormInputAccordion (line 99) | type FormInputAccordion = { label: string, inputs?: Array<FormInput>, hi...
type FormInputBanner (line 101) | type FormInputBanner = { inputs?: Array<FormInput>, hidden?: boolean, co...
type FormInputBase (line 103) | type FormInputBase = {
type FormInputCheckbox (line 134) | type FormInputCheckbox = {
type FormInputEditor (line 165) | type FormInputEditor = {
type FormInputFile (line 212) | type FormInputFile = {
type FormInputHStack (line 251) | type FormInputHStack = { inputs?: Array<FormInput>, hidden?: boolean, };
type FormInputHttpRequest (line 253) | type FormInputHttpRequest = {
type FormInputKeyValue (line 284) | type FormInputKeyValue = {
type FormInputMarkdown (line 315) | type FormInputMarkdown = { content: string, hidden?: boolean, };
type FormInputSelect (line 317) | type FormInputSelect = {
type FormInputSelectOption (line 352) | type FormInputSelectOption = { label: string, value: string, };
type FormInputText (line 354) | type FormInputText = {
type GenericCompletionOption (line 397) | type GenericCompletionOption = { label: string, detail?: string, info?: ...
type GetCookieValueRequest (line 399) | type GetCookieValueRequest = { name: string, };
type GetCookieValueResponse (line 401) | type GetCookieValueResponse = { value: string | null, };
type GetFolderActionsResponse (line 403) | type GetFolderActionsResponse = { actions: Array<FolderAction>, pluginRe...
type GetGrpcRequestActionsResponse (line 405) | type GetGrpcRequestActionsResponse = { actions: Array<GrpcRequestAction>...
type GetHttpAuthenticationConfigRequest (line 407) | type GetHttpAuthenticationConfigRequest = { contextId: string, values: {...
type GetHttpAuthenticationConfigResponse (line 409) | type GetHttpAuthenticationConfigResponse = { args: Array<FormInput>, plu...
type GetHttpAuthenticationSummaryResponse (line 411) | type GetHttpAuthenticationSummaryResponse = { name: string, label: strin...
type GetHttpRequestActionsResponse (line 413) | type GetHttpRequestActionsResponse = { actions: Array<HttpRequestAction>...
type GetHttpRequestByIdRequest (line 415) | type GetHttpRequestByIdRequest = { id: string, };
type GetHttpRequestByIdResponse (line 417) | type GetHttpRequestByIdResponse = { httpRequest: HttpRequest | null, };
type GetKeyValueRequest (line 419) | type GetKeyValueRequest = { key: string, };
type GetKeyValueResponse (line 421) | type GetKeyValueResponse = { value?: string, };
type GetTemplateFunctionConfigRequest (line 423) | type GetTemplateFunctionConfigRequest = { contextId: string, name: strin...
type GetTemplateFunctionConfigResponse (line 425) | type GetTemplateFunctionConfigResponse = { function: TemplateFunction, p...
type GetTemplateFunctionSummaryResponse (line 427) | type GetTemplateFunctionSummaryResponse = { functions: Array<TemplateFun...
type GetThemesRequest (line 429) | type GetThemesRequest = Record<string, never>;
type GetThemesResponse (line 431) | type GetThemesResponse = { themes: Array<Theme>, };
type GetWebsocketRequestActionsResponse (line 433) | type GetWebsocketRequestActionsResponse = { actions: Array<WebsocketRequ...
type GetWorkspaceActionsResponse (line 435) | type GetWorkspaceActionsResponse = { actions: Array<WorkspaceAction>, pl...
type GrpcRequestAction (line 437) | type GrpcRequestAction = { label: string, icon?: Icon, };
type HttpAuthenticationAction (line 439) | type HttpAuthenticationAction = { label: string, icon?: Icon, };
type HttpHeader (line 441) | type HttpHeader = { name: string, value: string, };
type HttpRequestAction (line 443) | type HttpRequestAction = { label: string, icon?: Icon, };
type Icon (line 445) | type Icon = "alert_triangle" | "check" | "check_circle" | "chevron_down"...
type ImportRequest (line 447) | type ImportRequest = { content: string, };
type ImportResources (line 449) | type ImportResources = { workspaces: Array<Workspace>, environments: Arr...
type ImportResponse (line 451) | type ImportResponse = { resources: ImportResources, };
type InternalEvent (line 453) | type InternalEvent = { id: string, pluginRefId: string, pluginName: stri...
type InternalEventPayload (line 455) | type InternalEventPayload = { "type": "boot_request" } & BootRequest | {...
type JsonPrimitive (line 457) | type JsonPrimitive = string | number | boolean | null;
type ListCookieNamesRequest (line 459) | type ListCookieNamesRequest = {};
type ListCookieNamesResponse (line 461) | type ListCookieNamesResponse = { names: Array<string>, };
type ListFoldersRequest (line 463) | type ListFoldersRequest = {};
type ListFoldersResponse (line 465) | type ListFoldersResponse = { folders: Array<Folder>, };
type ListHttpRequestsRequest (line 467) | type ListHttpRequestsRequest = { folderId?: string, };
type ListHttpRequestsResponse (line 469) | type ListHttpRequestsResponse = { httpRequests: Array<HttpRequest>, };
type ListOpenWorkspacesRequest (line 471) | type ListOpenWorkspacesRequest = Record<string, never>;
type ListOpenWorkspacesResponse (line 473) | type ListOpenWorkspacesResponse = { workspaces: Array<WorkspaceInfo>, };
type OpenExternalUrlRequest (line 475) | type OpenExternalUrlRequest = { url: string, };
type OpenWindowRequest (line 477) | type OpenWindowRequest = { url: string,
type PluginContext (line 483) | type PluginContext = { id: string, label: string | null, workspaceId: st...
type PromptFormRequest (line 485) | type PromptFormRequest = { id: string, title: string, description?: stri...
type PromptFormResponse (line 487) | type PromptFormResponse = { values: { [key in string]?: JsonPrimitive } ...
type PromptTextRequest (line 489) | type PromptTextRequest = { id: string, title: string, label: string, des...
type PromptTextResponse (line 503) | type PromptTextResponse = { value: string | null, };
type ReloadResponse (line 505) | type ReloadResponse = { silent: boolean, };
type RenderGrpcRequestRequest (line 507) | type RenderGrpcRequestRequest = { grpcRequest: GrpcRequest, purpose: Ren...
type RenderGrpcRequestResponse (line 509) | type RenderGrpcRequestResponse = { grpcRequest: GrpcRequest, };
type RenderHttpRequestRequest (line 511) | type RenderHttpRequestRequest = { httpRequest: HttpRequest, purpose: Ren...
type RenderHttpRequestResponse (line 513) | type RenderHttpRequestResponse = { httpRequest: HttpRequest, };
type RenderPurpose (line 515) | type RenderPurpose = "send" | "preview";
type SendHttpRequestRequest (line 517) | type SendHttpRequestRequest = { httpRequest: Partial<HttpRequest>, };
type SendHttpRequestResponse (line 519) | type SendHttpRequestResponse = { httpResponse: HttpResponse, };
type SetKeyValueRequest (line 521) | type SetKeyValueRequest = { key: string, value: string, };
type SetKeyValueResponse (line 523) | type SetKeyValueResponse = {};
type ShowToastRequest (line 525) | type ShowToastRequest = { message: string, color?: Color, icon?: Icon, t...
type TemplateFunction (line 527) | type TemplateFunction = { name: string, previewType?: TemplateFunctionPr...
type TemplateFunctionArg (line 541) | type TemplateFunctionArg = FormInput;
type TemplateFunctionPreviewType (line 543) | type TemplateFunctionPreviewType = "live" | "click" | "none";
type TemplateRenderRequest (line 545) | type TemplateRenderRequest = { data: JsonValue, purpose: RenderPurpose, };
type TemplateRenderResponse (line 547) | type TemplateRenderResponse = { data: JsonValue, };
type Theme (line 549) | type Theme = {
type ThemeComponentColors (line 571) | type ThemeComponentColors = { surface?: string, surfaceHighlight?: strin...
type ThemeComponents (line 573) | type ThemeComponents = { dialog?: ThemeComponentColors, menu?: ThemeComp...
type UpsertModelRequest (line 575) | type UpsertModelRequest = { model: AnyModel, };
type UpsertModelResponse (line 577) | type UpsertModelResponse = { model: AnyModel, };
type WebsocketRequestAction (line 579) | type WebsocketRequestAction = { label: string, icon?: Icon, };
type WindowInfoRequest (line 581) | type WindowInfoRequest = { label: string, };
type WindowInfoResponse (line 583) | type WindowInfoResponse = { requestId: string | null, environmentId: str...
type WindowNavigateEvent (line 585) | type WindowNavigateEvent = { url: string, };
type WindowSize (line 587) | type WindowSize = { width: number, height: number, };
type WorkspaceAction (line 589) | type WorkspaceAction = { label: string, icon?: Icon, };
type WorkspaceInfo (line 591) | type WorkspaceInfo = { id: string, name: string, };
FILE: crates/yaak-plugins/bindings/gen_models.ts
type AnyModel (line 3) | type AnyModel = CookieJar | Environment | Folder | GraphQlIntrospection ...
type ClientCertificate (line 5) | type ClientCertificate = { host: string, port: number | null, crtFile: s...
type Cookie (line 7) | type Cookie = { raw_cookie: string, domain: CookieDomain, expires: Cooki...
type CookieDomain (line 9) | type CookieDomain = { "HostOnly": string } | { "Suffix": string } | "Not...
type CookieExpires (line 11) | type CookieExpires = { "AtUtc": string } | "SessionEnd";
type CookieJar (line 13) | type CookieJar = { model: "cookie_jar", id: string, createdAt: string, u...
type DnsOverride (line 15) | type DnsOverride = { hostname: string, ipv4: Array<string>, ipv6: Array<...
type EditorKeymap (line 17) | type EditorKeymap = "default" | "vim" | "vscode" | "emacs";
type EncryptedKey (line 19) | type EncryptedKey = { encryptedKey: string, };
type Environment (line 21) | type Environment = { model: "environment", id: string, workspaceId: stri...
type EnvironmentVariable (line 28) | type EnvironmentVariable = { enabled?: boolean, name: string, value: str...
type Folder (line 30) | type Folder = { model: "folder", id: string, createdAt: string, updatedA...
type GraphQlIntrospection (line 32) | type GraphQlIntrospection = { model: "graphql_introspection", id: string...
type GrpcConnection (line 34) | type GrpcConnection = { model: "grpc_connection", id: string, createdAt:...
type GrpcConnectionState (line 36) | type GrpcConnectionState = "initialized" | "connected" | "closed";
type GrpcEvent (line 38) | type GrpcEvent = { model: "grpc_event", id: string, createdAt: string, u...
type GrpcEventType (line 40) | type GrpcEventType = "info" | "error" | "client_message" | "server_messa...
type GrpcRequest (line 42) | type GrpcRequest = { model: "grpc_request", id: string, createdAt: strin...
type HttpRequest (line 48) | type HttpRequest = { model: "http_request", id: string, createdAt: strin...
type HttpRequestHeader (line 54) | type HttpRequestHeader = { enabled?: boolean, name: string, value: strin...
type HttpResponse (line 56) | type HttpResponse = { model: "http_response", id: string, createdAt: str...
type HttpResponseEvent (line 58) | type HttpResponseEvent = { model: "http_response_event", id: string, cre...
type HttpResponseEventData (line 65) | type HttpResponseEventData = { "type": "setting", name: string, value: s...
type HttpResponseHeader (line 67) | type HttpResponseHeader = { name: string, value: string, };
type HttpResponseState (line 69) | type HttpResponseState = "initialized" | "connected" | "closed";
type HttpUrlParameter (line 71) | type HttpUrlParameter = { enabled?: boolean,
type KeyValue (line 78) | type KeyValue = { model: "key_value", id: string, createdAt: string, upd...
type Plugin (line 80) | type Plugin = { model: "plugin", id: string, createdAt: string, updatedA...
type PluginSource (line 82) | type PluginSource = "bundled" | "filesystem" | "registry";
type ProxySetting (line 84) | type ProxySetting = { "type": "enabled", http: string, https: string, au...
type ProxySettingAuth (line 86) | type ProxySettingAuth = { user: string, password: string, };
type Settings (line 88) | type Settings = { model: "settings", id: string, createdAt: string, upda...
type SyncState (line 90) | type SyncState = { model: "sync_state", id: string, workspaceId: string,...
type WebsocketConnection (line 92) | type WebsocketConnection = { model: "websocket_connection", id: string, ...
type WebsocketConnectionState (line 94) | type WebsocketConnectionState = "initialized" | "connected" | "closing" ...
type WebsocketEvent (line 96) | type WebsocketEvent = { model: "websocket_event", id: string, createdAt:...
type WebsocketEventType (line 98) | type WebsocketEventType = "binary" | "close" | "frame" | "open" | "ping"...
type WebsocketRequest (line 100) | type WebsocketRequest = { model: "websocket_request", id: string, create...
type Workspace (line 106) | type Workspace = { model: "workspace", id: string, createdAt: string, up...
type WorkspaceMeta (line 108) | type WorkspaceMeta = { model: "workspace_meta", id: string, workspaceId:...
FILE: crates/yaak-plugins/bindings/gen_search.ts
type PluginMetadata (line 3) | type PluginMetadata = { version: string, name: string, displayName: stri...
type PluginVersion (line 5) | type PluginVersion = { id: string, version: string, url: string, descrip...
FILE: crates/yaak-plugins/bindings/serde_json/JsonValue.ts
type JsonValue (line 3) | type JsonValue = number | string | boolean | Array<JsonValue> | { [key i...
FILE: crates/yaak-plugins/index.ts
function searchPlugins (line 8) | async function searchPlugins(query: string) {
function installPlugin (line 12) | async function installPlugin(name: string, version: string | null) {
function uninstallPlugin (line 16) | async function uninstallPlugin(pluginId: string) {
function checkPluginUpdates (line 20) | async function checkPluginUpdates() {
function updateAllPlugins (line 24) | async function updateAllPlugins() {
function installPluginFromDirectory (line 28) | async function installPluginFromDirectory(directory: string) {
FILE: crates/yaak-plugins/src/api.rs
function get_plugin (line 13) | pub async fn get_plugin(
function download_plugin_archive (line 32) | pub async fn download_plugin_archive(
function check_plugin_updates (line 55) | pub async fn check_plugin_updates(
function search_plugins (line 83) | pub async fn search_plugins(http_client: &Client, query: &str) -> Result...
function build_url (line 93) | fn build_url(path: &str) -> Url {
type PluginVersion (line 101) | pub struct PluginVersion {
type PluginSearchResponse (line 118) | pub struct PluginSearchResponse {
type PluginNameVersion (line 125) | pub struct PluginNameVersion {
type PluginUpdatesResponse (line 133) | pub struct PluginUpdatesResponse {
FILE: crates/yaak-plugins/src/checksum.rs
function compute_checksum (line 3) | pub(crate) fn compute_checksum(bytes: impl AsRef<[u8]>) -> String {
FILE: crates/yaak-plugins/src/error.rs
type Error (line 8) | pub enum Error {
method serialize (line 56) | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::E...
type Result (line 64) | pub type Result<T> = std::result::Result<T, Error>;
FILE: crates/yaak-plugins/src/events.rs
type InternalEvent (line 13) | pub struct InternalEvent {
type InternalEventRawPayload (line 27) | pub(crate) struct InternalEventRawPayload {
type PluginContext (line 39) | pub struct PluginContext {
method new_empty (line 46) | pub fn new_empty() -> Self {
method new (line 50) | pub fn new(label: Option<String>, workspace_id: Option<String>) -> Self {
type InternalEventPayload (line 58) | pub enum InternalEventPayload {
method type_name (line 196) | pub fn type_name(&self) -> String {
type EmptyPayload (line 209) | pub struct EmptyPayload {}
type ErrorResponse (line 214) | pub struct ErrorResponse {
type BootRequest (line 221) | pub struct BootRequest {
type ReloadResponse (line 229) | pub struct ReloadResponse {
type ImportRequest (line 236) | pub struct ImportRequest {
type ImportResponse (line 243) | pub struct ImportResponse {
type FilterRequest (line 250) | pub struct FilterRequest {
type FilterResponse (line 258) | pub struct FilterResponse {
type ExportHttpRequestRequest (line 267) | pub struct ExportHttpRequestRequest {
type ExportHttpRequestResponse (line 274) | pub struct ExportHttpRequestResponse {
type SendHttpRequestRequest (line 281) | pub struct SendHttpRequestRequest {
type SendHttpRequestResponse (line 289) | pub struct SendHttpRequestResponse {
type ListCookieNamesRequest (line 296) | pub struct ListCookieNamesRequest {}
type ListCookieNamesResponse (line 301) | pub struct ListCookieNamesResponse {
type GetCookieValueRequest (line 308) | pub struct GetCookieValueRequest {
type GetCookieValueResponse (line 315) | pub struct GetCookieValueResponse {
type CopyTextRequest (line 322) | pub struct CopyTextRequest {
type RenderHttpRequestRequest (line 329) | pub struct RenderHttpRequestRequest {
type RenderHttpRequestResponse (line 337) | pub struct RenderHttpRequestResponse {
type RenderGrpcRequestRequest (line 344) | pub struct RenderGrpcRequestRequest {
type RenderGrpcRequestResponse (line 352) | pub struct RenderGrpcRequestResponse {
type GetThemesRequest (line 359) | pub struct GetThemesRequest {}
type ThemeComponents (line 364) | pub struct ThemeComponents {
type ThemeComponentColors (line 394) | pub struct ThemeComponentColors {
type Theme (line 442) | pub struct Theme {
type GetThemesResponse (line 459) | pub struct GetThemesResponse {
type TemplateRenderRequest (line 466) | pub struct TemplateRenderRequest {
type TemplateRenderResponse (line 474) | pub struct TemplateRenderResponse {
type OpenWindowRequest (line 481) | pub struct OpenWindowRequest {
type OpenExternalUrlRequest (line 499) | pub struct OpenExternalUrlRequest {
type WindowSize (line 506) | pub struct WindowSize {
type CloseWindowRequest (line 514) | pub struct CloseWindowRequest {
type WindowNavigateEvent (line 521) | pub struct WindowNavigateEvent {
type ShowToastRequest (line 528) | pub struct ShowToastRequest {
type PromptTextRequest (line 544) | pub struct PromptTextRequest {
type PromptTextResponse (line 573) | pub struct PromptTextResponse {
type PromptFormRequest (line 580) | pub struct PromptFormRequest {
type DialogSize (line 597) | pub enum DialogSize {
type PromptFormResponse (line 608) | pub struct PromptFormResponse {
type WindowInfoRequest (line 617) | pub struct WindowInfoRequest {
type WindowInfoResponse (line 624) | pub struct WindowInfoResponse {
type ListOpenWorkspacesRequest (line 634) | pub struct ListOpenWorkspacesRequest {}
type ListOpenWorkspacesResponse (line 639) | pub struct ListOpenWorkspacesResponse {
type WorkspaceInfo (line 646) | pub struct WorkspaceInfo {
type Color (line 656) | pub enum Color {
method default (line 667) | fn default() -> Self {
type Icon (line 675) | pub enum Icon {
type GetHttpAuthenticationSummaryResponse (line 694) | pub struct GetHttpAuthenticationSummaryResponse {
type HttpAuthenticationAction (line 703) | pub struct HttpAuthenticationAction {
type GetHttpAuthenticationConfigRequest (line 713) | pub struct GetHttpAuthenticationConfigRequest {
type GetHttpAuthenticationConfigResponse (line 721) | pub struct GetHttpAuthenticationConfigResponse {
type HttpHeader (line 732) | pub struct HttpHeader {
type CallHttpAuthenticationRequest (line 740) | pub struct CallHttpAuthenticationRequest {
type CallHttpAuthenticationActionRequest (line 751) | pub struct CallHttpAuthenticationActionRequest {
type CallHttpAuthenticationActionArgs (line 760) | pub struct CallHttpAuthenticationActionArgs {
type JsonPrimitive (line 768) | pub enum JsonPrimitive {
method from (line 776) | fn from(value: serde_json::Value) -> Self {
type CallHttpAuthenticationResponse (line 790) | pub struct CallHttpAuthenticationResponse {
type GetTemplateFunctionSummaryResponse (line 805) | pub struct GetTemplateFunctionSummaryResponse {
type GetTemplateFunctionConfigRequest (line 813) | pub struct GetTemplateFunctionConfigRequest {
type GetTemplateFunctionConfigResponse (line 822) | pub struct GetTemplateFunctionConfigResponse {
type TemplateFunctionPreviewType (line 830) | pub enum TemplateFunctionPreviewType {
type TemplateFunction (line 839) | pub struct TemplateFunction {
type TemplateFunctionArg (line 863) | pub enum TemplateFunctionArg {
type FormInput (line 870) | pub enum FormInput {
type FormInputBase (line 887) | pub struct FormInputBase {
type FormInputText (line 923) | pub struct FormInputText {
type EditorLanguage (line 946) | pub enum EditorLanguage {
method default (line 973) | fn default() -> Self {
type FormInputEditor (line 981) | pub struct FormInputEditor {
type GenericCompletionOption (line 1011) | pub struct GenericCompletionOption {
type CompletionOptionType (line 1031) | pub enum CompletionOptionType {
type FormInputHttpRequest (line 1039) | pub struct FormInputHttpRequest {
type FormInputFile (line 1047) | pub struct FormInputFile {
type FileFilter (line 1074) | pub struct FileFilter {
type FormInputSelect (line 1083) | pub struct FormInputSelect {
type FormInputCheckbox (line 1094) | pub struct FormInputCheckbox {
type FormInputSelectOption (line 1102) | pub struct FormInputSelectOption {
type FormInputAccordion (line 1110) | pub struct FormInputAccordion {
type FormInputHStack (line 1123) | pub struct FormInputHStack {
type FormInputBanner (line 1134) | pub struct FormInputBanner {
type FormInputMarkdown (line 1148) | pub struct FormInputMarkdown {
type FormInputKeyValue (line 1158) | pub struct FormInputKeyValue {
type Content (line 1166) | pub enum Content {
method default (line 1172) | fn default() -> Self {
type CallTemplateFunctionRequest (line 1180) | pub struct CallTemplateFunctionRequest {
type CallTemplateFunctionResponse (line 1188) | pub struct CallTemplateFunctionResponse {
type CallTemplateFunctionArgs (line 1197) | pub struct CallTemplateFunctionArgs {
type RenderPurpose (line 1205) | pub enum RenderPurpose {
method default (line 1211) | fn default() -> Self {
type GetHttpRequestActionsResponse (line 1219) | pub struct GetHttpRequestActionsResponse {
type HttpRequestAction (line 1227) | pub struct HttpRequestAction {
type CallHttpRequestActionRequest (line 1236) | pub struct CallHttpRequestActionRequest {
type CallHttpRequestActionArgs (line 1245) | pub struct CallHttpRequestActionArgs {
type GetWebsocketRequestActionsResponse (line 1252) | pub struct GetWebsocketRequestActionsResponse {
type WebsocketRequestAction (line 1260) | pub struct WebsocketRequestAction {
type CallWebsocketRequestActionRequest (line 1269) | pub struct CallWebsocketRequestActionRequest {
type CallWebsocketRequestActionArgs (line 1278) | pub struct CallWebsocketRequestActionArgs {
type GetWorkspaceActionsResponse (line 1285) | pub struct GetWorkspaceActionsResponse {
type WorkspaceAction (line 1293) | pub struct WorkspaceAction {
type CallWorkspaceActionRequest (line 1302) | pub struct CallWorkspaceActionRequest {
type CallWorkspaceActionArgs (line 1311) | pub struct CallWorkspaceActionArgs {
type GetFolderActionsResponse (line 1318) | pub struct GetFolderActionsResponse {
type FolderAction (line 1326) | pub struct FolderAction {
type CallFolderActionRequest (line 1335) | pub struct CallFolderActionRequest {
type CallFolderActionArgs (line 1344) | pub struct CallFolderActionArgs {
type GetGrpcRequestActionsResponse (line 1351) | pub struct GetGrpcRequestActionsResponse {
type GrpcRequestAction (line 1359) | pub struct GrpcRequestAction {
type CallGrpcRequestActionRequest (line 1368) | pub struct CallGrpcRequestActionRequest {
type CallGrpcRequestActionArgs (line 1377) | pub struct CallGrpcRequestActionArgs {
type GetHttpRequestByIdRequest (line 1385) | pub struct GetHttpRequestByIdRequest {
type GetHttpRequestByIdResponse (line 1392) | pub struct GetHttpRequestByIdResponse {
type FindHttpResponsesRequest (line 1399) | pub struct FindHttpResponsesRequest {
type FindHttpResponsesResponse (line 1408) | pub struct FindHttpResponsesResponse {
type ListHttpRequestsRequest (line 1415) | pub struct ListHttpRequestsRequest {
type ListHttpRequestsResponse (line 1423) | pub struct ListHttpRequestsResponse {
type ListFoldersRequest (line 1430) | pub struct ListFoldersRequest {}
type ListFoldersResponse (line 1435) | pub struct ListFoldersResponse {
type UpsertModelRequest (line 1442) | pub struct UpsertModelRequest {
type UpsertModelResponse (line 1449) | pub struct UpsertModelResponse {
type DeleteModelRequest (line 1456) | pub struct DeleteModelRequest {
type DeleteModelResponse (line 1464) | pub struct DeleteModelResponse {
type ImportResources (line 1471) | pub struct ImportResources {
type GetKeyValueRequest (line 1483) | pub struct GetKeyValueRequest {
type GetKeyValueResponse (line 1490) | pub struct GetKeyValueResponse {
type SetKeyValueRequest (line 1498) | pub struct SetKeyValueRequest {
type SetKeyValueResponse (line 1506) | pub struct SetKeyValueResponse {}
type DeleteKeyValueRequest (line 1511) | pub struct DeleteKeyValueRequest {
type DeleteKeyValueResponse (line 1518) | pub struct DeleteKeyValueResponse {
FILE: crates/yaak-plugins/src/install.rs
function delete_and_uninstall (line 17) | pub async fn delete_and_uninstall(
function download_and_install (line 37) | pub async fn download_and_install(
FILE: crates/yaak-plugins/src/manager.rs
type PluginManager (line 44) | pub struct PluginManager {
method new (line 71) | pub async fn new(
method take_init_errors (line 200) | pub async fn take_init_errors(&self) -> Vec<(String, String)> {
method get_plugins_dir (line 205) | pub fn get_plugins_dir(&self) -> PathBuf {
method list_bundled_plugin_dirs (line 219) | pub async fn list_bundled_plugin_dirs(&self) -> Result<Vec<String>> {
method resolve_plugins_for_runtime_from_db (line 225) | pub async fn resolve_plugins_for_runtime_from_db(&self, plugins: Vec<P...
method resolve_plugins_for_runtime (line 243) | fn resolve_plugins_for_runtime(
method uninstall (line 276) | pub async fn uninstall(&self, plugin_context: &PluginContext, dir: &st...
method remove_plugin (line 281) | async fn remove_plugin(
method add_plugin (line 307) | pub async fn add_plugin(&self, plugin_context: &PluginContext, plugin:...
method initialize_all_plugins (line 353) | pub async fn initialize_all_plugins(
method subscribe (line 391) | pub async fn subscribe(&self, label: &str) -> (String, mpsc::Receiver<...
method unsubscribe (line 398) | pub async fn unsubscribe(&self, rx_id: &str) {
method terminate (line 402) | pub async fn terminate(&self) {
method reply (line 416) | pub async fn reply(
method get_plugin_by_ref_id (line 431) | pub async fn get_plugin_by_ref_id(&self, ref_id: &str) -> Option<Plugi...
method get_plugin_by_dir (line 435) | pub async fn get_plugin_by_dir(&self, dir: &str) -> Option<PluginHandl...
method get_plugin_by_name (line 439) | pub async fn get_plugin_by_name(&self, name: &str) -> Option<PluginHan...
method send_to_plugin_and_wait (line 449) | async fn send_to_plugin_and_wait(
method send_and_wait (line 477) | async fn send_and_wait(
method send_to_plugins_and_wait (line 487) | async fn send_to_plugins_and_wait(
method get_themes (line 569) | pub async fn get_themes(
method get_grpc_request_actions (line 591) | pub async fn get_grpc_request_actions(
method get_http_request_actions (line 613) | pub async fn get_http_request_actions(
method get_websocket_request_actions (line 635) | pub async fn get_websocket_request_actions(
method get_workspace_actions (line 657) | pub async fn get_workspace_actions(
method get_folder_actions (line 679) | pub async fn get_folder_actions(
method get_template_function_config (line 703) | pub async fn get_template_function_config(
method call_http_request_action (line 758) | pub async fn call_http_request_action(
method call_websocket_request_action (line 775) | pub async fn call_websocket_request_action(
method call_workspace_action (line 792) | pub async fn call_workspace_action(
method call_folder_action (line 809) | pub async fn call_folder_action(
method call_grpc_request_action (line 826) | pub async fn call_grpc_request_action(
method get_http_authentication_summaries (line 843) | pub async fn get_http_authentication_summaries(
method get_http_authentication_config (line 872) | pub async fn get_http_authentication_config(
method call_http_authentication_action (line 916) | pub async fn call_http_authentication_action(
method call_http_authentication (line 947) | pub async fn call_http_authentication(
method get_template_function_summaries (line 991) | pub async fn get_template_function_summaries(
method call_template_function (line 1019) | pub async fn call_template_function(
method import_data (line 1062) | pub async fn import_data(
method filter_data (line 1089) | pub async fn filter_data(
type PluginInitCallback (line 58) | pub type PluginInitCallback = Box<dyn Fn(ShowToastRequest) + Send + Sync>;
function source_priority (line 1130) | fn source_priority(source: &PluginSource) -> i32 {
function prefer_plugin (line 1138) | fn prefer_plugin(candidate: &Plugin, existing: &Plugin) -> bool {
function read_plugins_dir (line 1148) | async fn read_plugins_dir(dir: &PathBuf) -> Result<Vec<String>> {
function fix_windows_paths (line 1163) | fn fix_windows_paths(p: &PathBuf) -> String {
FILE: crates/yaak-plugins/src/native_template_functions.rs
function template_function_secure (line 26) | pub(crate) fn template_function_secure() -> TemplateFunction {
function template_function_keyring (line 48) | pub(crate) fn template_function_keyring() -> TemplateFunction {
function template_function_secure_run (line 111) | pub fn template_function_secure_run(
function template_function_secure_transform_arg (line 147) | pub fn template_function_secure_transform_arg(
function decrypt_secure_template_function (line 178) | pub fn decrypt_secure_template_function(
function encrypt_secure_template_function (line 217) | pub fn encrypt_secure_template_function(
function template_function_keychain_run (line 249) | pub fn template_function_keychain_run(args: HashMap<String, serde_json::...
FILE: crates/yaak-plugins/src/nodejs.rs
function start_nodejs_plugin_runtime (line 18) | pub async fn start_nodejs_plugin_runtime(
FILE: crates/yaak-plugins/src/plugin_handle.rs
type PluginHandle (line 10) | pub struct PluginHandle {
method new (line 19) | pub fn new(dir: &str, enabled: bool, tx: mpsc::Sender<InternalEvent>) ...
method info (line 32) | pub fn info(&self) -> PluginMetadata {
method build_event_to_send (line 36) | pub fn build_event_to_send(
method build_event_to_send_raw (line 45) | pub(crate) fn build_event_to_send_raw(
method send (line 62) | pub async fn send(&self, event: &InternalEvent) -> Result<()> {
FILE: crates/yaak-plugins/src/plugin_meta.rs
type PluginMetadata (line 10) | pub struct PluginMetadata {
function get_plugin_meta (line 19) | pub fn get_plugin_meta(plugin_dir: &Path) -> Result<PluginMetadata> {
type PackageJson (line 50) | struct PackageJson {
type RepositoryField (line 61) | enum RepositoryField {
FILE: crates/yaak-plugins/src/server_ws.rs
type PluginRuntimeServerWebsocket (line 12) | pub(crate) struct PluginRuntimeServerWebsocket {
method new (line 20) | pub fn new(
method listen (line 33) | pub async fn listen(&self, listener: TcpListener) {
method accept_connection (line 39) | async fn accept_connection(&self, stream: TcpStream) {
FILE: crates/yaak-plugins/src/template_callback.rs
type PluginTemplateCallback (line 19) | pub struct PluginTemplateCallback {
method new (line 27) | pub fn new(
method run (line 43) | async fn run(&self, fn_name: &str, args: HashMap<String, serde_json::Val...
method transform_arg (line 75) | fn transform_arg(&self, fn_name: &str, arg_name: &str, arg_value: &str) ...
FILE: crates/yaak-plugins/src/util.rs
function gen_id (line 4) | pub fn gen_id() -> String {
FILE: crates/yaak-sse/bindings/sse.ts
type ServerSentEvent (line 3) | type ServerSentEvent = { eventType: string, data: string, id: string | n...
FILE: crates/yaak-sse/src/sse.rs
type ServerSentEvent (line 7) | pub struct ServerSentEvent {
FILE: crates/yaak-sync/bindings/gen_models.ts
type DnsOverride (line 3) | type DnsOverride = { hostname: string, ipv4: Array<string>, ipv6: Array<...
type Environment (line 5) | type Environment = { model: "environment", id: string, workspaceId: stri...
type EnvironmentVariable (line 7) | type EnvironmentVariable = { enabled?: boolean, name: string, value: str...
type Folder (line 9) | type Folder = { model: "folder", id: string, createdAt: string, updatedA...
type GrpcRequest (line 11) | type GrpcRequest = { model: "grpc_request", id: string, createdAt: strin...
type HttpRequest (line 13) | type HttpRequest = { model: "http_request", id: string, createdAt: strin...
type HttpRequestHeader (line 15) | type HttpRequestHeader = { enabled?: boolean, name: string, value: strin...
type HttpUrlParameter (line 17) | type HttpUrlParameter = { enabled?: boolean, name: string, value: string...
type SyncModel (line 19) | type SyncModel = { "type": "workspace" } & Workspace | { "type": "enviro...
type SyncState (line 21) | type SyncState = { model: "sync_state", id: string, workspaceId: string,...
type WebsocketRequest (line 23) | type WebsocketRequest = { model: "websocket_request", id: string, create...
type Workspace (line 25) | type Workspace = { model: "workspace", id: string, createdAt: string, up...
FILE: crates/yaak-sync/bindings/gen_sync.ts
type FsCandidate (line 4) | type FsCandidate = { "type": "FsCandidate", model: SyncModel, relPath: s...
type SyncOp (line 6) | type SyncOp = { "type": "fsCreate", model: SyncModel, } | { "type": "fsU...
FILE: crates/yaak-sync/bindings/gen_watch.ts
type WatchEvent (line 3) | type WatchEvent = { paths: Array<string>, kind: string, };
FILE: crates/yaak-sync/bindings/git.ts
type GitCommit (line 3) | type GitCommit = { author: string, when: string, message: string | null, };
type GitStatus (line 5) | type GitStatus = "added" | "conflict" | "current" | "modified" | "remove...
type GitStatusEntry (line 7) | type GitStatusEntry = { relaPath: string, status: GitStatus, staged: boo...
FILE: crates/yaak-sync/index.ts
function calculateSync (line 9) | async function calculateSync(workspaceId: string, syncDir: string) {
function calculateSyncFsOnly (line 16) | async function calculateSyncFsOnly(dir: string) {
function applySync (line 20) | async function applySync(workspaceId: string, syncDir: string, syncOps: ...
function watchWorkspaceFiles (line 28) | function watchWorkspaceFiles(
function unlistenToWatcher (line 55) | function unlistenToWatcher(unlistenEvent: string) {
function getWatchKeys (line 61) | function getWatchKeys() {
function setWatchKeys (line 65) | function setWatchKeys(keys: string[]) {
function addWatchKey (line 69) | function addWatchKey(key: string) {
function removeWatchKey (line 74) | function removeWatchKey(key: string) {
FILE: crates/yaak-sync/src/error.rs
type Error (line 6) | pub enum Error {
method serialize (line 36) | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::E...
type Result (line 44) | pub type Result<T> = std::result::Result<T, Error>;
FILE: crates/yaak-sync/src/models.rs
type SyncModel (line 18) | pub enum SyncModel {
method deserialize (line 28) | fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
method from_bytes (line 101) | pub fn from_bytes(content: Vec<u8>, file_path: &Path) -> Result<Option...
method from_file (line 135) | pub fn from_file(file_path: &Path) -> Result<Option<(SyncModel, String...
method to_file_contents (line 144) | pub fn to_file_contents(&self, rel_path: &Path) -> Result<(Vec<u8>, St...
method id (line 159) | pub fn id(&self) -> String {
method workspace_id (line 170) | pub fn workspace_id(&self) -> String {
method updated_at (line 181) | pub fn updated_at(&self) -> NaiveDateTime {
type Error (line 194) | type Error = crate::error::Error;
method try_from (line 196) | fn try_from(value: AnyModel) -> Result<Self> {
function migrate_environment (line 86) | fn migrate_environment(obj: &mut Mapping) {
function deserializes_environment_via_syncmodel_with_fixups (line 230) | fn deserializes_environment_via_syncmodel_with_fixups() -> Result<()> {
FILE: crates/yaak-sync/src/sync.rs
type SyncOp (line 20) | pub enum SyncOp {
method workspace_id (line 49) | fn workspace_id(&self) -> String {
method fmt (line 63) | fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
type DbCandidate (line 81) | pub enum DbCandidate {
method model_id (line 89) | fn model_id(&self) -> String {
type FsCandidate (line 102) | pub struct FsCandidate {
function get_db_candidates (line 108) | pub fn get_db_candidates(
function get_fs_candidates (line 177) | pub fn get_fs_candidates(dir: &Path) -> Result<Vec<FsCandidate>> {
function compute_sync_ops (line 210) | pub fn compute_sync_ops(
function workspace_models (line 299) | fn workspace_models(db: &DbContext, version: &str, workspace_id: &str) -...
function apply_sync_ops (line 340) | pub fn apply_sync_ops(
type SyncStateOp (line 487) | pub enum SyncStateOp {
function apply_sync_state_ops (line 504) | pub fn apply_sync_state_ops(
function derive_model_filename (line 545) | fn derive_model_filename(m: &SyncModel) -> PathBuf {
function delete_model (line 550) | fn delete_model(db: &DbContext, model: &SyncModel) -> Result<()> {
FILE: crates/yaak-sync/src/watch.rs
type WatchEvent (line 13) | pub struct WatchEvent {
function watch_directory (line 22) | pub async fn watch_directory<F>(
FILE: crates/yaak-templates/bindings/parser.ts
type FnArg (line 3) | type FnArg = { name: string, value: Val, };
type Token (line 5) | type Token = { "type": "raw", text: string, } | { "type": "tag", val: Va...
type Tokens (line 7) | type Tokens = { tokens: Array<Token>, };
type Val (line 9) | type Val = { "type": "str", text: string, } | { "type": "var", name: str...
FILE: crates/yaak-templates/index.ts
function parseTemplate (line 5) | function parseTemplate(template: string) {
function escapeTemplate (line 9) | function escapeTemplate(template: string) {
function unescapeTemplate (line 13) | function unescapeTemplate(template: string) {
FILE: crates/yaak-templates/pkg/yaak_templates_bg.js
function __wbg_set_wasm (line 2) | function __wbg_set_wasm(val) {
function debugString (line 7) | function debugString(val) {
constant WASM_VECTOR_LEN (line 72) | let WASM_VECTOR_LEN = 0;
function getUint8ArrayMemory0 (line 76) | function getUint8ArrayMemory0() {
function passStringToWasm0 (line 100) | function passStringToWasm0(arg, malloc, realloc) {
function getDataViewMemory0 (line 141) | function getDataViewMemory0() {
function getStringFromWasm0 (line 154) | function getStringFromWasm0(ptr, len) {
function takeFromExternrefTable0 (line 159) | function takeFromExternrefTable0(idx) {
function escape_template (line 168) | function escape_template(template) {
function parse_template (line 182) | function parse_template(template) {
function unescape_template (line 196) | function unescape_template(template) {
function __wbg_new_405e22f390576ce2 (line 206) | function __wbg_new_405e22f390576ce2() {
function __wbg_new_78feb108b6472713 (line 211) | function __wbg_new_78feb108b6472713() {
function __wbg_set_37837023f3d740e8 (line 216) | function __wbg_set_37837023f3d740e8(arg0, arg1, arg2) {
function __wbg_set_3f1d0b984ed272ed (line 220) | function __wbg_set_3f1d0b984ed272ed(arg0, arg1, arg2) {
function __wbindgen_debug_string (line 224) | function __wbindgen_debug_string(arg0, arg1) {
function __wbindgen_init_externref_table (line 232) | function __wbindgen_init_externref_table() {
function __wbindgen_string_new (line 243) | function __wbindgen_string_new(arg0, arg1) {
function __wbindgen_throw (line 248) | function __wbindgen_throw(arg0, arg1) {
FILE: crates/yaak-templates/src/error.rs
type Error (line 6) | pub enum Error {
method into (line 27) | fn into(self) -> JsValue {
method serialize (line 18) | fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::E...
type Result (line 32) | pub type Result<T> = std::result::Result<T, Error>;
FILE: crates/yaak-templates/src/escape.rs
function escape_template (line 1) | pub fn escape_template(text: &str) -> String {
function unescape_template (line 37) | pub fn unescape_template(text: &str) -> String {
function test_escape_simple (line 84) | fn test_escape_simple() {
function test_already_escaped (line 91) | fn test_already_escaped() {
function test_double_backslash (line 98) | fn test_double_backslash() {
function test_escape_with_surrounding_text (line 105) | fn test_escape_with_surrounding_text() {
function test_preserve_already_escaped (line 112) | fn test_preserve_already_escaped() {
function test_multiple_occurrences (line 119) | fn test_multiple_occurrences() {
function test_mixed_escaped_and_unescaped (line 126) | fn test_mixed_escaped_and_unescaped() {
function test_unescape_simple (line 133) | fn test_unescape_simple() {
function test_unescape_with_text (line 140) | fn test_unescape_with_text() {
function test_unescape_multiple (line 147) | fn test_unescape_multiple() {
function test_unescape_double_backslash (line 154) | fn test_unescape_double_backslash() {
function test_unescape_plain_text (line 161) | fn test_unescape_plain_text() {
FILE: crates/yaak-templates/src/format_json.rs
type FormatState (line 1) | enum FormatState {
function format_json (line 8) | pub fn format_json(text: &str, tab: &str) -> String {
function test_simple_object (line 223) | fn test_simple_object() {
function test_escaped (line 237) | fn test_escaped() {
function test_simple_array (line 250) | fn test_simple_array() {
function test_extra_whitespace (line 266) | fn test_extra_whitespace() {
function test_invalid_json (line 287) | fn test_invalid_json() {
function test_skip_template_tags (line 306) | fn test_skip_template_tags() {
function test_graphql_response (line 319) | fn test_graphql_response() {
function test_immediate_close (line 355) | fn test_immediate_close() {
function test_more_closes (line 368) | fn test_more_closes() {
function test_line_comment_between_keys (line 380) | fn test_line_comment_between_keys() {
function test_line_comment_at_end (line 398) | fn test_line_comment_at_end() {
function test_block_comment (line 415) | fn test_block_comment() {
function test_comment_in_array (line 430) | fn test_comment_in_array() {
function test_comment_only_line (line 449) | fn test_comment_only_line() {
function test_multiline_block_comment (line 469) | fn test_multiline_block_comment() {
function test_comment_inside_string_ignored (line 501) | fn test_comment_inside_string_ignored() {
function test_comment_on_line_after_comma (line 515) | fn test_comment_on_line_after_comma() {
FILE: crates/yaak-templates/src/parser.rs
type Tokens (line 12) | pub struct Tokens {
method fmt (line 17) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
type FnArg (line 25) | pub struct FnArg {
method fmt (line 31) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
type Val (line 40) | pub enum Val {
method fmt (line 49) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
type Token (line 81) | pub enum Token {
method fmt (line 88) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
function transform_val (line 98) | fn transform_val<T: TemplateCallback>(val: &Val, cb: &T) -> Result<Val> {
function transform_args (line 121) | pub fn transform_args<T: TemplateCallback>(tokens: Tokens, cb: &T) -> Re...
type Parser (line 145) | pub struct Parser {
method new (line 153) | pub fn new(text: &str) -> Parser {
method parse (line 157) | pub fn parse(&mut self) -> Result<Tokens> {
method parse_tag (line 189) | fn parse_tag(&mut self) -> Result<Option<Token>> {
method debug_pos (line 210) | fn debug_pos(&self, x: &str) {
method parse_value (line 220) | fn parse_value(&mut self) -> Result<Option<Val>> {
method parse_fn (line 242) | fn parse_fn(&mut self) -> Result<Option<(String, Vec<FnArg>)>> {
method parse_fn_args (line 264) | fn parse_fn_args(&mut self) -> Result<Option<Vec<FnArg>>> {
method parse_ident (line 317) | fn parse_ident(&mut self) -> Option<String> {
method parse_fn_name (line 348) | fn parse_fn_name(&mut self) -> Option<String> {
method parse_string (line 374) | fn parse_string(&mut self) -> Result<Option<String>> {
method skip_whitespace (line 427) | fn skip_whitespace(&mut self) {
method next_char (line 437) | fn next_char(&mut self) -> char {
method peek_char (line 444) | fn peek_char(&self) -> char {
method push_token (line 449) | fn push_token(&mut self, token: Token) {
method match_str (line 460) | fn match_str(&mut self, value: &str) -> bool {
function escaped (line 484) | fn escaped() -> Result<()> {
function escaped_tricky (line 494) | fn escaped_tricky() -> Result<()> {
function var_simple (line 508) | fn var_simple() -> Result<()> {
function var_dashes (line 521) | fn var_dashes() -> Result<()> {
function var_underscores (line 535) | fn var_underscores() -> Result<()> {
function var_dots (line 549) | fn var_dots() -> Result<()> {
function var_prefixes (line 563) | fn var_prefixes() -> Result<()> {
function var_underscore_prefix (line 580) | fn var_underscore_prefix() -> Result<()> {
function var_boolean (line 594) | fn var_boolean() -> Result<()> {
function var_multiple_names_invalid (line 609) | fn var_multiple_names_invalid() -> Result<()> {
function tag_string (line 620) | fn tag_string() -> Result<()> {
function tag_b64_string (line 634) | fn tag_b64_string() -> Result<()> {
function var_surrounded (line 648) | fn var_surrounded() -> Result<()> {
function fn_simple (line 664) | fn fn_simple() -> Result<()> {
function fn_dot_name (line 678) | fn fn_dot_name() -> Result<()> {
function fn_ident_arg (line 692) | fn fn_ident_arg() -> Result<()> {
function fn_ident_args (line 714) | fn fn_ident_args() -> Result<()> {
function fn_mixed_args (line 737) | fn fn_mixed_args() -> Result<()> {
function fn_nested (line 764) | fn fn_nested() -> Result<()> {
function fn_nested_args (line 786) | fn fn_nested_args() -> Result<()> {
function token_display_var (line 823) | fn token_display_var() -> Result<()> {
function token_display_str (line 830) | fn token_display_str() -> Result<()> {
function token_display_complex_str (line 837) | fn token_display_complex_str() -> Result<()> {
function token_null_fn_arg (line 847) | fn token_null_fn_arg() -> Result<()> {
function token_display_fn (line 864) | fn token_display_fn() -> Result<()> {
function tokens_display (line 889) | fn tokens_display() -> Result<()> {
FILE: crates/yaak-templates/src/renderer.rs
constant MAX_DEPTH (line 9) | const MAX_DEPTH: usize = 50;
type TemplateCallback (line 11) | pub trait TemplateCallback {
method run (line 12) | fn run(
method transform_arg (line 18) | fn transform_arg(&self, fn_name: &str, arg_name: &str, arg_value: &str...
method run (line 183) | async fn run(
method transform_arg (line 191) | fn transform_arg(
method run (line 548) | async fn run(
method transform_arg (line 556) | fn transform_arg(
function render_json_value_raw (line 21) | pub async fn render_json_value_raw<T: TemplateCallback>(
function parse_and_render_at_depth (line 50) | async fn parse_and_render_at_depth<T: TemplateCallback>(
function parse_and_render (line 62) | pub async fn parse_and_render<T: TemplateCallback>(
type RenderErrorBehavior (line 71) | pub enum RenderErrorBehavior {
method handle (line 91) | pub fn handle(&self, r: Result<String>) -> Result<String> {
type RenderOptions (line 76) | pub struct RenderOptions {
method throw (line 81) | pub fn throw() -> Self {
method return_empty (line 85) | pub fn return_empty() -> Self {
function render (line 103) | pub async fn render<T: Te
Condensed preview — 1118 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,555K chars).
[
{
"path": ".claude/commands/release/generate-release-notes.md",
"chars": 2377,
"preview": "---\ndescription: Generate formatted release notes for Yaak releases\nallowed-tools: Bash(git tag:*)\n---\n\nGenerate formatt"
},
{
"path": ".claude/rules.md",
"chars": 909,
"preview": "# Project Rules\n\n## General Development\n\n- **NEVER** commit or push without explicit confirmation\n\n## Build and Lint\n\n- "
},
{
"path": ".claude-context.md",
"chars": 3401,
"preview": "# Claude Context: Detaching Tauri from Yaak\n\n## Goal\n\nMake Yaak runnable as a standalone CLI without Tauri as a dependen"
},
{
"path": ".codex/skills/release-generate-release-notes/SKILL.md",
"chars": 1964,
"preview": "---\nname: release-generate-release-notes\ndescription: Generate Yaak release notes from git history and PR metadata, incl"
},
{
"path": ".gitattributes",
"chars": 331,
"preview": "crates-tauri/yaak-app/vendored/**/* linguist-generated=true\ncrates-tauri/yaak-app/gen/schemas/**/* linguist-generated=tr"
},
{
"path": ".github/FUNDING.yml",
"chars": 63,
"preview": "# These are supported funding model platforms\n\ngithub: gschier\n"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 829,
"preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: \"\"\nlabels: \"\"\nassignees: \"\"\n---\n\n**Describe the bu"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 252,
"preview": "blank_issues_enabled: false\ncontact_links:\n - name: Bugs, Feedback, Feature Requests, and Questions\n url: https://fe"
},
{
"path": ".github/pull_request_template.md",
"chars": 591,
"preview": "## Summary\n\n<!-- Describe the bug and the fix in 1-3 sentences. -->\n\n## Submission\n\n- [ ] This PR is a bug fix or small-"
},
{
"path": ".github/workflows/ci.yml",
"chars": 658,
"preview": "on:\n pull_request:\n push:\n branches:\n - main\n\nname: Lint and Test\npermissions:\n contents: read\n\njobs:\n test:"
},
{
"path": ".github/workflows/claude.yml",
"chars": 1885,
"preview": "name: Claude Code\n\non:\n issue_comment:\n types: [created]\n pull_request_review_comment:\n types: [created]\n issue"
},
{
"path": ".github/workflows/flathub.yml",
"chars": 1569,
"preview": "name: Update Flathub\non:\n release:\n types: [published]\n\npermissions:\n contents: read\n\njobs:\n update-flathub:\n n"
},
{
"path": ".github/workflows/release-api-npm.yml",
"chars": 1511,
"preview": "name: Release API to NPM\n\non:\n push:\n tags: [yaak-api-*]\n workflow_dispatch:\n inputs:\n version:\n des"
},
{
"path": ".github/workflows/release-app.yml",
"chars": 7644,
"preview": "name: Release App Artifacts\non:\n push:\n tags: [v*]\n\njobs:\n build-artifacts:\n permissions:\n contents: write\n"
},
{
"path": ".github/workflows/release-cli-npm.yml",
"chars": 6490,
"preview": "name: Release CLI to NPM\n\non:\n push:\n tags: [yaak-cli-*]\n workflow_dispatch:\n inputs:\n version:\n des"
},
{
"path": ".github/workflows/sponsors.yml",
"chars": 1442,
"preview": "name: Generate Sponsors README\non:\n workflow_dispatch:\n schedule:\n - cron: 30 15 * * 0-6\npermissions:\n contents: w"
},
{
"path": ".gitignore",
"chars": 853,
"preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndis"
},
{
"path": ".node-version",
"chars": 8,
"preview": "24.14.0\n"
},
{
"path": ".npmrc",
"chars": 93,
"preview": "# vite-plugin-wasm has not yet declared Vite 8 in its peerDependencies\nlegacy-peer-deps=true\n"
},
{
"path": ".nvmrc",
"chars": 3,
"preview": "20\n"
},
{
"path": ".oxfmtignore",
"chars": 44,
"preview": "**/bindings/**\ncrates/yaak-templates/pkg/**\n"
},
{
"path": ".vite-hooks/post-checkout",
"chars": 46,
"preview": "node scripts/git-hooks/post-checkout.mjs \"$@\"\n"
},
{
"path": ".vite-hooks/pre-commit",
"chars": 8,
"preview": "vp lint\n"
},
{
"path": ".vscode/extensions.json",
"chars": 135,
"preview": "{\n \"recommendations\": [\n \"rust-lang.rust-analyzer\",\n \"bradlc.vscode-tailwindcss\",\n \"VoidZero.vite-plus-extensi"
},
{
"path": ".vscode/launch.json",
"chars": 536,
"preview": "{\n \"version\": \"0.2.0\",\n \"configurations\": [\n {\n \"type\": \"node\",\n \"request\": \"launch\",\n \"name\": \"Dev "
},
{
"path": ".vscode/settings.json",
"chars": 191,
"preview": "{\n \"editor.defaultFormatter\": \"oxc.oxc-vscode\",\n \"editor.formatOnSave\": true,\n \"editor.formatOnSaveMode\": \"file\",\n \""
},
{
"path": "AGENTS.md",
"chars": 193,
"preview": "- Tag safety: app releases use `v*` tags and CLI releases use `yaak-cli-*` tags; always confirm which one is requested b"
},
{
"path": "CONTRIBUTING.md",
"chars": 602,
"preview": "# Contributing to Yaak\n\nYaak accepts community pull requests for:\n\n- Bug fixes\n- Small-scope improvements directly tied "
},
{
"path": "Cargo.toml",
"chars": 2067,
"preview": "[workspace]\nresolver = \"2\"\nmembers = [\n \"crates/yaak\",\n # Shared crates (no Tauri dependency)\n \"crates/yaak-core\",\n "
},
{
"path": "DEVELOPMENT.md",
"chars": 1811,
"preview": "# Developer Setup\n\nYaak is a combined Node.js and Rust monorepo. It is a [Tauri](https://tauri.app) project, so\nuses Rus"
},
{
"path": "LICENSE",
"chars": 1061,
"preview": "MIT License\n\nCopyright (c) 2024 Yaak\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof th"
},
{
"path": "README.md",
"chars": 6020,
"preview": "<p align=\"center\">\n <a href=\"https://github.com/JamesIves/github-sponsors-readme-action\">\n <img width=\"200px\" src=\"h"
},
{
"path": "crates/yaak/Cargo.toml",
"chars": 519,
"preview": "[package]\nname = \"yaak\"\nversion = \"0.1.0\"\nedition = \"2024\"\npublish = false\n\n[dependencies]\nasync-trait = \"0.1\"\nlog = { w"
},
{
"path": "crates/yaak/src/error.rs",
"chars": 198,
"preview": "use thiserror::Error;\n\n#[derive(Debug, Error)]\npub enum Error {\n #[error(transparent)]\n Send(#[from] crate::send::"
},
{
"path": "crates/yaak/src/lib.rs",
"chars": 130,
"preview": "pub mod error;\npub mod plugin_events;\npub mod render;\npub mod send;\n\npub use error::Error;\npub type Result<T> = error::R"
},
{
"path": "crates/yaak/src/plugin_events.rs",
"chars": 28068,
"preview": "use yaak_models::models::AnyModel;\nuse yaak_models::query_manager::QueryManager;\nuse yaak_models::util::UpdateSource;\nus"
},
{
"path": "crates/yaak/src/render.rs",
"chars": 7095,
"preview": "use log::info;\nuse serde_json::Value;\nuse std::collections::BTreeMap;\nuse yaak_http::path_placeholders::apply_path_place"
},
{
"path": "crates/yaak/src/send.rs",
"chars": 39276,
"preview": "use crate::render::render_http_request;\nuse async_trait::async_trait;\nuse log::warn;\nuse std::path::{Path, PathBuf};\nuse"
},
{
"path": "crates/yaak-api/Cargo.toml",
"chars": 259,
"preview": "[package]\nname = \"yaak-api\"\nversion = \"0.1.0\"\nedition = \"2024\"\npublish = false\n\n[dependencies]\nlog = { workspace = true "
},
{
"path": "crates/yaak-api/src/error.rs",
"chars": 187,
"preview": "use thiserror::Error;\n\n#[derive(Error, Debug)]\npub enum Error {\n #[error(transparent)]\n ReqwestError(#[from] reqwe"
},
{
"path": "crates/yaak-api/src/lib.rs",
"chars": 2459,
"preview": "mod error;\n\npub use error::{Error, Result};\n\nuse log::{debug, warn};\nuse reqwest::Client;\nuse reqwest::header::{HeaderMa"
},
{
"path": "crates/yaak-common/Cargo.toml",
"chars": 185,
"preview": "[package]\nname = \"yaak-common\"\nversion = \"0.1.0\"\nedition = \"2024\"\npublish = false\n\n[dependencies]\nserde_json = { workspa"
},
{
"path": "crates/yaak-common/src/command.rs",
"chars": 1358,
"preview": "use std::ffi::{OsStr, OsString};\nuse std::io::{self, ErrorKind};\nuse std::process::Stdio;\n\n#[cfg(target_os = \"windows\")]"
},
{
"path": "crates/yaak-common/src/lib.rs",
"chars": 50,
"preview": "pub mod command;\npub mod platform;\npub mod serde;\n"
},
{
"path": "crates/yaak-common/src/platform.rs",
"chars": 1127,
"preview": "use crate::platform::OperatingSystem::{Linux, MacOS, Unknown, Windows};\n\npub enum OperatingSystem {\n Windows,\n Mac"
},
{
"path": "crates/yaak-common/src/serde.rs",
"chars": 767,
"preview": "use serde_json::Value;\nuse std::collections::BTreeMap;\n\npub fn get_bool(v: &Value, key: &str, fallback: bool) -> bool {\n"
},
{
"path": "crates/yaak-core/Cargo.toml",
"chars": 158,
"preview": "[package]\nname = \"yaak-core\"\nversion = \"0.0.0\"\nedition = \"2024\"\nauthors = [\"Gregory Schier\"]\npublish = false\n\n[dependenc"
},
{
"path": "crates/yaak-core/src/context.rs",
"chars": 1820,
"preview": "use std::path::PathBuf;\n\n/// Context for a workspace operation.\n///\n/// In Tauri, this is extracted from the WebviewWind"
},
{
"path": "crates/yaak-core/src/error.rs",
"chars": 318,
"preview": "use thiserror::Error;\n\npub type Result<T> = std::result::Result<T, Error>;\n\n#[derive(Error, Debug)]\npub enum Error {\n "
},
{
"path": "crates/yaak-core/src/lib.rs",
"chars": 311,
"preview": "//! Core abstractions for Yaak that work without Tauri.\n//!\n//! This crate provides foundational types and traits that a"
},
{
"path": "crates/yaak-crypto/Cargo.toml",
"chars": 474,
"preview": "[package]\nname = \"yaak-crypto\"\nversion = \"0.1.0\"\nedition = \"2021\"\npublish = false\n\n[dependencies]\nbase32 = \"0.5.1\" # For"
},
{
"path": "crates/yaak-crypto/index.ts",
"chars": 563,
"preview": "import { invoke } from \"@tauri-apps/api/core\";\n\nexport function enableEncryption(workspaceId: string) {\n return invoke<"
},
{
"path": "crates/yaak-crypto/package.json",
"chars": 104,
"preview": "{\n \"name\": \"@yaakapp-internal/crypto\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"main\": \"index.ts\"\n}\n"
},
{
"path": "crates/yaak-crypto/src/encryption.rs",
"chars": 3741,
"preview": "use crate::error::Error::{DecryptionError, EncryptionError, InvalidEncryptedData};\nuse crate::error::Result;\nuse chacha2"
},
{
"path": "crates/yaak-crypto/src/error.rs",
"chars": 1157,
"preview": "use serde::{Serialize, Serializer};\nuse std::io;\nuse thiserror::Error;\n\n#[derive(Error, Debug)]\npub enum Error {\n #[e"
},
{
"path": "crates/yaak-crypto/src/lib.rs",
"chars": 107,
"preview": "extern crate core;\n\npub mod encryption;\npub mod error;\npub mod manager;\nmod master_key;\nmod workspace_key;\n"
},
{
"path": "crates/yaak-crypto/src/manager.rs",
"chars": 6895,
"preview": "use crate::error::Error::{\n GenericError, IncorrectWorkspaceKey, MissingWorkspaceKey, WorkspaceKeyDecryptionError,\n};"
},
{
"path": "crates/yaak-crypto/src/master_key.rs",
"chars": 2606,
"preview": "use crate::encryption::{decrypt_data, encrypt_data};\nuse crate::error::Error::GenericError;\nuse crate::error::Result;\nus"
},
{
"path": "crates/yaak-crypto/src/workspace_key.rs",
"chars": 3504,
"preview": "use crate::encryption::{decrypt_data, encrypt_data};\nuse crate::error::Error::InvalidHumanKey;\nuse crate::error::Result;"
},
{
"path": "crates/yaak-git/Cargo.toml",
"chars": 640,
"preview": "[package]\nname = \"yaak-git\"\nversion = \"0.1.0\"\nedition = \"2024\"\npublish = false\n\n[dependencies]\nchrono = { workspace = tr"
},
{
"path": "crates/yaak-git/bindings/gen_git.ts",
"chars": 1565,
"preview": "// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.\nimport type"
},
{
"path": "crates/yaak-git/bindings/gen_models.ts",
"chars": 3030,
"preview": "// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.\n\nexport typ"
},
{
"path": "crates/yaak-git/index.ts",
"chars": 9620,
"preview": "import { useQuery } from \"@tanstack/react-query\";\nimport { invoke } from \"@tauri-apps/api/core\";\nimport { createFastMuta"
},
{
"path": "crates/yaak-git/package.json",
"chars": 101,
"preview": "{\n \"name\": \"@yaakapp-internal/git\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"main\": \"index.ts\"\n}\n"
},
{
"path": "crates/yaak-git/src/add.rs",
"chars": 403,
"preview": "use crate::error::Result;\nuse crate::repository::open_repo;\nuse git2::IndexAddOption;\nuse log::info;\nuse std::path::Path"
},
{
"path": "crates/yaak-git/src/binary.rs",
"chars": 617,
"preview": "use crate::error::Error::GitNotFound;\nuse crate::error::Result;\nuse std::path::Path;\nuse tokio::process::Command;\nuse ya"
},
{
"path": "crates/yaak-git/src/branch.rs",
"chars": 4961,
"preview": "use serde::{Deserialize, Serialize};\nuse ts_rs::TS;\n\nuse crate::binary::new_binary_command;\nuse crate::error::Error::Gen"
},
{
"path": "crates/yaak-git/src/clone.rs",
"chars": 1907,
"preview": "use crate::binary::new_binary_command;\nuse crate::error::Error::GenericError;\nuse crate::error::Result;\nuse log::info;\nu"
},
{
"path": "crates/yaak-git/src/commit.rs",
"chars": 617,
"preview": "use crate::binary::new_binary_command;\nuse crate::error::Error::GenericError;\nuse log::info;\nuse std::path::Path;\n\npub a"
},
{
"path": "crates/yaak-git/src/credential.rs",
"chars": 1547,
"preview": "use crate::binary::new_binary_command_global;\nuse crate::error::Error::GenericError;\nuse crate::error::Result;\nuse std::"
},
{
"path": "crates/yaak-git/src/error.rs",
"chars": 1536,
"preview": "use serde::{Serialize, Serializer};\nuse std::io;\nuse std::path::PathBuf;\nuse std::string::FromUtf8Error;\nuse thiserror::"
},
{
"path": "crates/yaak-git/src/fetch.rs",
"chars": 674,
"preview": "use crate::binary::new_binary_command;\nuse crate::error::Error::GenericError;\nuse crate::error::Result;\nuse std::path::P"
},
{
"path": "crates/yaak-git/src/init.rs",
"chars": 393,
"preview": "use crate::error::Result;\nuse crate::repository::open_repo;\nuse log::info;\nuse std::path::Path;\n\npub fn git_init(dir: &P"
},
{
"path": "crates/yaak-git/src/lib.rs",
"chars": 953,
"preview": "mod add;\nmod binary;\nmod branch;\nmod clone;\nmod commit;\nmod credential;\npub mod error;\nmod fetch;\nmod init;\nmod log;\n\nmo"
},
{
"path": "crates/yaak-git/src/log.rs",
"chars": 2085,
"preview": "use crate::repository::open_repo;\nuse chrono::{DateTime, Utc};\nuse serde::{Deserialize, Serialize};\nuse std::path::Path;"
},
{
"path": "crates/yaak-git/src/pull.rs",
"chars": 7646,
"preview": "use crate::binary::new_binary_command;\nuse crate::error::Error::GenericError;\nuse crate::error::Result;\nuse crate::repos"
},
{
"path": "crates/yaak-git/src/push.rs",
"chars": 3466,
"preview": "use crate::binary::new_binary_command;\nuse crate::error::Error::GenericError;\nuse crate::error::Result;\nuse crate::repos"
},
{
"path": "crates/yaak-git/src/remotes.rs",
"chars": 1286,
"preview": "use crate::error::Result;\nuse crate::repository::open_repo;\nuse log::warn;\nuse serde::{Deserialize, Serialize};\nuse std:"
},
{
"path": "crates/yaak-git/src/repository.rs",
"chars": 372,
"preview": "use crate::error::Error::{GitRepoNotFound, GitUnknown};\nuse std::path::Path;\n\npub(crate) fn open_repo(dir: &Path) -> cra"
},
{
"path": "crates/yaak-git/src/reset.rs",
"chars": 585,
"preview": "use crate::binary::new_binary_command;\nuse crate::error::Error::GenericError;\nuse crate::error::Result;\nuse std::path::P"
},
{
"path": "crates/yaak-git/src/status.rs",
"chars": 6845,
"preview": "use crate::repository::open_repo;\nuse crate::util::{local_branch_names, remote_branch_names};\nuse log::warn;\nuse serde::"
},
{
"path": "crates/yaak-git/src/unstage.rs",
"chars": 891,
"preview": "use crate::repository::open_repo;\nuse log::info;\nuse std::path::Path;\n\npub fn git_unstage(dir: &Path, rela_path: &Path) "
},
{
"path": "crates/yaak-git/src/util.rs",
"chars": 3661,
"preview": "use crate::error::Error::{GenericError, NoDefaultRemoteFound};\nuse crate::error::Result;\nuse git2::{Branch, BranchType, "
},
{
"path": "crates/yaak-grpc/Cargo.toml",
"chars": 957,
"preview": "[package]\nname = \"yaak-grpc\"\nversion = \"0.1.0\"\nedition = \"2024\"\npublish = false\n\n[dependencies]\nanyhow = \"1.0.97\"\nasync-"
},
{
"path": "crates/yaak-grpc/src/any.rs",
"chars": 1694,
"preview": "use log::error;\n\npub(crate) fn collect_any_types(json: &str, out: &mut Vec<String>) {\n let value = match serde_json::"
},
{
"path": "crates/yaak-grpc/src/client.rs",
"chars": 7471,
"preview": "use crate::error::Error::GenericError;\nuse crate::error::Result;\nuse crate::manager::decorate_req;\nuse crate::transport:"
},
{
"path": "crates/yaak-grpc/src/codec.rs",
"chars": 1291,
"preview": "use prost_reflect::prost::Message;\nuse prost_reflect::{DynamicMessage, MethodDescriptor};\nuse tonic::Status;\nuse tonic::"
},
{
"path": "crates/yaak-grpc/src/error.rs",
"chars": 1308,
"preview": "use crate::manager::GrpcStreamError;\nuse prost::DecodeError;\nuse serde::{Serialize, Serializer};\nuse serde_json::Error a"
},
{
"path": "crates/yaak-grpc/src/json_schema.rs",
"chars": 14865,
"preview": "use prost_reflect::{DescriptorPool, FieldDescriptor, MessageDescriptor};\nuse std::collections::{HashMap, HashSet, VecDeq"
},
{
"path": "crates/yaak-grpc/src/lib.rs",
"chars": 1678,
"preview": "use prost_reflect::{DynamicMessage, MethodDescriptor, SerializeOptions};\nuse serde::{Deserialize, Serialize};\nuse serde_"
},
{
"path": "crates/yaak-grpc/src/manager.rs",
"chars": 16197,
"preview": "use crate::codec::DynamicCodec;\nuse crate::error::Error::GenericError;\nuse crate::error::Result;\nuse crate::reflection::"
},
{
"path": "crates/yaak-grpc/src/reflection.rs",
"chars": 13972,
"preview": "use crate::any::collect_any_types;\nuse crate::client::AutoReflectionClient;\nuse crate::error::Error::GenericError;\nuse c"
},
{
"path": "crates/yaak-grpc/src/transport.rs",
"chars": 1210,
"preview": "use crate::error::Result;\nuse hyper_rustls::{HttpsConnector, HttpsConnectorBuilder};\nuse hyper_util::client::legacy::Cli"
},
{
"path": "crates/yaak-http/Cargo.toml",
"chars": 1068,
"preview": "[package]\nname = \"yaak-http\"\nversion = \"0.1.0\"\nedition = \"2024\"\npublish = false\n\n[dependencies]\nasync-compression = { ve"
},
{
"path": "crates/yaak-http/src/chained_reader.rs",
"chars": 2749,
"preview": "use std::io;\nuse std::pin::Pin;\nuse std::task::{Context, Poll};\nuse tokio::io::{AsyncRead, ReadBuf};\n\n/// A stream that "
},
{
"path": "crates/yaak-http/src/client.rs",
"chars": 4257,
"preview": "use crate::dns::LocalhostResolver;\nuse crate::error::Result;\nuse log::{debug, info, warn};\nuse reqwest::{Client, Proxy, "
},
{
"path": "crates/yaak-http/src/cookies.rs",
"chars": 16981,
"preview": "//! Custom cookie handling for HTTP requests\n//!\n//! This module provides cookie storage and matching functionality that"
},
{
"path": "crates/yaak-http/src/decompress.rs",
"chars": 7499,
"preview": "use crate::error::{Error, Result};\nuse async_compression::tokio::bufread::{\n BrotliDecoder, DeflateDecoder as AsyncDe"
},
{
"path": "crates/yaak-http/src/dns.rs",
"chars": 6605,
"preview": "use crate::sender::HttpResponseEvent;\nuse hyper_util::client::legacy::connect::dns::{\n GaiResolver as HyperGaiResolve"
},
{
"path": "crates/yaak-http/src/error.rs",
"chars": 881,
"preview": "use serde::{Serialize, Serializer};\nuse thiserror::Error;\n\n#[derive(Error, Debug)]\npub enum Error {\n #[error(\"Client "
},
{
"path": "crates/yaak-http/src/lib.rs",
"chars": 228,
"preview": "mod chained_reader;\npub mod client;\npub mod cookies;\npub mod decompress;\npub mod dns;\npub mod error;\npub mod manager;\npu"
},
{
"path": "crates/yaak-http/src/manager.rs",
"chars": 1619,
"preview": "use crate::client::HttpConnectionOptions;\nuse crate::dns::LocalhostResolver;\nuse crate::error::Result;\nuse reqwest::Clie"
},
{
"path": "crates/yaak-http/src/path_placeholders.rs",
"chars": 4789,
"preview": "use yaak_models::models::HttpUrlParameter;\n\npub fn apply_path_placeholders(\n url: &str,\n parameters: &Vec<HttpUrlP"
},
{
"path": "crates/yaak-http/src/proto.rs",
"chars": 841,
"preview": "use reqwest::Url;\nuse std::str::FromStr;\n\npub(crate) fn ensure_proto(url_str: &str) -> String {\n if url_str.is_empty("
},
{
"path": "crates/yaak-http/src/sender.rs",
"chars": 22891,
"preview": "use crate::decompress::{ContentEncoding, streaming_decoder};\nuse crate::error::{Error, Result};\nuse crate::types::{Senda"
},
{
"path": "crates/yaak-http/src/tee_reader.rs",
"chars": 4938,
"preview": "use std::io;\nuse std::pin::Pin;\nuse std::task::{Context, Poll};\nuse tokio::io::{AsyncRead, ReadBuf};\nuse tokio::sync::mp"
},
{
"path": "crates/yaak-http/src/transaction.rs",
"chars": 36319,
"preview": "use crate::cookies::CookieStore;\nuse crate::error::Result;\nuse crate::sender::{HttpResponse, HttpResponseEvent, HttpSend"
},
{
"path": "crates/yaak-http/src/types.rs",
"chars": 36729,
"preview": "use crate::chained_reader::{ChainedReader, ReaderType};\nuse crate::error::Error::RequestError;\nuse crate::error::Result;"
},
{
"path": "crates/yaak-http/tests/test.txt",
"chars": 21,
"preview": "This is a test file!\n"
},
{
"path": "crates/yaak-models/Cargo.toml",
"chars": 794,
"preview": "[package]\nname = \"yaak-models\"\nversion = \"0.1.0\"\nedition = \"2024\"\npublish = false\n\n[dependencies]\nchrono = { version = \""
},
{
"path": "crates/yaak-models/bindings/gen_models.ts",
"chars": 10006,
"preview": "// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.\n\nexport typ"
},
{
"path": "crates/yaak-models/bindings/gen_util.ts",
"chars": 459,
"preview": "// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.\nimport type"
},
{
"path": "crates/yaak-models/blob_migrations/00000000000000_init.sql",
"chars": 360,
"preview": "CREATE TABLE body_chunks\n(\n id TEXT PRIMARY KEY,\n body_id TEXT NOT NULL,\n chunk_index INTEGER N"
},
{
"path": "crates/yaak-models/build.rs",
"chars": 214,
"preview": "fn main() {\n // Migrations are embedded with include_dir!, so trigger rebuilds when SQL files change.\n println!(\"c"
},
{
"path": "crates/yaak-models/guest-js/atoms.ts",
"chars": 2949,
"preview": "import { atom } from \"jotai\";\n\nimport { selectAtom } from \"jotai/utils\";\nimport type { AnyModel } from \"../bindings/gen_"
},
{
"path": "crates/yaak-models/guest-js/index.ts",
"chars": 374,
"preview": "import { AnyModel } from \"../bindings/gen_models\";\n\nexport * from \"../bindings/gen_models\";\nexport * from \"../bindings/g"
},
{
"path": "crates/yaak-models/guest-js/store.ts",
"chars": 7881,
"preview": "import { invoke } from \"@tauri-apps/api/core\";\nimport { getCurrentWebviewWindow } from \"@tauri-apps/api/webviewWindow\";\n"
},
{
"path": "crates/yaak-models/guest-js/types.ts",
"chars": 343,
"preview": "import { createStore } from \"jotai\";\nimport { AnyModel } from \"../bindings/gen_models\";\n\nexport type ExtractModel<T, M> "
},
{
"path": "crates/yaak-models/guest-js/util.ts",
"chars": 537,
"preview": "import { ModelStoreData } from \"./types\";\n\nexport function newStoreData(): ModelStoreData {\n return {\n cookie_jar: {"
},
{
"path": "crates/yaak-models/migrations/20230225181302_init.sql",
"chars": 2576,
"preview": "CREATE TABLE key_values\n(\n model TEXT DEFAULT 'key_value' NOT NULL,\n created_at DATETIME DEFAULT CU"
},
{
"path": "crates/yaak-models/migrations/20230319042610_sort-priority.sql",
"chars": 81,
"preview": "ALTER TABLE main.http_requests ADD COLUMN sort_priority REAL NOT NULL DEFAULT 0;\n"
},
{
"path": "crates/yaak-models/migrations/20230330143214_request-auth.sql",
"chars": 143,
"preview": "ALTER TABLE http_requests ADD COLUMN authentication TEXT NOT NULL DEFAULT '{}';\nALTER TABLE http_requests ADD COLUMN aut"
},
{
"path": "crates/yaak-models/migrations/20230413232435_response-body-blob.sql",
"chars": 243,
"preview": "DELETE FROM main.http_responses;\nALTER TABLE http_responses DROP COLUMN body;\nALTER TABLE http_responses ADD COLUMN body"
},
{
"path": "crates/yaak-models/migrations/20231022205109_environments.sql",
"chars": 585,
"preview": "CREATE TABLE environments\n(\n id TEXT NOT NULL\n PRIMARY KEY,\n model "
},
{
"path": "crates/yaak-models/migrations/20231028161007_variables.sql",
"chars": 112,
"preview": "ALTER TABLE environments DROP COLUMN data;\nALTER TABLE environments ADD COLUMN variables DEFAULT '[]' NOT NULL;\n"
},
{
"path": "crates/yaak-models/migrations/20231103004111_workspace-variables.sql",
"chars": 67,
"preview": "ALTER TABLE workspaces ADD COLUMN variables DEFAULT '[]' NOT NULL;\n"
},
{
"path": "crates/yaak-models/migrations/20231103142807_folders.sql",
"chars": 787,
"preview": "CREATE TABLE folders\n(\n id TEXT NOT NULL\n PRIMARY KEY,\n model "
},
{
"path": "crates/yaak-models/migrations/20231112180500_body_object.sql",
"chars": 454,
"preview": "-- Rename old column to backup name\nALTER TABLE http_requests\n RENAME COLUMN body TO body_old;\n\n-- Create desired new"
},
{
"path": "crates/yaak-models/migrations/20231113183810_url_params.sql",
"chars": 84,
"preview": "ALTER TABLE http_requests\n ADD COLUMN url_parameters TEXT NOT NULL DEFAULT '[]';\n"
},
{
"path": "crates/yaak-models/migrations/20231122055216_remove_body.sql",
"chars": 45,
"preview": "ALTER TABLE http_responses DROP COLUMN body;\n"
},
{
"path": "crates/yaak-models/migrations/20240111221224_settings.sql",
"chars": 685,
"preview": "CREATE TABLE settings\n(\n id TEXT NOT NULL\n PRIMARY KEY,\n m"
},
{
"path": "crates/yaak-models/migrations/20240115193751_workspace_settings.sql",
"chars": 531,
"preview": "-- Add existing request-related settings to workspace\nALTER TABLE workspaces ADD COLUMN setting_request_timeout INTEGER "
},
{
"path": "crates/yaak-models/migrations/20240118181105_channel_setting.sql",
"chars": 79,
"preview": "ALTER TABLE settings ADD COLUMN update_channel TEXT DEFAULT 'stable' NOT NULL;\n"
},
{
"path": "crates/yaak-models/migrations/20240127013915_cookies.sql",
"chars": 475,
"preview": "CREATE TABLE cookie_jars\n(\n id TEXT NOT NULL PRIMARY KEY,\n model TE"
},
{
"path": "crates/yaak-models/migrations/20240128230717_more_response_attrs.sql",
"chars": 190,
"preview": "ALTER TABLE http_responses ADD COLUMN elapsed_headers INTEGER NOT NULL DEFAULT 0;\nALTER TABLE http_responses ADD COLUMN "
},
{
"path": "crates/yaak-models/migrations/20240203164833_grpc.sql",
"chars": 3994,
"preview": "CREATE TABLE grpc_requests\n(\n id TEXT NOT NULL\n "
},
{
"path": "crates/yaak-models/migrations/20240522031045_theme-settings.sql",
"chars": 166,
"preview": "ALTER TABLE settings\n ADD COLUMN theme_dark TEXT DEFAULT 'yaak-dark' NOT NULL;\nALTER TABLE settings\n ADD COLUMN th"
},
{
"path": "crates/yaak-models/migrations/20240529143147_more-settings.sql",
"chars": 312,
"preview": "ALTER TABLE settings ADD COLUMN interface_font_size INTEGER DEFAULT 15 NOT NULL;\nALTER TABLE settings ADD COLUMN interfa"
},
{
"path": "crates/yaak-models/migrations/20240607151115_open-workspace-setting.sql",
"chars": 85,
"preview": "ALTER TABLE settings ADD COLUMN open_workspace_new_window BOOLEAN NULL DEFAULT NULL;\n"
},
{
"path": "crates/yaak-models/migrations/20240814013812_fix-env-model.sql",
"chars": 114,
"preview": "ALTER TABLE environments DROP COLUMN model;\nALTER TABLE environments ADD COLUMN model TEXT DEFAULT 'environment';\n"
},
{
"path": "crates/yaak-models/migrations/20240826184943_disable-telemetry.sql",
"chars": 64,
"preview": "ALTER TABLE settings ADD COLUMN telemetry BOOLEAN DEFAULT TRUE;\n"
},
{
"path": "crates/yaak-models/migrations/20240829131004_plugins.sql",
"chars": 461,
"preview": "CREATE TABLE plugins\n(\n id TEXT NOT NULL\n PRIMARY KEY,\n model TE"
},
{
"path": "crates/yaak-models/migrations/20241003134208_response-state.sql",
"chars": 163,
"preview": "ALTER TABLE http_responses\n ADD COLUMN state TEXT DEFAULT 'closed' NOT NULL;\n\nALTER TABLE grpc_connections\n ADD CO"
},
{
"path": "crates/yaak-models/migrations/20241012181547_proxy-setting.sql",
"chars": 44,
"preview": "ALTER TABLE settings ADD COLUMN proxy TEXT;\n"
},
{
"path": "crates/yaak-models/migrations/20241217204951_docs.sql",
"chars": 233,
"preview": "ALTER TABLE http_requests\n ADD COLUMN description TEXT DEFAULT '' NOT NULL;\n\nALTER TABLE grpc_requests\n ADD COLUMN"
},
{
"path": "crates/yaak-models/migrations/20241219140051_base-environments.sql",
"chars": 2509,
"preview": "-- Add the new field\nALTER TABLE environments\n ADD COLUMN environment_id TEXT REFERENCES environments (id) ON DELETE "
},
{
"path": "crates/yaak-models/migrations/20250102141937_sync.sql",
"chars": 829,
"preview": "ALTER TABLE workspaces\n ADD COLUMN setting_sync_dir TEXT;\n\nCREATE TABLE sync_states\n(\n id TEXT "
},
{
"path": "crates/yaak-models/migrations/20250108035425_editor-keymap.sql",
"chars": 86,
"preview": "ALTER TABLE settings\n ADD COLUMN editor_keymap TEXT DEFAULT 'codemirror' NOT NULL;\n"
},
{
"path": "crates/yaak-models/migrations/20250108205117_workspace-meta.sql",
"chars": 458,
"preview": "CREATE TABLE workspace_metas\n(\n id TEXT NOT NULL\n PRIMARY KEY,\n "
},
{
"path": "crates/yaak-models/migrations/20250114160022_remove-workspace-sync-setting.sql",
"chars": 112,
"preview": "-- This setting was moved to the new workspace_metas table\nALTER TABLE workspaces DROP COLUMN setting_sync_dir;\n"
},
{
"path": "crates/yaak-models/migrations/20250123192023_plugin-kv.sql",
"chars": 469,
"preview": "CREATE TABLE plugin_key_values\n(\n model TEXT DEFAULT 'plugin_key_value' NOT NULL,\n created_at DATETIME "
},
{
"path": "crates/yaak-models/migrations/20250128155623_websockets.sql",
"chars": 3272,
"preview": "CREATE TABLE websocket_requests\n(\n id TEXT NOT NULL\n PRIMARY "
},
{
"path": "crates/yaak-models/migrations/20250302041707_hide-window-controls.sql",
"chars": 89,
"preview": "ALTER TABLE settings\n ADD COLUMN hide_window_controls BOOLEAN DEFAULT FALSE NOT NULL;\n"
},
{
"path": "crates/yaak-models/migrations/20250326193143_key-value-id.sql",
"chars": 2131,
"preview": "-- 1. Create the new table with `id` as the primary key\nCREATE TABLE key_values_new\n(\n id TEXT PRIMARY KEY,\n "
},
{
"path": "crates/yaak-models/migrations/20250401122407_encrypted-key.sql",
"chars": 78,
"preview": "ALTER TABLE workspace_metas ADD COLUMN encryption_key TEXT NULL DEFAULT NULL;\n"
},
{
"path": "crates/yaak-models/migrations/20250402144842_encryption-key-challenge.sql",
"chars": 70,
"preview": "ALTER TABLE workspaces ADD COLUMN encryption_key_challenge TEXT NULL;\n"
},
{
"path": "crates/yaak-models/migrations/20250424152740_remove-fks.sql",
"chars": 8548,
"preview": "-- NOTE: SQLite does not support dropping foreign keys, so we need to create new\n-- tables and copy data instead. To pre"
},
{
"path": "crates/yaak-models/migrations/20250507140702_remove-ev-sync-states.sql",
"chars": 575,
"preview": "-- There used to be sync code that skipped over environments because we didn't\n-- want to sync potentially insecure data"
},
{
"path": "crates/yaak-models/migrations/20250508161145_public-environments.sql",
"chars": 873,
"preview": "-- Add a public column to represent whether an environment can be shared or exported\nALTER TABLE environments\n ADD CO"
},
{
"path": "crates/yaak-models/migrations/20250516182745_default-attrs.sql",
"chars": 449,
"preview": "-- Auth\nALTER TABLE workspaces\n ADD COLUMN authentication TEXT NOT NULL DEFAULT '{}';\nALTER TABLE folders\n ADD COL"
},
{
"path": "crates/yaak-models/migrations/20250530174021_graphql-introspection.sql",
"chars": 770,
"preview": "-- Clean up old key/values that are no longer used\nDELETE\nFROM key_values\nWHERE key LIKE 'graphql_introspection::%';\n\nCR"
},
{
"path": "crates/yaak-models/migrations/20250531193722_sync-state-index.sql",
"chars": 1529,
"preview": "-- Add sync_dir to the unique index, or else it will fail if the user disables sync\n-- and re-enables it for a different"
},
{
"path": "crates/yaak-models/migrations/20250604102922_colored-methods-setting.sql",
"chars": 75,
"preview": "ALTER TABLE settings\n ADD COLUMN colored_methods BOOLEAN DEFAULT FALSE;\n"
},
{
"path": "crates/yaak-models/migrations/20250608150053_font-settings.sql",
"chars": 103,
"preview": "ALTER TABLE settings ADD COLUMN interface_font TEXT;\nALTER TABLE settings ADD COLUMN editor_font TEXT;\n"
},
{
"path": "crates/yaak-models/migrations/20250611120000_environment-color.sql",
"chars": 48,
"preview": "ALTER TABLE environments ADD COLUMN color TEXT; "
},
{
"path": "crates/yaak-models/migrations/20250727190746_autoupdate_setting.sql",
"chars": 74,
"preview": "ALTER TABLE settings ADD COLUMN autoupdate BOOLEAN DEFAULT true NOT NULL;\n"
},
{
"path": "crates/yaak-models/migrations/20250918141129_request-folder-environments.sql",
"chars": 1945,
"preview": "-- Create temporary table for migration\nCREATE TABLE environments__new\n(\n id TEXT "
},
{
"path": "crates/yaak-models/migrations/20250929132954_dismiss-license-badge.sql",
"chars": 346,
"preview": "ALTER TABLE settings\n ADD COLUMN hide_license_badge BOOLEAN DEFAULT FALSE;\n\n-- 2. Backfill based on old JSON\nUPDATE s"
},
{
"path": "crates/yaak-models/migrations/20251001082054_auto-download.sql",
"chars": 80,
"preview": "ALTER TABLE settings\n ADD COLUMN auto_download_updates BOOLEAN DEFAULT TRUE;\n"
},
{
"path": "crates/yaak-models/migrations/20251028060300_check_notifications_setting.sql",
"chars": 83,
"preview": "ALTER TABLE settings ADD COLUMN check_notifications BOOLEAN DEFAULT true NOT NULL;\n"
},
{
"path": "crates/yaak-models/migrations/20251029062024_aws-auth-name.sql",
"chars": 299,
"preview": "UPDATE http_requests\nSET authentication_type = 'awsv4'\nWHERE authentication_type = 'auth-aws-sig-v4';\n\nUPDATE folders\nSE"
},
{
"path": "crates/yaak-models/migrations/20251031070515_environment-sort-priority.sql",
"chars": 79,
"preview": "ALTER TABLE environments\n ADD COLUMN sort_priority REAL DEFAULT 0 NOT NULL;\n"
},
{
"path": "crates/yaak-models/migrations/20251202080000_use-native-titlebar.sql",
"chars": 149,
"preview": "-- Add a setting to force native window title bar / controls\nALTER TABLE settings\n ADD COLUMN use_native_titlebar BOO"
},
{
"path": "crates/yaak-models/migrations/20251209000000_client-certificates.sql",
"chars": 80,
"preview": "ALTER TABLE settings ADD COLUMN client_certificates TEXT DEFAULT '[]' NOT NULL;\n"
},
{
"path": "crates/yaak-models/migrations/20251219074602_default-workspace-headers.sql",
"chars": 696,
"preview": "-- Add default User-Agent header to workspaces that don't already have one (case-insensitive check)\nUPDATE workspaces\nSE"
},
{
"path": "crates/yaak-models/migrations/20251220000000_response-request-headers.sql",
"chars": 240,
"preview": "-- Add request_headers and content_length_compressed columns to http_responses table\nALTER TABLE http_responses ADD COLU"
},
{
"path": "crates/yaak-models/migrations/20251221000000_http-response-events.sql",
"chars": 763,
"preview": "CREATE TABLE http_response_events\n(\n id TEXT NOT NULL\n "
},
{
"path": "crates/yaak-models/migrations/20251221100000_request-content-length.sql",
"chars": 74,
"preview": "ALTER TABLE http_responses\n ADD COLUMN request_content_length INTEGER;\n"
},
{
"path": "crates/yaak-models/migrations/20260104000000_hotkeys.sql",
"chars": 68,
"preview": "ALTER TABLE settings ADD COLUMN hotkeys TEXT DEFAULT '{}' NOT NULL;\n"
},
{
"path": "crates/yaak-models/migrations/20260111000000_dns-timing.sql",
"chars": 125,
"preview": "-- Add DNS resolution timing to http_responses\nALTER TABLE http_responses ADD COLUMN elapsed_dns INTEGER DEFAULT 0 NOT N"
},
{
"path": "crates/yaak-models/migrations/20260112000000_dns-overrides.sql",
"chars": 127,
"preview": "-- Add DNS overrides setting to workspaces\nALTER TABLE workspaces ADD COLUMN setting_dns_overrides TEXT DEFAULT '[]' NOT"
},
{
"path": "crates/yaak-models/migrations/20260119045146_remove-default-workspace-headers.sql",
"chars": 525,
"preview": "-- Filter out headers that match the hardcoded defaults (User-Agent: yaak, Accept: */*),\n-- keeping any other custom hea"
},
{
"path": "crates/yaak-models/migrations/20260216000000_model-changes.sql",
"chars": 662,
"preview": "CREATE TABLE model_changes\n(\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n model TEXT "
},
{
"path": "crates/yaak-models/migrations/20260217000000_remove-legacy-faker-plugin.sql",
"chars": 160,
"preview": "-- Remove stale plugin rows left over from the brief period when faker shipped as bundled.\nDELETE FROM plugins\nWHERE dir"
},
{
"path": "crates/yaak-models/migrations/20260301000000_plugin-source-and-unique-directory.sql",
"chars": 1075,
"preview": "ALTER TABLE plugins\n ADD COLUMN source TEXT DEFAULT 'filesystem' NOT NULL;\n\n-- Existing registry installs have a URL;"
},
{
"path": "crates/yaak-models/package.json",
"chars": 113,
"preview": "{\n \"name\": \"@yaakapp-internal/models\",\n \"version\": \"1.0.0\",\n \"private\": true,\n \"main\": \"guest-js/index.ts\"\n}\n"
},
{
"path": "crates/yaak-models/src/blob_manager.rs",
"chars": 11352,
"preview": "use crate::error::Result;\nuse crate::util::generate_prefixed_id;\nuse include_dir::{Dir, include_dir};\nuse log::{debug, i"
},
{
"path": "crates/yaak-models/src/connection_or_tx.rs",
"chars": 747,
"preview": "use r2d2::PooledConnection;\nuse r2d2_sqlite::SqliteConnectionManager;\nuse rusqlite::{Connection, Statement, ToSql, Trans"
},
{
"path": "crates/yaak-models/src/db_context.rs",
"chars": 7984,
"preview": "use crate::connection_or_tx::ConnectionOrTx;\nuse crate::error::Error::ModelNotFound;\nuse crate::error::Result;\nuse crate"
},
{
"path": "crates/yaak-models/src/error.rs",
"chars": 1247,
"preview": "use serde::{Serialize, Serializer};\nuse thiserror::Error;\n\n#[derive(Error, Debug)]\npub enum Error {\n #[error(\"SQL err"
},
{
"path": "crates/yaak-models/src/lib.rs",
"chars": 3072,
"preview": "use crate::blob_manager::{BlobManager, migrate_blob_db};\nuse crate::error::{Error, Result};\nuse crate::migrate::migrate_"
},
{
"path": "crates/yaak-models/src/migrate.rs",
"chars": 4541,
"preview": "use crate::error::Error::MigrationError;\nuse crate::error::Result;\nuse include_dir::{Dir, DirEntry, include_dir};\nuse lo"
},
{
"path": "crates/yaak-models/src/models.rs",
"chars": 81226,
"preview": "use crate::error::Result;\nuse crate::models::HttpRequestIden::{\n Authentication, AuthenticationType, Body, BodyType, "
},
{
"path": "crates/yaak-models/src/queries/any_request.rs",
"chars": 696,
"preview": "use crate::db_context::DbContext;\nuse crate::error::Result;\nuse crate::models::{GrpcRequest, HttpRequest, WebsocketReque"
},
{
"path": "crates/yaak-models/src/queries/batch.rs",
"chars": 2805,
"preview": "use crate::db_context::DbContext;\nuse crate::error::Result;\nuse crate::models::{Environment, Folder, GrpcRequest, HttpRe"
},
{
"path": "crates/yaak-models/src/queries/cookie_jars.rs",
"chars": 1391,
"preview": "use crate::db_context::DbContext;\nuse crate::error::Result;\nuse crate::models::{CookieJar, CookieJarIden};\nuse crate::ut"
},
{
"path": "crates/yaak-models/src/queries/environments.rs",
"chars": 6903,
"preview": "use crate::db_context::DbContext;\nuse crate::error::Error::{MissingBaseEnvironment, MultipleBaseEnvironments};\nuse crate"
},
{
"path": "crates/yaak-models/src/queries/folders.rs",
"chars": 5217,
"preview": "use crate::connection_or_tx::ConnectionOrTx;\nuse crate::db_context::DbContext;\nuse crate::error::Result;\nuse crate::mode"
},
{
"path": "crates/yaak-models/src/queries/graphql_introspections.rs",
"chars": 1854,
"preview": "use crate::db_context::DbContext;\nuse crate::error::Result;\nuse crate::models::{GraphQlIntrospection, GraphQlIntrospecti"
},
{
"path": "crates/yaak-models/src/queries/grpc_connections.rs",
"chars": 3041,
"preview": "use crate::db_context::DbContext;\nuse crate::error::Result;\nuse crate::models::{GrpcConnection, GrpcConnectionIden, Grpc"
}
]
// ... and 918 more files (download for full content)
About this extraction
This page contains the full source code of the mountain-loop/yaak GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1118 files (3.2 MB), approximately 886.6k tokens, and a symbol index with 3944 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.