From 906fb231cc3c1e085550ecefc8c7616440134cd2 Mon Sep 17 00:00:00 2001 From: upstream-mirror Date: Wed, 23 Sep 2026 17:39:41 +0500 Subject: [PATCH] snapshot of https://github.com/mountain-loop/yaak.git (main, 2026-09-23; blobs > 131072B omitted) --- .claude-context.md | 83 + .claude/rules.md | 27 + .../release-generate-release-notes/SKILL.md | 52 + .codex/skills/yaak-changelog/SKILL.md | 104 + .../skills/yaak-changelog/agents/openai.yaml | 7 + .dockerignore | 11 + .gitattributes | 7 + .github/FUNDING.yml | 3 + .github/ISSUE_TEMPLATE/bug_report.md | 40 + .github/ISSUE_TEMPLATE/config.yml | 5 + .github/dependabot.yml | 55 + .github/pull_request_template.md | 22 + .github/scripts/check-contribution-policy.js | 881 +++++ .../scripts/preserve-release-artifacts.mjs | 79 + .github/workflows/ci.yml | 37 + .github/workflows/contribution-policy.yml | 48 + .github/workflows/flathub.yml | 56 + .github/workflows/release-api-npm.yml | 60 + .github/workflows/release-app.yml | 292 ++ .github/workflows/release-cli-npm.yml | 219 ++ .github/workflows/release-web-image.yml | 123 + .github/workflows/sponsors.yml | 45 + .gitignore | 61 + .node-version | 1 + .npmrc | 2 + .oxfmtrc.json | 8 + .vite-hooks/post-checkout | 1 + .vite-hooks/pre-commit | 2 + .vscode/extensions.json | 7 + .vscode/launch.json | 26 + .vscode/settings.json | 8 + AGENTS.md | 2 + CONTRIBUTING.md | 15 + Cargo.toml | 118 + DEVELOPMENT.md | 105 + Dockerfile.playground | 15 + Dockerfile.web | 49 + LICENSE | 21 + README.md | 80 + apps/yaak-client/.gitignore | 2 + apps/yaak-client/commands/commands.tsx | 170 + .../commands/createEnvironment.tsx | 51 + .../commands/deleteWebsocketConnections.ts | 8 + apps/yaak-client/commands/importCurl.ts | 52 + apps/yaak-client/commands/moveToWorkspace.tsx | 33 + .../commands/openFolderSettings.tsx | 17 + apps/yaak-client/commands/openSettings.tsx | 48 + .../commands/openWorkspaceFromSyncDir.tsx | 27 + .../commands/openWorkspaceSettings.tsx | 10 + apps/yaak-client/commands/switchWorkspace.tsx | 46 + .../components/BinaryFileEditor.tsx | 63 + apps/yaak-client/components/CargoFeature.tsx | 19 + .../components/CloneGitRepositoryDialog.tsx | 163 + .../yaak-client/components/ColorIndicator.tsx | 28 + .../components/CommandPaletteDialog.tsx | 507 +++ .../components/CommercialUseBanner.tsx | 129 + .../components/ConfirmLargeRequestBody.tsx | 74 + .../components/ConfirmLargeResponse.tsx | 61 + .../ConfirmLargeResponseRequest.tsx | 56 + apps/yaak-client/components/ContextMenus.tsx | 26 + apps/yaak-client/components/CookieDialog.tsx | 731 ++++ .../yaak-client/components/CookieDropdown.tsx | 92 + apps/yaak-client/components/CopyButton.tsx | 33 + .../yaak-client/components/CopyIconButton.tsx | 31 + .../yaak-client/components/CreateDropdown.tsx | 21 + .../components/CreateEnvironmentDialog.tsx | 68 + .../components/CreateWorkspaceDialog.tsx | 97 + apps/yaak-client/components/Dialogs.tsx | 41 + .../components/DnsOverridesEditor.tsx | 190 + apps/yaak-client/components/DropMarker.tsx | 34 + apps/yaak-client/components/DynamicForm.tsx | 628 +++ .../yaak-client/components/EmptyStateText.tsx | 24 + .../yaak-client/components/EncryptionHelp.tsx | 13 + .../components/EnvironmentActionsDropdown.tsx | 85 + .../components/EnvironmentColorIndicator.tsx | 23 + .../components/EnvironmentColorPicker.tsx | 33 + .../components/EnvironmentEditDialog.tsx | 444 +++ .../components/EnvironmentEditor.tsx | 175 + .../components/EnvironmentSharableTooltip.tsx | 7 + apps/yaak-client/components/ErrorBoundary.tsx | 66 + .../components/ExportDataDialog.tsx | 169 + apps/yaak-client/components/FeedbackToast.tsx | 76 + apps/yaak-client/components/FolderLayout.tsx | 212 ++ .../components/FolderSettingsDialog.tsx | 209 + .../components/FormMultipartEditor.tsx | 57 + .../components/FormUrlencodedEditor.tsx | 46 + apps/yaak-client/components/GlobalHooks.tsx | 45 + .../components/GrpcConnectionLayout.tsx | 129 + apps/yaak-client/components/GrpcEditor.tsx | 302 ++ .../components/GrpcProtoSelectionDialog.tsx | 183 + .../components/GrpcRequestPane.tsx | 318 ++ .../components/GrpcResponsePane.tsx | 248 ++ apps/yaak-client/components/HeadersEditor.tsx | 190 + .../components/HttpAuthenticationEditor.tsx | 260 ++ .../components/HttpRequestLayout.tsx | 69 + .../components/HttpRequestPane.tsx | 497 +++ .../components/HttpResponsePane.tsx | 461 +++ .../components/HttpResponseTimeline.tsx | 466 +++ apps/yaak-client/components/ImportCurl.tsx | 112 + .../components/ImportDataDialog.tsx | 795 ++++ apps/yaak-client/components/IsDev.tsx | 14 + .../yaak-client/components/JsonBodyEditor.tsx | 122 + .../components/KeyboardShortcutsDialog.tsx | 10 + .../components/LargeValueDialog.tsx | 274 ++ apps/yaak-client/components/LicenseBadge.tsx | 139 + apps/yaak-client/components/LocalImage.tsx | 30 + apps/yaak-client/components/Markdown.tsx | 113 + .../yaak-client/components/MarkdownEditor.tsx | 83 + .../components/ModelSettingsEditor.tsx | 660 ++++ .../components/MoveToWorkspaceDialog.tsx | 88 + apps/yaak-client/components/Onboarding.tsx | 212 ++ apps/yaak-client/components/Prose.css | 212 ++ apps/yaak-client/components/Prose.tsx | 12 + .../RecentGrpcConnectionsDropdown.tsx | 115 + .../RecentHttpResponsesDropdown.tsx | 159 + .../components/RecentRequestsDropdown.tsx | 101 + .../RecentWebsocketConnectionsDropdown.tsx | 119 + .../components/RedirectToLatestWorkspace.tsx | 51 + .../components/RequestBodyViewer.tsx | 102 + .../components/RequestMethodDropdown.tsx | 78 + .../components/ResponseCookies.tsx | 225 ++ .../components/ResponseHeaders.tsx | 110 + apps/yaak-client/components/ResponseInfo.tsx | 44 + apps/yaak-client/components/RouteError.tsx | 43 + apps/yaak-client/components/SelectFile.tsx | 138 + .../components/Settings/Settings.tsx | 155 + .../Settings/SettingsCertificates.tsx | 254 ++ .../components/Settings/SettingsGeneral.tsx | 180 + .../components/Settings/SettingsHotkeys.tsx | 365 ++ .../components/Settings/SettingsInterface.tsx | 274 ++ .../components/Settings/SettingsLicense.tsx | 187 + .../components/Settings/SettingsPlugins.tsx | 426 +++ .../components/Settings/SettingsProxy.tsx | 180 + .../components/Settings/SettingsTheme.tsx | 173 + .../components/SettingsDropdown.tsx | 113 + apps/yaak-client/components/Sidebar.tsx | 1182 ++++++ .../yaak-client/components/SidebarActions.tsx | 39 + .../components/SwitchWorkspaceDialog.tsx | 60 + .../components/SyncToFilesystemSetting.tsx | 121 + .../components/TemplateFunctionDialog.tsx | 296 ++ apps/yaak-client/components/Toasts.tsx | 43 + apps/yaak-client/components/UrlBar.tsx | 113 + .../components/UrlParameterEditor.tsx | 54 + .../components/WebsocketRequestLayout.tsx | 49 + .../components/WebsocketRequestPane.tsx | 314 ++ .../components/WebsocketResponsePane.tsx | 241 ++ apps/yaak-client/components/Workspace.tsx | 227 ++ .../components/WorkspaceActionsDropdown.tsx | 193 + .../components/WorkspaceEncryptionSetting.tsx | 356 ++ .../components/WorkspaceHeader.tsx | 94 + .../components/WorkspaceSettingsDialog.tsx | 191 + apps/yaak-client/components/core/Alert.tsx | 21 + .../components/core/AutoScroller.tsx | 118 + .../components/core/BulkPairEditor.test.ts | 36 + .../components/core/BulkPairEditor.tsx | 63 + apps/yaak-client/components/core/Button.tsx | 34 + .../components/core/ButtonInfiniteLoading.tsx | 25 + apps/yaak-client/components/core/Checkbox.tsx | 73 + .../components/core/CheckboxTree.tsx | 114 + .../components/core/ColorPicker.tsx | 117 + apps/yaak-client/components/core/Confirm.tsx | 74 + .../components/core/CountBadge.tsx | 48 + .../components/core/DetailsBanner.tsx | 60 + apps/yaak-client/components/core/Dialog.tsx | 131 + .../components/core/DismissibleBanner.tsx | 111 + apps/yaak-client/components/core/Dropdown.tsx | 1069 ++++++ .../core/Editor/BetterMatchDecorator.ts | 13 + .../components/core/Editor/DiffViewer.css | 41 + .../components/core/Editor/DiffViewer.tsx | 64 + .../components/core/Editor/Editor.css | 515 +++ .../components/core/Editor/Editor.tsx | 770 ++++ .../components/core/Editor/LazyEditor.tsx | 12 + .../components/core/Editor/extensions.ts | 343 ++ .../core/Editor/filter/extension.ts | 211 ++ .../core/Editor/filter/filter.grammar | 78 + .../core/Editor/filter/filter.test.ts | 42 + .../components/core/Editor/filter/filter.ts | 22 + .../core/Editor/filter/format.test.ts | 43 + .../components/core/Editor/filter/format.ts | 7 + .../core/Editor/filter/highlight.ts | 22 + .../components/core/Editor/filter/query.ts | 308 ++ .../core/Editor/genericCompletion.ts | 43 + .../core/Editor/hyperlink/extension.ts | 129 + .../components/core/Editor/json-lint.ts | 60 + .../core/Editor/json/breadcrumbExtension.ts | 41 + .../core/Editor/json/jsonPath.test.ts | 136 + .../components/core/Editor/json/jsonPath.ts | 102 + .../core/Editor/largeValues.test.ts | 500 +++ .../components/core/Editor/largeValues.ts | 584 +++ .../components/core/Editor/pairs/extension.ts | 12 + .../components/core/Editor/pairs/highlight.ts | 7 + .../core/Editor/pairs/pairs.grammar | 9 + .../core/Editor/pairs/pairs.terms.ts | 5 + .../core/Editor/pairs/pairs.test.ts | 26 + .../components/core/Editor/pairs/pairs.ts | 29 + .../core/Editor/searchMatchCount.test.ts | 202 + .../core/Editor/searchMatchCount.ts | 325 ++ .../components/core/Editor/singleLine.ts | 47 + .../components/core/Editor/sniffValue.test.ts | 170 + .../components/core/Editor/sniffValue.ts | 219 ++ .../components/core/Editor/text/extension.ts | 12 + .../components/core/Editor/text/text.grammar | 5 + .../components/core/Editor/text/text.terms.ts | 3 + .../components/core/Editor/text/text.ts | 16 + .../core/Editor/timeline/extension.ts | 12 + .../core/Editor/timeline/highlight.ts | 7 + .../core/Editor/timeline/timeline.grammar | 21 + .../core/Editor/timeline/timeline.terms.ts | 11 + .../core/Editor/timeline/timeline.ts | 21 + .../core/Editor/twig/completion.test.ts | 155 + .../components/core/Editor/twig/completion.ts | 156 + .../components/core/Editor/twig/extension.ts | 85 + .../components/core/Editor/twig/highlight.ts | 7 + .../core/Editor/twig/pathParameters.ts | 106 + .../core/Editor/twig/templateTags.ts | 224 ++ .../components/core/Editor/twig/twig.grammar | 17 + .../components/core/Editor/twig/twig.terms.ts | 7 + .../components/core/Editor/twig/twig.test.ts | 108 + .../components/core/Editor/twig/twig.ts | 20 + .../components/core/Editor/twig/util.ts | 37 + .../core/Editor/url/completion.test.ts | 49 + .../components/core/Editor/url/completion.ts | 51 + .../components/core/Editor/url/extension.ts | 12 + .../components/core/Editor/url/highlight.ts | 10 + .../components/core/Editor/url/url.grammar | 24 + .../components/core/Editor/url/url.terms.ts | 9 + .../components/core/Editor/url/url.test.ts | 52 + .../components/core/Editor/url/url.ts | 18 + .../components/core/EventViewer.tsx | 312 ++ .../components/core/EventViewerRow.tsx | 38 + apps/yaak-client/components/core/Hotkey.tsx | 45 + .../components/core/HotkeyLabel.tsx | 15 + .../components/core/HotkeyList.test.tsx | 25 + .../components/core/HotkeyList.tsx | 31 + .../components/core/HttpMethodTag.tsx | 91 + .../core/HttpResponseDurationTag.tsx | 45 + .../components/core/HttpStatusTag.tsx | 55 + .../components/core/IconButton.tsx | 37 + .../components/core/IconTooltip.tsx | 30 + apps/yaak-client/components/core/Input.tsx | 677 ++++ .../components/core/JsonAttributeTree.tsx | 146 + .../components/core/KeyValueRow.tsx | 106 + apps/yaak-client/components/core/Label.tsx | 49 + apps/yaak-client/components/core/Link.tsx | 63 + .../components/core/PairEditor.tsx | 971 +++++ .../components/core/PairEditor.util.tsx | 10 + .../components/core/PairOrBulkEditor.tsx | 38 + .../components/core/PillButton.tsx | 14 + .../components/core/PlainInput.tsx | 244 ++ apps/yaak-client/components/core/Prompt.tsx | 66 + .../components/core/RadioCards.tsx | 64 + .../components/core/RadioDropdown.tsx | 69 + .../components/core/SegmentedControl.tsx | 136 + apps/yaak-client/components/core/Select.tsx | 149 + .../yaak-client/components/core/Separator.tsx | 77 + .../components/core/SettingRow.tsx | 514 +++ apps/yaak-client/components/core/SizeTag.tsx | 22 + .../yaak-client/components/core/Tabs/Tabs.tsx | 585 +++ apps/yaak-client/components/core/Toast.tsx | 148 + apps/yaak-client/components/core/Tooltip.tsx | 165 + .../components/core/WebsocketStatusTag.tsx | 31 + .../components/git/BranchSelectionDialog.tsx | 43 + .../components/git/FileHistoryDialog.tsx | 131 + .../components/git/GitCommitDialog.tsx | 481 +++ .../components/git/GitDropdown.tsx | 681 ++++ .../components/git/GitRemotesDialog.tsx | 73 + .../components/git/HistoryDialog.tsx | 44 + apps/yaak-client/components/git/callbacks.tsx | 31 + .../components/git/credentials.tsx | 49 + apps/yaak-client/components/git/diverged.tsx | 100 + apps/yaak-client/components/git/git-util.ts | 36 + .../components/git/showAddRemoteDialog.tsx | 20 + .../components/git/uncommitted.tsx | 13 + .../graphql/GraphQLDocsExplorer.tsx | 1008 +++++ .../components/graphql/GraphQLEditor.tsx | 434 +++ .../components/graphql/graphqlAtoms.ts | 14 + .../responseViewers/AudioViewer.tsx | 30 + .../responseViewers/BinaryViewer.tsx | 37 + .../responseViewers/CsvViewer.test.tsx | 32 + .../components/responseViewers/CsvViewer.tsx | 63 + .../responseViewers/EventStreamViewer.tsx | 428 +++ .../responseViewers/HTMLOrTextViewer.tsx | 106 + .../responseViewers/ImageViewer.tsx | 39 + .../components/responseViewers/JsonViewer.tsx | 22 + .../responseViewers/MultipartViewer.tsx | 136 + .../components/responseViewers/PdfViewer.css | 3 + .../components/responseViewers/PdfViewer.tsx | 81 + .../responseViewers/RecentFiltersDropdown.tsx | 96 + .../responseViewers/ResponseBreadcrumbBar.tsx | 192 + .../components/responseViewers/SvgViewer.tsx | 30 + .../components/responseViewers/TextViewer.tsx | 222 ++ .../responseViewers/VideoViewer.tsx | 29 + .../responseViewers/WebPageViewer.tsx | 28 + apps/yaak-client/font-size.ts | 19 + apps/yaak-client/font.ts | 23 + apps/yaak-client/hooks/useActiveCookieJar.ts | 58 + .../yaak-client/hooks/useActiveEnvironment.ts | 29 + .../hooks/useActiveEnvironmentVariables.ts | 8 + apps/yaak-client/hooks/useActiveFolder.ts | 9 + apps/yaak-client/hooks/useActiveFolderId.ts | 11 + apps/yaak-client/hooks/useActiveRequest.ts | 23 + apps/yaak-client/hooks/useActiveRequestId.ts | 11 + apps/yaak-client/hooks/useActiveWorkspace.ts | 24 + .../hooks/useActiveWorkspaceChangedToast.tsx | 31 + apps/yaak-client/hooks/useAllRequests.ts | 40 + apps/yaak-client/hooks/useAuthTab.tsx | 206 + .../hooks/useCancelHttpResponse.ts | 9 + apps/yaak-client/hooks/useCheckForUpdates.tsx | 26 + apps/yaak-client/hooks/useClickOutside.ts | 41 + apps/yaak-client/hooks/useCopyHttpResponse.ts | 16 + apps/yaak-client/hooks/useCreateCookieJar.ts | 33 + .../hooks/useCreateDropdownItems.tsx | 118 + apps/yaak-client/hooks/useCreateWorkspace.tsx | 14 + .../hooks/useDeleteGrpcConnections.ts | 12 + .../hooks/useDeleteHttpResponses.ts | 12 + .../hooks/useDeleteSendHistory.tsx | 52 + .../hooks/useEnvironmentValueVisibility.ts | 10 + .../hooks/useEnvironmentVariables.ts | 66 + .../hooks/useEnvironmentsBreakdown.ts | 35 + .../hooks/useEventViewerKeyboard.ts | 85 + apps/yaak-client/hooks/useExportData.tsx | 41 + apps/yaak-client/hooks/useFastMutation.ts | 76 + .../hooks/useFloatingSidebarHidden.ts | 14 + apps/yaak-client/hooks/useFolderActions.ts | 50 + apps/yaak-client/hooks/useFormatText.ts | 30 + .../yaak-client/hooks/useGraphQLSchemaFile.ts | 18 + apps/yaak-client/hooks/useGrpc.ts | 78 + apps/yaak-client/hooks/useGrpcProtoFiles.ts | 17 + .../hooks/useGrpcRequestActions.ts | 53 + apps/yaak-client/hooks/useHeadersTab.tsx | 31 + apps/yaak-client/hooks/useHotKey.ts | 442 +++ .../hooks/useHttpAuthentication.ts | 49 + .../hooks/useHttpAuthenticationConfig.ts | 84 + .../hooks/useHttpRequestActions.ts | 50 + apps/yaak-client/hooks/useHttpRequestBody.ts | 32 + .../hooks/useHttpResponseEvents.ts | 32 + .../hooks/useInheritedAuthentication.ts | 46 + apps/yaak-client/hooks/useInheritedHeaders.ts | 53 + apps/yaak-client/hooks/useInstallPlugin.ts | 11 + .../yaak-client/hooks/useIntrospectGraphQL.ts | 268 ++ .../hooks/useIsEncryptionEnabled.ts | 7 + apps/yaak-client/hooks/useKeyValue.ts | 90 + apps/yaak-client/hooks/useKeyboardEvent.ts | 16 + .../hooks/useLatestGrpcConnection.ts | 7 + .../hooks/useLatestHttpResponse.ts | 7 + apps/yaak-client/hooks/useModelAncestors.ts | 41 + apps/yaak-client/hooks/useParentFolders.ts | 24 + .../hooks/usePinnedGrpcConnection.ts | 84 + .../hooks/usePinnedHttpResponse.ts | 29 + .../hooks/usePinnedWebsocketConnection.ts | 71 + apps/yaak-client/hooks/usePlatformEvent.ts | 12 + apps/yaak-client/hooks/usePluginInfo.ts | 29 + apps/yaak-client/hooks/usePlugins.ts | 37 + .../hooks/usePreferredAppearance.ts | 15 + apps/yaak-client/hooks/useRandomKey.ts | 8 + apps/yaak-client/hooks/useRecentCookieJars.ts | 53 + .../hooks/useRecentEnvironments.ts | 51 + apps/yaak-client/hooks/useRecentFilters.ts | 67 + apps/yaak-client/hooks/useRecentRequests.ts | 53 + apps/yaak-client/hooks/useRecentWorkspaces.ts | 48 + apps/yaak-client/hooks/useRenderTemplate.ts | 71 + apps/yaak-client/hooks/useRequestEditor.tsx | 85 + apps/yaak-client/hooks/useRequestUpdateKey.ts | 41 + .../hooks/useResolvedAppearance.ts | 10 + apps/yaak-client/hooks/useResolvedTheme.ts | 25 + .../hooks/useResponseBodyEventSource.ts | 17 + .../hooks/useResponseBodySseSummary.ts | 19 + apps/yaak-client/hooks/useResponseBodyText.ts | 43 + apps/yaak-client/hooks/useResponseBodyUrl.ts | 24 + apps/yaak-client/hooks/useResponseFilter.ts | 129 + apps/yaak-client/hooks/useResponseViewMode.ts | 8 + apps/yaak-client/hooks/useSaveResponse.tsx | 42 + apps/yaak-client/hooks/useScrollIntoView.ts | 9 + .../hooks/useSendAnyHttpRequest.test.ts | 133 + .../hooks/useSendAnyHttpRequest.ts | 37 + apps/yaak-client/hooks/useSendManyRequests.ts | 14 + apps/yaak-client/hooks/useSidebarHidden.ts | 14 + .../hooks/useSidebarItemCollapsed.ts | 12 + apps/yaak-client/hooks/useSidebarWidth.ts | 14 + .../hooks/useSseSummaryResultKeyPath.ts | 98 + apps/yaak-client/hooks/useStateWithDeps.ts | 14 + .../yaak-client/hooks/useStoplightsVisible.ts | 8 + .../hooks/useSyncFontSizeSetting.ts | 17 + .../hooks/useSyncWorkspaceChildModels.ts | 17 + .../hooks/useSyncWorkspaceRequestTitle.ts | 34 + apps/yaak-client/hooks/useSyncZoomSetting.ts | 16 + .../hooks/useTemplateFunctionConfig.ts | 76 + .../hooks/useTemplateFunctions.tsx | 61 + .../hooks/useTemplateTokensToString.ts | 15 + apps/yaak-client/hooks/useTimelineViewMode.ts | 14 + apps/yaak-client/hooks/useToggle.ts | 7 + .../hooks/useToggleCommandPalette.tsx | 20 + .../hooks/useWebsocketRequestActions.ts | 52 + apps/yaak-client/hooks/useWindowFocus.ts | 12 + apps/yaak-client/hooks/useWorkspaceActions.ts | 50 + apps/yaak-client/hooks/useZoom.ts | 27 + apps/yaak-client/index.html | 39 + apps/yaak-client/init/git.ts | 38 + apps/yaak-client/init/sync.ts | 78 + apps/yaak-client/lib/alert.ts | 29 + apps/yaak-client/lib/appInfo.ts | 23 + apps/yaak-client/lib/atoms.ts | 22 + .../lib/atoms/atomWithKVStorage.ts | 25 + apps/yaak-client/lib/capitalize.ts | 6 + apps/yaak-client/lib/color.ts | 20 + apps/yaak-client/lib/confirm.ts | 34 + apps/yaak-client/lib/confirmWebProxy.test.tsx | 64 + apps/yaak-client/lib/confirmWebProxy.tsx | 60 + apps/yaak-client/lib/contentType.ts | 99 + apps/yaak-client/lib/contextMenu.ts | 46 + apps/yaak-client/lib/copy.ts | 22 + .../lib/createRequestAndNavigate.tsx | 31 + apps/yaak-client/lib/data/acceptLanguages.ts | 15 + apps/yaak-client/lib/data/cacheControl.ts | 16 + apps/yaak-client/lib/data/charsets.ts | 121 + apps/yaak-client/lib/data/connections.ts | 1 + apps/yaak-client/lib/data/encodings.ts | 1 + apps/yaak-client/lib/data/headerNames.ts | 70 + .../lib/data/headerValuePresets.ts | 7 + apps/yaak-client/lib/data/mimetypes.ts | 213 ++ apps/yaak-client/lib/data/userAgents.ts | 51 + apps/yaak-client/lib/defaultHeaders.ts | 8 + .../lib/deleteModelWithConfirm.tsx | 65 + apps/yaak-client/lib/dialog.ts | 22 + apps/yaak-client/lib/diffYaml.ts | 14 + apps/yaak-client/lib/dnd.ts | 39 + apps/yaak-client/lib/docFingerprint.test.ts | 67 + apps/yaak-client/lib/docFingerprint.ts | 33 + .../duplicateRequestOrFolderAndNavigate.tsx | 19 + apps/yaak-client/lib/editEnvironment.tsx | 62 + apps/yaak-client/lib/encryption.ts | 57 + apps/yaak-client/lib/featureFeedback.tsx | 103 + .../lib/featureFeedbackConstants.ts | 8 + apps/yaak-client/lib/fireAndForget.ts | 16 + apps/yaak-client/lib/formatters.ts | 45 + apps/yaak-client/lib/generateId.ts | 7 + apps/yaak-client/lib/getNodeText.ts | 22 + apps/yaak-client/lib/gitWorktreeStatus.ts | 22 + .../lib/graphqlOperationNames.test.ts | 37 + apps/yaak-client/lib/graphqlOperationNames.ts | 26 + apps/yaak-client/lib/graphqlSchema.test.ts | 85 + apps/yaak-client/lib/graphqlSchema.ts | 51 + apps/yaak-client/lib/importData.tsx | 136 + apps/yaak-client/lib/initGlobalListeners.tsx | 370 ++ apps/yaak-client/lib/jotai.ts | 3 + apps/yaak-client/lib/jsonComments.ts | 30 + .../yaak-client/lib/jsonSchemaExample.test.ts | 251 ++ apps/yaak-client/lib/jsonSchemaExample.ts | 121 + apps/yaak-client/lib/keyValueStore.ts | 70 + apps/yaak-client/lib/largeValue.ts | 236 ++ apps/yaak-client/lib/markdown.ts | 27 + apps/yaak-client/lib/minPromiseMillis.ts | 19 + apps/yaak-client/lib/model_util.test.ts | 91 + apps/yaak-client/lib/model_util.ts | 95 + apps/yaak-client/lib/onboarding.ts | 44 + apps/yaak-client/lib/pathPlaceholders.test.ts | 214 ++ apps/yaak-client/lib/pathPlaceholders.ts | 102 + apps/yaak-client/lib/pluralize.ts | 20 + .../lib/prepareImportQuerystring.ts | 25 + apps/yaak-client/lib/pricingUrl.ts | 3 + apps/yaak-client/lib/prompt-form.tsx | 47 + apps/yaak-client/lib/prompt.ts | 45 + apps/yaak-client/lib/queryClient.ts | 18 + .../yaak-client/lib/renameModelWithPrompt.tsx | 32 + .../lib/requestBodyConversion.test.ts | 152 + apps/yaak-client/lib/requestBodyConversion.ts | 199 + apps/yaak-client/lib/requestSettings.ts | 99 + apps/yaak-client/lib/resolvedModelName.ts | 61 + apps/yaak-client/lib/responseBody.ts | 78 + apps/yaak-client/lib/reveal.ts | 9 + apps/yaak-client/lib/router.ts | 12 + apps/yaak-client/lib/rpc.ts | 19 + apps/yaak-client/lib/scopes.ts | 3 + apps/yaak-client/lib/sendEphemeralRequest.ts | 17 + .../lib/setWorkspaceSearchParams.ts | 47 + apps/yaak-client/lib/settings.ts | 6 + .../lib/setupOrConfigureEncryption.tsx | 32 + apps/yaak-client/lib/showColorPicker.tsx | 23 + apps/yaak-client/lib/sleep.ts | 3 + apps/yaak-client/lib/themes.ts | 36 + apps/yaak-client/lib/toast.tsx | 70 + apps/yaak-client/lib/truncate.ts | 4 + apps/yaak-client/main.css | 96 + apps/yaak-client/main.tsx | 46 + apps/yaak-client/modules.d.ts | 1 + apps/yaak-client/package.json | 102 + apps/yaak-client/postcss.config.cjs | 3 + apps/yaak-client/react-augment.d.ts | 8 + apps/yaak-client/routeTree.gen.ts | 151 + apps/yaak-client/routes/__root.tsx | 54 + apps/yaak-client/routes/index.tsx | 19 + .../routes/workspaces/$workspaceId/index.tsx | 40 + .../$workspaceId/requests/$requestId.tsx | 23 + .../workspaces/$workspaceId/settings.tsx | 19 + apps/yaak-client/routes/workspaces/index.tsx | 10 + apps/yaak-client/theme.ts | 81 + apps/yaak-client/tsconfig.json | 28 + apps/yaak-client/tsconfig.node.json | 11 + apps/yaak-client/tsr.config.json | 3 + apps/yaak-client/vite-env.d.ts | 1 + apps/yaak-client/vite.config.ts | 226 ++ apps/yaak-client/web/og.html | 129 + apps/yaak-proxy/components/ActionButton.tsx | 31 + .../components/ActionIconButton.tsx | 29 + apps/yaak-proxy/components/ExchangesTable.tsx | 77 + apps/yaak-proxy/components/ProxyLayout.tsx | 146 + apps/yaak-proxy/components/Sidebar.tsx | 219 ++ apps/yaak-proxy/font-size.ts | 2 + apps/yaak-proxy/hooks/useActionMetadata.ts | 32 + apps/yaak-proxy/hooks/useRpcEvent.ts | 15 + apps/yaak-proxy/hooks/useRpcMutation.ts | 18 + apps/yaak-proxy/hooks/useRpcQuery.ts | 20 + apps/yaak-proxy/hooks/useRpcQueryWithEvent.ts | 23 + apps/yaak-proxy/index.html | 28 + apps/yaak-proxy/lib/fireAndForget.ts | 5 + apps/yaak-proxy/lib/hotkeys.ts | 63 + apps/yaak-proxy/lib/rpc.ts | 17 + apps/yaak-proxy/lib/store.ts | 11 + apps/yaak-proxy/lib/tauri.ts | 30 + apps/yaak-proxy/lib/theme.ts | 35 + apps/yaak-proxy/main.css | 92 + apps/yaak-proxy/main.tsx | 44 + apps/yaak-proxy/package.json | 37 + apps/yaak-proxy/postcss.config.cjs | 3 + apps/yaak-proxy/tsconfig.json | 28 + apps/yaak-proxy/tsconfig.node.json | 11 + apps/yaak-proxy/vite-env.d.ts | 1 + apps/yaak-proxy/vite.config.ts | 16 + crates-cli/yaak-cli/Cargo.toml | 59 + crates-cli/yaak-cli/README.md | 66 + crates-cli/yaak-cli/skills/use-yaak/SKILL.md | 168 + crates-cli/yaak-cli/src/cli.rs | 622 +++ crates-cli/yaak-cli/src/commands/agent.rs | 269 ++ crates-cli/yaak-cli/src/commands/auth.rs | 596 +++ .../yaak-cli/src/commands/cookie_jar.rs | 42 + .../yaak-cli/src/commands/environment.rs | 179 + crates-cli/yaak-cli/src/commands/folder.rs | 159 + .../yaak-cli/src/commands/import_export.rs | 277 ++ crates-cli/yaak-cli/src/commands/mod.rs | 12 + crates-cli/yaak-cli/src/commands/plugin.rs | 1018 +++++ crates-cli/yaak-cli/src/commands/request.rs | 620 +++ crates-cli/yaak-cli/src/commands/response.rs | 141 + crates-cli/yaak-cli/src/commands/send.rs | 242 ++ .../src/commands/template_function.rs | 111 + crates-cli/yaak-cli/src/commands/workspace.rs | 140 + crates-cli/yaak-cli/src/context.rs | 163 + crates-cli/yaak-cli/src/main.rs | 331 ++ crates-cli/yaak-cli/src/plugin_events.rs | 1211 ++++++ crates-cli/yaak-cli/src/ui.rs | 42 + crates-cli/yaak-cli/src/utils/confirm.rs | 16 + crates-cli/yaak-cli/src/utils/http.rs | 47 + crates-cli/yaak-cli/src/utils/json.rs | 131 + crates-cli/yaak-cli/src/utils/mod.rs | 5 + crates-cli/yaak-cli/src/utils/schema.rs | 15 + crates-cli/yaak-cli/src/utils/workspace.rs | 19 + crates-cli/yaak-cli/src/version.rs | 3 + crates-cli/yaak-cli/src/version_check.rs | 225 ++ .../yaak-cli/tests/common/http_server.rs | 89 + crates-cli/yaak-cli/tests/common/mod.rs | 101 + .../yaak-cli/tests/environment_commands.rs | 146 + crates-cli/yaak-cli/tests/folder_commands.rs | 122 + .../yaak-cli/tests/import_export_commands.rs | 324 ++ crates-cli/yaak-cli/tests/request_commands.rs | 291 ++ crates-cli/yaak-cli/tests/send_commands.rs | 50 + .../yaak-cli/tests/workspace_commands.rs | 77 + crates-proxy/yaak-proxy-lib/Cargo.toml | 21 + .../bindings/ModelChangeEvent.ts | 3 + .../yaak-proxy-lib/bindings/gen_models.ts | 8 + .../yaak-proxy-lib/bindings/gen_rpc.ts | 28 + crates-proxy/yaak-proxy-lib/bindings/index.ts | 2 + .../migrations/00000001_init.sql | 14 + crates-proxy/yaak-proxy-lib/package.json | 6 + crates-proxy/yaak-proxy-lib/src/actions.rs | 49 + crates-proxy/yaak-proxy-lib/src/db.rs | 31 + crates-proxy/yaak-proxy-lib/src/lib.rs | 271 ++ crates-proxy/yaak-proxy-lib/src/models.rs | 119 + crates-server/yaak-playground/Cargo.toml | 25 + crates-server/yaak-playground/README.md | 21 + crates-server/yaak-playground/src/auth.rs | 185 + crates-server/yaak-playground/src/config.rs | 59 + crates-server/yaak-playground/src/data.rs | 59 + crates-server/yaak-playground/src/error.rs | 57 + crates-server/yaak-playground/src/lib.rs | 170 + crates-server/yaak-playground/src/limits.rs | 50 + crates-server/yaak-playground/src/main.rs | 29 + .../yaak-playground/src/openapi.json | 396 ++ .../yaak-playground/src/resources.rs | 229 ++ crates-server/yaak-playground/src/seed.json | 88 + crates-server/yaak-playground/src/store.rs | 83 + crates-server/yaak-playground/tests/api.rs | 262 ++ crates-server/yaak-web/Cargo.toml | 40 + crates-server/yaak-web/README.md | 237 ++ crates-server/yaak-web/bindings/gen_models.ts | 135 + crates-server/yaak-web/bindings/gen_web.ts | 64 + crates-server/yaak-web/index.ts | 4 + crates-server/yaak-web/package.json | 6 + crates-server/yaak-web/src/config.rs | 98 + crates-server/yaak-web/src/guard.rs | 271 ++ crates-server/yaak-web/src/lib.rs | 295 ++ crates-server/yaak-web/src/limits.rs | 90 + crates-server/yaak-web/src/main.rs | 35 + crates-server/yaak-web/src/send.rs | 359 ++ crates-server/yaak-web/src/wire.rs | 97 + crates-server/yaak-web/tests/logging.rs | 98 + crates-server/yaak-web/tests/router.rs | 89 + crates-tauri/yaak-app-client/.gitignore | 10 + crates-tauri/yaak-app-client/Cargo.toml | 101 + .../yaak-app-client/bindings/gen_watch.ts | 3 + .../yaak-app-client/bindings/index.ts | 37 + .../yaak-app-client/bindings/plugins_ext.ts | 5 + crates-tauri/yaak-app-client/build.rs | 3 + .../yaak-app-client/capabilities/default.json | 55 + .../yaak-app-client/icons/dev/128x128.png | Bin 0 -> 6214 bytes .../yaak-app-client/icons/dev/128x128@2x.png | Bin 0 -> 12644 bytes .../yaak-app-client/icons/dev/32x32.png | Bin 0 -> 1509 bytes .../yaak-app-client/icons/dev/64x64.png | Bin 0 -> 2978 bytes .../icons/dev/Square107x107Logo.png | Bin 0 -> 5001 bytes .../icons/dev/Square142x142Logo.png | Bin 0 -> 6864 bytes .../icons/dev/Square150x150Logo.png | Bin 0 -> 7139 bytes .../icons/dev/Square284x284Logo.png | Bin 0 -> 13915 bytes .../icons/dev/Square30x30Logo.png | Bin 0 -> 1413 bytes .../icons/dev/Square310x310Logo.png | Bin 0 -> 15253 bytes .../icons/dev/Square44x44Logo.png | Bin 0 -> 2034 bytes .../icons/dev/Square71x71Logo.png | Bin 0 -> 3439 bytes .../icons/dev/Square89x89Logo.png | Bin 0 -> 4214 bytes .../yaak-app-client/icons/dev/StoreLogo.png | Bin 0 -> 2326 bytes .../dev/android/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2341 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 7751 bytes .../android/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 2341 bytes .../dev/android/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2329 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 5057 bytes .../android/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 2329 bytes .../dev/android/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4542 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 10421 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 4542 bytes .../dev/android/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6868 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 16153 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 6868 bytes .../android/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 9100 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 22021 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 9100 bytes .../yaak-app-client/icons/dev/icon.icns | Bin 0 -> 122779 bytes .../yaak-app-client/icons/dev/icon.ico | Bin 0 -> 21841 bytes .../yaak-app-client/icons/dev/icon.png | Bin 0 -> 26374 bytes .../icons/dev/ios/AppIcon-20x20@1x.png | Bin 0 -> 848 bytes .../icons/dev/ios/AppIcon-20x20@2x-1.png | Bin 0 -> 1852 bytes .../icons/dev/ios/AppIcon-20x20@2x.png | Bin 0 -> 1852 bytes .../icons/dev/ios/AppIcon-20x20@3x.png | Bin 0 -> 2846 bytes .../icons/dev/ios/AppIcon-29x29@1x.png | Bin 0 -> 1294 bytes .../icons/dev/ios/AppIcon-29x29@2x-1.png | Bin 0 -> 2740 bytes .../icons/dev/ios/AppIcon-29x29@2x.png | Bin 0 -> 2740 bytes .../icons/dev/ios/AppIcon-29x29@3x.png | Bin 0 -> 3989 bytes .../icons/dev/ios/AppIcon-40x40@1x.png | Bin 0 -> 1852 bytes .../icons/dev/ios/AppIcon-40x40@2x-1.png | Bin 0 -> 3759 bytes .../icons/dev/ios/AppIcon-40x40@2x.png | Bin 0 -> 3759 bytes .../icons/dev/ios/AppIcon-40x40@3x.png | Bin 0 -> 5762 bytes .../icons/dev/ios/AppIcon-512@2x.png | Bin 0 -> 32171 bytes .../icons/dev/ios/AppIcon-60x60@2x.png | Bin 0 -> 5762 bytes .../icons/dev/ios/AppIcon-60x60@3x.png | Bin 0 -> 8545 bytes .../icons/dev/ios/AppIcon-76x76@1x.png | Bin 0 -> 3429 bytes .../icons/dev/ios/AppIcon-76x76@2x.png | Bin 0 -> 7313 bytes .../icons/dev/ios/AppIcon-83.5x83.5@2x.png | Bin 0 -> 7943 bytes .../yaak-app-client/icons/icon-dev.png | Bin 0 -> 31969 bytes .../yaak-app-client/icons/release/128x128.png | Bin 0 -> 14307 bytes .../icons/release/128x128@2x.png | Bin 0 -> 37023 bytes .../yaak-app-client/icons/release/32x32.png | Bin 0 -> 2229 bytes .../yaak-app-client/icons/release/64x64.png | Bin 0 -> 5719 bytes .../icons/release/Square107x107Logo.png | Bin 0 -> 11181 bytes .../icons/release/Square142x142Logo.png | Bin 0 -> 16232 bytes .../icons/release/Square150x150Logo.png | Bin 0 -> 17385 bytes .../icons/release/Square284x284Logo.png | Bin 0 -> 43368 bytes .../icons/release/Square30x30Logo.png | Bin 0 -> 2090 bytes .../icons/release/Square310x310Logo.png | Bin 0 -> 49313 bytes .../icons/release/Square44x44Logo.png | Bin 0 -> 3356 bytes .../icons/release/Square71x71Logo.png | Bin 0 -> 6599 bytes .../icons/release/Square89x89Logo.png | Bin 0 -> 8705 bytes .../icons/release/StoreLogo.png | Bin 0 -> 4128 bytes .../android/mipmap-hdpi/ic_launcher.png | Bin 0 -> 4006 bytes .../mipmap-hdpi/ic_launcher_foreground.png | Bin 0 -> 19241 bytes .../android/mipmap-hdpi/ic_launcher_round.png | Bin 0 -> 4006 bytes .../android/mipmap-mdpi/ic_launcher.png | Bin 0 -> 3951 bytes .../mipmap-mdpi/ic_launcher_foreground.png | Bin 0 -> 11245 bytes .../android/mipmap-mdpi/ic_launcher_round.png | Bin 0 -> 3951 bytes .../android/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 9706 bytes .../mipmap-xhdpi/ic_launcher_foreground.png | Bin 0 -> 28929 bytes .../mipmap-xhdpi/ic_launcher_round.png | Bin 0 -> 9706 bytes .../android/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 16664 bytes .../mipmap-xxhdpi/ic_launcher_foreground.png | Bin 0 -> 52521 bytes .../mipmap-xxhdpi/ic_launcher_round.png | Bin 0 -> 16664 bytes .../android/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 24506 bytes .../mipmap-xxxhdpi/ic_launcher_foreground.png | Bin 0 -> 83359 bytes .../mipmap-xxxhdpi/ic_launcher_round.png | Bin 0 -> 24506 bytes .../yaak-app-client/icons/release/icon.ico | Bin 0 -> 52268 bytes .../yaak-app-client/icons/release/icon.png | Bin 0 -> 110500 bytes .../icons/release/ios/AppIcon-20x20@1x.png | Bin 0 -> 1087 bytes .../icons/release/ios/AppIcon-20x20@2x-1.png | Bin 0 -> 2826 bytes .../icons/release/ios/AppIcon-20x20@2x.png | Bin 0 -> 2826 bytes .../icons/release/ios/AppIcon-20x20@3x.png | Bin 0 -> 4901 bytes .../icons/release/ios/AppIcon-29x29@1x.png | Bin 0 -> 1801 bytes .../icons/release/ios/AppIcon-29x29@2x-1.png | Bin 0 -> 4770 bytes .../icons/release/ios/AppIcon-29x29@2x.png | Bin 0 -> 4770 bytes .../icons/release/ios/AppIcon-29x29@3x.png | Bin 0 -> 8113 bytes .../icons/release/ios/AppIcon-40x40@1x.png | Bin 0 -> 2826 bytes .../icons/release/ios/AppIcon-40x40@2x-1.png | Bin 0 -> 7347 bytes .../icons/release/ios/AppIcon-40x40@2x.png | Bin 0 -> 7347 bytes .../icons/release/ios/AppIcon-40x40@3x.png | Bin 0 -> 12449 bytes .../icons/release/ios/AppIcon-60x60@2x.png | Bin 0 -> 12449 bytes .../icons/release/ios/AppIcon-60x60@3x.png | Bin 0 -> 21555 bytes .../icons/release/ios/AppIcon-76x76@1x.png | Bin 0 -> 6759 bytes .../icons/release/ios/AppIcon-76x76@2x.png | Bin 0 -> 17124 bytes .../release/ios/AppIcon-83.5x83.5@2x.png | Bin 0 -> 19446 bytes crates-tauri/yaak-app-client/index.ts | 4 + .../yaak-app-client/macos/entitlements.plist | 10 + .../macos/entitlements.yaaknode.plist | 13 + .../macos/entitlements.yaakprotoc.plist | 6 + crates-tauri/yaak-app-client/package.json | 6 + crates-tauri/yaak-app-client/src/encoding.rs | 20 + crates-tauri/yaak-app-client/src/error.rs | 84 + crates-tauri/yaak-app-client/src/feedback.rs | 67 + crates-tauri/yaak-app-client/src/git_ext.rs | 162 + .../yaak-app-client/src/git_watcher.rs | 185 + crates-tauri/yaak-app-client/src/grpc.rs | 80 + crates-tauri/yaak-app-client/src/history.rs | 78 + .../yaak-app-client/src/http_request.rs | 179 + crates-tauri/yaak-app-client/src/import.rs | 185 + crates-tauri/yaak-app-client/src/lib.rs | 1590 ++++++++ crates-tauri/yaak-app-client/src/main.rs | 17 + .../yaak-app-client/src/models_ext.rs | 196 + .../yaak-app-client/src/notifications.rs | 179 + .../yaak-app-client/src/plugin_events.rs | 480 +++ .../yaak-app-client/src/plugins_ext.rs | 440 +++ crates-tauri/yaak-app-client/src/render.rs | 8 + crates-tauri/yaak-app-client/src/restart.rs | 107 + crates-tauri/yaak-app-client/src/rpc_ext.rs | 1235 ++++++ crates-tauri/yaak-app-client/src/sync_ext.rs | 92 + crates-tauri/yaak-app-client/src/updates.rs | 594 +++ .../yaak-app-client/src/uri_scheme.rs | 139 + .../yaak-app-client/src/window_menu.rs | 176 + crates-tauri/yaak-app-client/src/ws_ext.rs | 490 +++ crates-tauri/yaak-app-client/static/greg.jpeg | Bin 0 -> 10775 bytes crates-tauri/yaak-app-client/tauri.conf.json | 47 + .../tauri.development.conf.json | 13 + .../yaak-app-client/tauri.linux.conf.json | 3 + .../yaak-app-client/tauri.release.conf.json | 58 + crates-tauri/yaak-app-client/template.desktop | 9 + crates-tauri/yaak-app-proxy/.gitignore | 8 + crates-tauri/yaak-app-proxy/Cargo.toml | 27 + crates-tauri/yaak-app-proxy/bindings/index.ts | 1 + crates-tauri/yaak-app-proxy/build.rs | 3 + .../yaak-app-proxy/capabilities/default.json | 18 + crates-tauri/yaak-app-proxy/package.json | 6 + crates-tauri/yaak-app-proxy/src/lib.rs | 105 + crates-tauri/yaak-app-proxy/src/main.rs | 5 + .../yaak-app-proxy/src/window_menu.rs | 138 + crates-tauri/yaak-app-proxy/tauri.conf.json | 24 + .../tauri.development.conf.json | 13 + .../yaak-app-proxy/tauri.release.conf.json | 5 + crates-tauri/yaak-app-proxy/template.desktop | 9 + crates-tauri/yaak-fonts/Cargo.toml | 16 + crates-tauri/yaak-fonts/bindings/gen_fonts.ts | 3 + crates-tauri/yaak-fonts/build.rs | 5 + crates-tauri/yaak-fonts/index.ts | 14 + crates-tauri/yaak-fonts/package.json | 6 + .../yaak-fonts/permissions/default.toml | 3 + crates-tauri/yaak-fonts/src/commands.rs | 38 + crates-tauri/yaak-fonts/src/error.rs | 15 + crates-tauri/yaak-fonts/src/lib.rs | 15 + crates-tauri/yaak-license/Cargo.toml | 22 + .../yaak-license/bindings/gen_models.ts | 3 + crates-tauri/yaak-license/bindings/license.ts | 11 + crates-tauri/yaak-license/bindings/models.ts | 3 + crates-tauri/yaak-license/build.rs | 5 + crates-tauri/yaak-license/index.ts | 53 + crates-tauri/yaak-license/package.json | 6 + .../yaak-license/permissions/default.toml | 3 + crates-tauri/yaak-license/src/commands.rs | 18 + crates-tauri/yaak-license/src/error.rs | 34 + crates-tauri/yaak-license/src/lib.rs | 17 + crates-tauri/yaak-license/src/license.rs | 261 ++ crates-tauri/yaak-mac-window/Cargo.toml | 22 + crates-tauri/yaak-mac-window/build.rs | 5 + crates-tauri/yaak-mac-window/index.ts | 9 + crates-tauri/yaak-mac-window/package.json | 6 + .../yaak-mac-window/permissions/default.toml | 3 + crates-tauri/yaak-mac-window/src/commands.rs | 36 + crates-tauri/yaak-mac-window/src/lib.rs | 44 + crates-tauri/yaak-mac-window/src/mac.rs | 429 +++ .../yaak-system-appearance/Cargo.toml | 17 + .../yaak-system-appearance/src/lib.rs | 208 + crates-tauri/yaak-tauri-utils/Cargo.toml | 10 + crates-tauri/yaak-tauri-utils/src/lib.rs | 1 + crates-tauri/yaak-tauri-utils/src/window.rs | 53 + crates-tauri/yaak-window/Cargo.toml | 14 + crates-tauri/yaak-window/src/lib.rs | 3 + crates-tauri/yaak-window/src/window.rs | 259 ++ crates-tauri/yaak-window/src/window_state.rs | 218 ++ crates/common/yaak-database/Cargo.toml | 28 + .../yaak-database/src/connection_or_tx.rs | 24 + crates/common/yaak-database/src/db_context.rs | 194 + crates/common/yaak-database/src/error.rs | 37 + crates/common/yaak-database/src/lib.rs | 26 + crates/common/yaak-database/src/migrate.rs | 79 + crates/common/yaak-database/src/pool.rs | 81 + crates/common/yaak-database/src/traits.rs | 36 + .../common/yaak-database/src/update_source.rs | 31 + crates/common/yaak-database/src/util.rs | 20 + crates/common/yaak-rpc-schema/Cargo.toml | 18 + crates/common/yaak-rpc-schema/README.md | 44 + .../yaak-rpc-schema/bindings/gen_api.ts | 8 + .../yaak-rpc-schema/bindings/gen_events.ts | 389 ++ .../yaak-rpc-schema/bindings/gen_git.ts | 35 + .../yaak-rpc-schema/bindings/gen_grpc.ts | 5 + .../yaak-rpc-schema/bindings/gen_models.ts | 522 +++ .../yaak-rpc-schema/bindings/gen_rpc.ts | 261 ++ .../yaak-rpc-schema/bindings/gen_search.ts | 5 + .../yaak-rpc-schema/bindings/gen_sync.ts | 6 + .../yaak-rpc-schema/bindings/gen_util.ts | 107 + .../common/yaak-rpc-schema/bindings/parser.ts | 9 + crates/common/yaak-rpc-schema/bindings/sse.ts | 3 + crates/common/yaak-rpc-schema/index.ts | 4 + crates/common/yaak-rpc-schema/package.json | 6 + crates/common/yaak-rpc-schema/src/lib.rs | 1054 ++++++ crates/common/yaak-rpc/Cargo.toml | 12 + crates/common/yaak-rpc/src/lib.rs | 259 ++ crates/yaak-api/Cargo.toml | 12 + crates/yaak-api/src/error.rs | 9 + crates/yaak-api/src/lib.rs | 80 + crates/yaak-commands/Cargo.toml | 21 + crates/yaak-commands/src/actions.rs | 157 + crates/yaak-commands/src/auth.rs | 62 + crates/yaak-commands/src/data.rs | 30 + crates/yaak-commands/src/encryption.rs | 41 + crates/yaak-commands/src/error.rs | 30 + crates/yaak-commands/src/host.rs | 229 ++ crates/yaak-commands/src/lib.rs | 28 + crates/yaak-commands/src/models.rs | 187 + crates/yaak-commands/src/plugins.rs | 48 + crates/yaak-commands/src/render.rs | 74 + crates/yaak-commands/src/resolve.rs | 56 + crates/yaak-commands/src/responses.rs | 86 + crates/yaak-commands/src/templates.rs | 79 + crates/yaak-commands/tests/test_host.rs | 580 +++ crates/yaak-common/Cargo.toml | 9 + crates/yaak-common/src/command.rs | 42 + crates/yaak-common/src/lib.rs | 3 + crates/yaak-common/src/platform.rs | 55 + crates/yaak-common/src/serde.rs | 30 + crates/yaak-core/Cargo.toml | 9 + crates/yaak-core/src/context.rs | 37 + crates/yaak-core/src/error.rs | 15 + crates/yaak-core/src/lib.rs | 10 + crates/yaak-crypto/Cargo.toml | 15 + crates/yaak-crypto/index.ts | 17 + crates/yaak-crypto/package.json | 6 + crates/yaak-crypto/src/encryption.rs | 119 + crates/yaak-crypto/src/error.rs | 50 + crates/yaak-crypto/src/lib.rs | 7 + crates/yaak-crypto/src/manager.rs | 189 + crates/yaak-crypto/src/master_key.rs | 78 + crates/yaak-crypto/src/workspace_key.rs | 116 + crates/yaak-git/Cargo.toml | 24 + crates/yaak-git/bindings/gen_git.ts | 35 + crates/yaak-git/bindings/gen_models.ts | 179 + crates/yaak-git/index.ts | 424 +++ crates/yaak-git/package.json | 6 + crates/yaak-git/src/add.rs | 16 + crates/yaak-git/src/binary.rs | 17 + crates/yaak-git/src/branch.rs | 153 + crates/yaak-git/src/clone.rs | 53 + crates/yaak-git/src/commit.rs | 106 + crates/yaak-git/src/credential.rs | 44 + crates/yaak-git/src/error.rs | 64 + crates/yaak-git/src/fetch.rs | 22 + crates/yaak-git/src/init.rs | 14 + crates/yaak-git/src/lib.rs | 44 + crates/yaak-git/src/log.rs | 145 + crates/yaak-git/src/pull.rs | 208 + crates/yaak-git/src/push.rs | 89 + crates/yaak-git/src/remotes.rs | 47 + crates/yaak-git/src/repository.rs | 38 + crates/yaak-git/src/reset.rs | 20 + crates/yaak-git/src/restore.rs | 76 + crates/yaak-git/src/status.rs | 375 ++ crates/yaak-git/src/unstage.rs | 27 + crates/yaak-git/src/util.rs | 121 + crates/yaak-grpc/Cargo.toml | 28 + crates/yaak-grpc/bindings/gen_grpc.ts | 5 + crates/yaak-grpc/src/any.rs | 61 + crates/yaak-grpc/src/client.rs | 188 + crates/yaak-grpc/src/codec.rs | 50 + crates/yaak-grpc/src/error.rs | 51 + crates/yaak-grpc/src/json_schema.rs | 382 ++ crates/yaak-grpc/src/lib.rs | 56 + crates/yaak-grpc/src/manager.rs | 553 +++ crates/yaak-grpc/src/reflection.rs | 533 +++ crates/yaak-grpc/src/transport.rs | 40 + crates/yaak-http/Cargo.toml | 43 + crates/yaak-http/src/chained_reader.rs | 78 + crates/yaak-http/src/client.rs | 504 +++ crates/yaak-http/src/cookies.rs | 581 +++ crates/yaak-http/src/decompress.rs | 188 + crates/yaak-http/src/dns.rs | 225 ++ crates/yaak-http/src/error.rs | 43 + crates/yaak-http/src/lib.rs | 16 + crates/yaak-http/src/manager.rs | 53 + crates/yaak-http/src/proto.rs | 29 + crates/yaak-http/src/sender.rs | 641 ++++ crates/yaak-http/src/tee_reader.rs | 159 + crates/yaak-http/src/transaction.rs | 1089 ++++++ crates/yaak-http/src/types.rs | 1262 +++++++ crates/yaak-http/tests/test.txt | 1 + crates/yaak-lifecycle/Cargo.toml | 10 + crates/yaak-lifecycle/src/lib.rs | 126 + crates/yaak-models/Cargo.toml | 29 + .../yaak-models/bindings/ModelChangeEvent.ts | 3 + crates/yaak-models/bindings/gen_models.ts | 580 +++ crates/yaak-models/bindings/gen_util.ts | 107 + .../blob_migrations/00000000000000_init.sql | 12 + crates/yaak-models/build.rs | 5 + crates/yaak-models/guest-js/atoms.test.ts | 59 + crates/yaak-models/guest-js/atoms.ts | 87 + crates/yaak-models/guest-js/index.ts | 11 + crates/yaak-models/guest-js/store.ts | 413 ++ crates/yaak-models/guest-js/types.ts | 8 + crates/yaak-models/guest-js/util.ts | 26 + .../migrations/20230225181302_init.sql | 65 + .../20230319042610_sort-priority.sql | 1 + .../20230330143214_request-auth.sql | 2 + .../20230413232435_response-body-blob.sql | 5 + .../20231022205109_environments.sql | 15 + .../migrations/20231028161007_variables.sql | 2 + .../20231103004111_workspace-variables.sql | 1 + .../migrations/20231103142807_folders.sql | 19 + .../migrations/20231112180500_body_object.sql | 16 + .../migrations/20231113183810_url_params.sql | 2 + .../migrations/20231122055216_remove_body.sql | 1 + .../migrations/20240111221224_settings.sql | 13 + .../20240115193751_workspace_settings.sql | 9 + .../20240118181105_channel_setting.sql | 1 + .../migrations/20240127013915_cookies.sql | 10 + .../20240128230717_more_response_attrs.sql | 3 + .../migrations/20240203164833_grpc.sql | 68 + .../20240522031045_theme-settings.sql | 4 + .../20240529143147_more-settings.sql | 4 + .../20240607151115_open-workspace-setting.sql | 1 + .../20240814013812_fix-env-model.sql | 2 + .../20240826184943_disable-telemetry.sql | 1 + .../migrations/20240829131004_plugins.sql | 12 + .../20241003134208_response-state.sql | 5 + .../20241012181547_proxy-setting.sql | 1 + .../migrations/20241217204951_docs.sql | 8 + .../20241219140051_base-environments.sql | 45 + .../migrations/20250102141937_sync.sql | 21 + .../20250108035425_editor-keymap.sql | 2 + .../20250108205117_workspace-meta.sql | 11 + ...14160022_remove-workspace-sync-setting.sql | 2 + .../migrations/20250123192023_plugin-kv.sql | 11 + .../migrations/20250128155623_websockets.sql | 66 + .../20250302041707_hide-window-controls.sql | 2 + .../20250326193143_key-value-id.sql | 43 + .../20250401122407_encrypted-key.sql | 1 + ...0250402144842_encryption-key-challenge.sql | 1 + .../migrations/20250424152740_remove-fks.sql | 243 ++ .../20250507140702_remove-ev-sync-states.sql | 11 + .../20250508161145_public-environments.sql | 20 + .../20250516182745_default-attrs.sql | 15 + .../20250530174021_graphql-introspection.sql | 21 + .../20250531193722_sync-state-index.sql | 43 + ...20250604102922_colored-methods-setting.sql | 2 + .../20250608150053_font-settings.sql | 2 + .../20250611120000_environment-color.sql | 1 + .../20250727190746_autoupdate_setting.sql | 1 + ...0918141129_request-folder-environments.sql | 62 + .../20250929132954_dismiss-license-badge.sql | 10 + .../20251001082054_auto-download.sql | 2 + ...1028060300_check_notifications_setting.sql | 1 + .../20251029062024_aws-auth-name.sql | 11 + ...251031070515_environment-sort-priority.sql | 2 + .../20251202080000_use-native-titlebar.sql | 3 + .../20251209000000_client-certificates.sql | 1 + ...251219074602_default-workspace-headers.sql | 15 + ...0251220000000_response-request-headers.sql | 3 + .../20251221000000_http-response-events.sql | 15 + .../20251221100000_request-content-length.sql | 2 + .../migrations/20260104000000_hotkeys.sql | 1 + .../migrations/20260111000000_dns-timing.sql | 2 + .../20260112000000_dns-overrides.sql | 2 + ...45146_remove-default-workspace-headers.sql | 12 + .../20260216000000_model-changes.sql | 12 + ...60217000000_remove-legacy-faker-plugin.sql | 3 + ...000_plugin-source-and-unique-directory.sql | 33 + ...60302000000_inherited-request-settings.sql | 17 + .../20260303000000_protocol-tls-settings.sql | 3 + .../20260629000000_request-message-size.sql | 7 + .../20260704000000_prompt-feedback.sql | 3 + .../20260826000000_http-version.sql | 5 + .../20260901000000_import-sources.sql | 25 + ...60902000000_import-source-content-hash.sql | 24 + crates/yaak-models/package.json | 6 + crates/yaak-models/src/blob_manager.rs | 414 ++ crates/yaak-models/src/client_db.rs | 176 + crates/yaak-models/src/connection_or_tx.rs | 1 + crates/yaak-models/src/cookies.rs | 107 + crates/yaak-models/src/error.rs | 69 + crates/yaak-models/src/example.rs | 104 + crates/yaak-models/src/example_workspace.json | 181 + crates/yaak-models/src/export.rs | 33 + crates/yaak-models/src/lib.rs | 183 + crates/yaak-models/src/migrate.rs | 147 + crates/yaak-models/src/models.rs | 3358 +++++++++++++++++ crates/yaak-models/src/models_ops.rs | 89 + crates/yaak-models/src/path_placeholders.rs | 220 ++ crates/yaak-models/src/queries/any_request.rs | 21 + crates/yaak-models/src/queries/batch.rs | 73 + crates/yaak-models/src/queries/cookie_jars.rs | 50 + .../yaak-models/src/queries/duplicate_name.rs | 56 + .../yaak-models/src/queries/environments.rs | 362 ++ crates/yaak-models/src/queries/folders.rs | 223 ++ .../src/queries/graphql_introspections.rs | 54 + .../src/queries/grpc_connections.rs | 97 + crates/yaak-models/src/queries/grpc_events.rs | 24 + .../yaak-models/src/queries/grpc_requests.rs | 150 + .../yaak-models/src/queries/http_requests.rs | 312 ++ .../src/queries/http_response_events.rs | 20 + .../yaak-models/src/queries/http_responses.rs | 300 ++ .../src/queries/import_source_resources.rs | 96 + .../yaak-models/src/queries/import_sources.rs | 47 + crates/yaak-models/src/queries/key_values.rs | 179 + crates/yaak-models/src/queries/mod.rs | 88 + .../yaak-models/src/queries/model_changes.rs | 330 ++ .../src/queries/plugin_key_values.rs | 85 + crates/yaak-models/src/queries/plugins.rs | 37 + crates/yaak-models/src/queries/settings.rs | 61 + crates/yaak-models/src/queries/sync_states.rs | 48 + .../src/queries/websocket_connections.rs | 100 + .../src/queries/websocket_events.rs | 24 + .../src/queries/websocket_requests.rs | 172 + .../src/queries/workspace_metas.rs | 39 + crates/yaak-models/src/queries/workspaces.rs | 218 ++ crates/yaak-models/src/query_manager.rs | 85 + crates/yaak-models/src/render.rs | 250 ++ crates/yaak-models/src/util.rs | 328 ++ crates/yaak-plugins/Cargo.toml | 30 + crates/yaak-plugins/bindings/gen_api.ts | 8 + crates/yaak-plugins/bindings/gen_events.ts | 663 ++++ crates/yaak-plugins/bindings/gen_models.ts | 514 +++ crates/yaak-plugins/bindings/gen_search.ts | 5 + .../bindings/serde_json/JsonValue.ts | 3 + crates/yaak-plugins/index.ts | 30 + crates/yaak-plugins/package.json | 6 + crates/yaak-plugins/src/api.rs | 135 + crates/yaak-plugins/src/checksum.rs | 8 + crates/yaak-plugins/src/error.rs | 64 + crates/yaak-plugins/src/events.rs | 1639 ++++++++ crates/yaak-plugins/src/install.rs | 92 + crates/yaak-plugins/src/lib.rs | 21 + crates/yaak-plugins/src/manager.rs | 1255 ++++++ .../src/native_template_functions.rs | 269 ++ crates/yaak-plugins/src/nodejs.rs | 98 + crates/yaak-plugins/src/plugin_handle.rs | 66 + crates/yaak-plugins/src/plugin_meta.rs | 64 + crates/yaak-plugins/src/server_ws.rs | 150 + crates/yaak-plugins/src/template_callback.rs | 87 + crates/yaak-plugins/src/util.rs | 6 + crates/yaak-proxy/Cargo.toml | 25 + crates/yaak-proxy/src/body.rs | 113 + crates/yaak-proxy/src/cert.rs | 69 + crates/yaak-proxy/src/connection.rs | 32 + crates/yaak-proxy/src/lib.rs | 183 + crates/yaak-proxy/src/request.rs | 339 ++ crates/yaak-sse/Cargo.toml | 9 + crates/yaak-sse/bindings/sse.ts | 3 + crates/yaak-sse/index.ts | 2 + crates/yaak-sse/package.json | 12 + crates/yaak-sse/src/lib.rs | 1 + crates/yaak-sse/src/sse.rs | 12 + crates/yaak-sse/summary.test.ts | 51 + crates/yaak-sse/summary.ts | 131 + crates/yaak-sync/Cargo.toml | 20 + crates/yaak-sync/bindings/gen_models.ts | 192 + crates/yaak-sync/bindings/gen_sync.ts | 6 + crates/yaak-sync/bindings/gen_watch.ts | 3 + crates/yaak-sync/bindings/git.ts | 7 + crates/yaak-sync/index.ts | 82 + crates/yaak-sync/package.json | 6 + crates/yaak-sync/src/error.rs | 44 + crates/yaak-sync/src/lib.rs | 4 + crates/yaak-sync/src/models.rs | 311 ++ crates/yaak-sync/src/sync.rs | 605 +++ crates/yaak-sync/src/watch.rs | 90 + crates/yaak-templates/Cargo.toml | 29 + crates/yaak-templates/bindings/parser.ts | 9 + crates/yaak-templates/build-wasm.cjs | 39 + crates/yaak-templates/index.ts | 15 + crates/yaak-templates/package.json | 15 + crates/yaak-templates/pkg/package.json | 17 + crates/yaak-templates/pkg/yaak_templates.d.ts | 8 + crates/yaak-templates/pkg/yaak_templates.js | 6 + .../yaak-templates/pkg/yaak_templates_bg.js | 241 ++ .../yaak-templates/pkg/yaak_templates_bg.wasm | Bin 0 -> 67385 bytes .../pkg/yaak_templates_bg.wasm.d.ts | 11 + crates/yaak-templates/src/error.rs | 32 + crates/yaak-templates/src/escape.rs | 166 + crates/yaak-templates/src/format_json.rs | 533 +++ crates/yaak-templates/src/lib.rs | 11 + crates/yaak-templates/src/parser.rs | 904 +++++ crates/yaak-templates/src/renderer.rs | 691 ++++ .../yaak-templates/src/strip_json_comments.rs | 326 ++ crates/yaak-templates/src/wasm.rs | 22 + crates/yaak-tls/Cargo.toml | 18 + crates/yaak-tls/src/error.rs | 26 + crates/yaak-tls/src/lib.rs | 499 +++ crates/yaak-wasm/Cargo.toml | 41 + crates/yaak-wasm/build-wasm.cjs | 69 + crates/yaak-wasm/index.ts | 6 + crates/yaak-wasm/package.json | 15 + crates/yaak-wasm/pkg/package.json | 17 + crates/yaak-wasm/pkg/yaak_wasm.d.ts | 62 + crates/yaak-wasm/pkg/yaak_wasm.js | 9 + crates/yaak-wasm/pkg/yaak_wasm_bg.js | 1009 +++++ crates/yaak-wasm/pkg/yaak_wasm_bg.wasm.d.ts | 33 + crates/yaak-wasm/src/lib.rs | 641 ++++ crates/yaak-ws/Cargo.toml | 24 + crates/yaak-ws/index.ts | 43 + crates/yaak-ws/package.json | 6 + crates/yaak-ws/src/connect.rs | 60 + crates/yaak-ws/src/error.rs | 32 + crates/yaak-ws/src/lib.rs | 12 + crates/yaak-ws/src/manager.rs | 121 + crates/yaak-ws/src/render.rs | 80 + crates/yaak/Cargo.toml | 28 + crates/yaak/src/error.rs | 21 + crates/yaak/src/import.rs | 3019 +++++++++++++++ crates/yaak/src/lib.rs | 8 + crates/yaak/src/plugin_events.rs | 815 ++++ crates/yaak/src/response_body.rs | 235 ++ crates/yaak/src/send.rs | 1539 ++++++++ flatpak/app.yaak.Yaak.metainfo.xml | 57 + flatpak/fix-lockfile.mjs | 75 + flatpak/generate-sources.sh | 48 + flatpak/update-manifest.sh | 86 + greptile.json | 3 + npm/cli-darwin-arm64/bin/.gitkeep | 0 npm/cli-darwin-arm64/package.json | 15 + npm/cli-darwin-x64/bin/.gitkeep | 0 npm/cli-darwin-x64/package.json | 15 + npm/cli-linux-arm64/bin/.gitkeep | 0 npm/cli-linux-arm64/package.json | 15 + npm/cli-linux-x64/bin/.gitkeep | 0 npm/cli-linux-x64/package.json | 15 + npm/cli-win32-arm64/bin/.gitkeep | 0 npm/cli-win32-arm64/package.json | 15 + npm/cli-win32-x64/bin/.gitkeep | 0 npm/cli-win32-x64/package.json | 15 + npm/cli/.gitignore | 2 + npm/cli/bin/cli.js | 31 + npm/cli/common.js | 20 + npm/cli/index.js | 21 + npm/cli/install.js | 97 + npm/cli/package.json | 26 + npm/cli/prepublish.js | 5 + npm/prepare-publish.js | 77 + package.json | 150 + packages/common-lib/debounce.test.ts | 76 + packages/common-lib/debounce.ts | 32 + packages/common-lib/eagerDebounceAsync.ts | 36 + packages/common-lib/formatSize.ts | 20 + packages/common-lib/index.ts | 4 + packages/common-lib/jsonPath.ts | 39 + packages/common-lib/package.json | 6 + packages/common-lib/templateFunction.ts | 49 + packages/model-store/package.json | 11 + packages/model-store/src/index.ts | 94 + packages/platform/package.json | 23 + packages/platform/src/capabilities.ts | 14 + packages/platform/src/index.ts | 15 + packages/platform/src/index.web.ts | 23 + packages/platform/src/registry.ts | 66 + packages/platform/src/tauri/index.ts | 228 ++ packages/platform/src/types.ts | 318 ++ packages/platform/src/web/README.md | 228 ++ packages/platform/src/web/commands.ts | 373 ++ packages/platform/src/web/connection.ts | 236 ++ packages/platform/src/web/errors.ts | 32 + packages/platform/src/web/ids.ts | 14 + packages/platform/src/web/index.ts | 383 ++ packages/platform/src/web/protocol.ts | 53 + packages/platform/src/web/send.ts | 352 ++ packages/platform/src/web/server.ts | 83 + packages/platform/src/web/storage.ts | 18 + packages/platform/src/web/worker.ts | 196 + packages/platform/tsconfig.json | 12 + packages/plugin-runtime-types/.gitignore | 2 + packages/plugin-runtime-types/README.md | 28 + packages/plugin-runtime-types/package.json | 38 + .../src/bindings/gen_api.ts | 8 + .../src/bindings/gen_events.ts | 663 ++++ .../src/bindings/gen_models.ts | 514 +++ .../src/bindings/gen_search.ts | 5 + .../src/bindings/serde_json/JsonValue.ts | 3 + packages/plugin-runtime-types/src/helpers.ts | 2 + packages/plugin-runtime-types/src/index.ts | 9 + .../src/plugins/AuthenticationPlugin.ts | 45 + .../src/plugins/Context.ts | 236 ++ .../src/plugins/FilterPlugin.ts | 11 + .../src/plugins/FolderActionPlugin.ts | 6 + .../src/plugins/GrpcRequestActionPlugin.ts | 6 + .../src/plugins/HttpRequestActionPlugin.ts | 6 + .../src/plugins/ImporterPlugin.ts | 31 + .../src/plugins/TemplateFunctionPlugin.ts | 32 + .../src/plugins/ThemePlugin.ts | 3 + .../plugins/WebsocketRequestActionPlugin.ts | 9 + .../src/plugins/WorkspaceActionPlugin.ts | 6 + .../plugin-runtime-types/src/plugins/index.ts | 44 + .../plugin-runtime-types/src/themes/index.ts | 44 + packages/plugin-runtime-types/tsconfig.json | 14 + packages/plugin-runtime/.node-version | 1 + packages/plugin-runtime/package.json | 16 + packages/plugin-runtime/src/EventChannel.ts | 19 + packages/plugin-runtime/src/PluginHandle.ts | 26 + packages/plugin-runtime/src/PluginInstance.ts | 1099 ++++++ packages/plugin-runtime/src/common.ts | 75 + packages/plugin-runtime/src/index.ts | 73 + .../plugin-runtime/src/interceptStdout.ts | 29 + packages/plugin-runtime/src/metadata.ts | 190 + packages/plugin-runtime/src/migrations.ts | 22 + packages/plugin-runtime/src/responseBody.ts | 194 + packages/plugin-runtime/tests/common.test.ts | 151 + .../plugin-runtime/tests/responseBody.test.ts | 203 + .../tests/sendHttpRequest.test.ts | 65 + packages/plugin-runtime/tsconfig.json | 17 + packages/tailwind-config/index.css | 124 + packages/tailwind-config/package.json | 6 + packages/theme/package.json | 13 + packages/theme/src/appearance.ts | 85 + packages/theme/src/defaultThemes.ts | 76 + packages/theme/src/index.ts | 28 + packages/theme/src/window.ts | 413 ++ packages/theme/src/yaakColor.ts | 386 ++ packages/theme/tsconfig.json | 12 + packages/ui/package.json | 11 + packages/ui/src/components/Banner.tsx | 28 + packages/ui/src/components/Button.tsx | 127 + packages/ui/src/components/DropMarker.tsx | 34 + packages/ui/src/components/FormattedError.tsx | 23 + packages/ui/src/components/HeaderSize.tsx | 100 + packages/ui/src/components/Heading.tsx | 22 + packages/ui/src/components/Icon.tsx | 340 ++ packages/ui/src/components/IconButton.tsx | 95 + packages/ui/src/components/InlineCode.tsx | 15 + packages/ui/src/components/LoadingIcon.tsx | 35 + packages/ui/src/components/Overlay.tsx | 90 + packages/ui/src/components/Portal.tsx | 13 + packages/ui/src/components/ResizeHandle.tsx | 112 + packages/ui/src/components/SidebarLayout.tsx | 146 + packages/ui/src/components/SplitLayout.tsx | 168 + packages/ui/src/components/Stacks.tsx | 93 + packages/ui/src/components/Table.tsx | 128 + packages/ui/src/components/WindowControls.tsx | 99 + packages/ui/src/components/tree/Tree.tsx | 835 ++++ .../src/components/tree/TreeDragOverlay.tsx | 31 + .../ui/src/components/tree/TreeDropMarker.tsx | 36 + .../src/components/tree/TreeIndentGuide.tsx | 32 + packages/ui/src/components/tree/TreeItem.tsx | 415 ++ .../ui/src/components/tree/TreeItemList.tsx | 191 + packages/ui/src/components/tree/atoms.ts | 76 + packages/ui/src/components/tree/common.ts | 100 + packages/ui/src/components/tree/context.ts | 60 + .../ui/src/components/tree/keyboard.test.ts | 20 + packages/ui/src/components/tree/keyboard.ts | 7 + .../src/components/tree/useSelectableItems.ts | 30 + packages/ui/src/hooks/useContainerSize.ts | 30 + packages/ui/src/hooks/useDebouncedState.ts | 12 + packages/ui/src/hooks/useDebouncedValue.ts | 8 + packages/ui/src/hooks/useIsFullscreen.ts | 22 + packages/ui/src/hooks/usePortal.ts | 26 + packages/ui/src/hooks/useTimedBoolean.ts | 19 + packages/ui/src/index.ts | 48 + packages/ui/src/lib/clamp.ts | 3 + packages/ui/src/lib/constants.ts | 4 + packages/ui/src/lib/dnd.ts | 39 + packages/ui/src/lib/minPromiseMillis.ts | 16 + packages/ui/tsconfig.json | 14 + plugins-external/.gitignore | 1 + plugins-external/faker/README.md | 76 + plugins-external/faker/package.json | 24 + plugins-external/faker/src/index.ts | 106 + .../tests/__snapshots__/init.test.ts.snap | 234 ++ plugins-external/faker/tests/init.test.ts | 31 + plugins-external/faker/tsconfig.json | 3 + plugins-external/httpsnippet/README.md | 52 + plugins-external/httpsnippet/package.json | 24 + plugins-external/httpsnippet/src/index.ts | 317 ++ plugins-external/mcp-server/README.md | 58 + plugins-external/mcp-server/package.json | 28 + plugins-external/mcp-server/src/index.ts | 36 + plugins-external/mcp-server/src/server.ts | 72 + .../mcp-server/src/tools/folder.ts | 148 + .../mcp-server/src/tools/helpers.ts | 32 + .../mcp-server/src/tools/httpRequest.test.ts | 98 + .../mcp-server/src/tools/httpRequest.ts | 201 + .../mcp-server/src/tools/schemas.ts | 67 + .../mcp-server/src/tools/toast.ts | 59 + .../mcp-server/src/tools/window.ts | 47 + .../mcp-server/src/tools/workspace.ts | 24 + plugins-external/mcp-server/src/types.ts | 5 + plugins-external/mcp-server/tsconfig.json | 7 + plugins/.gitignore | 1 + plugins/action-copy-curl/README.md | 68 + plugins/action-copy-curl/package.json | 17 + plugins/action-copy-curl/src/index.ts | 179 + plugins/action-copy-curl/tests/index.test.ts | 470 +++ plugins/action-copy-curl/tsconfig.json | 3 + plugins/action-copy-grpcurl/README.md | 75 + plugins/action-copy-grpcurl/package.json | 17 + plugins/action-copy-grpcurl/src/index.ts | 158 + .../action-copy-grpcurl/tests/index.test.ts | 195 + plugins/action-copy-grpcurl/tsconfig.json | 3 + plugins/action-send-folder/package.json | 16 + plugins/action-send-folder/src/index.ts | 99 + plugins/action-send-folder/tsconfig.json | 3 + plugins/auth-apikey/package.json | 16 + plugins/auth-apikey/src/index.ts | 54 + plugins/auth-apikey/tsconfig.json | 3 + plugins/auth-aws/README.md | 49 + plugins/auth-aws/package.json | 22 + plugins/auth-aws/src/index.ts | 89 + plugins/auth-aws/tsconfig.json | 3 + plugins/auth-basic/README.md | 44 + plugins/auth-basic/package.json | 17 + plugins/auth-basic/src/index.ts | 30 + plugins/auth-basic/tests/index.test.ts | 87 + plugins/auth-basic/tsconfig.json | 3 + plugins/auth-bearer/README.md | 47 + plugins/auth-bearer/package.json | 17 + plugins/auth-bearer/src/index.ts | 39 + plugins/auth-bearer/tests/index.test.ts | 67 + plugins/auth-bearer/tsconfig.json | 3 + plugins/auth-digest/README.md | 56 + plugins/auth-digest/package.json | 17 + plugins/auth-digest/src/digest.ts | 294 ++ plugins/auth-digest/src/index.ts | 75 + plugins/auth-digest/tests/digest.test.ts | 390 ++ plugins/auth-digest/tests/index.test.ts | 375 ++ plugins/auth-digest/tsconfig.json | 3 + plugins/auth-jwt/README.md | 54 + plugins/auth-jwt/package.json | 22 + plugins/auth-jwt/src/index.ts | 148 + plugins/auth-jwt/tsconfig.json | 3 + plugins/auth-ntlm/package.json | 20 + plugins/auth-ntlm/src/index.ts | 94 + plugins/auth-ntlm/src/modules.d.ts | 1 + plugins/auth-ntlm/tests/index.test.ts | 89 + plugins/auth-ntlm/tsconfig.json | 3 + plugins/auth-oauth1/package.json | 20 + plugins/auth-oauth1/src/index.ts | 217 ++ plugins/auth-oauth1/tests/plaintext.test.ts | 57 + plugins/auth-oauth1/tsconfig.json | 3 + plugins/auth-oauth2/README.md | 74 + plugins/auth-oauth2/package.json | 23 + plugins/auth-oauth2/src/callbackServer.ts | 345 ++ plugins/auth-oauth2/src/customParams.ts | 121 + plugins/auth-oauth2/src/fetchAccessToken.ts | 104 + .../src/getOrRefreshAccessToken.ts | 128 + .../src/grants/authorizationCode.ts | 218 ++ .../src/grants/clientCredentials.ts | 175 + plugins/auth-oauth2/src/grants/implicit.ts | 207 + plugins/auth-oauth2/src/grants/password.ts | 69 + plugins/auth-oauth2/src/index.ts | 680 ++++ plugins/auth-oauth2/src/store.ts | 86 + plugins/auth-oauth2/src/util.ts | 112 + .../tests/authorizationCode.test.ts | 137 + .../auth-oauth2/tests/customParams.test.ts | 164 + .../tests/fetchAccessToken.test.ts | 198 + .../tests/getOrRefreshAccessToken.test.ts | 141 + plugins/auth-oauth2/tests/store.test.ts | 56 + plugins/auth-oauth2/tests/util.test.ts | 162 + plugins/auth-oauth2/tsconfig.json | 3 + plugins/filter-jsonpath/README.md | 59 + plugins/filter-jsonpath/package.json | 24 + plugins/filter-jsonpath/src/index.ts | 39 + .../filter-jsonpath/tests/breadcrumbs.test.ts | 130 + plugins/filter-jsonpath/tsconfig.json | 3 + plugins/filter-xpath/package.json | 15 + plugins/filter-xpath/src/index.ts | 28 + plugins/filter-xpath/tsconfig.json | 3 + plugins/importer-curl/package.json | 15 + plugins/importer-curl/src/graphql.ts | 117 + plugins/importer-curl/src/index.ts | 775 ++++ plugins/importer-curl/tests/graphql.test.ts | 146 + plugins/importer-curl/tests/index.test.ts | 1026 +++++ plugins/importer-curl/tsconfig.json | 3 + plugins/importer-insomnia/package.json | 15 + plugins/importer-insomnia/src/common.ts | 147 + plugins/importer-insomnia/src/index.ts | 37 + plugins/importer-insomnia/src/v4.ts | 190 + plugins/importer-insomnia/src/v5.ts | 285 ++ plugins/importer-insomnia/tests/body.test.ts | 91 + .../tests/fixtures/basic.input.json | 187 + .../tests/fixtures/basic.output.json | 144 + .../fixtures/version-5-minimal.input.yaml | 74 + .../fixtures/version-5-minimal.output.json | 128 + .../tests/fixtures/version-5.input.yaml | 146 + .../tests/fixtures/version-5.output.json | 203 + plugins/importer-insomnia/tests/index.test.ts | 67 + plugins/importer-insomnia/tsconfig.json | 3 + plugins/importer-openapi/package.json | 16 + plugins/importer-openapi/src/index.ts | 2268 +++++++++++ .../tests/__snapshots__/index.test.ts.snap | 2947 +++++++++++++++ .../tests/fixtures/petstore.yaml | 819 ++++ .../tests/fixtures/real-world/SOURCES.md | 8 + .../tests/fixtures/real-world/apis-guru.yaml | 399 ++ .../tests/fixtures/real-world/httpbin.yaml | 1121 ++++++ .../tests/fixtures/real-world/nasa-apod.yaml | 69 + .../tests/fixtures/real-world/xkcd.yaml | 78 + plugins/importer-openapi/tests/index.test.ts | 2419 ++++++++++++ plugins/importer-openapi/tests/roundtrip.mjs | 306 ++ plugins/importer-openapi/tsconfig.json | 3 + .../importer-postman-environment/package.json | 13 + .../importer-postman-environment/src/index.ts | 135 + .../tests/fixtures/environment.input.json | 27 + .../tests/fixtures/environment.output.json | 35 + .../tests/index.test.ts | 22 + .../tsconfig.json | 3 + plugins/importer-postman/package.json | 13 + plugins/importer-postman/src/index.ts | 659 ++++ .../tests/fixtures/auth.input.json | 1032 +++++ .../tests/fixtures/auth.output.json | 421 +++ .../fixtures/dynamic-variables.input.json | 67 + .../fixtures/dynamic-variables.output.json | 95 + .../tests/fixtures/nested.input.json | 38 + .../tests/fixtures/nested.output.json | 99 + .../tests/fixtures/params.input.json | 126 + .../tests/fixtures/params.output.json | 107 + plugins/importer-postman/tests/index.test.ts | 201 + plugins/importer-postman/tsconfig.json | 3 + plugins/importer-yaak/package.json | 12 + plugins/importer-yaak/src/index.ts | 96 + plugins/importer-yaak/tests/index.test.ts | 179 + plugins/importer-yaak/tsconfig.json | 3 + .../template-function-1password/package.json | 19 + .../template-function-1password/src/index.ts | 283 ++ .../template-function-1password/tsconfig.json | 3 + plugins/template-function-cookie/package.json | 11 + plugins/template-function-cookie/src/index.ts | 37 + .../template-function-cookie/tsconfig.json | 3 + plugins/template-function-ctx/package.json | 11 + plugins/template-function-ctx/src/index.ts | 30 + plugins/template-function-ctx/tsconfig.json | 3 + plugins/template-function-encode/package.json | 11 + plugins/template-function-encode/src/index.ts | 62 + .../template-function-encode/tsconfig.json | 3 + plugins/template-function-fs/package.json | 11 + plugins/template-function-fs/src/index.ts | 51 + plugins/template-function-fs/tsconfig.json | 3 + plugins/template-function-hash/package.json | 11 + plugins/template-function-hash/src/index.ts | 82 + plugins/template-function-hash/tsconfig.json | 3 + plugins/template-function-json/package.json | 20 + plugins/template-function-json/src/index.ts | 154 + .../tests/escape.test.ts | 50 + plugins/template-function-json/tsconfig.json | 3 + plugins/template-function-prompt/package.json | 14 + plugins/template-function-prompt/src/index.ts | 195 + .../template-function-prompt/tsconfig.json | 3 + plugins/template-function-random/package.json | 11 + plugins/template-function-random/src/index.ts | 44 + .../template-function-random/tsconfig.json | 3 + plugins/template-function-regex/package.json | 12 + plugins/template-function-regex/src/index.ts | 76 + .../tests/regex.test.ts | 196 + plugins/template-function-regex/tsconfig.json | 3 + .../template-function-request/package.json | 11 + .../template-function-request/src/index.ts | 290 ++ .../template-function-request/tsconfig.json | 3 + .../template-function-response/package.json | 14 + .../template-function-response/src/index.ts | 335 ++ .../template-function-response/tsconfig.json | 3 + .../template-function-timestamp/package.json | 16 + .../template-function-timestamp/src/index.ts | 187 + .../tests/formatDatetime.test.ts | 72 + .../template-function-timestamp/tsconfig.json | 3 + plugins/template-function-uuid/package.json | 14 + plugins/template-function-uuid/src/index.ts | 81 + .../template-function-uuid/tests/uuid.test.ts | 37 + plugins/template-function-uuid/tsconfig.json | 3 + plugins/template-function-xml/package.json | 17 + plugins/template-function-xml/src/index.ts | 87 + plugins/template-function-xml/tsconfig.json | 3 + plugins/themes-yaak/package.json | 11 + plugins/themes-yaak/src/index.ts | 116 + plugins/themes-yaak/src/themes/andromeda.ts | 47 + .../themes-yaak/src/themes/atom-one-dark.ts | 47 + plugins/themes-yaak/src/themes/ayu.ts | 122 + plugins/themes-yaak/src/themes/bluloco.ts | 77 + plugins/themes-yaak/src/themes/catppuccin.ts | 165 + plugins/themes-yaak/src/themes/cobalt2.ts | 47 + plugins/themes-yaak/src/themes/dracula.ts | 29 + plugins/themes-yaak/src/themes/everforest.ts | 77 + plugins/themes-yaak/src/themes/fleet.ts | 173 + .../themes-yaak/src/themes/github-dimmed.ts | 46 + plugins/themes-yaak/src/themes/github.ts | 55 + plugins/themes-yaak/src/themes/gruvbox.ts | 21 + .../themes-yaak/src/themes/high-contrast.ts | 46 + plugins/themes-yaak/src/themes/horizon.ts | 47 + .../themes-yaak/src/themes/hotdog-stand.ts | 58 + .../themes-yaak/src/themes/material-darker.ts | 39 + .../themes-yaak/src/themes/material-ocean.ts | 43 + .../src/themes/material-palenight.ts | 45 + plugins/themes-yaak/src/themes/monokai-pro.ts | 217 ++ plugins/themes-yaak/src/themes/moonlight.ts | 28 + plugins/themes-yaak/src/themes/night-owl.ts | 78 + plugins/themes-yaak/src/themes/noctis.ts | 47 + plugins/themes-yaak/src/themes/nord.ts | 85 + .../themes-yaak/src/themes/one-dark-pro.ts | 44 + plugins/themes-yaak/src/themes/panda.ts | 47 + plugins/themes-yaak/src/themes/relaxing.ts | 18 + plugins/themes-yaak/src/themes/rose-pine.ts | 111 + .../src/themes/shades-of-purple.ts | 99 + plugins/themes-yaak/src/themes/slack.ts | 47 + plugins/themes-yaak/src/themes/solarized.ts | 77 + .../themes-yaak/src/themes/synthwave-84.ts | 53 + plugins/themes-yaak/src/themes/tokyo-night.ts | 121 + plugins/themes-yaak/src/themes/triangle.ts | 44 + plugins/themes-yaak/src/themes/vitesse.ts | 77 + .../src/themes/winter-is-coming.ts | 47 + plugins/themes-yaak/tsconfig.json | 3 + rustfmt.toml | 8 + scripts/.gitignore | 1 + scripts/create-migration.cjs | 46 + scripts/extract-archive.cjs | 77 + scripts/git-hooks/post-checkout.mjs | 219 ++ scripts/install-wasm-pack.cjs | 18 + scripts/publish-core-plugins.cjs | 19 + scripts/replace-version.cjs | 15 + scripts/run-build.mjs | 62 + scripts/run-dev.mjs | 121 + scripts/run-web.mjs | 120 + scripts/run-workspaces-dev.mjs | 85 + scripts/vendor-node.cjs | 114 + scripts/vendor-plugins.cjs | 41 + scripts/vendor-protoc.cjs | 114 + tsconfig.json | 21 + vite.config.ts | 35 + 1544 files changed, 164131 insertions(+) create mode 100644 .claude-context.md create mode 100644 .claude/rules.md create mode 100644 .codex/skills/release-generate-release-notes/SKILL.md create mode 100644 .codex/skills/yaak-changelog/SKILL.md create mode 100644 .codex/skills/yaak-changelog/agents/openai.yaml create mode 100644 .dockerignore create mode 100644 .gitattributes create mode 100644 .github/FUNDING.yml create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/dependabot.yml create mode 100644 .github/pull_request_template.md create mode 100644 .github/scripts/check-contribution-policy.js create mode 100644 .github/scripts/preserve-release-artifacts.mjs create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/contribution-policy.yml create mode 100644 .github/workflows/flathub.yml create mode 100644 .github/workflows/release-api-npm.yml create mode 100644 .github/workflows/release-app.yml create mode 100644 .github/workflows/release-cli-npm.yml create mode 100644 .github/workflows/release-web-image.yml create mode 100644 .github/workflows/sponsors.yml create mode 100644 .gitignore create mode 100644 .node-version create mode 100644 .npmrc create mode 100644 .oxfmtrc.json create mode 100755 .vite-hooks/post-checkout create mode 100644 .vite-hooks/pre-commit create mode 100644 .vscode/extensions.json create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 AGENTS.md create mode 100644 CONTRIBUTING.md create mode 100644 Cargo.toml create mode 100644 DEVELOPMENT.md create mode 100644 Dockerfile.playground create mode 100644 Dockerfile.web create mode 100644 LICENSE create mode 100644 README.md create mode 100644 apps/yaak-client/.gitignore create mode 100644 apps/yaak-client/commands/commands.tsx create mode 100644 apps/yaak-client/commands/createEnvironment.tsx create mode 100644 apps/yaak-client/commands/deleteWebsocketConnections.ts create mode 100644 apps/yaak-client/commands/importCurl.ts create mode 100644 apps/yaak-client/commands/moveToWorkspace.tsx create mode 100644 apps/yaak-client/commands/openFolderSettings.tsx create mode 100644 apps/yaak-client/commands/openSettings.tsx create mode 100644 apps/yaak-client/commands/openWorkspaceFromSyncDir.tsx create mode 100644 apps/yaak-client/commands/openWorkspaceSettings.tsx create mode 100644 apps/yaak-client/commands/switchWorkspace.tsx create mode 100644 apps/yaak-client/components/BinaryFileEditor.tsx create mode 100644 apps/yaak-client/components/CargoFeature.tsx create mode 100644 apps/yaak-client/components/CloneGitRepositoryDialog.tsx create mode 100644 apps/yaak-client/components/ColorIndicator.tsx create mode 100644 apps/yaak-client/components/CommandPaletteDialog.tsx create mode 100644 apps/yaak-client/components/CommercialUseBanner.tsx create mode 100644 apps/yaak-client/components/ConfirmLargeRequestBody.tsx create mode 100644 apps/yaak-client/components/ConfirmLargeResponse.tsx create mode 100644 apps/yaak-client/components/ConfirmLargeResponseRequest.tsx create mode 100644 apps/yaak-client/components/ContextMenus.tsx create mode 100644 apps/yaak-client/components/CookieDialog.tsx create mode 100644 apps/yaak-client/components/CookieDropdown.tsx create mode 100644 apps/yaak-client/components/CopyButton.tsx create mode 100644 apps/yaak-client/components/CopyIconButton.tsx create mode 100644 apps/yaak-client/components/CreateDropdown.tsx create mode 100644 apps/yaak-client/components/CreateEnvironmentDialog.tsx create mode 100644 apps/yaak-client/components/CreateWorkspaceDialog.tsx create mode 100644 apps/yaak-client/components/Dialogs.tsx create mode 100644 apps/yaak-client/components/DnsOverridesEditor.tsx create mode 100644 apps/yaak-client/components/DropMarker.tsx create mode 100644 apps/yaak-client/components/DynamicForm.tsx create mode 100644 apps/yaak-client/components/EmptyStateText.tsx create mode 100644 apps/yaak-client/components/EncryptionHelp.tsx create mode 100644 apps/yaak-client/components/EnvironmentActionsDropdown.tsx create mode 100644 apps/yaak-client/components/EnvironmentColorIndicator.tsx create mode 100644 apps/yaak-client/components/EnvironmentColorPicker.tsx create mode 100644 apps/yaak-client/components/EnvironmentEditDialog.tsx create mode 100644 apps/yaak-client/components/EnvironmentEditor.tsx create mode 100644 apps/yaak-client/components/EnvironmentSharableTooltip.tsx create mode 100644 apps/yaak-client/components/ErrorBoundary.tsx create mode 100644 apps/yaak-client/components/ExportDataDialog.tsx create mode 100644 apps/yaak-client/components/FeedbackToast.tsx create mode 100644 apps/yaak-client/components/FolderLayout.tsx create mode 100644 apps/yaak-client/components/FolderSettingsDialog.tsx create mode 100644 apps/yaak-client/components/FormMultipartEditor.tsx create mode 100644 apps/yaak-client/components/FormUrlencodedEditor.tsx create mode 100644 apps/yaak-client/components/GlobalHooks.tsx create mode 100644 apps/yaak-client/components/GrpcConnectionLayout.tsx create mode 100644 apps/yaak-client/components/GrpcEditor.tsx create mode 100644 apps/yaak-client/components/GrpcProtoSelectionDialog.tsx create mode 100644 apps/yaak-client/components/GrpcRequestPane.tsx create mode 100644 apps/yaak-client/components/GrpcResponsePane.tsx create mode 100644 apps/yaak-client/components/HeadersEditor.tsx create mode 100644 apps/yaak-client/components/HttpAuthenticationEditor.tsx create mode 100644 apps/yaak-client/components/HttpRequestLayout.tsx create mode 100644 apps/yaak-client/components/HttpRequestPane.tsx create mode 100644 apps/yaak-client/components/HttpResponsePane.tsx create mode 100644 apps/yaak-client/components/HttpResponseTimeline.tsx create mode 100644 apps/yaak-client/components/ImportCurl.tsx create mode 100644 apps/yaak-client/components/ImportDataDialog.tsx create mode 100644 apps/yaak-client/components/IsDev.tsx create mode 100644 apps/yaak-client/components/JsonBodyEditor.tsx create mode 100644 apps/yaak-client/components/KeyboardShortcutsDialog.tsx create mode 100644 apps/yaak-client/components/LargeValueDialog.tsx create mode 100644 apps/yaak-client/components/LicenseBadge.tsx create mode 100644 apps/yaak-client/components/LocalImage.tsx create mode 100644 apps/yaak-client/components/Markdown.tsx create mode 100644 apps/yaak-client/components/MarkdownEditor.tsx create mode 100644 apps/yaak-client/components/ModelSettingsEditor.tsx create mode 100644 apps/yaak-client/components/MoveToWorkspaceDialog.tsx create mode 100644 apps/yaak-client/components/Onboarding.tsx create mode 100644 apps/yaak-client/components/Prose.css create mode 100644 apps/yaak-client/components/Prose.tsx create mode 100644 apps/yaak-client/components/RecentGrpcConnectionsDropdown.tsx create mode 100644 apps/yaak-client/components/RecentHttpResponsesDropdown.tsx create mode 100644 apps/yaak-client/components/RecentRequestsDropdown.tsx create mode 100644 apps/yaak-client/components/RecentWebsocketConnectionsDropdown.tsx create mode 100644 apps/yaak-client/components/RedirectToLatestWorkspace.tsx create mode 100644 apps/yaak-client/components/RequestBodyViewer.tsx create mode 100644 apps/yaak-client/components/RequestMethodDropdown.tsx create mode 100644 apps/yaak-client/components/ResponseCookies.tsx create mode 100644 apps/yaak-client/components/ResponseHeaders.tsx create mode 100644 apps/yaak-client/components/ResponseInfo.tsx create mode 100644 apps/yaak-client/components/RouteError.tsx create mode 100644 apps/yaak-client/components/SelectFile.tsx create mode 100644 apps/yaak-client/components/Settings/Settings.tsx create mode 100644 apps/yaak-client/components/Settings/SettingsCertificates.tsx create mode 100644 apps/yaak-client/components/Settings/SettingsGeneral.tsx create mode 100644 apps/yaak-client/components/Settings/SettingsHotkeys.tsx create mode 100644 apps/yaak-client/components/Settings/SettingsInterface.tsx create mode 100644 apps/yaak-client/components/Settings/SettingsLicense.tsx create mode 100644 apps/yaak-client/components/Settings/SettingsPlugins.tsx create mode 100644 apps/yaak-client/components/Settings/SettingsProxy.tsx create mode 100644 apps/yaak-client/components/Settings/SettingsTheme.tsx create mode 100644 apps/yaak-client/components/SettingsDropdown.tsx create mode 100644 apps/yaak-client/components/Sidebar.tsx create mode 100644 apps/yaak-client/components/SidebarActions.tsx create mode 100644 apps/yaak-client/components/SwitchWorkspaceDialog.tsx create mode 100644 apps/yaak-client/components/SyncToFilesystemSetting.tsx create mode 100644 apps/yaak-client/components/TemplateFunctionDialog.tsx create mode 100644 apps/yaak-client/components/Toasts.tsx create mode 100644 apps/yaak-client/components/UrlBar.tsx create mode 100644 apps/yaak-client/components/UrlParameterEditor.tsx create mode 100644 apps/yaak-client/components/WebsocketRequestLayout.tsx create mode 100644 apps/yaak-client/components/WebsocketRequestPane.tsx create mode 100644 apps/yaak-client/components/WebsocketResponsePane.tsx create mode 100644 apps/yaak-client/components/Workspace.tsx create mode 100644 apps/yaak-client/components/WorkspaceActionsDropdown.tsx create mode 100644 apps/yaak-client/components/WorkspaceEncryptionSetting.tsx create mode 100644 apps/yaak-client/components/WorkspaceHeader.tsx create mode 100644 apps/yaak-client/components/WorkspaceSettingsDialog.tsx create mode 100644 apps/yaak-client/components/core/Alert.tsx create mode 100644 apps/yaak-client/components/core/AutoScroller.tsx create mode 100644 apps/yaak-client/components/core/BulkPairEditor.test.ts create mode 100644 apps/yaak-client/components/core/BulkPairEditor.tsx create mode 100644 apps/yaak-client/components/core/Button.tsx create mode 100644 apps/yaak-client/components/core/ButtonInfiniteLoading.tsx create mode 100644 apps/yaak-client/components/core/Checkbox.tsx create mode 100644 apps/yaak-client/components/core/CheckboxTree.tsx create mode 100644 apps/yaak-client/components/core/ColorPicker.tsx create mode 100644 apps/yaak-client/components/core/Confirm.tsx create mode 100644 apps/yaak-client/components/core/CountBadge.tsx create mode 100644 apps/yaak-client/components/core/DetailsBanner.tsx create mode 100644 apps/yaak-client/components/core/Dialog.tsx create mode 100644 apps/yaak-client/components/core/DismissibleBanner.tsx create mode 100644 apps/yaak-client/components/core/Dropdown.tsx create mode 100644 apps/yaak-client/components/core/Editor/BetterMatchDecorator.ts create mode 100644 apps/yaak-client/components/core/Editor/DiffViewer.css create mode 100644 apps/yaak-client/components/core/Editor/DiffViewer.tsx create mode 100644 apps/yaak-client/components/core/Editor/Editor.css create mode 100644 apps/yaak-client/components/core/Editor/Editor.tsx create mode 100644 apps/yaak-client/components/core/Editor/LazyEditor.tsx create mode 100644 apps/yaak-client/components/core/Editor/extensions.ts create mode 100644 apps/yaak-client/components/core/Editor/filter/extension.ts create mode 100644 apps/yaak-client/components/core/Editor/filter/filter.grammar create mode 100644 apps/yaak-client/components/core/Editor/filter/filter.test.ts create mode 100644 apps/yaak-client/components/core/Editor/filter/filter.ts create mode 100644 apps/yaak-client/components/core/Editor/filter/format.test.ts create mode 100644 apps/yaak-client/components/core/Editor/filter/format.ts create mode 100644 apps/yaak-client/components/core/Editor/filter/highlight.ts create mode 100644 apps/yaak-client/components/core/Editor/filter/query.ts create mode 100644 apps/yaak-client/components/core/Editor/genericCompletion.ts create mode 100644 apps/yaak-client/components/core/Editor/hyperlink/extension.ts create mode 100644 apps/yaak-client/components/core/Editor/json-lint.ts create mode 100644 apps/yaak-client/components/core/Editor/json/breadcrumbExtension.ts create mode 100644 apps/yaak-client/components/core/Editor/json/jsonPath.test.ts create mode 100644 apps/yaak-client/components/core/Editor/json/jsonPath.ts create mode 100644 apps/yaak-client/components/core/Editor/largeValues.test.ts create mode 100644 apps/yaak-client/components/core/Editor/largeValues.ts create mode 100644 apps/yaak-client/components/core/Editor/pairs/extension.ts create mode 100644 apps/yaak-client/components/core/Editor/pairs/highlight.ts create mode 100644 apps/yaak-client/components/core/Editor/pairs/pairs.grammar create mode 100644 apps/yaak-client/components/core/Editor/pairs/pairs.terms.ts create mode 100644 apps/yaak-client/components/core/Editor/pairs/pairs.test.ts create mode 100644 apps/yaak-client/components/core/Editor/pairs/pairs.ts create mode 100644 apps/yaak-client/components/core/Editor/searchMatchCount.test.ts create mode 100644 apps/yaak-client/components/core/Editor/searchMatchCount.ts create mode 100644 apps/yaak-client/components/core/Editor/singleLine.ts create mode 100644 apps/yaak-client/components/core/Editor/sniffValue.test.ts create mode 100644 apps/yaak-client/components/core/Editor/sniffValue.ts create mode 100644 apps/yaak-client/components/core/Editor/text/extension.ts create mode 100644 apps/yaak-client/components/core/Editor/text/text.grammar create mode 100644 apps/yaak-client/components/core/Editor/text/text.terms.ts create mode 100644 apps/yaak-client/components/core/Editor/text/text.ts create mode 100644 apps/yaak-client/components/core/Editor/timeline/extension.ts create mode 100644 apps/yaak-client/components/core/Editor/timeline/highlight.ts create mode 100644 apps/yaak-client/components/core/Editor/timeline/timeline.grammar create mode 100644 apps/yaak-client/components/core/Editor/timeline/timeline.terms.ts create mode 100644 apps/yaak-client/components/core/Editor/timeline/timeline.ts create mode 100644 apps/yaak-client/components/core/Editor/twig/completion.test.ts create mode 100644 apps/yaak-client/components/core/Editor/twig/completion.ts create mode 100644 apps/yaak-client/components/core/Editor/twig/extension.ts create mode 100644 apps/yaak-client/components/core/Editor/twig/highlight.ts create mode 100644 apps/yaak-client/components/core/Editor/twig/pathParameters.ts create mode 100644 apps/yaak-client/components/core/Editor/twig/templateTags.ts create mode 100644 apps/yaak-client/components/core/Editor/twig/twig.grammar create mode 100644 apps/yaak-client/components/core/Editor/twig/twig.terms.ts create mode 100644 apps/yaak-client/components/core/Editor/twig/twig.test.ts create mode 100644 apps/yaak-client/components/core/Editor/twig/twig.ts create mode 100644 apps/yaak-client/components/core/Editor/twig/util.ts create mode 100644 apps/yaak-client/components/core/Editor/url/completion.test.ts create mode 100644 apps/yaak-client/components/core/Editor/url/completion.ts create mode 100644 apps/yaak-client/components/core/Editor/url/extension.ts create mode 100644 apps/yaak-client/components/core/Editor/url/highlight.ts create mode 100644 apps/yaak-client/components/core/Editor/url/url.grammar create mode 100644 apps/yaak-client/components/core/Editor/url/url.terms.ts create mode 100644 apps/yaak-client/components/core/Editor/url/url.test.ts create mode 100644 apps/yaak-client/components/core/Editor/url/url.ts create mode 100644 apps/yaak-client/components/core/EventViewer.tsx create mode 100644 apps/yaak-client/components/core/EventViewerRow.tsx create mode 100644 apps/yaak-client/components/core/Hotkey.tsx create mode 100644 apps/yaak-client/components/core/HotkeyLabel.tsx create mode 100644 apps/yaak-client/components/core/HotkeyList.test.tsx create mode 100644 apps/yaak-client/components/core/HotkeyList.tsx create mode 100644 apps/yaak-client/components/core/HttpMethodTag.tsx create mode 100644 apps/yaak-client/components/core/HttpResponseDurationTag.tsx create mode 100644 apps/yaak-client/components/core/HttpStatusTag.tsx create mode 100644 apps/yaak-client/components/core/IconButton.tsx create mode 100644 apps/yaak-client/components/core/IconTooltip.tsx create mode 100644 apps/yaak-client/components/core/Input.tsx create mode 100644 apps/yaak-client/components/core/JsonAttributeTree.tsx create mode 100644 apps/yaak-client/components/core/KeyValueRow.tsx create mode 100644 apps/yaak-client/components/core/Label.tsx create mode 100644 apps/yaak-client/components/core/Link.tsx create mode 100644 apps/yaak-client/components/core/PairEditor.tsx create mode 100644 apps/yaak-client/components/core/PairEditor.util.tsx create mode 100644 apps/yaak-client/components/core/PairOrBulkEditor.tsx create mode 100644 apps/yaak-client/components/core/PillButton.tsx create mode 100644 apps/yaak-client/components/core/PlainInput.tsx create mode 100644 apps/yaak-client/components/core/Prompt.tsx create mode 100644 apps/yaak-client/components/core/RadioCards.tsx create mode 100644 apps/yaak-client/components/core/RadioDropdown.tsx create mode 100644 apps/yaak-client/components/core/SegmentedControl.tsx create mode 100644 apps/yaak-client/components/core/Select.tsx create mode 100644 apps/yaak-client/components/core/Separator.tsx create mode 100644 apps/yaak-client/components/core/SettingRow.tsx create mode 100644 apps/yaak-client/components/core/SizeTag.tsx create mode 100644 apps/yaak-client/components/core/Tabs/Tabs.tsx create mode 100644 apps/yaak-client/components/core/Toast.tsx create mode 100644 apps/yaak-client/components/core/Tooltip.tsx create mode 100644 apps/yaak-client/components/core/WebsocketStatusTag.tsx create mode 100644 apps/yaak-client/components/git/BranchSelectionDialog.tsx create mode 100644 apps/yaak-client/components/git/FileHistoryDialog.tsx create mode 100644 apps/yaak-client/components/git/GitCommitDialog.tsx create mode 100644 apps/yaak-client/components/git/GitDropdown.tsx create mode 100644 apps/yaak-client/components/git/GitRemotesDialog.tsx create mode 100644 apps/yaak-client/components/git/HistoryDialog.tsx create mode 100644 apps/yaak-client/components/git/callbacks.tsx create mode 100644 apps/yaak-client/components/git/credentials.tsx create mode 100644 apps/yaak-client/components/git/diverged.tsx create mode 100644 apps/yaak-client/components/git/git-util.ts create mode 100644 apps/yaak-client/components/git/showAddRemoteDialog.tsx create mode 100644 apps/yaak-client/components/git/uncommitted.tsx create mode 100644 apps/yaak-client/components/graphql/GraphQLDocsExplorer.tsx create mode 100644 apps/yaak-client/components/graphql/GraphQLEditor.tsx create mode 100644 apps/yaak-client/components/graphql/graphqlAtoms.ts create mode 100644 apps/yaak-client/components/responseViewers/AudioViewer.tsx create mode 100644 apps/yaak-client/components/responseViewers/BinaryViewer.tsx create mode 100644 apps/yaak-client/components/responseViewers/CsvViewer.test.tsx create mode 100644 apps/yaak-client/components/responseViewers/CsvViewer.tsx create mode 100644 apps/yaak-client/components/responseViewers/EventStreamViewer.tsx create mode 100644 apps/yaak-client/components/responseViewers/HTMLOrTextViewer.tsx create mode 100644 apps/yaak-client/components/responseViewers/ImageViewer.tsx create mode 100644 apps/yaak-client/components/responseViewers/JsonViewer.tsx create mode 100644 apps/yaak-client/components/responseViewers/MultipartViewer.tsx create mode 100644 apps/yaak-client/components/responseViewers/PdfViewer.css create mode 100644 apps/yaak-client/components/responseViewers/PdfViewer.tsx create mode 100644 apps/yaak-client/components/responseViewers/RecentFiltersDropdown.tsx create mode 100644 apps/yaak-client/components/responseViewers/ResponseBreadcrumbBar.tsx create mode 100644 apps/yaak-client/components/responseViewers/SvgViewer.tsx create mode 100644 apps/yaak-client/components/responseViewers/TextViewer.tsx create mode 100644 apps/yaak-client/components/responseViewers/VideoViewer.tsx create mode 100644 apps/yaak-client/components/responseViewers/WebPageViewer.tsx create mode 100644 apps/yaak-client/font-size.ts create mode 100644 apps/yaak-client/font.ts create mode 100644 apps/yaak-client/hooks/useActiveCookieJar.ts create mode 100644 apps/yaak-client/hooks/useActiveEnvironment.ts create mode 100644 apps/yaak-client/hooks/useActiveEnvironmentVariables.ts create mode 100644 apps/yaak-client/hooks/useActiveFolder.ts create mode 100644 apps/yaak-client/hooks/useActiveFolderId.ts create mode 100644 apps/yaak-client/hooks/useActiveRequest.ts create mode 100644 apps/yaak-client/hooks/useActiveRequestId.ts create mode 100644 apps/yaak-client/hooks/useActiveWorkspace.ts create mode 100644 apps/yaak-client/hooks/useActiveWorkspaceChangedToast.tsx create mode 100644 apps/yaak-client/hooks/useAllRequests.ts create mode 100644 apps/yaak-client/hooks/useAuthTab.tsx create mode 100644 apps/yaak-client/hooks/useCancelHttpResponse.ts create mode 100644 apps/yaak-client/hooks/useCheckForUpdates.tsx create mode 100644 apps/yaak-client/hooks/useClickOutside.ts create mode 100644 apps/yaak-client/hooks/useCopyHttpResponse.ts create mode 100644 apps/yaak-client/hooks/useCreateCookieJar.ts create mode 100644 apps/yaak-client/hooks/useCreateDropdownItems.tsx create mode 100644 apps/yaak-client/hooks/useCreateWorkspace.tsx create mode 100644 apps/yaak-client/hooks/useDeleteGrpcConnections.ts create mode 100644 apps/yaak-client/hooks/useDeleteHttpResponses.ts create mode 100644 apps/yaak-client/hooks/useDeleteSendHistory.tsx create mode 100644 apps/yaak-client/hooks/useEnvironmentValueVisibility.ts create mode 100644 apps/yaak-client/hooks/useEnvironmentVariables.ts create mode 100644 apps/yaak-client/hooks/useEnvironmentsBreakdown.ts create mode 100644 apps/yaak-client/hooks/useEventViewerKeyboard.ts create mode 100644 apps/yaak-client/hooks/useExportData.tsx create mode 100644 apps/yaak-client/hooks/useFastMutation.ts create mode 100644 apps/yaak-client/hooks/useFloatingSidebarHidden.ts create mode 100644 apps/yaak-client/hooks/useFolderActions.ts create mode 100644 apps/yaak-client/hooks/useFormatText.ts create mode 100644 apps/yaak-client/hooks/useGraphQLSchemaFile.ts create mode 100644 apps/yaak-client/hooks/useGrpc.ts create mode 100644 apps/yaak-client/hooks/useGrpcProtoFiles.ts create mode 100644 apps/yaak-client/hooks/useGrpcRequestActions.ts create mode 100644 apps/yaak-client/hooks/useHeadersTab.tsx create mode 100644 apps/yaak-client/hooks/useHotKey.ts create mode 100644 apps/yaak-client/hooks/useHttpAuthentication.ts create mode 100644 apps/yaak-client/hooks/useHttpAuthenticationConfig.ts create mode 100644 apps/yaak-client/hooks/useHttpRequestActions.ts create mode 100644 apps/yaak-client/hooks/useHttpRequestBody.ts create mode 100644 apps/yaak-client/hooks/useHttpResponseEvents.ts create mode 100644 apps/yaak-client/hooks/useInheritedAuthentication.ts create mode 100644 apps/yaak-client/hooks/useInheritedHeaders.ts create mode 100644 apps/yaak-client/hooks/useInstallPlugin.ts create mode 100644 apps/yaak-client/hooks/useIntrospectGraphQL.ts create mode 100644 apps/yaak-client/hooks/useIsEncryptionEnabled.ts create mode 100644 apps/yaak-client/hooks/useKeyValue.ts create mode 100644 apps/yaak-client/hooks/useKeyboardEvent.ts create mode 100644 apps/yaak-client/hooks/useLatestGrpcConnection.ts create mode 100644 apps/yaak-client/hooks/useLatestHttpResponse.ts create mode 100644 apps/yaak-client/hooks/useModelAncestors.ts create mode 100644 apps/yaak-client/hooks/useParentFolders.ts create mode 100644 apps/yaak-client/hooks/usePinnedGrpcConnection.ts create mode 100644 apps/yaak-client/hooks/usePinnedHttpResponse.ts create mode 100644 apps/yaak-client/hooks/usePinnedWebsocketConnection.ts create mode 100644 apps/yaak-client/hooks/usePlatformEvent.ts create mode 100644 apps/yaak-client/hooks/usePluginInfo.ts create mode 100644 apps/yaak-client/hooks/usePlugins.ts create mode 100644 apps/yaak-client/hooks/usePreferredAppearance.ts create mode 100644 apps/yaak-client/hooks/useRandomKey.ts create mode 100644 apps/yaak-client/hooks/useRecentCookieJars.ts create mode 100644 apps/yaak-client/hooks/useRecentEnvironments.ts create mode 100644 apps/yaak-client/hooks/useRecentFilters.ts create mode 100644 apps/yaak-client/hooks/useRecentRequests.ts create mode 100644 apps/yaak-client/hooks/useRecentWorkspaces.ts create mode 100644 apps/yaak-client/hooks/useRenderTemplate.ts create mode 100644 apps/yaak-client/hooks/useRequestEditor.tsx create mode 100644 apps/yaak-client/hooks/useRequestUpdateKey.ts create mode 100644 apps/yaak-client/hooks/useResolvedAppearance.ts create mode 100644 apps/yaak-client/hooks/useResolvedTheme.ts create mode 100644 apps/yaak-client/hooks/useResponseBodyEventSource.ts create mode 100644 apps/yaak-client/hooks/useResponseBodySseSummary.ts create mode 100644 apps/yaak-client/hooks/useResponseBodyText.ts create mode 100644 apps/yaak-client/hooks/useResponseBodyUrl.ts create mode 100644 apps/yaak-client/hooks/useResponseFilter.ts create mode 100644 apps/yaak-client/hooks/useResponseViewMode.ts create mode 100644 apps/yaak-client/hooks/useSaveResponse.tsx create mode 100644 apps/yaak-client/hooks/useScrollIntoView.ts create mode 100644 apps/yaak-client/hooks/useSendAnyHttpRequest.test.ts create mode 100644 apps/yaak-client/hooks/useSendAnyHttpRequest.ts create mode 100644 apps/yaak-client/hooks/useSendManyRequests.ts create mode 100644 apps/yaak-client/hooks/useSidebarHidden.ts create mode 100644 apps/yaak-client/hooks/useSidebarItemCollapsed.ts create mode 100644 apps/yaak-client/hooks/useSidebarWidth.ts create mode 100644 apps/yaak-client/hooks/useSseSummaryResultKeyPath.ts create mode 100644 apps/yaak-client/hooks/useStateWithDeps.ts create mode 100644 apps/yaak-client/hooks/useStoplightsVisible.ts create mode 100644 apps/yaak-client/hooks/useSyncFontSizeSetting.ts create mode 100644 apps/yaak-client/hooks/useSyncWorkspaceChildModels.ts create mode 100644 apps/yaak-client/hooks/useSyncWorkspaceRequestTitle.ts create mode 100644 apps/yaak-client/hooks/useSyncZoomSetting.ts create mode 100644 apps/yaak-client/hooks/useTemplateFunctionConfig.ts create mode 100644 apps/yaak-client/hooks/useTemplateFunctions.tsx create mode 100644 apps/yaak-client/hooks/useTemplateTokensToString.ts create mode 100644 apps/yaak-client/hooks/useTimelineViewMode.ts create mode 100644 apps/yaak-client/hooks/useToggle.ts create mode 100644 apps/yaak-client/hooks/useToggleCommandPalette.tsx create mode 100644 apps/yaak-client/hooks/useWebsocketRequestActions.ts create mode 100644 apps/yaak-client/hooks/useWindowFocus.ts create mode 100644 apps/yaak-client/hooks/useWorkspaceActions.ts create mode 100644 apps/yaak-client/hooks/useZoom.ts create mode 100644 apps/yaak-client/index.html create mode 100644 apps/yaak-client/init/git.ts create mode 100644 apps/yaak-client/init/sync.ts create mode 100644 apps/yaak-client/lib/alert.ts create mode 100644 apps/yaak-client/lib/appInfo.ts create mode 100644 apps/yaak-client/lib/atoms.ts create mode 100644 apps/yaak-client/lib/atoms/atomWithKVStorage.ts create mode 100644 apps/yaak-client/lib/capitalize.ts create mode 100644 apps/yaak-client/lib/color.ts create mode 100644 apps/yaak-client/lib/confirm.ts create mode 100644 apps/yaak-client/lib/confirmWebProxy.test.tsx create mode 100644 apps/yaak-client/lib/confirmWebProxy.tsx create mode 100644 apps/yaak-client/lib/contentType.ts create mode 100644 apps/yaak-client/lib/contextMenu.ts create mode 100644 apps/yaak-client/lib/copy.ts create mode 100644 apps/yaak-client/lib/createRequestAndNavigate.tsx create mode 100644 apps/yaak-client/lib/data/acceptLanguages.ts create mode 100644 apps/yaak-client/lib/data/cacheControl.ts create mode 100644 apps/yaak-client/lib/data/charsets.ts create mode 100644 apps/yaak-client/lib/data/connections.ts create mode 100644 apps/yaak-client/lib/data/encodings.ts create mode 100644 apps/yaak-client/lib/data/headerNames.ts create mode 100644 apps/yaak-client/lib/data/headerValuePresets.ts create mode 100644 apps/yaak-client/lib/data/mimetypes.ts create mode 100644 apps/yaak-client/lib/data/userAgents.ts create mode 100644 apps/yaak-client/lib/defaultHeaders.ts create mode 100644 apps/yaak-client/lib/deleteModelWithConfirm.tsx create mode 100644 apps/yaak-client/lib/dialog.ts create mode 100644 apps/yaak-client/lib/diffYaml.ts create mode 100644 apps/yaak-client/lib/dnd.ts create mode 100644 apps/yaak-client/lib/docFingerprint.test.ts create mode 100644 apps/yaak-client/lib/docFingerprint.ts create mode 100644 apps/yaak-client/lib/duplicateRequestOrFolderAndNavigate.tsx create mode 100644 apps/yaak-client/lib/editEnvironment.tsx create mode 100644 apps/yaak-client/lib/encryption.ts create mode 100644 apps/yaak-client/lib/featureFeedback.tsx create mode 100644 apps/yaak-client/lib/featureFeedbackConstants.ts create mode 100644 apps/yaak-client/lib/fireAndForget.ts create mode 100644 apps/yaak-client/lib/formatters.ts create mode 100644 apps/yaak-client/lib/generateId.ts create mode 100644 apps/yaak-client/lib/getNodeText.ts create mode 100644 apps/yaak-client/lib/gitWorktreeStatus.ts create mode 100644 apps/yaak-client/lib/graphqlOperationNames.test.ts create mode 100644 apps/yaak-client/lib/graphqlOperationNames.ts create mode 100644 apps/yaak-client/lib/graphqlSchema.test.ts create mode 100644 apps/yaak-client/lib/graphqlSchema.ts create mode 100644 apps/yaak-client/lib/importData.tsx create mode 100644 apps/yaak-client/lib/initGlobalListeners.tsx create mode 100644 apps/yaak-client/lib/jotai.ts create mode 100644 apps/yaak-client/lib/jsonComments.ts create mode 100644 apps/yaak-client/lib/jsonSchemaExample.test.ts create mode 100644 apps/yaak-client/lib/jsonSchemaExample.ts create mode 100644 apps/yaak-client/lib/keyValueStore.ts create mode 100644 apps/yaak-client/lib/largeValue.ts create mode 100644 apps/yaak-client/lib/markdown.ts create mode 100644 apps/yaak-client/lib/minPromiseMillis.ts create mode 100644 apps/yaak-client/lib/model_util.test.ts create mode 100644 apps/yaak-client/lib/model_util.ts create mode 100644 apps/yaak-client/lib/onboarding.ts create mode 100644 apps/yaak-client/lib/pathPlaceholders.test.ts create mode 100644 apps/yaak-client/lib/pathPlaceholders.ts create mode 100644 apps/yaak-client/lib/pluralize.ts create mode 100644 apps/yaak-client/lib/prepareImportQuerystring.ts create mode 100644 apps/yaak-client/lib/pricingUrl.ts create mode 100644 apps/yaak-client/lib/prompt-form.tsx create mode 100644 apps/yaak-client/lib/prompt.ts create mode 100644 apps/yaak-client/lib/queryClient.ts create mode 100644 apps/yaak-client/lib/renameModelWithPrompt.tsx create mode 100644 apps/yaak-client/lib/requestBodyConversion.test.ts create mode 100644 apps/yaak-client/lib/requestBodyConversion.ts create mode 100644 apps/yaak-client/lib/requestSettings.ts create mode 100644 apps/yaak-client/lib/resolvedModelName.ts create mode 100644 apps/yaak-client/lib/responseBody.ts create mode 100644 apps/yaak-client/lib/reveal.ts create mode 100644 apps/yaak-client/lib/router.ts create mode 100644 apps/yaak-client/lib/rpc.ts create mode 100644 apps/yaak-client/lib/scopes.ts create mode 100644 apps/yaak-client/lib/sendEphemeralRequest.ts create mode 100644 apps/yaak-client/lib/setWorkspaceSearchParams.ts create mode 100644 apps/yaak-client/lib/settings.ts create mode 100644 apps/yaak-client/lib/setupOrConfigureEncryption.tsx create mode 100644 apps/yaak-client/lib/showColorPicker.tsx create mode 100644 apps/yaak-client/lib/sleep.ts create mode 100644 apps/yaak-client/lib/themes.ts create mode 100644 apps/yaak-client/lib/toast.tsx create mode 100644 apps/yaak-client/lib/truncate.ts create mode 100644 apps/yaak-client/main.css create mode 100644 apps/yaak-client/main.tsx create mode 100644 apps/yaak-client/modules.d.ts create mode 100644 apps/yaak-client/package.json create mode 100644 apps/yaak-client/postcss.config.cjs create mode 100644 apps/yaak-client/react-augment.d.ts create mode 100644 apps/yaak-client/routeTree.gen.ts create mode 100644 apps/yaak-client/routes/__root.tsx create mode 100644 apps/yaak-client/routes/index.tsx create mode 100644 apps/yaak-client/routes/workspaces/$workspaceId/index.tsx create mode 100644 apps/yaak-client/routes/workspaces/$workspaceId/requests/$requestId.tsx create mode 100644 apps/yaak-client/routes/workspaces/$workspaceId/settings.tsx create mode 100644 apps/yaak-client/routes/workspaces/index.tsx create mode 100644 apps/yaak-client/theme.ts create mode 100644 apps/yaak-client/tsconfig.json create mode 100644 apps/yaak-client/tsconfig.node.json create mode 100644 apps/yaak-client/tsr.config.json create mode 100644 apps/yaak-client/vite-env.d.ts create mode 100644 apps/yaak-client/vite.config.ts create mode 100644 apps/yaak-client/web/og.html create mode 100644 apps/yaak-proxy/components/ActionButton.tsx create mode 100644 apps/yaak-proxy/components/ActionIconButton.tsx create mode 100644 apps/yaak-proxy/components/ExchangesTable.tsx create mode 100644 apps/yaak-proxy/components/ProxyLayout.tsx create mode 100644 apps/yaak-proxy/components/Sidebar.tsx create mode 100644 apps/yaak-proxy/font-size.ts create mode 100644 apps/yaak-proxy/hooks/useActionMetadata.ts create mode 100644 apps/yaak-proxy/hooks/useRpcEvent.ts create mode 100644 apps/yaak-proxy/hooks/useRpcMutation.ts create mode 100644 apps/yaak-proxy/hooks/useRpcQuery.ts create mode 100644 apps/yaak-proxy/hooks/useRpcQueryWithEvent.ts create mode 100644 apps/yaak-proxy/index.html create mode 100644 apps/yaak-proxy/lib/fireAndForget.ts create mode 100644 apps/yaak-proxy/lib/hotkeys.ts create mode 100644 apps/yaak-proxy/lib/rpc.ts create mode 100644 apps/yaak-proxy/lib/store.ts create mode 100644 apps/yaak-proxy/lib/tauri.ts create mode 100644 apps/yaak-proxy/lib/theme.ts create mode 100644 apps/yaak-proxy/main.css create mode 100644 apps/yaak-proxy/main.tsx create mode 100644 apps/yaak-proxy/package.json create mode 100644 apps/yaak-proxy/postcss.config.cjs create mode 100644 apps/yaak-proxy/tsconfig.json create mode 100644 apps/yaak-proxy/tsconfig.node.json create mode 100644 apps/yaak-proxy/vite-env.d.ts create mode 100644 apps/yaak-proxy/vite.config.ts create mode 100644 crates-cli/yaak-cli/Cargo.toml create mode 100644 crates-cli/yaak-cli/README.md create mode 100644 crates-cli/yaak-cli/skills/use-yaak/SKILL.md create mode 100644 crates-cli/yaak-cli/src/cli.rs create mode 100644 crates-cli/yaak-cli/src/commands/agent.rs create mode 100644 crates-cli/yaak-cli/src/commands/auth.rs create mode 100644 crates-cli/yaak-cli/src/commands/cookie_jar.rs create mode 100644 crates-cli/yaak-cli/src/commands/environment.rs create mode 100644 crates-cli/yaak-cli/src/commands/folder.rs create mode 100644 crates-cli/yaak-cli/src/commands/import_export.rs create mode 100644 crates-cli/yaak-cli/src/commands/mod.rs create mode 100644 crates-cli/yaak-cli/src/commands/plugin.rs create mode 100644 crates-cli/yaak-cli/src/commands/request.rs create mode 100644 crates-cli/yaak-cli/src/commands/response.rs create mode 100644 crates-cli/yaak-cli/src/commands/send.rs create mode 100644 crates-cli/yaak-cli/src/commands/template_function.rs create mode 100644 crates-cli/yaak-cli/src/commands/workspace.rs create mode 100644 crates-cli/yaak-cli/src/context.rs create mode 100644 crates-cli/yaak-cli/src/main.rs create mode 100644 crates-cli/yaak-cli/src/plugin_events.rs create mode 100644 crates-cli/yaak-cli/src/ui.rs create mode 100644 crates-cli/yaak-cli/src/utils/confirm.rs create mode 100644 crates-cli/yaak-cli/src/utils/http.rs create mode 100644 crates-cli/yaak-cli/src/utils/json.rs create mode 100644 crates-cli/yaak-cli/src/utils/mod.rs create mode 100644 crates-cli/yaak-cli/src/utils/schema.rs create mode 100644 crates-cli/yaak-cli/src/utils/workspace.rs create mode 100644 crates-cli/yaak-cli/src/version.rs create mode 100644 crates-cli/yaak-cli/src/version_check.rs create mode 100644 crates-cli/yaak-cli/tests/common/http_server.rs create mode 100644 crates-cli/yaak-cli/tests/common/mod.rs create mode 100644 crates-cli/yaak-cli/tests/environment_commands.rs create mode 100644 crates-cli/yaak-cli/tests/folder_commands.rs create mode 100644 crates-cli/yaak-cli/tests/import_export_commands.rs create mode 100644 crates-cli/yaak-cli/tests/request_commands.rs create mode 100644 crates-cli/yaak-cli/tests/send_commands.rs create mode 100644 crates-cli/yaak-cli/tests/workspace_commands.rs create mode 100644 crates-proxy/yaak-proxy-lib/Cargo.toml create mode 100644 crates-proxy/yaak-proxy-lib/bindings/ModelChangeEvent.ts create mode 100644 crates-proxy/yaak-proxy-lib/bindings/gen_models.ts create mode 100644 crates-proxy/yaak-proxy-lib/bindings/gen_rpc.ts create mode 100644 crates-proxy/yaak-proxy-lib/bindings/index.ts create mode 100644 crates-proxy/yaak-proxy-lib/migrations/00000001_init.sql create mode 100644 crates-proxy/yaak-proxy-lib/package.json create mode 100644 crates-proxy/yaak-proxy-lib/src/actions.rs create mode 100644 crates-proxy/yaak-proxy-lib/src/db.rs create mode 100644 crates-proxy/yaak-proxy-lib/src/lib.rs create mode 100644 crates-proxy/yaak-proxy-lib/src/models.rs create mode 100644 crates-server/yaak-playground/Cargo.toml create mode 100644 crates-server/yaak-playground/README.md create mode 100644 crates-server/yaak-playground/src/auth.rs create mode 100644 crates-server/yaak-playground/src/config.rs create mode 100644 crates-server/yaak-playground/src/data.rs create mode 100644 crates-server/yaak-playground/src/error.rs create mode 100644 crates-server/yaak-playground/src/lib.rs create mode 100644 crates-server/yaak-playground/src/limits.rs create mode 100644 crates-server/yaak-playground/src/main.rs create mode 100644 crates-server/yaak-playground/src/openapi.json create mode 100644 crates-server/yaak-playground/src/resources.rs create mode 100644 crates-server/yaak-playground/src/seed.json create mode 100644 crates-server/yaak-playground/src/store.rs create mode 100644 crates-server/yaak-playground/tests/api.rs create mode 100644 crates-server/yaak-web/Cargo.toml create mode 100644 crates-server/yaak-web/README.md create mode 100644 crates-server/yaak-web/bindings/gen_models.ts create mode 100644 crates-server/yaak-web/bindings/gen_web.ts create mode 100644 crates-server/yaak-web/index.ts create mode 100644 crates-server/yaak-web/package.json create mode 100644 crates-server/yaak-web/src/config.rs create mode 100644 crates-server/yaak-web/src/guard.rs create mode 100644 crates-server/yaak-web/src/lib.rs create mode 100644 crates-server/yaak-web/src/limits.rs create mode 100644 crates-server/yaak-web/src/main.rs create mode 100644 crates-server/yaak-web/src/send.rs create mode 100644 crates-server/yaak-web/src/wire.rs create mode 100644 crates-server/yaak-web/tests/logging.rs create mode 100644 crates-server/yaak-web/tests/router.rs create mode 100644 crates-tauri/yaak-app-client/.gitignore create mode 100644 crates-tauri/yaak-app-client/Cargo.toml create mode 100644 crates-tauri/yaak-app-client/bindings/gen_watch.ts create mode 100644 crates-tauri/yaak-app-client/bindings/index.ts create mode 100644 crates-tauri/yaak-app-client/bindings/plugins_ext.ts create mode 100644 crates-tauri/yaak-app-client/build.rs create mode 100644 crates-tauri/yaak-app-client/capabilities/default.json create mode 100644 crates-tauri/yaak-app-client/icons/dev/128x128.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/128x128@2x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/32x32.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/64x64.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/Square107x107Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/Square142x142Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/Square150x150Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/Square284x284Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/Square30x30Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/Square310x310Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/Square44x44Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/Square71x71Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/Square89x89Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/StoreLogo.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-hdpi/ic_launcher.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-hdpi/ic_launcher_round.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-mdpi/ic_launcher.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-mdpi/ic_launcher_round.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-xhdpi/ic_launcher.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-xhdpi/ic_launcher_round.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-xxhdpi/ic_launcher.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-xxxhdpi/ic_launcher.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/android/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/icon.icns create mode 100644 crates-tauri/yaak-app-client/icons/dev/icon.ico create mode 100644 crates-tauri/yaak-app-client/icons/dev/icon.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-20x20@1x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-20x20@2x-1.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-20x20@2x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-20x20@3x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-29x29@1x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-29x29@2x-1.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-29x29@2x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-29x29@3x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-40x40@1x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-40x40@2x-1.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-40x40@2x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-40x40@3x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-512@2x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-60x60@2x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-60x60@3x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-76x76@1x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-76x76@2x.png create mode 100644 crates-tauri/yaak-app-client/icons/dev/ios/AppIcon-83.5x83.5@2x.png create mode 100644 crates-tauri/yaak-app-client/icons/icon-dev.png create mode 100644 crates-tauri/yaak-app-client/icons/release/128x128.png create mode 100644 crates-tauri/yaak-app-client/icons/release/128x128@2x.png create mode 100644 crates-tauri/yaak-app-client/icons/release/32x32.png create mode 100644 crates-tauri/yaak-app-client/icons/release/64x64.png create mode 100644 crates-tauri/yaak-app-client/icons/release/Square107x107Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/release/Square142x142Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/release/Square150x150Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/release/Square284x284Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/release/Square30x30Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/release/Square310x310Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/release/Square44x44Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/release/Square71x71Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/release/Square89x89Logo.png create mode 100644 crates-tauri/yaak-app-client/icons/release/StoreLogo.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-hdpi/ic_launcher.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-hdpi/ic_launcher_foreground.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-hdpi/ic_launcher_round.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-mdpi/ic_launcher.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-mdpi/ic_launcher_foreground.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-mdpi/ic_launcher_round.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-xhdpi/ic_launcher.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-xhdpi/ic_launcher_foreground.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-xhdpi/ic_launcher_round.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-xxhdpi/ic_launcher.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-xxhdpi/ic_launcher_foreground.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-xxhdpi/ic_launcher_round.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-xxxhdpi/ic_launcher.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-xxxhdpi/ic_launcher_foreground.png create mode 100644 crates-tauri/yaak-app-client/icons/release/android/mipmap-xxxhdpi/ic_launcher_round.png create mode 100644 crates-tauri/yaak-app-client/icons/release/icon.ico create mode 100644 crates-tauri/yaak-app-client/icons/release/icon.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-20x20@1x.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-20x20@2x-1.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-20x20@2x.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-20x20@3x.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-29x29@1x.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-29x29@2x-1.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-29x29@2x.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-29x29@3x.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-40x40@1x.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-40x40@2x-1.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-40x40@2x.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-40x40@3x.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-60x60@2x.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-60x60@3x.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-76x76@1x.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-76x76@2x.png create mode 100644 crates-tauri/yaak-app-client/icons/release/ios/AppIcon-83.5x83.5@2x.png create mode 100644 crates-tauri/yaak-app-client/index.ts create mode 100644 crates-tauri/yaak-app-client/macos/entitlements.plist create mode 100644 crates-tauri/yaak-app-client/macos/entitlements.yaaknode.plist create mode 100644 crates-tauri/yaak-app-client/macos/entitlements.yaakprotoc.plist create mode 100644 crates-tauri/yaak-app-client/package.json create mode 100644 crates-tauri/yaak-app-client/src/encoding.rs create mode 100644 crates-tauri/yaak-app-client/src/error.rs create mode 100644 crates-tauri/yaak-app-client/src/feedback.rs create mode 100644 crates-tauri/yaak-app-client/src/git_ext.rs create mode 100644 crates-tauri/yaak-app-client/src/git_watcher.rs create mode 100644 crates-tauri/yaak-app-client/src/grpc.rs create mode 100644 crates-tauri/yaak-app-client/src/history.rs create mode 100644 crates-tauri/yaak-app-client/src/http_request.rs create mode 100644 crates-tauri/yaak-app-client/src/import.rs create mode 100644 crates-tauri/yaak-app-client/src/lib.rs create mode 100644 crates-tauri/yaak-app-client/src/main.rs create mode 100644 crates-tauri/yaak-app-client/src/models_ext.rs create mode 100644 crates-tauri/yaak-app-client/src/notifications.rs create mode 100644 crates-tauri/yaak-app-client/src/plugin_events.rs create mode 100644 crates-tauri/yaak-app-client/src/plugins_ext.rs create mode 100644 crates-tauri/yaak-app-client/src/render.rs create mode 100644 crates-tauri/yaak-app-client/src/restart.rs create mode 100644 crates-tauri/yaak-app-client/src/rpc_ext.rs create mode 100644 crates-tauri/yaak-app-client/src/sync_ext.rs create mode 100644 crates-tauri/yaak-app-client/src/updates.rs create mode 100644 crates-tauri/yaak-app-client/src/uri_scheme.rs create mode 100644 crates-tauri/yaak-app-client/src/window_menu.rs create mode 100644 crates-tauri/yaak-app-client/src/ws_ext.rs create mode 100644 crates-tauri/yaak-app-client/static/greg.jpeg create mode 100644 crates-tauri/yaak-app-client/tauri.conf.json create mode 100644 crates-tauri/yaak-app-client/tauri.development.conf.json create mode 100644 crates-tauri/yaak-app-client/tauri.linux.conf.json create mode 100644 crates-tauri/yaak-app-client/tauri.release.conf.json create mode 100644 crates-tauri/yaak-app-client/template.desktop create mode 100644 crates-tauri/yaak-app-proxy/.gitignore create mode 100644 crates-tauri/yaak-app-proxy/Cargo.toml create mode 100644 crates-tauri/yaak-app-proxy/bindings/index.ts create mode 100644 crates-tauri/yaak-app-proxy/build.rs create mode 100644 crates-tauri/yaak-app-proxy/capabilities/default.json create mode 100644 crates-tauri/yaak-app-proxy/package.json create mode 100644 crates-tauri/yaak-app-proxy/src/lib.rs create mode 100644 crates-tauri/yaak-app-proxy/src/main.rs create mode 100644 crates-tauri/yaak-app-proxy/src/window_menu.rs create mode 100644 crates-tauri/yaak-app-proxy/tauri.conf.json create mode 100644 crates-tauri/yaak-app-proxy/tauri.development.conf.json create mode 100644 crates-tauri/yaak-app-proxy/tauri.release.conf.json create mode 100644 crates-tauri/yaak-app-proxy/template.desktop create mode 100644 crates-tauri/yaak-fonts/Cargo.toml create mode 100644 crates-tauri/yaak-fonts/bindings/gen_fonts.ts create mode 100644 crates-tauri/yaak-fonts/build.rs create mode 100644 crates-tauri/yaak-fonts/index.ts create mode 100644 crates-tauri/yaak-fonts/package.json create mode 100644 crates-tauri/yaak-fonts/permissions/default.toml create mode 100644 crates-tauri/yaak-fonts/src/commands.rs create mode 100644 crates-tauri/yaak-fonts/src/error.rs create mode 100644 crates-tauri/yaak-fonts/src/lib.rs create mode 100644 crates-tauri/yaak-license/Cargo.toml create mode 100644 crates-tauri/yaak-license/bindings/gen_models.ts create mode 100644 crates-tauri/yaak-license/bindings/license.ts create mode 100644 crates-tauri/yaak-license/bindings/models.ts create mode 100644 crates-tauri/yaak-license/build.rs create mode 100644 crates-tauri/yaak-license/index.ts create mode 100644 crates-tauri/yaak-license/package.json create mode 100644 crates-tauri/yaak-license/permissions/default.toml create mode 100644 crates-tauri/yaak-license/src/commands.rs create mode 100644 crates-tauri/yaak-license/src/error.rs create mode 100644 crates-tauri/yaak-license/src/lib.rs create mode 100644 crates-tauri/yaak-license/src/license.rs create mode 100644 crates-tauri/yaak-mac-window/Cargo.toml create mode 100644 crates-tauri/yaak-mac-window/build.rs create mode 100644 crates-tauri/yaak-mac-window/index.ts create mode 100644 crates-tauri/yaak-mac-window/package.json create mode 100644 crates-tauri/yaak-mac-window/permissions/default.toml create mode 100644 crates-tauri/yaak-mac-window/src/commands.rs create mode 100644 crates-tauri/yaak-mac-window/src/lib.rs create mode 100644 crates-tauri/yaak-mac-window/src/mac.rs create mode 100644 crates-tauri/yaak-system-appearance/Cargo.toml create mode 100644 crates-tauri/yaak-system-appearance/src/lib.rs create mode 100644 crates-tauri/yaak-tauri-utils/Cargo.toml create mode 100644 crates-tauri/yaak-tauri-utils/src/lib.rs create mode 100644 crates-tauri/yaak-tauri-utils/src/window.rs create mode 100644 crates-tauri/yaak-window/Cargo.toml create mode 100644 crates-tauri/yaak-window/src/lib.rs create mode 100644 crates-tauri/yaak-window/src/window.rs create mode 100644 crates-tauri/yaak-window/src/window_state.rs create mode 100644 crates/common/yaak-database/Cargo.toml create mode 100644 crates/common/yaak-database/src/connection_or_tx.rs create mode 100644 crates/common/yaak-database/src/db_context.rs create mode 100644 crates/common/yaak-database/src/error.rs create mode 100644 crates/common/yaak-database/src/lib.rs create mode 100644 crates/common/yaak-database/src/migrate.rs create mode 100644 crates/common/yaak-database/src/pool.rs create mode 100644 crates/common/yaak-database/src/traits.rs create mode 100644 crates/common/yaak-database/src/update_source.rs create mode 100644 crates/common/yaak-database/src/util.rs create mode 100644 crates/common/yaak-rpc-schema/Cargo.toml create mode 100644 crates/common/yaak-rpc-schema/README.md create mode 100644 crates/common/yaak-rpc-schema/bindings/gen_api.ts create mode 100644 crates/common/yaak-rpc-schema/bindings/gen_events.ts create mode 100644 crates/common/yaak-rpc-schema/bindings/gen_git.ts create mode 100644 crates/common/yaak-rpc-schema/bindings/gen_grpc.ts create mode 100644 crates/common/yaak-rpc-schema/bindings/gen_models.ts create mode 100644 crates/common/yaak-rpc-schema/bindings/gen_rpc.ts create mode 100644 crates/common/yaak-rpc-schema/bindings/gen_search.ts create mode 100644 crates/common/yaak-rpc-schema/bindings/gen_sync.ts create mode 100644 crates/common/yaak-rpc-schema/bindings/gen_util.ts create mode 100644 crates/common/yaak-rpc-schema/bindings/parser.ts create mode 100644 crates/common/yaak-rpc-schema/bindings/sse.ts create mode 100644 crates/common/yaak-rpc-schema/index.ts create mode 100644 crates/common/yaak-rpc-schema/package.json create mode 100644 crates/common/yaak-rpc-schema/src/lib.rs create mode 100644 crates/common/yaak-rpc/Cargo.toml create mode 100644 crates/common/yaak-rpc/src/lib.rs create mode 100644 crates/yaak-api/Cargo.toml create mode 100644 crates/yaak-api/src/error.rs create mode 100644 crates/yaak-api/src/lib.rs create mode 100644 crates/yaak-commands/Cargo.toml create mode 100644 crates/yaak-commands/src/actions.rs create mode 100644 crates/yaak-commands/src/auth.rs create mode 100644 crates/yaak-commands/src/data.rs create mode 100644 crates/yaak-commands/src/encryption.rs create mode 100644 crates/yaak-commands/src/error.rs create mode 100644 crates/yaak-commands/src/host.rs create mode 100644 crates/yaak-commands/src/lib.rs create mode 100644 crates/yaak-commands/src/models.rs create mode 100644 crates/yaak-commands/src/plugins.rs create mode 100644 crates/yaak-commands/src/render.rs create mode 100644 crates/yaak-commands/src/resolve.rs create mode 100644 crates/yaak-commands/src/responses.rs create mode 100644 crates/yaak-commands/src/templates.rs create mode 100644 crates/yaak-commands/tests/test_host.rs create mode 100644 crates/yaak-common/Cargo.toml create mode 100644 crates/yaak-common/src/command.rs create mode 100644 crates/yaak-common/src/lib.rs create mode 100644 crates/yaak-common/src/platform.rs create mode 100644 crates/yaak-common/src/serde.rs create mode 100644 crates/yaak-core/Cargo.toml create mode 100644 crates/yaak-core/src/context.rs create mode 100644 crates/yaak-core/src/error.rs create mode 100644 crates/yaak-core/src/lib.rs create mode 100644 crates/yaak-crypto/Cargo.toml create mode 100644 crates/yaak-crypto/index.ts create mode 100644 crates/yaak-crypto/package.json create mode 100644 crates/yaak-crypto/src/encryption.rs create mode 100644 crates/yaak-crypto/src/error.rs create mode 100644 crates/yaak-crypto/src/lib.rs create mode 100644 crates/yaak-crypto/src/manager.rs create mode 100644 crates/yaak-crypto/src/master_key.rs create mode 100644 crates/yaak-crypto/src/workspace_key.rs create mode 100644 crates/yaak-git/Cargo.toml create mode 100644 crates/yaak-git/bindings/gen_git.ts create mode 100644 crates/yaak-git/bindings/gen_models.ts create mode 100644 crates/yaak-git/index.ts create mode 100644 crates/yaak-git/package.json create mode 100644 crates/yaak-git/src/add.rs create mode 100644 crates/yaak-git/src/binary.rs create mode 100644 crates/yaak-git/src/branch.rs create mode 100644 crates/yaak-git/src/clone.rs create mode 100644 crates/yaak-git/src/commit.rs create mode 100644 crates/yaak-git/src/credential.rs create mode 100644 crates/yaak-git/src/error.rs create mode 100644 crates/yaak-git/src/fetch.rs create mode 100644 crates/yaak-git/src/init.rs create mode 100644 crates/yaak-git/src/lib.rs create mode 100644 crates/yaak-git/src/log.rs create mode 100644 crates/yaak-git/src/pull.rs create mode 100644 crates/yaak-git/src/push.rs create mode 100644 crates/yaak-git/src/remotes.rs create mode 100644 crates/yaak-git/src/repository.rs create mode 100644 crates/yaak-git/src/reset.rs create mode 100644 crates/yaak-git/src/restore.rs create mode 100644 crates/yaak-git/src/status.rs create mode 100644 crates/yaak-git/src/unstage.rs create mode 100644 crates/yaak-git/src/util.rs create mode 100644 crates/yaak-grpc/Cargo.toml create mode 100644 crates/yaak-grpc/bindings/gen_grpc.ts create mode 100644 crates/yaak-grpc/src/any.rs create mode 100644 crates/yaak-grpc/src/client.rs create mode 100644 crates/yaak-grpc/src/codec.rs create mode 100644 crates/yaak-grpc/src/error.rs create mode 100644 crates/yaak-grpc/src/json_schema.rs create mode 100644 crates/yaak-grpc/src/lib.rs create mode 100644 crates/yaak-grpc/src/manager.rs create mode 100644 crates/yaak-grpc/src/reflection.rs create mode 100644 crates/yaak-grpc/src/transport.rs create mode 100644 crates/yaak-http/Cargo.toml create mode 100644 crates/yaak-http/src/chained_reader.rs create mode 100644 crates/yaak-http/src/client.rs create mode 100644 crates/yaak-http/src/cookies.rs create mode 100644 crates/yaak-http/src/decompress.rs create mode 100644 crates/yaak-http/src/dns.rs create mode 100644 crates/yaak-http/src/error.rs create mode 100644 crates/yaak-http/src/lib.rs create mode 100644 crates/yaak-http/src/manager.rs create mode 100644 crates/yaak-http/src/proto.rs create mode 100644 crates/yaak-http/src/sender.rs create mode 100644 crates/yaak-http/src/tee_reader.rs create mode 100644 crates/yaak-http/src/transaction.rs create mode 100644 crates/yaak-http/src/types.rs create mode 100644 crates/yaak-http/tests/test.txt create mode 100644 crates/yaak-lifecycle/Cargo.toml create mode 100644 crates/yaak-lifecycle/src/lib.rs create mode 100644 crates/yaak-models/Cargo.toml create mode 100644 crates/yaak-models/bindings/ModelChangeEvent.ts create mode 100644 crates/yaak-models/bindings/gen_models.ts create mode 100644 crates/yaak-models/bindings/gen_util.ts create mode 100644 crates/yaak-models/blob_migrations/00000000000000_init.sql create mode 100644 crates/yaak-models/build.rs create mode 100644 crates/yaak-models/guest-js/atoms.test.ts create mode 100644 crates/yaak-models/guest-js/atoms.ts create mode 100644 crates/yaak-models/guest-js/index.ts create mode 100644 crates/yaak-models/guest-js/store.ts create mode 100644 crates/yaak-models/guest-js/types.ts create mode 100644 crates/yaak-models/guest-js/util.ts create mode 100644 crates/yaak-models/migrations/20230225181302_init.sql create mode 100644 crates/yaak-models/migrations/20230319042610_sort-priority.sql create mode 100644 crates/yaak-models/migrations/20230330143214_request-auth.sql create mode 100644 crates/yaak-models/migrations/20230413232435_response-body-blob.sql create mode 100644 crates/yaak-models/migrations/20231022205109_environments.sql create mode 100644 crates/yaak-models/migrations/20231028161007_variables.sql create mode 100644 crates/yaak-models/migrations/20231103004111_workspace-variables.sql create mode 100644 crates/yaak-models/migrations/20231103142807_folders.sql create mode 100644 crates/yaak-models/migrations/20231112180500_body_object.sql create mode 100644 crates/yaak-models/migrations/20231113183810_url_params.sql create mode 100644 crates/yaak-models/migrations/20231122055216_remove_body.sql create mode 100644 crates/yaak-models/migrations/20240111221224_settings.sql create mode 100644 crates/yaak-models/migrations/20240115193751_workspace_settings.sql create mode 100644 crates/yaak-models/migrations/20240118181105_channel_setting.sql create mode 100644 crates/yaak-models/migrations/20240127013915_cookies.sql create mode 100644 crates/yaak-models/migrations/20240128230717_more_response_attrs.sql create mode 100644 crates/yaak-models/migrations/20240203164833_grpc.sql create mode 100644 crates/yaak-models/migrations/20240522031045_theme-settings.sql create mode 100644 crates/yaak-models/migrations/20240529143147_more-settings.sql create mode 100644 crates/yaak-models/migrations/20240607151115_open-workspace-setting.sql create mode 100644 crates/yaak-models/migrations/20240814013812_fix-env-model.sql create mode 100644 crates/yaak-models/migrations/20240826184943_disable-telemetry.sql create mode 100644 crates/yaak-models/migrations/20240829131004_plugins.sql create mode 100644 crates/yaak-models/migrations/20241003134208_response-state.sql create mode 100644 crates/yaak-models/migrations/20241012181547_proxy-setting.sql create mode 100644 crates/yaak-models/migrations/20241217204951_docs.sql create mode 100644 crates/yaak-models/migrations/20241219140051_base-environments.sql create mode 100644 crates/yaak-models/migrations/20250102141937_sync.sql create mode 100644 crates/yaak-models/migrations/20250108035425_editor-keymap.sql create mode 100644 crates/yaak-models/migrations/20250108205117_workspace-meta.sql create mode 100644 crates/yaak-models/migrations/20250114160022_remove-workspace-sync-setting.sql create mode 100644 crates/yaak-models/migrations/20250123192023_plugin-kv.sql create mode 100644 crates/yaak-models/migrations/20250128155623_websockets.sql create mode 100644 crates/yaak-models/migrations/20250302041707_hide-window-controls.sql create mode 100644 crates/yaak-models/migrations/20250326193143_key-value-id.sql create mode 100644 crates/yaak-models/migrations/20250401122407_encrypted-key.sql create mode 100644 crates/yaak-models/migrations/20250402144842_encryption-key-challenge.sql create mode 100644 crates/yaak-models/migrations/20250424152740_remove-fks.sql create mode 100644 crates/yaak-models/migrations/20250507140702_remove-ev-sync-states.sql create mode 100644 crates/yaak-models/migrations/20250508161145_public-environments.sql create mode 100644 crates/yaak-models/migrations/20250516182745_default-attrs.sql create mode 100644 crates/yaak-models/migrations/20250530174021_graphql-introspection.sql create mode 100644 crates/yaak-models/migrations/20250531193722_sync-state-index.sql create mode 100644 crates/yaak-models/migrations/20250604102922_colored-methods-setting.sql create mode 100644 crates/yaak-models/migrations/20250608150053_font-settings.sql create mode 100644 crates/yaak-models/migrations/20250611120000_environment-color.sql create mode 100644 crates/yaak-models/migrations/20250727190746_autoupdate_setting.sql create mode 100644 crates/yaak-models/migrations/20250918141129_request-folder-environments.sql create mode 100644 crates/yaak-models/migrations/20250929132954_dismiss-license-badge.sql create mode 100644 crates/yaak-models/migrations/20251001082054_auto-download.sql create mode 100644 crates/yaak-models/migrations/20251028060300_check_notifications_setting.sql create mode 100644 crates/yaak-models/migrations/20251029062024_aws-auth-name.sql create mode 100644 crates/yaak-models/migrations/20251031070515_environment-sort-priority.sql create mode 100644 crates/yaak-models/migrations/20251202080000_use-native-titlebar.sql create mode 100644 crates/yaak-models/migrations/20251209000000_client-certificates.sql create mode 100644 crates/yaak-models/migrations/20251219074602_default-workspace-headers.sql create mode 100644 crates/yaak-models/migrations/20251220000000_response-request-headers.sql create mode 100644 crates/yaak-models/migrations/20251221000000_http-response-events.sql create mode 100644 crates/yaak-models/migrations/20251221100000_request-content-length.sql create mode 100644 crates/yaak-models/migrations/20260104000000_hotkeys.sql create mode 100644 crates/yaak-models/migrations/20260111000000_dns-timing.sql create mode 100644 crates/yaak-models/migrations/20260112000000_dns-overrides.sql create mode 100644 crates/yaak-models/migrations/20260119045146_remove-default-workspace-headers.sql create mode 100644 crates/yaak-models/migrations/20260216000000_model-changes.sql create mode 100644 crates/yaak-models/migrations/20260217000000_remove-legacy-faker-plugin.sql create mode 100644 crates/yaak-models/migrations/20260301000000_plugin-source-and-unique-directory.sql create mode 100644 crates/yaak-models/migrations/20260302000000_inherited-request-settings.sql create mode 100644 crates/yaak-models/migrations/20260303000000_protocol-tls-settings.sql create mode 100644 crates/yaak-models/migrations/20260629000000_request-message-size.sql create mode 100644 crates/yaak-models/migrations/20260704000000_prompt-feedback.sql create mode 100644 crates/yaak-models/migrations/20260826000000_http-version.sql create mode 100644 crates/yaak-models/migrations/20260901000000_import-sources.sql create mode 100644 crates/yaak-models/migrations/20260902000000_import-source-content-hash.sql create mode 100644 crates/yaak-models/package.json create mode 100644 crates/yaak-models/src/blob_manager.rs create mode 100644 crates/yaak-models/src/client_db.rs create mode 100644 crates/yaak-models/src/connection_or_tx.rs create mode 100644 crates/yaak-models/src/cookies.rs create mode 100644 crates/yaak-models/src/error.rs create mode 100644 crates/yaak-models/src/example.rs create mode 100644 crates/yaak-models/src/example_workspace.json create mode 100644 crates/yaak-models/src/export.rs create mode 100644 crates/yaak-models/src/lib.rs create mode 100644 crates/yaak-models/src/migrate.rs create mode 100644 crates/yaak-models/src/models.rs create mode 100644 crates/yaak-models/src/models_ops.rs create mode 100644 crates/yaak-models/src/path_placeholders.rs create mode 100644 crates/yaak-models/src/queries/any_request.rs create mode 100644 crates/yaak-models/src/queries/batch.rs create mode 100644 crates/yaak-models/src/queries/cookie_jars.rs create mode 100644 crates/yaak-models/src/queries/duplicate_name.rs create mode 100644 crates/yaak-models/src/queries/environments.rs create mode 100644 crates/yaak-models/src/queries/folders.rs create mode 100644 crates/yaak-models/src/queries/graphql_introspections.rs create mode 100644 crates/yaak-models/src/queries/grpc_connections.rs create mode 100644 crates/yaak-models/src/queries/grpc_events.rs create mode 100644 crates/yaak-models/src/queries/grpc_requests.rs create mode 100644 crates/yaak-models/src/queries/http_requests.rs create mode 100644 crates/yaak-models/src/queries/http_response_events.rs create mode 100644 crates/yaak-models/src/queries/http_responses.rs create mode 100644 crates/yaak-models/src/queries/import_source_resources.rs create mode 100644 crates/yaak-models/src/queries/import_sources.rs create mode 100644 crates/yaak-models/src/queries/key_values.rs create mode 100644 crates/yaak-models/src/queries/mod.rs create mode 100644 crates/yaak-models/src/queries/model_changes.rs create mode 100644 crates/yaak-models/src/queries/plugin_key_values.rs create mode 100644 crates/yaak-models/src/queries/plugins.rs create mode 100644 crates/yaak-models/src/queries/settings.rs create mode 100644 crates/yaak-models/src/queries/sync_states.rs create mode 100644 crates/yaak-models/src/queries/websocket_connections.rs create mode 100644 crates/yaak-models/src/queries/websocket_events.rs create mode 100644 crates/yaak-models/src/queries/websocket_requests.rs create mode 100644 crates/yaak-models/src/queries/workspace_metas.rs create mode 100644 crates/yaak-models/src/queries/workspaces.rs create mode 100644 crates/yaak-models/src/query_manager.rs create mode 100644 crates/yaak-models/src/render.rs create mode 100644 crates/yaak-models/src/util.rs create mode 100644 crates/yaak-plugins/Cargo.toml create mode 100644 crates/yaak-plugins/bindings/gen_api.ts create mode 100644 crates/yaak-plugins/bindings/gen_events.ts create mode 100644 crates/yaak-plugins/bindings/gen_models.ts create mode 100644 crates/yaak-plugins/bindings/gen_search.ts create mode 100644 crates/yaak-plugins/bindings/serde_json/JsonValue.ts create mode 100644 crates/yaak-plugins/index.ts create mode 100644 crates/yaak-plugins/package.json create mode 100644 crates/yaak-plugins/src/api.rs create mode 100644 crates/yaak-plugins/src/checksum.rs create mode 100644 crates/yaak-plugins/src/error.rs create mode 100644 crates/yaak-plugins/src/events.rs create mode 100644 crates/yaak-plugins/src/install.rs create mode 100644 crates/yaak-plugins/src/lib.rs create mode 100644 crates/yaak-plugins/src/manager.rs create mode 100644 crates/yaak-plugins/src/native_template_functions.rs create mode 100644 crates/yaak-plugins/src/nodejs.rs create mode 100644 crates/yaak-plugins/src/plugin_handle.rs create mode 100644 crates/yaak-plugins/src/plugin_meta.rs create mode 100644 crates/yaak-plugins/src/server_ws.rs create mode 100644 crates/yaak-plugins/src/template_callback.rs create mode 100644 crates/yaak-plugins/src/util.rs create mode 100644 crates/yaak-proxy/Cargo.toml create mode 100644 crates/yaak-proxy/src/body.rs create mode 100644 crates/yaak-proxy/src/cert.rs create mode 100644 crates/yaak-proxy/src/connection.rs create mode 100644 crates/yaak-proxy/src/lib.rs create mode 100644 crates/yaak-proxy/src/request.rs create mode 100644 crates/yaak-sse/Cargo.toml create mode 100644 crates/yaak-sse/bindings/sse.ts create mode 100644 crates/yaak-sse/index.ts create mode 100644 crates/yaak-sse/package.json create mode 100644 crates/yaak-sse/src/lib.rs create mode 100644 crates/yaak-sse/src/sse.rs create mode 100644 crates/yaak-sse/summary.test.ts create mode 100644 crates/yaak-sse/summary.ts create mode 100644 crates/yaak-sync/Cargo.toml create mode 100644 crates/yaak-sync/bindings/gen_models.ts create mode 100644 crates/yaak-sync/bindings/gen_sync.ts create mode 100644 crates/yaak-sync/bindings/gen_watch.ts create mode 100644 crates/yaak-sync/bindings/git.ts create mode 100644 crates/yaak-sync/index.ts create mode 100644 crates/yaak-sync/package.json create mode 100644 crates/yaak-sync/src/error.rs create mode 100644 crates/yaak-sync/src/lib.rs create mode 100644 crates/yaak-sync/src/models.rs create mode 100644 crates/yaak-sync/src/sync.rs create mode 100644 crates/yaak-sync/src/watch.rs create mode 100644 crates/yaak-templates/Cargo.toml create mode 100644 crates/yaak-templates/bindings/parser.ts create mode 100644 crates/yaak-templates/build-wasm.cjs create mode 100644 crates/yaak-templates/index.ts create mode 100644 crates/yaak-templates/package.json create mode 100644 crates/yaak-templates/pkg/package.json create mode 100644 crates/yaak-templates/pkg/yaak_templates.d.ts create mode 100644 crates/yaak-templates/pkg/yaak_templates.js create mode 100644 crates/yaak-templates/pkg/yaak_templates_bg.js create mode 100644 crates/yaak-templates/pkg/yaak_templates_bg.wasm create mode 100644 crates/yaak-templates/pkg/yaak_templates_bg.wasm.d.ts create mode 100644 crates/yaak-templates/src/error.rs create mode 100644 crates/yaak-templates/src/escape.rs create mode 100644 crates/yaak-templates/src/format_json.rs create mode 100644 crates/yaak-templates/src/lib.rs create mode 100644 crates/yaak-templates/src/parser.rs create mode 100644 crates/yaak-templates/src/renderer.rs create mode 100644 crates/yaak-templates/src/strip_json_comments.rs create mode 100644 crates/yaak-templates/src/wasm.rs create mode 100644 crates/yaak-tls/Cargo.toml create mode 100644 crates/yaak-tls/src/error.rs create mode 100644 crates/yaak-tls/src/lib.rs create mode 100644 crates/yaak-wasm/Cargo.toml create mode 100644 crates/yaak-wasm/build-wasm.cjs create mode 100644 crates/yaak-wasm/index.ts create mode 100644 crates/yaak-wasm/package.json create mode 100644 crates/yaak-wasm/pkg/package.json create mode 100644 crates/yaak-wasm/pkg/yaak_wasm.d.ts create mode 100644 crates/yaak-wasm/pkg/yaak_wasm.js create mode 100644 crates/yaak-wasm/pkg/yaak_wasm_bg.js create mode 100644 crates/yaak-wasm/pkg/yaak_wasm_bg.wasm.d.ts create mode 100644 crates/yaak-wasm/src/lib.rs create mode 100644 crates/yaak-ws/Cargo.toml create mode 100644 crates/yaak-ws/index.ts create mode 100644 crates/yaak-ws/package.json create mode 100644 crates/yaak-ws/src/connect.rs create mode 100644 crates/yaak-ws/src/error.rs create mode 100644 crates/yaak-ws/src/lib.rs create mode 100644 crates/yaak-ws/src/manager.rs create mode 100644 crates/yaak-ws/src/render.rs create mode 100644 crates/yaak/Cargo.toml create mode 100644 crates/yaak/src/error.rs create mode 100644 crates/yaak/src/import.rs create mode 100644 crates/yaak/src/lib.rs create mode 100644 crates/yaak/src/plugin_events.rs create mode 100644 crates/yaak/src/response_body.rs create mode 100644 crates/yaak/src/send.rs create mode 100644 flatpak/app.yaak.Yaak.metainfo.xml create mode 100644 flatpak/fix-lockfile.mjs create mode 100755 flatpak/generate-sources.sh create mode 100755 flatpak/update-manifest.sh create mode 100644 greptile.json create mode 100644 npm/cli-darwin-arm64/bin/.gitkeep create mode 100644 npm/cli-darwin-arm64/package.json create mode 100644 npm/cli-darwin-x64/bin/.gitkeep create mode 100644 npm/cli-darwin-x64/package.json create mode 100644 npm/cli-linux-arm64/bin/.gitkeep create mode 100644 npm/cli-linux-arm64/package.json create mode 100644 npm/cli-linux-x64/bin/.gitkeep create mode 100644 npm/cli-linux-x64/package.json create mode 100644 npm/cli-win32-arm64/bin/.gitkeep create mode 100644 npm/cli-win32-arm64/package.json create mode 100644 npm/cli-win32-x64/bin/.gitkeep create mode 100644 npm/cli-win32-x64/package.json create mode 100644 npm/cli/.gitignore create mode 100755 npm/cli/bin/cli.js create mode 100644 npm/cli/common.js create mode 100644 npm/cli/index.js create mode 100644 npm/cli/install.js create mode 100644 npm/cli/package.json create mode 100644 npm/cli/prepublish.js create mode 100644 npm/prepare-publish.js create mode 100644 package.json create mode 100644 packages/common-lib/debounce.test.ts create mode 100644 packages/common-lib/debounce.ts create mode 100644 packages/common-lib/eagerDebounceAsync.ts create mode 100644 packages/common-lib/formatSize.ts create mode 100644 packages/common-lib/index.ts create mode 100644 packages/common-lib/jsonPath.ts create mode 100644 packages/common-lib/package.json create mode 100644 packages/common-lib/templateFunction.ts create mode 100644 packages/model-store/package.json create mode 100644 packages/model-store/src/index.ts create mode 100644 packages/platform/package.json create mode 100644 packages/platform/src/capabilities.ts create mode 100644 packages/platform/src/index.ts create mode 100644 packages/platform/src/index.web.ts create mode 100644 packages/platform/src/registry.ts create mode 100644 packages/platform/src/tauri/index.ts create mode 100644 packages/platform/src/types.ts create mode 100644 packages/platform/src/web/README.md create mode 100644 packages/platform/src/web/commands.ts create mode 100644 packages/platform/src/web/connection.ts create mode 100644 packages/platform/src/web/errors.ts create mode 100644 packages/platform/src/web/ids.ts create mode 100644 packages/platform/src/web/index.ts create mode 100644 packages/platform/src/web/protocol.ts create mode 100644 packages/platform/src/web/send.ts create mode 100644 packages/platform/src/web/server.ts create mode 100644 packages/platform/src/web/storage.ts create mode 100644 packages/platform/src/web/worker.ts create mode 100644 packages/platform/tsconfig.json create mode 100644 packages/plugin-runtime-types/.gitignore create mode 100644 packages/plugin-runtime-types/README.md create mode 100644 packages/plugin-runtime-types/package.json create mode 100644 packages/plugin-runtime-types/src/bindings/gen_api.ts create mode 100644 packages/plugin-runtime-types/src/bindings/gen_events.ts create mode 100644 packages/plugin-runtime-types/src/bindings/gen_models.ts create mode 100644 packages/plugin-runtime-types/src/bindings/gen_search.ts create mode 100644 packages/plugin-runtime-types/src/bindings/serde_json/JsonValue.ts create mode 100644 packages/plugin-runtime-types/src/helpers.ts create mode 100644 packages/plugin-runtime-types/src/index.ts create mode 100644 packages/plugin-runtime-types/src/plugins/AuthenticationPlugin.ts create mode 100644 packages/plugin-runtime-types/src/plugins/Context.ts create mode 100644 packages/plugin-runtime-types/src/plugins/FilterPlugin.ts create mode 100644 packages/plugin-runtime-types/src/plugins/FolderActionPlugin.ts create mode 100644 packages/plugin-runtime-types/src/plugins/GrpcRequestActionPlugin.ts create mode 100644 packages/plugin-runtime-types/src/plugins/HttpRequestActionPlugin.ts create mode 100644 packages/plugin-runtime-types/src/plugins/ImporterPlugin.ts create mode 100644 packages/plugin-runtime-types/src/plugins/TemplateFunctionPlugin.ts create mode 100644 packages/plugin-runtime-types/src/plugins/ThemePlugin.ts create mode 100644 packages/plugin-runtime-types/src/plugins/WebsocketRequestActionPlugin.ts create mode 100644 packages/plugin-runtime-types/src/plugins/WorkspaceActionPlugin.ts create mode 100644 packages/plugin-runtime-types/src/plugins/index.ts create mode 100644 packages/plugin-runtime-types/src/themes/index.ts create mode 100644 packages/plugin-runtime-types/tsconfig.json create mode 100644 packages/plugin-runtime/.node-version create mode 100644 packages/plugin-runtime/package.json create mode 100644 packages/plugin-runtime/src/EventChannel.ts create mode 100644 packages/plugin-runtime/src/PluginHandle.ts create mode 100644 packages/plugin-runtime/src/PluginInstance.ts create mode 100644 packages/plugin-runtime/src/common.ts create mode 100644 packages/plugin-runtime/src/index.ts create mode 100644 packages/plugin-runtime/src/interceptStdout.ts create mode 100644 packages/plugin-runtime/src/metadata.ts create mode 100644 packages/plugin-runtime/src/migrations.ts create mode 100644 packages/plugin-runtime/src/responseBody.ts create mode 100644 packages/plugin-runtime/tests/common.test.ts create mode 100644 packages/plugin-runtime/tests/responseBody.test.ts create mode 100644 packages/plugin-runtime/tests/sendHttpRequest.test.ts create mode 100644 packages/plugin-runtime/tsconfig.json create mode 100644 packages/tailwind-config/index.css create mode 100644 packages/tailwind-config/package.json create mode 100644 packages/theme/package.json create mode 100644 packages/theme/src/appearance.ts create mode 100644 packages/theme/src/defaultThemes.ts create mode 100644 packages/theme/src/index.ts create mode 100644 packages/theme/src/window.ts create mode 100644 packages/theme/src/yaakColor.ts create mode 100644 packages/theme/tsconfig.json create mode 100644 packages/ui/package.json create mode 100644 packages/ui/src/components/Banner.tsx create mode 100644 packages/ui/src/components/Button.tsx create mode 100644 packages/ui/src/components/DropMarker.tsx create mode 100644 packages/ui/src/components/FormattedError.tsx create mode 100644 packages/ui/src/components/HeaderSize.tsx create mode 100644 packages/ui/src/components/Heading.tsx create mode 100644 packages/ui/src/components/Icon.tsx create mode 100644 packages/ui/src/components/IconButton.tsx create mode 100644 packages/ui/src/components/InlineCode.tsx create mode 100644 packages/ui/src/components/LoadingIcon.tsx create mode 100644 packages/ui/src/components/Overlay.tsx create mode 100644 packages/ui/src/components/Portal.tsx create mode 100644 packages/ui/src/components/ResizeHandle.tsx create mode 100644 packages/ui/src/components/SidebarLayout.tsx create mode 100644 packages/ui/src/components/SplitLayout.tsx create mode 100644 packages/ui/src/components/Stacks.tsx create mode 100644 packages/ui/src/components/Table.tsx create mode 100644 packages/ui/src/components/WindowControls.tsx create mode 100644 packages/ui/src/components/tree/Tree.tsx create mode 100644 packages/ui/src/components/tree/TreeDragOverlay.tsx create mode 100644 packages/ui/src/components/tree/TreeDropMarker.tsx create mode 100644 packages/ui/src/components/tree/TreeIndentGuide.tsx create mode 100644 packages/ui/src/components/tree/TreeItem.tsx create mode 100644 packages/ui/src/components/tree/TreeItemList.tsx create mode 100644 packages/ui/src/components/tree/atoms.ts create mode 100644 packages/ui/src/components/tree/common.ts create mode 100644 packages/ui/src/components/tree/context.ts create mode 100644 packages/ui/src/components/tree/keyboard.test.ts create mode 100644 packages/ui/src/components/tree/keyboard.ts create mode 100644 packages/ui/src/components/tree/useSelectableItems.ts create mode 100644 packages/ui/src/hooks/useContainerSize.ts create mode 100644 packages/ui/src/hooks/useDebouncedState.ts create mode 100644 packages/ui/src/hooks/useDebouncedValue.ts create mode 100644 packages/ui/src/hooks/useIsFullscreen.ts create mode 100644 packages/ui/src/hooks/usePortal.ts create mode 100644 packages/ui/src/hooks/useTimedBoolean.ts create mode 100644 packages/ui/src/index.ts create mode 100644 packages/ui/src/lib/clamp.ts create mode 100644 packages/ui/src/lib/constants.ts create mode 100644 packages/ui/src/lib/dnd.ts create mode 100644 packages/ui/src/lib/minPromiseMillis.ts create mode 100644 packages/ui/tsconfig.json create mode 100644 plugins-external/.gitignore create mode 100644 plugins-external/faker/README.md create mode 100755 plugins-external/faker/package.json create mode 100755 plugins-external/faker/src/index.ts create mode 100644 plugins-external/faker/tests/__snapshots__/init.test.ts.snap create mode 100644 plugins-external/faker/tests/init.test.ts create mode 100755 plugins-external/faker/tsconfig.json create mode 100644 plugins-external/httpsnippet/README.md create mode 100644 plugins-external/httpsnippet/package.json create mode 100644 plugins-external/httpsnippet/src/index.ts create mode 100644 plugins-external/mcp-server/README.md create mode 100644 plugins-external/mcp-server/package.json create mode 100644 plugins-external/mcp-server/src/index.ts create mode 100644 plugins-external/mcp-server/src/server.ts create mode 100644 plugins-external/mcp-server/src/tools/folder.ts create mode 100644 plugins-external/mcp-server/src/tools/helpers.ts create mode 100644 plugins-external/mcp-server/src/tools/httpRequest.test.ts create mode 100644 plugins-external/mcp-server/src/tools/httpRequest.ts create mode 100644 plugins-external/mcp-server/src/tools/schemas.ts create mode 100644 plugins-external/mcp-server/src/tools/toast.ts create mode 100644 plugins-external/mcp-server/src/tools/window.ts create mode 100644 plugins-external/mcp-server/src/tools/workspace.ts create mode 100644 plugins-external/mcp-server/src/types.ts create mode 100644 plugins-external/mcp-server/tsconfig.json create mode 100644 plugins/.gitignore create mode 100644 plugins/action-copy-curl/README.md create mode 100644 plugins/action-copy-curl/package.json create mode 100644 plugins/action-copy-curl/src/index.ts create mode 100644 plugins/action-copy-curl/tests/index.test.ts create mode 100644 plugins/action-copy-curl/tsconfig.json create mode 100644 plugins/action-copy-grpcurl/README.md create mode 100644 plugins/action-copy-grpcurl/package.json create mode 100644 plugins/action-copy-grpcurl/src/index.ts create mode 100644 plugins/action-copy-grpcurl/tests/index.test.ts create mode 100644 plugins/action-copy-grpcurl/tsconfig.json create mode 100644 plugins/action-send-folder/package.json create mode 100644 plugins/action-send-folder/src/index.ts create mode 100644 plugins/action-send-folder/tsconfig.json create mode 100644 plugins/auth-apikey/package.json create mode 100644 plugins/auth-apikey/src/index.ts create mode 100644 plugins/auth-apikey/tsconfig.json create mode 100644 plugins/auth-aws/README.md create mode 100644 plugins/auth-aws/package.json create mode 100644 plugins/auth-aws/src/index.ts create mode 100644 plugins/auth-aws/tsconfig.json create mode 100644 plugins/auth-basic/README.md create mode 100644 plugins/auth-basic/package.json create mode 100644 plugins/auth-basic/src/index.ts create mode 100644 plugins/auth-basic/tests/index.test.ts create mode 100644 plugins/auth-basic/tsconfig.json create mode 100644 plugins/auth-bearer/README.md create mode 100644 plugins/auth-bearer/package.json create mode 100644 plugins/auth-bearer/src/index.ts create mode 100644 plugins/auth-bearer/tests/index.test.ts create mode 100644 plugins/auth-bearer/tsconfig.json create mode 100644 plugins/auth-digest/README.md create mode 100644 plugins/auth-digest/package.json create mode 100644 plugins/auth-digest/src/digest.ts create mode 100644 plugins/auth-digest/src/index.ts create mode 100644 plugins/auth-digest/tests/digest.test.ts create mode 100644 plugins/auth-digest/tests/index.test.ts create mode 100644 plugins/auth-digest/tsconfig.json create mode 100644 plugins/auth-jwt/README.md create mode 100644 plugins/auth-jwt/package.json create mode 100644 plugins/auth-jwt/src/index.ts create mode 100644 plugins/auth-jwt/tsconfig.json create mode 100644 plugins/auth-ntlm/package.json create mode 100644 plugins/auth-ntlm/src/index.ts create mode 100644 plugins/auth-ntlm/src/modules.d.ts create mode 100644 plugins/auth-ntlm/tests/index.test.ts create mode 100644 plugins/auth-ntlm/tsconfig.json create mode 100644 plugins/auth-oauth1/package.json create mode 100644 plugins/auth-oauth1/src/index.ts create mode 100644 plugins/auth-oauth1/tests/plaintext.test.ts create mode 100644 plugins/auth-oauth1/tsconfig.json create mode 100644 plugins/auth-oauth2/README.md create mode 100644 plugins/auth-oauth2/package.json create mode 100644 plugins/auth-oauth2/src/callbackServer.ts create mode 100644 plugins/auth-oauth2/src/customParams.ts create mode 100644 plugins/auth-oauth2/src/fetchAccessToken.ts create mode 100644 plugins/auth-oauth2/src/getOrRefreshAccessToken.ts create mode 100644 plugins/auth-oauth2/src/grants/authorizationCode.ts create mode 100644 plugins/auth-oauth2/src/grants/clientCredentials.ts create mode 100644 plugins/auth-oauth2/src/grants/implicit.ts create mode 100644 plugins/auth-oauth2/src/grants/password.ts create mode 100644 plugins/auth-oauth2/src/index.ts create mode 100644 plugins/auth-oauth2/src/store.ts create mode 100644 plugins/auth-oauth2/src/util.ts create mode 100644 plugins/auth-oauth2/tests/authorizationCode.test.ts create mode 100644 plugins/auth-oauth2/tests/customParams.test.ts create mode 100644 plugins/auth-oauth2/tests/fetchAccessToken.test.ts create mode 100644 plugins/auth-oauth2/tests/getOrRefreshAccessToken.test.ts create mode 100644 plugins/auth-oauth2/tests/store.test.ts create mode 100644 plugins/auth-oauth2/tests/util.test.ts create mode 100644 plugins/auth-oauth2/tsconfig.json create mode 100644 plugins/filter-jsonpath/README.md create mode 100644 plugins/filter-jsonpath/package.json create mode 100644 plugins/filter-jsonpath/src/index.ts create mode 100644 plugins/filter-jsonpath/tests/breadcrumbs.test.ts create mode 100644 plugins/filter-jsonpath/tsconfig.json create mode 100644 plugins/filter-xpath/package.json create mode 100644 plugins/filter-xpath/src/index.ts create mode 100644 plugins/filter-xpath/tsconfig.json create mode 100644 plugins/importer-curl/package.json create mode 100644 plugins/importer-curl/src/graphql.ts create mode 100644 plugins/importer-curl/src/index.ts create mode 100644 plugins/importer-curl/tests/graphql.test.ts create mode 100644 plugins/importer-curl/tests/index.test.ts create mode 100644 plugins/importer-curl/tsconfig.json create mode 100644 plugins/importer-insomnia/package.json create mode 100644 plugins/importer-insomnia/src/common.ts create mode 100644 plugins/importer-insomnia/src/index.ts create mode 100644 plugins/importer-insomnia/src/v4.ts create mode 100644 plugins/importer-insomnia/src/v5.ts create mode 100644 plugins/importer-insomnia/tests/body.test.ts create mode 100644 plugins/importer-insomnia/tests/fixtures/basic.input.json create mode 100644 plugins/importer-insomnia/tests/fixtures/basic.output.json create mode 100644 plugins/importer-insomnia/tests/fixtures/version-5-minimal.input.yaml create mode 100644 plugins/importer-insomnia/tests/fixtures/version-5-minimal.output.json create mode 100644 plugins/importer-insomnia/tests/fixtures/version-5.input.yaml create mode 100644 plugins/importer-insomnia/tests/fixtures/version-5.output.json create mode 100644 plugins/importer-insomnia/tests/index.test.ts create mode 100644 plugins/importer-insomnia/tsconfig.json create mode 100644 plugins/importer-openapi/package.json create mode 100644 plugins/importer-openapi/src/index.ts create mode 100644 plugins/importer-openapi/tests/__snapshots__/index.test.ts.snap create mode 100644 plugins/importer-openapi/tests/fixtures/petstore.yaml create mode 100644 plugins/importer-openapi/tests/fixtures/real-world/SOURCES.md create mode 100644 plugins/importer-openapi/tests/fixtures/real-world/apis-guru.yaml create mode 100644 plugins/importer-openapi/tests/fixtures/real-world/httpbin.yaml create mode 100644 plugins/importer-openapi/tests/fixtures/real-world/nasa-apod.yaml create mode 100644 plugins/importer-openapi/tests/fixtures/real-world/xkcd.yaml create mode 100644 plugins/importer-openapi/tests/index.test.ts create mode 100644 plugins/importer-openapi/tests/roundtrip.mjs create mode 100644 plugins/importer-openapi/tsconfig.json create mode 100644 plugins/importer-postman-environment/package.json create mode 100644 plugins/importer-postman-environment/src/index.ts create mode 100644 plugins/importer-postman-environment/tests/fixtures/environment.input.json create mode 100644 plugins/importer-postman-environment/tests/fixtures/environment.output.json create mode 100644 plugins/importer-postman-environment/tests/index.test.ts create mode 100644 plugins/importer-postman-environment/tsconfig.json create mode 100644 plugins/importer-postman/package.json create mode 100644 plugins/importer-postman/src/index.ts create mode 100644 plugins/importer-postman/tests/fixtures/auth.input.json create mode 100644 plugins/importer-postman/tests/fixtures/auth.output.json create mode 100644 plugins/importer-postman/tests/fixtures/dynamic-variables.input.json create mode 100644 plugins/importer-postman/tests/fixtures/dynamic-variables.output.json create mode 100644 plugins/importer-postman/tests/fixtures/nested.input.json create mode 100644 plugins/importer-postman/tests/fixtures/nested.output.json create mode 100644 plugins/importer-postman/tests/fixtures/params.input.json create mode 100644 plugins/importer-postman/tests/fixtures/params.output.json create mode 100644 plugins/importer-postman/tests/index.test.ts create mode 100644 plugins/importer-postman/tsconfig.json create mode 100644 plugins/importer-yaak/package.json create mode 100644 plugins/importer-yaak/src/index.ts create mode 100644 plugins/importer-yaak/tests/index.test.ts create mode 100644 plugins/importer-yaak/tsconfig.json create mode 100644 plugins/template-function-1password/package.json create mode 100644 plugins/template-function-1password/src/index.ts create mode 100644 plugins/template-function-1password/tsconfig.json create mode 100644 plugins/template-function-cookie/package.json create mode 100644 plugins/template-function-cookie/src/index.ts create mode 100644 plugins/template-function-cookie/tsconfig.json create mode 100644 plugins/template-function-ctx/package.json create mode 100644 plugins/template-function-ctx/src/index.ts create mode 100644 plugins/template-function-ctx/tsconfig.json create mode 100644 plugins/template-function-encode/package.json create mode 100644 plugins/template-function-encode/src/index.ts create mode 100644 plugins/template-function-encode/tsconfig.json create mode 100644 plugins/template-function-fs/package.json create mode 100644 plugins/template-function-fs/src/index.ts create mode 100644 plugins/template-function-fs/tsconfig.json create mode 100755 plugins/template-function-hash/package.json create mode 100755 plugins/template-function-hash/src/index.ts create mode 100644 plugins/template-function-hash/tsconfig.json create mode 100755 plugins/template-function-json/package.json create mode 100755 plugins/template-function-json/src/index.ts create mode 100644 plugins/template-function-json/tests/escape.test.ts create mode 100644 plugins/template-function-json/tsconfig.json create mode 100644 plugins/template-function-prompt/package.json create mode 100644 plugins/template-function-prompt/src/index.ts create mode 100644 plugins/template-function-prompt/tsconfig.json create mode 100644 plugins/template-function-random/package.json create mode 100644 plugins/template-function-random/src/index.ts create mode 100644 plugins/template-function-random/tsconfig.json create mode 100644 plugins/template-function-regex/package.json create mode 100644 plugins/template-function-regex/src/index.ts create mode 100644 plugins/template-function-regex/tests/regex.test.ts create mode 100644 plugins/template-function-regex/tsconfig.json create mode 100755 plugins/template-function-request/package.json create mode 100755 plugins/template-function-request/src/index.ts create mode 100644 plugins/template-function-request/tsconfig.json create mode 100644 plugins/template-function-response/package.json create mode 100644 plugins/template-function-response/src/index.ts create mode 100644 plugins/template-function-response/tsconfig.json create mode 100755 plugins/template-function-timestamp/package.json create mode 100755 plugins/template-function-timestamp/src/index.ts create mode 100644 plugins/template-function-timestamp/tests/formatDatetime.test.ts create mode 100644 plugins/template-function-timestamp/tsconfig.json create mode 100644 plugins/template-function-uuid/package.json create mode 100644 plugins/template-function-uuid/src/index.ts create mode 100644 plugins/template-function-uuid/tests/uuid.test.ts create mode 100644 plugins/template-function-uuid/tsconfig.json create mode 100644 plugins/template-function-xml/package.json create mode 100755 plugins/template-function-xml/src/index.ts create mode 100644 plugins/template-function-xml/tsconfig.json create mode 100644 plugins/themes-yaak/package.json create mode 100644 plugins/themes-yaak/src/index.ts create mode 100644 plugins/themes-yaak/src/themes/andromeda.ts create mode 100644 plugins/themes-yaak/src/themes/atom-one-dark.ts create mode 100644 plugins/themes-yaak/src/themes/ayu.ts create mode 100644 plugins/themes-yaak/src/themes/bluloco.ts create mode 100644 plugins/themes-yaak/src/themes/catppuccin.ts create mode 100644 plugins/themes-yaak/src/themes/cobalt2.ts create mode 100644 plugins/themes-yaak/src/themes/dracula.ts create mode 100644 plugins/themes-yaak/src/themes/everforest.ts create mode 100644 plugins/themes-yaak/src/themes/fleet.ts create mode 100644 plugins/themes-yaak/src/themes/github-dimmed.ts create mode 100644 plugins/themes-yaak/src/themes/github.ts create mode 100644 plugins/themes-yaak/src/themes/gruvbox.ts create mode 100644 plugins/themes-yaak/src/themes/high-contrast.ts create mode 100644 plugins/themes-yaak/src/themes/horizon.ts create mode 100644 plugins/themes-yaak/src/themes/hotdog-stand.ts create mode 100644 plugins/themes-yaak/src/themes/material-darker.ts create mode 100644 plugins/themes-yaak/src/themes/material-ocean.ts create mode 100644 plugins/themes-yaak/src/themes/material-palenight.ts create mode 100644 plugins/themes-yaak/src/themes/monokai-pro.ts create mode 100644 plugins/themes-yaak/src/themes/moonlight.ts create mode 100644 plugins/themes-yaak/src/themes/night-owl.ts create mode 100644 plugins/themes-yaak/src/themes/noctis.ts create mode 100644 plugins/themes-yaak/src/themes/nord.ts create mode 100644 plugins/themes-yaak/src/themes/one-dark-pro.ts create mode 100644 plugins/themes-yaak/src/themes/panda.ts create mode 100644 plugins/themes-yaak/src/themes/relaxing.ts create mode 100644 plugins/themes-yaak/src/themes/rose-pine.ts create mode 100644 plugins/themes-yaak/src/themes/shades-of-purple.ts create mode 100644 plugins/themes-yaak/src/themes/slack.ts create mode 100644 plugins/themes-yaak/src/themes/solarized.ts create mode 100644 plugins/themes-yaak/src/themes/synthwave-84.ts create mode 100644 plugins/themes-yaak/src/themes/tokyo-night.ts create mode 100644 plugins/themes-yaak/src/themes/triangle.ts create mode 100644 plugins/themes-yaak/src/themes/vitesse.ts create mode 100644 plugins/themes-yaak/src/themes/winter-is-coming.ts create mode 100644 plugins/themes-yaak/tsconfig.json create mode 100644 rustfmt.toml create mode 100644 scripts/.gitignore create mode 100644 scripts/create-migration.cjs create mode 100644 scripts/extract-archive.cjs create mode 100644 scripts/git-hooks/post-checkout.mjs create mode 100644 scripts/install-wasm-pack.cjs create mode 100644 scripts/publish-core-plugins.cjs create mode 100644 scripts/replace-version.cjs create mode 100644 scripts/run-build.mjs create mode 100644 scripts/run-dev.mjs create mode 100644 scripts/run-web.mjs create mode 100644 scripts/run-workspaces-dev.mjs create mode 100644 scripts/vendor-node.cjs create mode 100644 scripts/vendor-plugins.cjs create mode 100644 scripts/vendor-protoc.cjs create mode 100644 tsconfig.json create mode 100644 vite.config.ts diff --git a/.claude-context.md b/.claude-context.md new file mode 100644 index 0000000..97e20f6 --- /dev/null +++ b/.claude-context.md @@ -0,0 +1,83 @@ +# 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-client, 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-client/` +- 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-client/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-client/src/lib.rs` - Main Tauri app, setup block initializes managers +- `crates-tauri/yaak-app-client/src/commands.rs` - Migrated Tauri commands +- `crates-tauri/yaak-app-client/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 ` to verify a crate builds without Tauri +- Run `npm run client:dev` to test the Tauri app still works +- Run `cargo run -p yaak-cli -- --help` to test the CLI diff --git a/.claude/rules.md b/.claude/rules.md new file mode 100644 index 0000000..aa0fb39 --- /dev/null +++ b/.claude/rules.md @@ -0,0 +1,27 @@ +# 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 diff --git a/.codex/skills/release-generate-release-notes/SKILL.md b/.codex/skills/release-generate-release-notes/SKILL.md new file mode 100644 index 0000000..f5df99c --- /dev/null +++ b/.codex/skills/release-generate-release-notes/SKILL.md @@ -0,0 +1,52 @@ +--- +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 ..` +4. For linked PRs, fetch metadata: + - `gh pr view --json number,title,body,author,url` +5. Extract useful details: + - Feedback URLs (`feedback.yaak.app`) + - Contributor GitHub handles from `author.login` + - Plugin install links or other notable context +6. Format notes using Yaak style: + - Changelog badge at top + - Bulleted items with PR links where available + - Contributor handles for external PRs + - 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. +- Append contributor attribution to PR-backed bullets for non-`@gschier` authors, using `by [@handle](https://github.com/handle)`. +- 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 --draft --prerelease --title "Release " --notes ''` + +If a draft release for the tag already exists, update it instead: + +`gh release edit --title "Release " --notes-file ` + +Use title format `Release `, e.g. `v2026.2.1-beta.1` -> `Release 2026.2.1-beta.1`. diff --git a/.codex/skills/yaak-changelog/SKILL.md b/.codex/skills/yaak-changelog/SKILL.md new file mode 100644 index 0000000..48cd860 --- /dev/null +++ b/.codex/skills/yaak-changelog/SKILL.md @@ -0,0 +1,104 @@ +--- +name: yaak-changelog +description: Create or edit Yaak changelogs. Beta and draft prerelease changelogs live only in the GitHub release body; stable release changelogs live in `src/content/changelog/YYYYMMDD_VERSION/`. Use when Codex needs to update a beta GitHub release body, generate a stable website changelog from beta releases, update `_release.yaml` or `_intro.md`, expand major entries into markdown files, or preserve Yaak's changelog writing style. +--- + +# Yaak Changelog + +Use this skill to create Yaak changelogs in the correct place: + +- Beta or draft prerelease changelogs live only on the GitHub release. +- Stable release changelogs live in website files under `src/content/changelog/YYYYMMDD_VERSION/`. + +## Workflow + +1. Identify the target release. +- If the target tag contains `-beta` or the GitHub release is a draft prerelease, update the GitHub release body only. Do not create or edit `src/content/changelog/` files for beta releases. +- For a new stable changelog, gather all beta release notes for that version since the previous stable release, then create or edit website changelog files. +- Prefer `gh api` or GitHub release pages. If network access is restricted, request permission before querying GitHub. +- Extract PR numbers and `yaak.app/feedback` URLs while fetching. If most bullets do not include PR references, fetch again with a more specific prompt. +- Fetch PR authors when generating or revising release notes. Include contributor attribution for non-`@gschier` PR authors. + +2. Parse release bullets. +- Treat each release-note bullet as one changelog entry. +- Skip dependency-only, generated, build-only, test-only, CI-only, and internal maintenance bullets unless they have a clear user-facing impact that can be described in user terms. +- For stable website changelogs, skip bullets prefixed with `[beta-only]`. +- Preserve the entry wording closely. Remove wrapping quotes from titles. +- Map categories to `feature`, `fix`, `improvement`, or `breaking`. +- Convert `#NNN` into `https://github.com/mountain-loop/yaak/pull/NNN`. + +3. For beta or draft prerelease changelogs, update the GitHub release. +- Keep the changelog in the GitHub release body. Do not create a website changelog directory. +- Do not add a changelog badge or link to `yaak.app/changelog/VERSION` for beta releases. +- Prefer concise bullets with PR links and feedback links when available. +- When a bullet has a feedback URL, wrap the changelog item text itself in the feedback link, then put the PR link after it. Example: `- [Fixed request history timestamps](https://yaak.app/feedback/posts/request-history-time-stamp) in [#492](https://github.com/mountain-loop/yaak/pull/492)`. +- Append `by [@handle](https://github.com/handle)` to PR-backed bullets authored by external contributors. Do not append `by @gschier` for `@gschier` PRs. +- Include a `**Full Changelog**` comparison link using the previous beta tag when it exists, or the previous stable tag for `beta.1`. +- Use `gh release edit TAG --repo mountain-loop/yaak --notes-file ...` or the GitHub release API to update the draft/prerelease body. +- Stop after verifying the GitHub release body. The website checks below do not apply. + +4. For stable website changelogs, create or edit the release directory. +- Path format: `src/content/changelog/YYYYMMDD_VERSION/`. +- For a new release, use today's date for `YYYYMMDD`. +- For an existing release, keep the original directory date. +- Do not create changelog directories for beta releases. + +5. Write `_release.yaml`. +- Include `draft`, optional `title`, `summary`, `image`, `youtube`, and `entries`. +- Keep minor items as quick entries without `content`. +- Use `content` only when an entry needs its own markdown section. + +```yaml +title: "What's New in 2026.1.0" +summary: "Brief overview of the most important additions and fixes" +draft: true +entries: + - title: "Request debugging" + category: feature + pr: "https://github.com/mountain-loop/yaak/pull/123" + feedback: "https://feedback.yaak.app/p/request-debugging" + content: "request-debugging.md" + - title: "Fix broken cookie clearing" + category: fix + pr: "https://github.com/mountain-loop/yaak/pull/124" +``` + +6. Expand major entries. +- Expand 3 to 6 major items when enough context exists. +- Create slugified markdown files and reference them with `content`. +- Read the related PR before writing expanded content. +- Add emoji prefixes only for expanded entry titles if it helps distinguish major sections. + +7. Handle images. +- Reuse screenshots from PRs when they exist. +- Convert GitHub private attachment URLs to `https://github.com/user-attachments/assets/UUID` before upload. +- Upload with `go run cmd/yaakadmin/main.go upload "URL"` when the environment permits it. +- If no real image is available, use a placeholder with real alt text and a caption. + +8. Write `_intro.md`. +- Add a short overview paragraph at the top of the release. +- Focus on the major themes across the release instead of repeating every bullet. + +9. Follow Yaak writing style. +- Be direct and factual. Avoid hype. +- State what changed and how to use it. +- Keep paragraphs short. +- Use backticks for code symbols, settings, and literal values. +- Use bold sparingly for the most important phrase in a section. + +## File Rules + +- Beta releases must not create or edit files in `src/content/changelog/`. +- Main files are `_release.yaml` and optional `_intro.md`. +- Expanded entry files are regular markdown files such as `request-debugging.md`. +- `entries[].content` must match an existing markdown filename in the same directory. +- Images for changelog pages live under `static/changelog/VERSION/` when committed to the repo. + +## Checks + +- For beta releases, verify `gh release view TAG --repo mountain-loop/yaak --json body,tagName,isDraft,isPrerelease` and ensure no website changelog files were created. +- For beta releases, verify feedback-backed bullets use the feedback URL as the link target for the whole item text, not as a separate trailing `Feedback:` link. +- For stable releases, ensure each user-facing source bullet becomes exactly one changelog entry unless it is `[beta-only]` or dependency-only/internal maintenance. +- Ensure most entries include `pr` when the source release notes provide one. +- For stable releases, ensure every referenced `content` file exists. +- If the user wants stable website verification, run the site and inspect `/changelog/VERSION` and `/rss.xml`. diff --git a/.codex/skills/yaak-changelog/agents/openai.yaml b/.codex/skills/yaak-changelog/agents/openai.yaml new file mode 100644 index 0000000..d4d46b3 --- /dev/null +++ b/.codex/skills/yaak-changelog/agents/openai.yaml @@ -0,0 +1,7 @@ +interface: + display_name: "Yaak Changelog" + short_description: "Generate Yaak changelog releases" + default_prompt: "Use $yaak-changelog to create or update a Yaak changelog release from GitHub release notes." + +policy: + allow_implicit_invocation: true diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..50e4b2f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +node_modules +**/node_modules +dist +**/dist +target +**/target +.claude +vendored +**/vendored +*.log +.git diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..67ab542 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +crates-tauri/yaak-app-client/vendored/**/* linguist-generated=true +crates-tauri/yaak-app-client/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 diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..c1cde08 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1,3 @@ +# These are supported funding model platforms + +github: gschier diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..9b77ea7 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,40 @@ +--- +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. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..c9e2ff5 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +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." diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..0a86c6a --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,55 @@ +version: 2 + +updates: + - package-ecosystem: npm + directory: / + schedule: + interval: weekly + day: monday + open-pull-requests-limit: 5 + ignore: + # Build tooling majors are opted into, not queued. These never reach a + # user, so the cost of being a release behind is low and the cost of a + # surprise is a broken build. Note this also suppresses security PRs for + # these, so Dependabot alerts are the backstop. + - dependency-name: typescript + update-types: ["version-update:semver-major"] + - dependency-name: vitest + update-types: ["version-update:semver-major"] + - dependency-name: "@types/*" + update-types: ["version-update:semver-major"] + - dependency-name: "vite-plugin-*" + update-types: ["version-update:semver-major"] + # 0.8 dropped stateExtensions and updateSchema from the package root and + # exposes no subpath to reach them, which GrpcEditor needs. Unpin once + # that editor moves to the jsonSchema helper. + - dependency-name: codemirror-json-schema + groups: + npm-production: + dependency-type: production + update-types: + - minor + - patch + npm-development: + dependency-type: development + update-types: + - minor + - patch + + - package-ecosystem: cargo + directory: / + schedule: + interval: weekly + day: monday + open-pull-requests-limit: 5 + ignore: + # Held at 11.10.0 to pin what rolldown_resolver ("^11") resolves to; it + # does not build against 11.11. See crates-cli/yaak-cli/Cargo.toml. + - dependency-name: oxc_resolver + groups: + cargo: + patterns: + - "*" + update-types: + - minor + - patch diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000..49d7b7e --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,22 @@ +## Summary + + + +## Submission + + + +- [ ] This PR is a bug fix. +- [ ] If this PR is not a bug fix, I linked the feedback item where @gschier explicitly gave me permission to work on it. +- [ ] I have read and followed [`CONTRIBUTING.md`](CONTRIBUTING.md). +- [ ] I tested this change locally. +- [ ] I added or updated tests, or tests are not reasonable for this change. +- [ ] I added screenshots or recordings, or this change does not affect the UI. + +Explicit permission feedback item (required if not a bug fix): + + + +## Related + + diff --git a/.github/scripts/check-contribution-policy.js b/.github/scripts/check-contribution-policy.js new file mode 100644 index 0000000..2c7dc57 --- /dev/null +++ b/.github/scripts/check-contribution-policy.js @@ -0,0 +1,881 @@ +const fs = require("node:fs"); + +const COMMENT_MARKER = ""; + +const MAINTAINER_LOGINS = new Set(["gschier"]); +const MAINTAINER_ASSOCIATIONS = new Set(["OWNER", "MEMBER", "COLLABORATOR"]); +const MAINTAINER_PERMISSIONS = new Set(["admin", "maintain", "write"]); +const REVIEWER_LOGIN = "gschier"; + +const LARGE_DIFF_CHANGED_FILES = 20; +const LARGE_DIFF_CHANGED_LINES = 800; +const SUMMARY_TITLE_MAX_LENGTH = 80; +const MIN_AUTOMATIC_PR_NUMBER = 494; + +const LABELS = { + inScope: { + name: "contribution: in scope", + color: "0E8A16", + description: "Community PR appears to be in scope for maintainer review.", + }, + outOfScope: { + name: "contribution: out of scope", + color: "B60205", + description: "Community PR does not match Yaak's contribution policy.", + }, + explicitPermission: { + name: "contribution: explicit permission", + color: "5319E7", + description: + "Community PR links feedback where @gschier explicitly allowed the work.", + }, + missingTemplate: { + name: "contribution: missing template", + color: "D93F0B", + description: + "Community PR is missing enough of the pull request template to review.", + }, + policyUnmet: { + name: "contribution: policy unmet", + color: "B60205", + description: + "Community PR does not currently satisfy the contribution policy.", + }, + needsScopeReview: { + name: "contribution: needs scope review", + color: "FBCA04", + description: + "Community PR may be broader than Yaak's bug-fix contribution policy.", + }, +}; + +const MANAGED_LABEL_NAMES = [ + ...new Set(Object.values(LABELS).map((label) => label.name)), +]; + +// Each checkbox lists its current label first, followed by legacy labels still +// accepted from PRs opened against older versions of the template. +const CHECKBOXES = { + bugFix: ["This PR is a bug fix."], + explicitPermission: [ + "If this PR is not a bug fix, I linked the feedback item where @gschier explicitly gave me permission to work on it.", + ], + readContributing: [ + "I have read and followed [`CONTRIBUTING.md`](CONTRIBUTING.md).", + ], + testedLocally: ["I tested this change locally."], + testsUpdated: [ + "I added or updated tests, or tests are not reasonable for this change.", + "I added or updated tests when reasonable.", + ], + screenshotsAdded: [ + "I added screenshots or recordings, or this change does not affect the UI.", + "I added screenshots or recordings for UI changes when reasonable.", + ], +}; + +function escapeRegExp(value) { + return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); +} + +function normalizeBody(body) { + return (body || "").replace(/\r\n/g, "\n"); +} + +function stripComments(value) { + return value.replace(//g, "").trim(); +} + +function getSection(body, heading) { + const pattern = new RegExp(`^##\\s+${escapeRegExp(heading)}\\s*$`, "gim"); + const match = pattern.exec(body); + + if (match == null) { + return null; + } + + const rest = body.slice(match.index + match[0].length); + const nextHeadingIndex = rest.search(/^##\s+/m); + return nextHeadingIndex === -1 ? rest : rest.slice(0, nextHeadingIndex); +} + +function hasMeaningfulText(value) { + return stripComments(value || "").length > 0; +} + +function normalizeCheckboxLabel(label) { + return label + .replace(/\[([^\]]+)\]\([^)]+\)/g, "$1") + .replace(/`/g, "") + .replace(/\s+/g, " ") + .trim(); +} + +function checkboxState(body, labels) { + const expectedLabels = new Set(labels.map(normalizeCheckboxLabel)); + + for (const line of body.split("\n")) { + const match = line.match(/^\s*[-*]\s*\[([ xX])\]\s*(.*?)\s*$/i); + + if (match == null) { + continue; + } + + if (expectedLabels.has(normalizeCheckboxLabel(match[2]))) { + return match[1].toLowerCase() === "x"; + } + } + + return null; +} + +function findFeedbackUrl(body) { + return ( + body.match( + /https?:\/\/(?:www\.)?(?:yaak\.app\/feedback|feedback\.yaak\.app)\/[^\s)>\]]+/i, + )?.[0] ?? null + ); +} + +function getLabelNames(pr) { + return new Set((pr.labels || []).map((label) => label.name)); +} + +function analyzePullRequest(pr) { + const body = normalizeBody(pr.body); + const labelNames = getLabelNames(pr); + const states = Object.fromEntries( + Object.entries(CHECKBOXES).map(([key, label]) => [ + key, + checkboxState(body, label), + ]), + ); + const sectionCount = ["Summary", "Submission", "Related"].filter( + (heading) => getSection(body, heading) != null, + ).length; + const checkboxCount = Object.values(states).filter( + (state) => state != null, + ).length; + const templateUsed = sectionCount >= 2 && checkboxCount >= 3; + const blockers = []; + const totalChangedLines = + Number(pr.additions || 0) + Number(pr.deletions || 0); + const changedFiles = Number(pr.changed_files || 0); + const largeDiff = + changedFiles > LARGE_DIFF_CHANGED_FILES || + totalChangedLines > LARGE_DIFF_CHANGED_LINES; + + if (labelNames.has(LABELS.outOfScope.name)) { + return { + blockers: [ + { + label: LABELS.outOfScope.name, + message: "Marked out of scope by maintainer label.", + }, + ], + changedFiles, + desiredLabels: [LABELS.outOfScope.name], + largeDiff, + status: "out_of_scope", + templateUsed, + totalChangedLines, + }; + } + + if (labelNames.has(LABELS.inScope.name)) { + return { + blockers: [], + changedFiles, + desiredLabels: [LABELS.inScope.name], + largeDiff, + status: "in_scope", + templateUsed, + totalChangedLines, + }; + } + + if (labelNames.has(LABELS.explicitPermission.name)) { + return { + blockers: [], + changedFiles, + desiredLabels: [LABELS.explicitPermission.name], + largeDiff, + status: "in_scope", + templateUsed, + totalChangedLines, + }; + } + + if (!templateUsed) { + blockers.push({ + label: LABELS.missingTemplate.name, + message: + "Update the PR description with the repository pull request template.", + }); + } else { + const summary = getSection(body, "Summary"); + const hasSummary = hasMeaningfulText(summary); + const feedbackUrl = findFeedbackUrl(body); + const bugFix = states.bugFix === true; + const explicitPermission = states.explicitPermission === true; + + if (!hasSummary) { + blockers.push({ + label: LABELS.policyUnmet.name, + message: + "Add a short summary describing the bug fix or permitted change.", + }); + } + + if (bugFix && explicitPermission) { + blockers.push({ + label: LABELS.policyUnmet.name, + message: + "Choose either the bug-fix checkbox or the explicit-permission checkbox, not both.", + }); + } else if (!bugFix && !explicitPermission) { + blockers.push({ + label: LABELS.policyUnmet.name, + message: + "Check whether this is a bug fix, or confirm that explicit permission from @gschier is linked.", + }); + } else if (explicitPermission && feedbackUrl == null) { + blockers.push({ + label: LABELS.policyUnmet.name, + message: + "Link the feedback item where @gschier explicitly gave you permission to work on this.", + }); + } + + if (states.readContributing !== true) { + blockers.push({ + label: LABELS.policyUnmet.name, + message: "Confirm that `CONTRIBUTING.md` was read and followed.", + }); + } + + if (states.testedLocally !== true) { + blockers.push({ + label: LABELS.policyUnmet.name, + message: "Confirm that the change was tested locally.", + }); + } + + if (states.testsUpdated !== true) { + blockers.push({ + label: LABELS.policyUnmet.name, + message: + "Confirm that tests were added or updated, or that tests are not reasonable for this change. Check the box either way.", + }); + } + + if (states.screenshotsAdded !== true) { + blockers.push({ + label: LABELS.policyUnmet.name, + message: + "Confirm that screenshots or recordings were added, or that this change does not affect the UI. Check the box either way.", + }); + } + } + + const desiredLabels = new Set(); + + if (blockers.length === 0) { + desiredLabels.add( + largeDiff + ? LABELS.needsScopeReview.name + : states.explicitPermission + ? LABELS.explicitPermission.name + : LABELS.inScope.name, + ); + } else if ( + blockers.some((blocker) => blocker.label === LABELS.missingTemplate.name) + ) { + desiredLabels.add(LABELS.missingTemplate.name); + } else { + desiredLabels.add(LABELS.policyUnmet.name); + } + + return { + blockers, + changedFiles, + desiredLabels: [...desiredLabels], + largeDiff, + status: blockers.length === 0 ? "in_scope" : "blocked", + templateUsed, + totalChangedLines, + }; +} + +function buildBlockingComment(analysis) { + const lines = [ + COMMENT_MARKER, + "Thanks for the PR. Yaak currently accepts community PRs for bug fixes, plus larger changes that link a feedback item where @gschier explicitly gave permission to work on it.", + "", + "This PR cannot be accepted yet because the following contribution policy requirements were unmet:", + "", + ...analysis.blockers.map((blocker) => `- ${blocker.message}`), + ]; + + if (!analysis.templateUsed) { + lines.push( + "", + "You can copy this template into the PR description and keep any existing context that is still useful.", + "", + "
", + "PR description template", + "", + "```md", + getPullRequestTemplate(), + "```", + "", + "
", + ); + } + + if (analysis.largeDiff) { + lines.push( + "", + `This PR also changes ${analysis.changedFiles} files and ${analysis.totalChangedLines} lines, so it has been labeled as needing scope review. That label is advisory, but maintainers may ask for the scope to be reduced.`, + ); + } + + return lines.join("\n"); +} + +function getPullRequestTemplate() { + return fs.readFileSync(".github/pull_request_template.md", "utf8").trim(); +} + +function buildInScopeComment() { + return [ + COMMENT_MARKER, + "Thanks for the PR. This appears to match Yaak's contribution policy and is awaiting review by @gschier.", + "", + "This only means the PR is in scope for review. It does not mean the change has been reviewed or accepted for merge.", + ].join("\n"); +} + +function buildOutOfScopeComment() { + return [ + COMMENT_MARKER, + "Thanks for the PR. This does not appear to match Yaak's current contribution policy.", + "", + "Yaak currently accepts community PRs for bug fixes, or changes tied to a feedback item where @gschier explicitly gave permission to work on it.", + "", + "If this PR is tied to a feedback item where @gschier explicitly gave permission, please link it in the PR description.", + ].join("\n"); +} + +function buildPolicyComment(analysis) { + if (analysis.status === "out_of_scope") { + return buildOutOfScopeComment(); + } + + if (analysis.blockers.length > 0) { + return buildBlockingComment(analysis); + } + + return buildInScopeComment(); +} + +function escapeHtml(value) { + return String(value) + .replace(/&/g, "&") + .replace(//g, ">") + .replace(/"/g, """) + .replace(/'/g, "'"); +} + +function truncateTitle(title) { + if (title.length <= SUMMARY_TITLE_MAX_LENGTH) { + return title; + } + + return `${title.slice(0, SUMMARY_TITLE_MAX_LENGTH - 3).trimEnd()}...`; +} + +function escapeTableText(value) { + return escapeHtml(value).replace(/\n/g, "
"); +} + +function summarizeResult({ pr, analysis, skipped, skipReason }) { + const comment = + analysis == null + ? "None" + : buildPolicyComment(analysis).replace(COMMENT_MARKER, "").trim(); + const summary = { + blocked: analysis?.blockers.length > 0, + comment, + details: "None", + labels: + analysis?.desiredLabels.length > 0 + ? analysis.desiredLabels.join(", ") + : "None", + number: pr.number, + prLink: `#${pr.number}`, + status: "In scope", + title: escapeHtml(truncateTitle(pr.title)), + }; + + if (skipped) { + return { + ...summary, + blocked: false, + comment: "None", + details: escapeHtml(skipReason), + labels: "None", + status: "Skipped", + }; + } + + if (summary.blocked) { + return { + ...summary, + comment: escapeTableText(summary.comment), + details: escapeHtml( + analysis.blockers.map((blocker) => blocker.message).join("; "), + ), + labels: escapeHtml(summary.labels), + status: analysis.status === "out_of_scope" ? "Out of scope" : "Blocked", + }; + } + + return { + ...summary, + comment: escapeTableText(summary.comment), + labels: escapeHtml(summary.labels), + }; +} + +async function isOfficialMaintainer({ github, owner, repo, pr }) { + if (MAINTAINER_LOGINS.has(pr.user.login)) { + return true; + } + + if (MAINTAINER_ASSOCIATIONS.has(pr.author_association)) { + return true; + } + + try { + const response = await github.rest.repos.getCollaboratorPermissionLevel({ + owner, + repo, + username: pr.user.login, + }); + + return MAINTAINER_PERMISSIONS.has(response.data.permission); + } catch (error) { + if (error.status === 404) { + return false; + } + + throw error; + } +} + +async function ensureManagedLabels({ github, owner, repo }) { + for (const label of Object.values(LABELS)) { + try { + await github.rest.issues.getLabel({ + owner, + repo, + name: label.name, + }); + } catch (error) { + if (error.status !== 404) { + throw error; + } + + await github.rest.issues.createLabel({ + owner, + repo, + name: label.name, + color: label.color, + description: label.description, + }); + } + } +} + +async function syncLabels({ github, owner, repo, issueNumber, desiredLabels }) { + const desired = new Set(desiredLabels); + + await ensureManagedLabels({ github, owner, repo }); + + for (const labelName of MANAGED_LABEL_NAMES) { + if (desired.has(labelName)) { + continue; + } + + try { + await github.rest.issues.removeLabel({ + owner, + repo, + issue_number: issueNumber, + name: labelName, + }); + } catch (error) { + if (error.status !== 404) { + throw error; + } + } + } + + if (desired.size > 0) { + await github.rest.issues.addLabels({ + owner, + repo, + issue_number: issueNumber, + labels: [...desired], + }); + } +} + +async function findPolicyComment({ github, owner, repo, issueNumber }) { + const comments = await github.paginate(github.rest.issues.listComments, { + owner, + repo, + issue_number: issueNumber, + per_page: 100, + }); + + return comments.find( + (comment) => + comment.user.type === "Bot" && comment.body?.includes(COMMENT_MARKER), + ); +} + +async function upsertPolicyComment({ github, owner, repo, issueNumber, body }) { + const existingComment = await findPolicyComment({ + github, + owner, + repo, + issueNumber, + }); + + if (existingComment == null) { + await github.rest.issues.createComment({ + owner, + repo, + issue_number: issueNumber, + body, + }); + return; + } + + await github.rest.issues.updateComment({ + owner, + repo, + comment_id: existingComment.id, + body, + }); +} + +async function deletePolicyComment({ github, owner, repo, issueNumber }) { + const existingComment = await findPolicyComment({ + github, + owner, + repo, + issueNumber, + }); + + if (existingComment == null) { + return; + } + + await github.rest.issues.deleteComment({ + owner, + repo, + comment_id: existingComment.id, + }); +} + +async function requestMaintainerReview({ github, owner, repo, pr }) { + if (pr.user.login === REVIEWER_LOGIN) { + return; + } + + try { + await github.rest.pulls.requestReviewers({ + owner, + repo, + pull_number: pr.number, + reviewers: [REVIEWER_LOGIN], + }); + } catch (error) { + if (error.status === 422) { + return; + } + + throw error; + } +} + +async function checkPullRequest({ + github, + core, + owner, + repo, + pullNumber, + dryRun, + minimumAutomaticPullNumber, +}) { + const response = await github.rest.pulls.get({ + owner, + repo, + pull_number: pullNumber, + }); + const pr = response.data; + const issueNumber = pr.number; + + if (pr.user.type === "Bot") { + core.notice( + `Skipping contribution policy for bot PR #${pr.number} from @${pr.user.login}.`, + ); + return { + blocked: false, + number: pr.number, + summary: summarizeResult({ + pr, + skipped: true, + skipReason: `bot @${pr.user.login}`, + }), + skipped: true, + }; + } + + if ( + minimumAutomaticPullNumber != null && + pr.number < minimumAutomaticPullNumber + ) { + core.notice( + `Skipping contribution policy for PR #${pr.number} because automatic checks start at PR #${minimumAutomaticPullNumber}.`, + ); + return { + blocked: false, + number: pr.number, + summary: summarizeResult({ + pr, + skipped: true, + skipReason: `before automatic rollout PR #${minimumAutomaticPullNumber}`, + }), + skipped: true, + }; + } + + if (pr.draft) { + core.notice(`Skipping contribution policy for draft PR #${pr.number}.`); + return { + blocked: false, + number: pr.number, + summary: summarizeResult({ + pr, + skipped: true, + skipReason: "draft", + }), + skipped: true, + }; + } + + if (await isOfficialMaintainer({ github, owner, repo, pr })) { + core.notice( + `Skipping contribution policy for maintainer PR #${pr.number} from @${pr.user.login}.`, + ); + if (!dryRun) { + await syncLabels({ github, owner, repo, issueNumber, desiredLabels: [] }); + await deletePolicyComment({ github, owner, repo, issueNumber }); + } + return { + blocked: false, + number: pr.number, + summary: summarizeResult({ + pr, + skipped: true, + skipReason: `maintainer @${pr.user.login}`, + }), + skipped: true, + }; + } + + const analysis = analyzePullRequest(pr); + + if (dryRun) { + const summary = summarizeResult({ pr, analysis }); + core.notice( + `[dry-run] PR #${summary.number}: ${summary.status}; labels: ${summary.labels}; details: ${summary.details}`, + ); + return { + blocked: analysis.blockers.length > 0, + number: pr.number, + summary, + skipped: false, + }; + } + + await syncLabels({ + github, + owner, + repo, + issueNumber, + desiredLabels: analysis.desiredLabels, + }); + + if (analysis.blockers.length > 0) { + await upsertPolicyComment({ + github, + owner, + repo, + issueNumber, + body: buildPolicyComment(analysis), + }); + return { + blocked: true, + number: pr.number, + summary: summarizeResult({ pr, analysis }), + skipped: false, + }; + } + + await upsertPolicyComment({ + github, + owner, + repo, + issueNumber, + body: buildPolicyComment(analysis), + }); + await requestMaintainerReview({ github, owner, repo, pr }); + core.notice(`Contribution policy check passed for PR #${pr.number}.`); + return { + blocked: false, + number: pr.number, + summary: summarizeResult({ pr, analysis }), + skipped: false, + }; +} + +async function listOpenPullRequests({ github, owner, repo }) { + return github.paginate(github.rest.pulls.list, { + owner, + repo, + state: "open", + per_page: 100, + }); +} + +function getManualPullRequestNumbers({ context, core }) { + const value = String(context.payload.inputs?.pr || "all").trim(); + + if (value.toLowerCase() === "all") { + return null; + } + + const pullNumber = Number(value); + + if (!Number.isInteger(pullNumber) || pullNumber <= 0) { + core.setFailed('The "pr" input must be "all" or a positive PR number.'); + return []; + } + + return [pullNumber]; +} + +async function run({ github, context, core }) { + const { owner, repo } = context.repo; + const payloadPr = context.payload.pull_request; + const dryRunInput = context.payload.inputs?.dry_run; + const dryRun = + context.eventName === "workflow_dispatch" && + dryRunInput !== false && + dryRunInput !== "false"; + const minimumAutomaticPullNumber = + payloadPr == null ? null : MIN_AUTOMATIC_PR_NUMBER; + let pullNumbers; + + if (payloadPr != null) { + pullNumbers = [payloadPr.number]; + } else { + pullNumbers = getManualPullRequestNumbers({ context, core }); + } + + if (pullNumbers?.length === 0) { + return; + } + + const pullRequests = + pullNumbers == null + ? await listOpenPullRequests({ github, owner, repo }) + : pullNumbers.map((number) => ({ number })); + const results = []; + + if (dryRun) { + core.notice( + `Running contribution policy in dry-run mode for ${ + pullNumbers == null + ? "all open PRs" + : pullNumbers.map((number) => `#${number}`).join(", ") + }.`, + ); + } + + for (const pr of pullRequests) { + results.push( + await checkPullRequest({ + github, + core, + owner, + repo, + pullNumber: pr.number, + dryRun, + minimumAutomaticPullNumber, + }), + ); + } + + await core.summary + .addHeading(`Contribution Policy ${dryRun ? "Dry Run" : "Results"}`) + .addTable([ + [ + { data: "PR", header: true }, + { data: "Title", header: true }, + { data: "Status", header: true }, + { data: "Labels", header: true }, + { data: "Details", header: true }, + { data: "Comment", header: true }, + ], + ...results.map((result) => [ + result.summary.prLink, + result.summary.title, + result.summary.status, + result.summary.labels, + result.summary.details, + result.summary.comment, + ]), + ]) + .write(); + + const blockedPullRequests = results.filter((result) => result.blocked); + + if (blockedPullRequests.length > 0) { + if (dryRun) { + core.warning( + `Dry run found contribution policy failures for PR(s): ${blockedPullRequests + .map((result) => `#${result.number}`) + .join(", ")}`, + ); + return; + } + + core.setFailed( + `Contribution policy failed for PR(s): ${blockedPullRequests + .map((result) => `#${result.number}`) + .join(", ")}`, + ); + } +} + +module.exports = { + analyzePullRequest, + run, +}; diff --git a/.github/scripts/preserve-release-artifacts.mjs b/.github/scripts/preserve-release-artifacts.mjs new file mode 100644 index 0000000..e64cfe9 --- /dev/null +++ b/.github/scripts/preserve-release-artifacts.mjs @@ -0,0 +1,79 @@ +// Retain only distributable bundle files, never the target tree or signing material. +import { createHash } from "node:crypto"; +import { + copyFileSync, + createReadStream, + existsSync, + mkdirSync, + readdirSync, + writeFileSync, +} from "node:fs"; +import { join, relative } from "node:path"; + +const env = process.env; +const bundle = join("target", env.RELEASE_TARGET || "", "release", "bundle"); +const destination = join(env.RUNNER_TEMP, "yaak-release-artifacts"); +const extensions = + /\.(dmg|deb|rpm|AppImage|exe|msi|app\.tar\.gz|AppImage\.tar\.gz|nsis\.zip|msi\.zip)(\.sig)?$/; +const files = []; + +function snapshot(directory) { + if (!existsSync(directory)) return; + for (const entry of readdirSync(directory, { withFileTypes: true })) { + const source = join(directory, entry.name); + // Only descend through the bundler's immediate output folders. This excludes + // .app trees and the extracted CEF deb contents (which contain executables). + if (entry.isDirectory() && directory === bundle) { + snapshot(source); + } else if ( + entry.isFile() && + (extensions.test(entry.name) || /^yaak-cef_.*_linux_.*\.tar\.gz$/.test(entry.name)) + ) { + // Match tauri-action's default macOS updater asset naming exactly. + const arch = env.RELEASE_ARCH === "arm64" ? "aarch64" : "x64"; + const assetName = entry.name.replace(/\.app\.tar\.gz(\.sig)?$/, `_${arch}.app.tar.gz$1`); + mkdirSync(destination, { recursive: true }); + const retained = join(destination, assetName); + // The second snapshot must not overwrite the original user installer/signature. + if (!existsSync(retained)) copyFileSync(source, retained); + files.push({ source: relative(".", source), assetName }); + } + } +} + +snapshot(bundle); +if (existsSync(destination)) { + const assets = readdirSync(destination) + .filter((name) => name !== "provenance.json") + .sort(); + const checksums = []; + for (const assetName of assets) { + const hash = createHash("sha256"); + for await (const chunk of createReadStream(join(destination, assetName))) hash.update(chunk); + checksums.push({ assetName, sha256: hash.digest("hex") }); + } + writeFileSync( + join(destination, "provenance.json"), + JSON.stringify( + { + repository: env.GITHUB_REPOSITORY, + tag: env.GITHUB_REF_NAME, + sha: env.GITHUB_SHA, + runId: env.GITHUB_RUN_ID, + runAttempt: env.GITHUB_RUN_ATTEMPT, + workflowRef: env.GITHUB_WORKFLOW_REF, + workflowSha: env.GITHUB_WORKFLOW_SHA, + tauriAction: "tauri-apps/tauri-action@v0", + platform: env.RELEASE_PLATFORM, + runtime: env.RELEASE_RUNTIME, + arch: env.RELEASE_ARCH, + target: env.RELEASE_TARGET, + args: env.RELEASE_ARGS, + assets: checksums, + }, + null, + 2, + ) + "\n", + ); +} +console.log(`Found ${files.length} distributable bundle files in ${bundle}`); diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..dd4f908 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,37 @@ +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 --features yaak-app-client/wry + - name: OpenAPI import round-trip + run: | + cargo build -p yaak-cli + node plugins/importer-openapi/tests/roundtrip.mjs diff --git a/.github/workflows/contribution-policy.yml b/.github/workflows/contribution-policy.yml new file mode 100644 index 0000000..0567c9f --- /dev/null +++ b/.github/workflows/contribution-policy.yml @@ -0,0 +1,48 @@ +name: Contribution Policy + +on: + workflow_dispatch: + inputs: + pr: + description: PR number or all + required: true + default: all + type: string + dry_run: + description: Dry run + required: true + default: true + type: boolean + pull_request_target: + types: + - opened + - edited + - reopened + - synchronize + - ready_for_review + - labeled + - unlabeled + +permissions: + contents: read + issues: write + pull-requests: write + +jobs: + check: + if: github.repository == 'mountain-loop/yaak' + name: Check contribution policy + runs-on: ubuntu-latest + steps: + - name: Checkout policy script + uses: actions/checkout@v4 + with: + ref: main + fetch-depth: 1 + + - name: Check contribution policy + uses: actions/github-script@v7 + with: + script: | + const { run } = require("./.github/scripts/check-contribution-policy.js"); + await run({ github, context, core }); diff --git a/.github/workflows/flathub.yml b/.github/workflows/flathub.yml new file mode 100644 index 0000000..ce015ba --- /dev/null +++ b/.github/workflows/flathub.yml @@ -0,0 +1,56 @@ +name: Update Flathub + +on: + workflow_dispatch: + inputs: + tag: + description: Release tag to publish to Flathub + required: true + type: string + +permissions: + contents: read + +jobs: + update-flathub: + if: github.repository == 'mountain-loop/yaak' + name: Update Flathub manifest + runs-on: ubuntu-latest + 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: "24" + + - 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 "${{ inputs.tag }}" 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 ${{ inputs.tag }}" + git push diff --git a/.github/workflows/release-api-npm.yml b/.github/workflows/release-api-npm.yml new file mode 100644 index 0000000..cc0f5c3 --- /dev/null +++ b/.github/workflows/release-api-npm.yml @@ -0,0 +1,60 @@ +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: + if: github.repository == 'mountain-loop/yaak' + 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 diff --git a/.github/workflows/release-app.yml b/.github/workflows/release-app.yml new file mode 100644 index 0000000..a9bb6c4 --- /dev/null +++ b/.github/workflows/release-app.yml @@ -0,0 +1,292 @@ +name: Release App Artifacts +on: + push: + tags: [v*] + +jobs: + build-artifacts: + if: github.repository == 'mountain-loop/yaak' + 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 --config ./tauri.release.conf.json --config ''{"build":{"features":["updater","license","wry"]}}''' + yaak_arch: "arm64" + os: "macos" + runtime: "wry" + targets: "aarch64-apple-darwin" + - platform: "macos-latest" # for Intel-based Macs. + args: '--target x86_64-apple-darwin --config ./tauri.release.conf.json --config ''{"build":{"features":["updater","license","wry"]}}''' + yaak_arch: "x64" + os: "macos" + runtime: "wry" + targets: "x86_64-apple-darwin" + - platform: "ubuntu-22.04" + args: '--config ./tauri.release.conf.json --config ''{"build":{"features":["updater","license","wry"]}}''' + yaak_arch: "x64" + os: "ubuntu" + runtime: "wry" + targets: "" + - platform: "ubuntu-22.04-arm" + args: '--config ./tauri.release.conf.json --config ''{"build":{"features":["updater","license","wry"]}}''' + yaak_arch: "arm64" + os: "ubuntu" + runtime: "wry" + targets: "" + - platform: "ubuntu-22.04" + args: >- + --bundles deb + --config ./tauri.release.conf.json + --config '{"productName":"yaak-cef","mainBinaryName":"yaak-cef","identifier":"app.yaak.desktop.cef","build":{"features":["license","cef"]},"bundle":{"createUpdaterArtifacts":false}}' + yaak_arch: "x64" + os: "ubuntu" + runtime: "cef" + targets: "" + - platform: "ubuntu-22.04-arm" + args: >- + --bundles deb + --config ./tauri.release.conf.json + --config '{"productName":"yaak-cef","mainBinaryName":"yaak-cef","identifier":"app.yaak.desktop.cef","build":{"features":["license","cef"]},"bundle":{"createUpdaterArtifacts":false}}' + yaak_arch: "arm64" + os: "ubuntu" + runtime: "cef" + targets: "" + - platform: "windows-latest" + args: '--config ./tauri.release.conf.json --config ''{"build":{"features":["updater","license","wry"]}}''' + yaak_arch: "x64" + os: "windows" + runtime: "wry" + targets: "" + # Windows ARM64 + - platform: "windows-latest" + args: '--target aarch64-pc-windows-msvc --config ./tauri.release.conf.json --config ''{"build":{"features":["updater","license","wry"]}}''' + yaak_arch: "arm64" + os: "windows" + runtime: "wry" + targets: "aarch64-pc-windows-msvc" + runs-on: ${{ matrix.platform }} + timeout-minutes: 360 + 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: Cache CEF (Linux only) + if: matrix.os == 'ubuntu' && matrix.runtime == 'cef' + uses: actions/cache@v4 + with: + path: ~/.cache/tauri-cef + key: cef-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('Cargo.lock') }} + + - name: install dependencies (Linux only) + if: matrix.os == 'ubuntu' + run: | + sudo apt-get update + sudo apt-get install -y cmake ninja-build libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev libnss3 patchelf xdg-utils + # crates/yaak-wasm compiles SQLite to wasm via sqlite-wasm-rs, whose C shim + # uses C23 [[noreturn]] and expects a freestanding wasm32 target. Ubuntu + # 22.04 ships only clang <=15: 14 rejects the attribute, and 15 falls + # through to host glibc headers ("bits/libc-header-start.h" not found). + # clang-18 handles it (it is what ubuntu-24.04 uses). Install it from + # apt.llvm.org since 22.04's repos stop at 15. Only the wasm build uses + # this compiler, so the shipped binary keeps 22.04's glibc floor. + wget -qO /tmp/llvm.sh https://apt.llvm.org/llvm.sh + chmod +x /tmp/llvm.sh + sudo /tmp/llvm.sh 18 + echo "CC_wasm32_unknown_unknown=/usr/bin/clang-18" >> "$GITHUB_ENV" + echo "AR_wasm32_unknown_unknown=/usr/bin/llvm-ar-18" >> "$GITHUB_ENV" + + - 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 --features yaak-app-client/wry + + - 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-client/macos/entitlements.yaakprotoc.plist --sign "$APPLE_SIGNING_IDENTITY" crates-tauri/yaak-app-client/vendored/protoc/yaakprotoc || true + codesign --force --options runtime --entitlements crates-tauri/yaak-app-client/macos/entitlements.yaaknode.plist --sign "$APPLE_SIGNING_IDENTITY" crates-tauri/yaak-app-client/vendored/node/yaaknode || true + + - name: Build and upload Tauri bundles + 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: + # Also retries builds; upload retries alone cannot clean up starter assets. + retryAttempts: 3 + tauriScript: "node ../../node_modules/@tauri-apps/cli/tauri.js" + tagName: "v__VERSION__" + releaseName: "Release __VERSION__" + releaseBody: "" + releaseDraft: true + prerelease: true + projectPath: ./crates-tauri/yaak-app-client + args: "${{ matrix.args }}" + + # Snapshot before the per-machine build overwrites the regular NSIS bundle/signature. + - name: Snapshot Tauri bundles + if: ${{ !cancelled() }} + run: node .github/scripts/preserve-release-artifacts.mjs + env: + RELEASE_TARGET: ${{ matrix.targets }} + RELEASE_PLATFORM: ${{ matrix.platform }} + RELEASE_RUNTIME: ${{ matrix.runtime }} + RELEASE_ARCH: ${{ matrix.yaak_arch }} + RELEASE_ARGS: ${{ matrix.args }} + + - name: Build and upload CEF tarball from deb (Linux only) + if: matrix.os == 'ubuntu' && matrix.runtime == 'cef' + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -euo pipefail + deb=$(find target/release/bundle/deb -maxdepth 1 -type f -name '*.deb' | head -n 1) + version="${GITHUB_REF_NAME#v}" + extract_dir="target/release/bundle/deb/yaak-cef-linux-${{ matrix.yaak_arch }}" + tarball="target/release/bundle/deb/yaak-cef_${version}_linux_${{ matrix.yaak_arch }}.tar.gz" + rm -rf "$extract_dir" + mkdir -p "$extract_dir" + dpkg-deb -x "$deb" "$extract_dir" + tar -C "$extract_dir" -czf "$tarball" . + for attempt in 1 2 3 4; do + if gh release upload "$GITHUB_REF_NAME" "$tarball" --clobber; then + break + fi + if [ "$attempt" -eq 4 ]; then exit 1; fi + sleep 10 + done + + # 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 + Push-Location crates-tauri/yaak-app-client + npx tauri bundle ${{ matrix.args }} --bundles nsis --config '{"bundle":{"createUpdaterArtifacts":true,"windows":{"nsis":{"installMode":"perMachine"}}}}' + if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE } + Pop-Location + $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 + foreach ($asset in @($dest, $destSig)) { + for ($attempt = 1; $attempt -le 4; $attempt++) { + gh release upload "$env:GITHUB_REF_NAME" "$asset" --clobber + if ($LASTEXITCODE -eq 0) { break } + if ($attempt -eq 4) { exit $LASTEXITCODE } + Start-Sleep -Seconds 10 + } + } + + - name: Snapshot additional release bundles + if: ${{ !cancelled() }} + run: node .github/scripts/preserve-release-artifacts.mjs + env: + RELEASE_TARGET: ${{ matrix.targets }} + RELEASE_PLATFORM: ${{ matrix.platform }} + RELEASE_RUNTIME: ${{ matrix.runtime }} + RELEASE_ARCH: ${{ matrix.yaak_arch }} + RELEASE_ARGS: ${{ matrix.args }} + + - name: Retain release bundles for recovery + if: ${{ !cancelled() }} + uses: actions/upload-artifact@v4 + with: + name: release-${{ github.ref_name }}-${{ matrix.platform }}-${{ matrix.runtime }}-${{ matrix.yaak_arch }}-${{ github.run_id }}-attempt-${{ github.run_attempt }} + path: ${{ runner.temp }}/yaak-release-artifacts/ + retention-days: 7 + if-no-files-found: warn diff --git a/.github/workflows/release-cli-npm.yml b/.github/workflows/release-cli-npm.yml new file mode 100644 index 0000000..8c45739 --- /dev/null +++ b/.github/workflows/release-cli-npm.yml @@ -0,0 +1,219 @@ +name: Release CLI to NPM + +on: + push: + tags: [v*] + 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: + if: github.repository == 'mountain-loop/yaak' + 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-client/vendored/plugin-runtime/index.cjs + crates-tauri/yaak-app-client/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-client/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}" + 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}" + 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 diff --git a/.github/workflows/release-web-image.yml b/.github/workflows/release-web-image.yml new file mode 100644 index 0000000..eee30e0 --- /dev/null +++ b/.github/workflows/release-web-image.yml @@ -0,0 +1,123 @@ +name: Release web image + +# Builds ghcr.io/mountain-loop/yaak-web: the browser client and the server that serves it. +# One image per architecture on its own native runner (emulating a Rust release build is hours), +# joined into one multi-arch tag at the end. + +on: + push: + tags: [v*] + workflow_dispatch: + inputs: + version: + description: Version to publish, without the v (e.g. 2026.2.0). Empty publishes main and sha tags only. + required: false + type: string + +permissions: + contents: read + packages: write + +env: + IMAGE: ghcr.io/mountain-loop/yaak-web + +jobs: + build: + if: github.repository == 'mountain-loop/yaak' + name: Build ${{ matrix.platform }} + runs-on: ${{ matrix.runner }} + strategy: + fail-fast: false + matrix: + include: + - platform: linux/amd64 + runner: ubuntu-22.04 + arch: amd64 + - platform: linux/arm64 + runner: ubuntu-22.04-arm + arch: arm64 + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push by digest + id: build + uses: docker/build-push-action@v6 + with: + context: . + file: Dockerfile.web + platforms: ${{ matrix.platform }} + outputs: type=image,name=${{ env.IMAGE }},push-by-digest=true,name-canonical=true,push=true + + - name: Export digest + run: | + mkdir -p "${{ runner.temp }}/digests" + digest="${{ steps.build.outputs.digest }}" + touch "${{ runner.temp }}/digests/${digest#sha256:}" + + - name: Upload digest + uses: actions/upload-artifact@v4 + with: + name: digest-${{ matrix.arch }} + path: ${{ runner.temp }}/digests/* + if-no-files-found: error + retention-days: 1 + + publish: + name: Publish manifest + needs: build + runs-on: ubuntu-latest + + steps: + - name: Download digests + uses: actions/download-artifact@v4 + with: + path: ${{ runner.temp }}/digests + pattern: digest-* + merge-multiple: true + + - name: Set up Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # `latest` follows a release tag, and a manual run that names a version — the way to + # publish before the first release. A prerelease (v2026.2.1-beta.1) never takes it. + - name: Tags + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.IMAGE }} + flavor: latest=false + tags: | + type=semver,pattern={{version}} + type=raw,value=${{ inputs.version }},enable=${{ inputs.version != '' }} + type=raw,value=latest,enable=${{ inputs.version != '' || (github.event_name == 'push' && !contains(github.ref_name, '-')) }} + type=ref,event=branch + type=sha,format=short + + - name: Create and push the manifest + working-directory: ${{ runner.temp }}/digests + run: | + docker buildx imagetools create \ + $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ + $(printf '${{ env.IMAGE }}@sha256:%s ' *) + + - name: Inspect + run: docker buildx imagetools inspect ${{ env.IMAGE }}:${{ steps.meta.outputs.version }} diff --git a/.github/workflows/sponsors.yml b/.github/workflows/sponsors.yml new file mode 100644 index 0000000..a68a005 --- /dev/null +++ b/.github/workflows/sponsors.yml @@ -0,0 +1,45 @@ +name: Generate Sponsors README +on: + workflow_dispatch: + schedule: + - cron: 30 15 * * 0-6 +permissions: + contents: write +jobs: + deploy: + if: github.repository == 'mountain-loop/yaak' + 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: 'User avatar: {{{ login }}}  ' + 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: 'User avatar: {{{ login }}}  ' + 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: "." diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1beb88f --- /dev/null +++ b/.gitignore @@ -0,0 +1,61 @@ +# 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-client/tauri.worktree.conf.json +crates-tauri/yaak-app-proxy/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 +.claude/worktrees/ diff --git a/.node-version b/.node-version new file mode 100644 index 0000000..d845d9d --- /dev/null +++ b/.node-version @@ -0,0 +1 @@ +24.14.0 diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..dc68961 --- /dev/null +++ b/.npmrc @@ -0,0 +1,2 @@ +# vite-plugin-wasm has not yet declared Vite 8 in its peerDependencies +legacy-peer-deps=true diff --git a/.oxfmtrc.json b/.oxfmtrc.json new file mode 100644 index 0000000..682f3b9 --- /dev/null +++ b/.oxfmtrc.json @@ -0,0 +1,8 @@ +{ + "printWidth": 100, + "ignorePatterns": [ + "**/bindings/**", + "crates/yaak-templates/pkg/**", + "apps/yaak-client/routeTree.gen.ts" + ] +} diff --git a/.vite-hooks/post-checkout b/.vite-hooks/post-checkout new file mode 100755 index 0000000..8ca7227 --- /dev/null +++ b/.vite-hooks/post-checkout @@ -0,0 +1 @@ +node scripts/git-hooks/post-checkout.mjs "$@" diff --git a/.vite-hooks/pre-commit b/.vite-hooks/pre-commit new file mode 100644 index 0000000..e0686b6 --- /dev/null +++ b/.vite-hooks/pre-commit @@ -0,0 +1,2 @@ +vp lint +vp staged diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..b2b5eb7 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + "recommendations": [ + "rust-lang.rust-analyzer", + "bradlc.vscode-tailwindcss", + "VoidZero.vite-plus-extension-pack" + ] +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..daca8f7 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,26 @@ +{ + "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"] + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..b806535 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "editor.defaultFormatter": "oxc.oxc-vscode", + "editor.formatOnSave": true, + "editor.formatOnSaveMode": "file", + "editor.codeActionsOnSave": { + "source.fixAll.oxc": "explicit" + } +} diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..f0ed185 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,2 @@ +- Tag safety: app AND CLI releases both ship from `v*` tags (the CLI is version-locked to the app and publishes to npm on every app tag); `@yaakapp/api` uses `yaak-api-*` tags. Always confirm which is requested before retagging. +- Do not commit, push, or tag without explicit approval diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..d8b23a8 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,15 @@ +# Contributing to Yaak + +Yaak accepts community pull requests for: + +- Bug fixes + +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, include a link to the [feedback item](https://yaak.app/feedback) where @gschier explicitly gave you permission to work on it. + +## Development Setup + +For local setup and development workflows, see [`DEVELOPMENT.md`](DEVELOPMENT.md). diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..1e877ca --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,118 @@ +[workspace] +resolver = "2" +members = [ + "crates/yaak", + "crates/yaak-commands", + # Common/foundation crates + "crates/common/yaak-database", + "crates/common/yaak-rpc", + "crates/common/yaak-rpc-schema", + # 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-lifecycle", + "crates/yaak-models", + "crates/yaak-plugins", + "crates/yaak-sse", + "crates/yaak-sync", + "crates/yaak-templates", + "crates/yaak-tls", + "crates/yaak-ws", + "crates/yaak-wasm", + "crates/yaak-api", + "crates/yaak-proxy", + # Proxy-specific crates + "crates-proxy/yaak-proxy-lib", + # Server crates (the browser tier's hosted send executor) + "crates-server/yaak-web", + "crates-server/yaak-playground", + # CLI crates + "crates-cli/yaak-cli", + # Tauri-specific crates + "crates-tauri/yaak-app-client", + "crates-tauri/yaak-app-proxy", + "crates-tauri/yaak-fonts", + "crates-tauri/yaak-license", + "crates-tauri/yaak-mac-window", + "crates-tauri/yaak-system-appearance", + "crates-tauri/yaak-tauri-utils", + "crates-tauri/yaak-window", +] + +[workspace.dependencies] +chrono = "0.4.42" +hex = "0.4.3" +keyring = "3.6.3" +log = "0.4.29" +reqwest = { version = "0.13.5", default-features = false, features = [ + # reqwest 0.13 switched `default-tls` from native-tls to rustls; keep the + # rest of the old default set and stay on native-tls. + "charset", + "http2", + "system-proxy", + "native-tls", +] } +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 = { version = "2.11.1", default-features = false, features = [ + "common-controls-v6", + "compression", + "dynamic-acl", +] } +tauri-plugin = "2.6.1" +tauri-plugin-dialog = { version = "2.7.1", default-features = false } +tauri-plugin-shell = "2.3.5" +thiserror = "2.0.17" +tokio = "1.48.0" +ts-rs = "11.1.0" + +# Internal crates - common/foundation +yaak-database = { path = "crates/common/yaak-database" } +yaak-rpc = { path = "crates/common/yaak-rpc" } +yaak-rpc-schema = { path = "crates/common/yaak-rpc-schema" } + +# Internal crates - shared +yaak-core = { path = "crates/yaak-core" } +yaak = { path = "crates/yaak" } +yaak-commands = { path = "crates/yaak-commands" } +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-lifecycle = { path = "crates/yaak-lifecycle" } +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" } +yaak-proxy = { path = "crates/yaak-proxy" } + +# Internal crates - proxy +yaak-proxy-lib = { path = "crates-proxy/yaak-proxy-lib" } + +# 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-system-appearance = { path = "crates-tauri/yaak-system-appearance" } +yaak-tauri-utils = { path = "crates-tauri/yaak-tauri-utils" } +yaak-window = { path = "crates-tauri/yaak-window" } + +[profile.release] +strip = false + +[patch.crates-io] +tauri = { git = "https://github.com/tauri-apps/tauri", rev = "d9bc695c18d9a25baec21d8a5f36d72e3a14ee53" } +tauri-build = { git = "https://github.com/tauri-apps/tauri", rev = "d9bc695c18d9a25baec21d8a5f36d72e3a14ee53" } diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..df43cae --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,105 @@ +# 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 +``` + +## Run the App in a Browser + +The client can also run as a plain web page, with no Tauri and no local process +behind it. Set `YAAK_TARGET=web` and start the frontend on its own: + +```shell +YAAK_TARGET=web npm run dev --workspace @yaakapp/yaak-client +``` + +That flag picks the browser host in `packages/platform/src/web/`, which answers +commands from an IndexedDB database the page owns instead of from the Rust +engine. Data persists across reloads and is shared between tabs on the same +origin. Sending HTTP is not available yet — the Send button reports that and +everything else about the request is still saved. `packages/platform/src/web/README.md` +lists which commands the browser host implements and which it declines. + +Desktop builds are unaffected: without the flag the platform package installs +the Tauri host exactly as before. + +## 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//.grammar > components/core/Editor//.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. diff --git a/Dockerfile.playground b/Dockerfile.playground new file mode 100644 index 0000000..e631eb1 --- /dev/null +++ b/Dockerfile.playground @@ -0,0 +1,15 @@ +# syntax=docker/dockerfile:1 +# The playground API behind yaak.run. See crates-server/yaak-playground/README.md. + +FROM rust:1-bookworm AS build +WORKDIR /app +COPY . . +RUN cargo build --release -p yaak-playground + +FROM debian:bookworm-slim +COPY --from=build /app/target/release/yaak-playground /usr/local/bin/yaak-playground +ENV HOST=0.0.0.0 +ENV PORT=8080 +EXPOSE 8080 +USER nobody +CMD ["yaak-playground"] diff --git a/Dockerfile.web b/Dockerfile.web new file mode 100644 index 0000000..460b5a1 --- /dev/null +++ b/Dockerfile.web @@ -0,0 +1,49 @@ +# syntax=docker/dockerfile:1 +# Yaak in a browser, whole: the web client and the server that executes its sends, in one +# image serving both from one origin. +# +# docker run -p 8080:8080 ghcr.io/mountain-loop/yaak-web +# +# See crates-server/yaak-web/README.md for the knobs. + +FROM node:22-slim AS web +WORKDIR /app +RUN apt-get update && apt-get install -y --no-install-recommends \ + git python3 make g++ ca-certificates && rm -rf /var/lib/apt/lists/* +COPY . . +# `npm ci` runs a prepare hook (`vp config`) that shells out to git, and there is no .git in +# the build context — it is ignored, and in a worktree it is a pointer file anyway. +RUN git init -q && git add -A \ + && git -c user.email=build@yaak.app -c user.name=build commit -qm build +# Empty means the tab posts sends to its own origin, which is what this image serves. Set it +# only to build a bundle for a deployment whose server lives somewhere else. +ARG VITE_YAAK_WEB_URL="" +ENV VITE_YAAK_WEB_URL=$VITE_YAAK_WEB_URL +ENV YAAK_TARGET=web +# crates/yaak-wasm's wasm package is committed; rebuilding it needs a clang with a WebAssembly +# backend, which this image has no reason to carry. +ENV SKIP_WASM_BUILD=1 +RUN npm ci +RUN node_modules/.bin/vp -C apps/yaak-client build + +FROM rust:1-bookworm AS server +WORKDIR /app +RUN apt-get update && apt-get install -y --no-install-recommends \ + pkg-config libssl-dev protobuf-compiler && rm -rf /var/lib/apt/lists/* +COPY . . +RUN cargo build --release -p yaak-web + +FROM debian:bookworm-slim +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates libssl3 && rm -rf /var/lib/apt/lists/* +COPY --from=server /app/target/release/yaak-web /usr/local/bin/yaak-web +COPY --from=web /app/dist/apps/yaak-client /srv +# 0.0.0.0 so the port is reachable from outside the container. PORT is the variable a +# platform-as-a-service assigns, so a deploy that sets it needs nothing else changed. +ENV HOST=0.0.0.0 +ENV PORT=8080 +EXPOSE 8080 +USER nobody +# Overriding the command (dropping --serve) leaves the stateless send executor: +# docker run ghcr.io/mountain-loop/yaak-web yaak-web +CMD ["yaak-web", "--serve", "/srv"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ed6c1c3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..7778b21 --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +

+ + + +

+ +

+ 💫 Yaak ➟ Desktop API Client 💫 +

+ +

+ A fast, privacy-first API client for REST, GraphQL, SSE, WebSocket, and gRPC – built with Tauri, Rust, and React. +

+

+ Development is funded by community-purchased licenses. You can also become a sponsor to have your logo appear below. 💖 +

+
+ +

+ User avatar: MVST-Solutions  User avatar: dharsanb  User avatar: railwayapp  User avatar: caseyamcl  User avatar: bytebase  User avatar: rauchg  User avatar:    +

+

+ User avatar: seanwash  User avatar: jerath  User avatar: itsa-sh  User avatar: dmmulroy  User avatar: timcole  User avatar: VLZH  User avatar: terasaka2k  User avatar: andriyor  User avatar: majudhu  User avatar: axelrindle  User avatar: jirizverina  User avatar: chip-well  User avatar: GRAYAH  User avatar: flashblaze  User avatar: Frostist  User avatar: PurplProto   +

+ +![Yaak API Client](https://yaak.app/static/screenshot.png) + +## Install + +Download Yaak for macOS, Windows, or Linux from [yaak.app/download](https://yaak.app/download). Package managers and other install methods are in the [installation docs](https://yaak.app/docs/getting-started/installation). + +## 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. +> If your PR is not a bug fix, link the [feedback item](https://yaak.app/feedback) where @gschier explicitly gave you permission to work on it. +> 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) + +## License + +The source is [MIT licensed](LICENSE) and can be built and run for free, for both personal and commercial use. + +The prebuilt binaries follow Yaak's [pricing terms](https://yaak.app/pricing): free for personal use, license required for commercial use. diff --git a/apps/yaak-client/.gitignore b/apps/yaak-client/.gitignore new file mode 100644 index 0000000..371c82b --- /dev/null +++ b/apps/yaak-client/.gitignore @@ -0,0 +1,2 @@ +vite.config.d.ts +vite.config.js diff --git a/apps/yaak-client/commands/commands.tsx b/apps/yaak-client/commands/commands.tsx new file mode 100644 index 0000000..40618a7 --- /dev/null +++ b/apps/yaak-client/commands/commands.tsx @@ -0,0 +1,170 @@ +import { createWorkspaceModel, type Folder, modelTypeLabel } from "@yaakapp-internal/models"; +import { applySync, calculateSync } from "@yaakapp-internal/sync"; +import { Button } from "../components/core/Button"; +import { + Banner, + InlineCode, + Table, + TableBody, + TableCell, + TableHead, + TableHeaderCell, + TableRow, + TruncatedWideTableCell, +} from "@yaakapp-internal/ui"; +import { activeWorkspaceIdAtom } from "../hooks/useActiveWorkspace"; +import { createFastMutation } from "../hooks/useFastMutation"; +import { showDialog } from "../lib/dialog"; +import { jotaiStore } from "../lib/jotai"; +import { pluralizeCount } from "../lib/pluralize"; +import { showPrompt } from "../lib/prompt"; +import { resolvedModelNameWithFolders } from "../lib/resolvedModelName"; + +export const createFolder = createFastMutation< + string | null, + void, + Partial> +>({ + mutationKey: ["create_folder"], + mutationFn: async (patch) => { + const workspaceId = jotaiStore.get(activeWorkspaceIdAtom); + if (workspaceId == null) { + throw new Error("Cannot create folder when there's no active workspace"); + } + + if (!patch.name) { + const name = await showPrompt({ + id: "new-folder", + label: "Name", + defaultValue: "Folder", + title: "New Folder", + confirmText: "Create", + placeholder: "Name", + }); + if (name == null) return null; + + patch.name = name; + } + + patch.sortPriority = patch.sortPriority || -Date.now(); + const id = await createWorkspaceModel({ model: "folder", workspaceId, ...patch }); + return id; + }, +}); + +export const syncWorkspace = createFastMutation< + void, + void, + { workspaceId: string; syncDir: string; force?: boolean } +>({ + mutationKey: [], + mutationFn: async ({ workspaceId, syncDir, force }) => { + const ops = (await calculateSync(workspaceId, syncDir)) ?? []; + if (ops.length === 0) { + console.log("Nothing to sync", workspaceId, syncDir); + return; + } + console.log("Syncing workspace", workspaceId, syncDir, ops); + + const dbOps = ops.filter((o) => o.type.startsWith("db")); + + if (dbOps.length === 0) { + await applySync(workspaceId, syncDir, ops); + return; + } + + const isDeletingWorkspace = ops.some( + (o) => o.type === "dbDelete" && o.model.model === "workspace", + ); + + console.log("Directory changes detected", { dbOps, ops }); + + if (force) { + await applySync(workspaceId, syncDir, ops); + return; + } + + showDialog({ + id: "commit-sync", + title: "Changes Detected", + size: "md", + render: ({ hide }) => ( +
{ + e.preventDefault(); + await applySync(workspaceId, syncDir, ops); + hide(); + }} + > + {isDeletingWorkspace ? ( + + 🚨 Changes contain a workspace deletion! + + ) : ( + + )} +

+ {pluralizeCount("file", dbOps.length)} in the directory{" "} + {dbOps.length === 1 ? "has" : "have"} changed. Do you want to update your workspace? +

+ + + + Type + Name + Operation + + + + {dbOps.map((op, i) => { + let name: string; + let label: string; + let color: string; + let model: string; + + if (op.type === "dbCreate") { + label = "create"; + name = resolvedModelNameWithFolders(op.fs.model); + color = "text-success"; + model = modelTypeLabel(op.fs.model); + } else if (op.type === "dbUpdate") { + label = "update"; + name = resolvedModelNameWithFolders(op.fs.model); + color = "text-info"; + model = modelTypeLabel(op.fs.model); + } else if (op.type === "dbDelete") { + label = "delete"; + name = resolvedModelNameWithFolders(op.model); + color = "text-danger"; + model = modelTypeLabel(op.model); + } else { + return null; + } + + return ( + // oxlint-disable-next-line react/no-array-index-key + + {model} + {name} + + {label} + + + ); + })} + +
+
+ + +
+ + ), + }); + }, +}); diff --git a/apps/yaak-client/commands/createEnvironment.tsx b/apps/yaak-client/commands/createEnvironment.tsx new file mode 100644 index 0000000..80f68e1 --- /dev/null +++ b/apps/yaak-client/commands/createEnvironment.tsx @@ -0,0 +1,51 @@ +import type { Environment } from "@yaakapp-internal/models"; +import { CreateEnvironmentDialog } from "../components/CreateEnvironmentDialog"; +import { activeWorkspaceIdAtom } from "../hooks/useActiveWorkspace"; +import { createFastMutation } from "../hooks/useFastMutation"; +import { showDialog } from "../lib/dialog"; +import { jotaiStore } from "../lib/jotai"; +import { setWorkspaceSearchParams } from "../lib/setWorkspaceSearchParams"; + +export const createSubEnvironmentAndActivate = createFastMutation< + string | null, + unknown, + Environment | null +>({ + mutationKey: ["create_environment"], + mutationFn: async (baseEnvironment) => { + if (baseEnvironment == null) { + throw new Error("No base environment passed"); + } + + const workspaceId = jotaiStore.get(activeWorkspaceIdAtom); + if (workspaceId == null) { + throw new Error("Cannot create environment when no active workspace"); + } + + return new Promise((resolve) => { + showDialog({ + id: "new-environment", + title: "New Environment", + description: "Create multiple environments with different sets of variables", + size: "sm", + onClose: () => resolve(null), + render: ({ hide }) => ( + { + resolve(id); + }} + /> + ), + }); + }); + }, + onSuccess: async (environmentId) => { + if (environmentId == null) { + return; // Was not created + } + + setWorkspaceSearchParams({ environment_id: environmentId }); + }, +}); diff --git a/apps/yaak-client/commands/deleteWebsocketConnections.ts b/apps/yaak-client/commands/deleteWebsocketConnections.ts new file mode 100644 index 0000000..e2ce134 --- /dev/null +++ b/apps/yaak-client/commands/deleteWebsocketConnections.ts @@ -0,0 +1,8 @@ +import type { WebsocketRequest } from "@yaakapp-internal/models"; +import { deleteWebsocketConnections as cmdDeleteWebsocketConnections } from "@yaakapp-internal/ws"; +import { createFastMutation } from "../hooks/useFastMutation"; + +export const deleteWebsocketConnections = createFastMutation({ + mutationKey: ["delete_websocket_connections"], + mutationFn: async (request: WebsocketRequest) => cmdDeleteWebsocketConnections(request.id), +}); diff --git a/apps/yaak-client/commands/importCurl.ts b/apps/yaak-client/commands/importCurl.ts new file mode 100644 index 0000000..37973c3 --- /dev/null +++ b/apps/yaak-client/commands/importCurl.ts @@ -0,0 +1,52 @@ +import type { HttpRequest } from "@yaakapp-internal/models"; +import { patchModelById } from "@yaakapp-internal/models"; +import { activeWorkspaceIdAtom } from "../hooks/useActiveWorkspace"; +import { createFastMutation } from "../hooks/useFastMutation"; +import { wasUpdatedExternally } from "../hooks/useRequestUpdateKey"; +import { createRequestAndNavigate } from "../lib/createRequestAndNavigate"; +import { jotaiStore } from "../lib/jotai"; +import { rpc } from "../lib/rpc"; +import { showToast } from "../lib/toast"; + +export function looksLikeCurl(text: string) { + return text.trim().startsWith("curl "); +} + +export const importCurl = createFastMutation< + void, + string, + { overwriteRequestId?: string; command: string } +>({ + mutationKey: ["import_curl"], + mutationFn: async ({ overwriteRequestId, command }) => { + const workspaceId = jotaiStore.get(activeWorkspaceIdAtom); + const importedRequest: HttpRequest = await rpc("cmd_curl_to_request", { + command, + workspaceId, + }); + + let verb: string; + if (overwriteRequestId == null) { + verb = "Created"; + await createRequestAndNavigate(importedRequest); + } else { + verb = "Updated"; + await patchModelById(importedRequest.model, overwriteRequestId, (r: HttpRequest) => ({ + ...importedRequest, + id: r.id, + createdAt: r.createdAt, + workspaceId: r.workspaceId, + folderId: r.folderId, + name: r.name, + sortPriority: r.sortPriority, + })); + + setTimeout(() => wasUpdatedExternally(overwriteRequestId), 100); + } + + showToast({ + color: "success", + message: `${verb} request from Curl`, + }); + }, +}); diff --git a/apps/yaak-client/commands/moveToWorkspace.tsx b/apps/yaak-client/commands/moveToWorkspace.tsx new file mode 100644 index 0000000..3428a58 --- /dev/null +++ b/apps/yaak-client/commands/moveToWorkspace.tsx @@ -0,0 +1,33 @@ +import type { GrpcRequest, HttpRequest, WebsocketRequest } from "@yaakapp-internal/models"; + +import { MoveToWorkspaceDialog } from "../components/MoveToWorkspaceDialog"; +import { activeWorkspaceIdAtom } from "../hooks/useActiveWorkspace"; +import { createFastMutation } from "../hooks/useFastMutation"; +import { pluralizeCount } from "../lib/pluralize"; +import { showDialog } from "../lib/dialog"; +import { jotaiStore } from "../lib/jotai"; + +export const moveToWorkspace = createFastMutation({ + mutationKey: ["move_workspace"], + mutationFn: async (requests: (HttpRequest | GrpcRequest | WebsocketRequest)[]) => { + const activeWorkspaceId = jotaiStore.get(activeWorkspaceIdAtom); + if (activeWorkspaceId == null) return; + if (requests.length === 0) return; + + const title = + requests.length === 1 ? "Move Request" : `Move ${pluralizeCount("Request", requests.length)}`; + + showDialog({ + id: "change-workspace", + title, + size: "sm", + render: ({ hide }) => ( + + ), + }); + }, +}); diff --git a/apps/yaak-client/commands/openFolderSettings.tsx b/apps/yaak-client/commands/openFolderSettings.tsx new file mode 100644 index 0000000..e08ad57 --- /dev/null +++ b/apps/yaak-client/commands/openFolderSettings.tsx @@ -0,0 +1,17 @@ +import { getModel } from "@yaakapp-internal/models"; +import type { FolderSettingsTab } from "../components/FolderSettingsDialog"; +import { FolderSettingsDialog } from "../components/FolderSettingsDialog"; +import { showDialog } from "../lib/dialog"; + +export function openFolderSettings(folderId: string, tab?: FolderSettingsTab) { + const folder = getModel("folder", folderId); + if (folder == null) return; + showDialog({ + id: "folder-settings", + title: null, + size: "lg", + className: "h-200", + noPadding: true, + render: () => , + }); +} diff --git a/apps/yaak-client/commands/openSettings.tsx b/apps/yaak-client/commands/openSettings.tsx new file mode 100644 index 0000000..7d7e103 --- /dev/null +++ b/apps/yaak-client/commands/openSettings.tsx @@ -0,0 +1,48 @@ +import { platform } from "@yaakapp-internal/platform"; +import type { SettingsTab, SettingsTabWithSubtab } from "../components/Settings/Settings"; +import { activeWorkspaceIdAtom } from "../hooks/useActiveWorkspace"; +import { createFastMutation } from "../hooks/useFastMutation"; +import { showDialog } from "../lib/dialog"; +import { jotaiStore } from "../lib/jotai"; +import { router } from "../lib/router"; +import { rpc } from "../lib/rpc"; + +export const openSettings = createFastMutation({ + mutationKey: ["open_settings"], + mutationFn: async (tab) => { + const workspaceId = jotaiStore.get(activeWorkspaceIdAtom); + if (workspaceId == null) return; + + // Settings is its own window where the host has windows to give. Where it + // doesn't — a browser tab — it's a dialog like any other, so opening it + // doesn't take you away from the request you were working on. + if (!platform.capabilities.multiWindow) { + // Imported here so Settings stays out of the startup bundle, the way the + // route that renders it on desktop already keeps it + const { default: Settings } = await import("../components/Settings/Settings"); + showDialog({ + id: "settings", + size: "md", + className: "h-[calc(100vh-5rem)] max-h-150! overflow-hidden", + noPadding: true, + noScroll: true, + // Keyed so opening a specific tab while the dialog is already up moves to it + render: ({ hide }) => , + }); + return; + } + + const location = router.buildLocation({ + to: "/workspaces/$workspaceId/settings", + params: { workspaceId }, + search: { tab: (tab ?? undefined) as SettingsTab | undefined }, + }); + + await rpc("cmd_new_child_window", { + url: location.href, + label: "settings", + title: "Yaak Settings", + innerSize: [750, 600], + }); + }, +}); diff --git a/apps/yaak-client/commands/openWorkspaceFromSyncDir.tsx b/apps/yaak-client/commands/openWorkspaceFromSyncDir.tsx new file mode 100644 index 0000000..9c5b6d2 --- /dev/null +++ b/apps/yaak-client/commands/openWorkspaceFromSyncDir.tsx @@ -0,0 +1,27 @@ +import { applySync, calculateSyncFsOnly } from "@yaakapp-internal/sync"; +import { createFastMutation } from "../hooks/useFastMutation"; +import { showSimpleAlert } from "../lib/alert"; +import { router } from "../lib/router"; + +export const openWorkspaceFromSyncDir = createFastMutation({ + mutationKey: [], + mutationFn: async (dir) => { + const ops = await calculateSyncFsOnly(dir); + + const workspace = ops + .map((o) => (o.type === "dbCreate" && o.fs.model.type === "workspace" ? o.fs.model : null)) + .filter((m) => m)[0]; + + if (workspace == null) { + showSimpleAlert("Failed to Open", "No workspace found in directory"); + return; + } + + await applySync(workspace.id, dir, ops); + + await router.navigate({ + to: "/workspaces/$workspaceId", + params: { workspaceId: workspace.id }, + }); + }, +}); diff --git a/apps/yaak-client/commands/openWorkspaceSettings.tsx b/apps/yaak-client/commands/openWorkspaceSettings.tsx new file mode 100644 index 0000000..1af368f --- /dev/null +++ b/apps/yaak-client/commands/openWorkspaceSettings.tsx @@ -0,0 +1,10 @@ +import type { WorkspaceSettingsTab } from "../components/WorkspaceSettingsDialog"; +import { WorkspaceSettingsDialog } from "../components/WorkspaceSettingsDialog"; +import { activeWorkspaceIdAtom } from "../hooks/useActiveWorkspace"; +import { jotaiStore } from "../lib/jotai"; + +export function openWorkspaceSettings(tab?: WorkspaceSettingsTab) { + const workspaceId = jotaiStore.get(activeWorkspaceIdAtom); + if (workspaceId == null) return; + WorkspaceSettingsDialog.show(workspaceId, tab); +} diff --git a/apps/yaak-client/commands/switchWorkspace.tsx b/apps/yaak-client/commands/switchWorkspace.tsx new file mode 100644 index 0000000..9891d57 --- /dev/null +++ b/apps/yaak-client/commands/switchWorkspace.tsx @@ -0,0 +1,46 @@ +import { platform } from "@yaakapp-internal/platform"; +import { createFastMutation } from "../hooks/useFastMutation"; +import { getRecentCookieJars } from "../hooks/useRecentCookieJars"; +import { getRecentEnvironments } from "../hooks/useRecentEnvironments"; +import { getRecentRequests } from "../hooks/useRecentRequests"; +import { router } from "../lib/router"; +import { rpc } from "../lib/rpc"; + +export const switchWorkspace = createFastMutation< + void, + unknown, + { + workspaceId: string; + inNewWindow: boolean; + } +>({ + mutationKey: ["open_workspace"], + mutationFn: async ({ workspaceId, inNewWindow }) => { + const environmentId = (await getRecentEnvironments(workspaceId))[0] ?? undefined; + const requestId = (await getRecentRequests(workspaceId))[0] ?? undefined; + const cookieJarId = (await getRecentCookieJars(workspaceId))[0] ?? undefined; + const search = { + environment_id: environmentId, + cookie_jar_id: cookieJarId, + request_id: requestId, + }; + + // A host without windows opens the workspace here instead. Refusing would + // strand the user on the workspace they were trying to leave. + if (inNewWindow && platform.capabilities.multiWindow) { + const location = router.buildLocation({ + to: "/workspaces/$workspaceId", + params: { workspaceId }, + search, + }); + await rpc("cmd_new_main_window", { url: location.href }); + return; + } + + await router.navigate({ + to: "/workspaces/$workspaceId", + params: { workspaceId }, + search, + }); + }, +}); diff --git a/apps/yaak-client/components/BinaryFileEditor.tsx b/apps/yaak-client/components/BinaryFileEditor.tsx new file mode 100644 index 0000000..ccab5fa --- /dev/null +++ b/apps/yaak-client/components/BinaryFileEditor.tsx @@ -0,0 +1,63 @@ +import type { HttpRequest } from "@yaakapp-internal/models"; +import { Banner, HStack, InlineCode, VStack } from "@yaakapp-internal/ui"; +import mime from "mime"; +import { useKeyValue } from "../hooks/useKeyValue"; +import { Button } from "./core/Button"; +import { SelectFile } from "./SelectFile"; + +type Props = { + requestId: string; + contentType: string | null; + body: HttpRequest["body"]; + onChange: (body: HttpRequest["body"]) => void; + onChangeContentType: (contentType: string | null) => void; +}; + +export function BinaryFileEditor({ + contentType, + body, + onChange, + onChangeContentType, + requestId, +}: Props) { + const ignoreContentType = useKeyValue({ + namespace: "global", + key: ["ignore_content_type", requestId], + fallback: false, + }); + + const handleChange = async ({ filePath }: { filePath: string | null }) => { + await ignoreContentType.set(false); + onChange({ filePath: filePath ?? undefined }); + }; + + const filePath = typeof body.filePath === "string" ? body.filePath : null; + const mimeType = mime.getType(filePath ?? "") ?? "application/octet-stream"; + + return ( + + + {filePath != null && mimeType !== contentType && !ignoreContentType.value && ( + +
+
Set Content-Type header
+ {mimeType} for current request? +
+ + + + +
+ )} +
+ ); +} diff --git a/apps/yaak-client/components/CargoFeature.tsx b/apps/yaak-client/components/CargoFeature.tsx new file mode 100644 index 0000000..7a5d1fe --- /dev/null +++ b/apps/yaak-client/components/CargoFeature.tsx @@ -0,0 +1,19 @@ +import type { ReactNode } from "react"; +import { appInfo } from "../lib/appInfo"; + +interface Props { + children: ReactNode; + feature: "updater" | "license"; +} + +const featureMap: Record = { + updater: appInfo.featureUpdater, + license: appInfo.featureLicense, +}; + +export function CargoFeature({ children, feature }: Props) { + if (featureMap[feature]) { + return <>{children}; + } + return null; +} diff --git a/apps/yaak-client/components/CloneGitRepositoryDialog.tsx b/apps/yaak-client/components/CloneGitRepositoryDialog.tsx new file mode 100644 index 0000000..1602110 --- /dev/null +++ b/apps/yaak-client/components/CloneGitRepositoryDialog.tsx @@ -0,0 +1,163 @@ +import { gitClone } from "@yaakapp-internal/git"; +import { Banner, VStack } from "@yaakapp-internal/ui"; +import { useState } from "react"; +import { openWorkspaceFromSyncDir } from "../commands/openWorkspaceFromSyncDir"; +import { appInfo } from "../lib/appInfo"; +import { CommercialUseBanner } from "./CommercialUseBanner"; +import { showErrorToast } from "../lib/toast"; +import { Button } from "./core/Button"; +import { Checkbox } from "./core/Checkbox"; +import { IconButton } from "./core/IconButton"; +import { PlainInput } from "./core/PlainInput"; +import { promptCredentials } from "./git/credentials"; +import { platform } from "@yaakapp-internal/platform"; + +interface Props { + hide: () => void; +} + +// Detect path separator from an existing path (defaults to /) +function getPathSeparator(path: string): string { + return path.includes("\\") ? "\\" : "/"; +} + +export function CloneGitRepositoryDialog({ hide }: Props) { + const [url, setUrl] = useState(""); + const [baseDirectory, setBaseDirectory] = useState(appInfo.defaultProjectDir); + const [directoryOverride, setDirectoryOverride] = useState(null); + const [hasSubdirectory, setHasSubdirectory] = useState(false); + const [subdirectory, setSubdirectory] = useState(""); + const [isCloning, setIsCloning] = useState(false); + const [error, setError] = useState(null); + + const repoName = extractRepoName(url); + const sep = getPathSeparator(baseDirectory); + const computedDirectory = repoName ? `${baseDirectory}${sep}${repoName}` : baseDirectory; + const directory = directoryOverride ?? computedDirectory; + const workspaceDirectory = + hasSubdirectory && subdirectory ? `${directory}${sep}${subdirectory}` : directory; + + const handleSelectDirectory = async () => { + const dir = await platform.dialog.open({ + title: "Select Directory", + directory: true, + multiple: false, + }); + if (dir != null) { + setBaseDirectory(dir); + setDirectoryOverride(null); + } + }; + + const handleClone = async (e: React.FormEvent) => { + e.preventDefault(); + if (!url || !directory) return; + + setIsCloning(true); + setError(null); + + try { + const result = await gitClone(url, directory, promptCredentials); + + if (result.type === "needs_credentials") { + setError( + result.error ?? "Authentication failed. Please check your credentials and try again.", + ); + return; + } + + // Open the workspace from the cloned directory (or subdirectory) + await openWorkspaceFromSyncDir.mutateAsync(workspaceDirectory); + + hide(); + } catch (err) { + setError(String(err)); + showErrorToast({ + id: "git-clone-error", + title: "Clone Failed", + message: String(err), + }); + } finally { + setIsCloning(false); + } + }; + + return ( + + {error && ( + + {error} + + )} + + + + + + + } + /> + + + + {hasSubdirectory && ( + + )} + + + + ); +} + +function extractRepoName(url: string): string { + // Handle various Git URL formats: + // https://github.com/user/repo.git + // git@github.com:user/repo.git + // https://github.com/user/repo + const match = url.match(/\/([^/]+?)(\.git)?$/); + if (match?.[1]) { + return match[1]; + } + // Fallback for SSH-style URLs + const sshMatch = url.match(/:([^/]+?)(\.git)?$/); + if (sshMatch?.[1]) { + return sshMatch[1]; + } + return ""; +} diff --git a/apps/yaak-client/components/ColorIndicator.tsx b/apps/yaak-client/components/ColorIndicator.tsx new file mode 100644 index 0000000..c5ed3a1 --- /dev/null +++ b/apps/yaak-client/components/ColorIndicator.tsx @@ -0,0 +1,28 @@ +import classNames from "classnames"; +import type { CSSProperties } from "react"; + +interface Props { + color: string | null; + onClick?: () => void; + className?: string; +} + +export function ColorIndicator({ color, onClick, className }: Props) { + const style: CSSProperties = { backgroundColor: color ?? undefined }; + const finalClassName = classNames( + className, + "inline-block w-[0.75em] h-[0.75em] rounded-full mr-1.5 border border-transparent shrink-0", + ); + + if (onClick) { + return ( + + ); +} + +function CommandPaletteAction({ action }: { action: HotkeyAction }) { + return ; +} diff --git a/apps/yaak-client/components/CommercialUseBanner.tsx b/apps/yaak-client/components/CommercialUseBanner.tsx new file mode 100644 index 0000000..a69283d --- /dev/null +++ b/apps/yaak-client/components/CommercialUseBanner.tsx @@ -0,0 +1,129 @@ +import { checkLicense } from "@yaakapp-internal/license"; +import { useCallback, useEffect, useRef, useState } from "react"; +import { useKeyValue } from "../hooks/useKeyValue"; +import { appInfo } from "../lib/appInfo"; +import { pricingUrl } from "../lib/pricingUrl"; +import { DismissibleBanner } from "./core/DismissibleBanner"; +import { platform } from "@yaakapp-internal/platform"; + +const COMMERCIAL_USE_SNOOZE_MS = 7 * 24 * 60 * 60 * 1000; +const COMMERCIAL_USE_BANNER_MESSAGE = + "Personal use of Yaak is free. If you’re using Yaak at work, please purchase a license."; + +export function CommercialUseBanner({ + source, + title, +}: { + source: string; + title: string; +}) { + const [visible, setVisible] = useState(false); + const snoozeStartedRef = useRef(false); + const { + isLoading: isSnoozeLoading, + set: setSnoozedAt, + value: snoozedAt, + } = useKeyValue({ + namespace: "global", + key: "commercial-use-banner-snoozed-at", + fallback: null, + }); + + useEffect(() => { + let canceled = false; + + shouldShowCommercialUsePrompt() + .then((shouldShow) => { + if (!canceled) setVisible(shouldShow); + }) + .catch(console.error); + + return () => { + canceled = true; + }; + }, [source]); + + const snoozed = isSnoozed(snoozedAt, COMMERCIAL_USE_SNOOZE_MS); + const handleShow = useCallback(() => { + if (snoozeStartedRef.current || snoozed) { + return; + } + + snoozeStartedRef.current = true; + setSnoozedAt(JSON.stringify({ source, at: new Date().toISOString() })).catch(console.error); + }, [setSnoozedAt, snoozed, source]); + + if (!visible || isSnoozeLoading || (snoozed && !snoozeStartedRef.current)) { + return null; + } + + return ( +
+ + setSnoozedAt(JSON.stringify({ source, at: new Date().toISOString() })) + } + onShow={handleShow} + actions={[ + { + label: "Purchase License", + color: "info", + variant: "solid", + onClick: () => { + openCommercialUsePricing(source).catch(console.error); + }, + }, + ]} + > +
+

{title}

+

{COMMERCIAL_USE_BANNER_MESSAGE}

+
+
+
+ ); +} + +async function shouldShowCommercialUsePrompt(): Promise { + // Open-source builds omit the Rust license plugin, so never show commercial-use prompts there. + if (appInfo.featureLicense !== true) { + return false; + } + + try { + const license = await checkLicense(); + return license.status === "personal_use"; + } catch (err) { + console.log("Failed to check license before commercial-use prompt", err); + return false; + } +} + +async function openCommercialUsePricing(source: string): Promise { + await platform.openUrl(pricingUrl(`app.commercial-use.${source}`)).catch(console.error); +} + +function isSnoozed(value: string | null, ms: number): boolean { + if (value == null) return false; + + try { + const snooze = JSON.parse(value) as { at?: unknown }; + const at = typeof snooze.at === "string" ? snooze.at : null; + return isWithinMs(at, ms); + } catch { + // Older builds stored only the timestamp, so keep respecting that as a global snooze. + return isWithinMs(value, ms); + } +} + +function isWithinMs(date: string | null, ms: number): boolean { + if (date == null) return false; + + const time = new Date(date).getTime(); + if (Number.isNaN(time)) return false; + + return Date.now() - time < ms; +} diff --git a/apps/yaak-client/components/ConfirmLargeRequestBody.tsx b/apps/yaak-client/components/ConfirmLargeRequestBody.tsx new file mode 100644 index 0000000..f8acf53 --- /dev/null +++ b/apps/yaak-client/components/ConfirmLargeRequestBody.tsx @@ -0,0 +1,74 @@ +import type { HttpRequest } from "@yaakapp-internal/models"; +import { patchModel } from "@yaakapp-internal/models"; +import { Banner, HStack, InlineCode } from "@yaakapp-internal/ui"; +import type { ReactNode } from "react"; +import { useToggle } from "../hooks/useToggle"; +import { showConfirm } from "../lib/confirm"; +import { Button } from "./core/Button"; +import { Link } from "./core/Link"; +import { SizeTag } from "./core/SizeTag"; + +interface Props { + children: ReactNode; + request: HttpRequest; +} + +const LARGE_TEXT_BYTES = 2 * 1000 * 1000; + +export function ConfirmLargeRequestBody({ children, request }: Props) { + const [showLargeResponse, toggleShowLargeResponse] = useToggle(); + + if (request.body?.text == null) { + return children; + } + + const contentLength = request.body.text.length ?? 0; + const tooLargeBytes = LARGE_TEXT_BYTES; + const isLarge = contentLength > tooLargeBytes; + if (!showLargeResponse && isLarge) { + return ( + +

+ Rendering content over{" "} + + + {" "} + may impact performance. +

+

+ See{" "} + + Working With Large Values + {" "} + for tips. +

+ + + + +
+ ); + } + + return <>{children}; +} diff --git a/apps/yaak-client/components/ConfirmLargeResponse.tsx b/apps/yaak-client/components/ConfirmLargeResponse.tsx new file mode 100644 index 0000000..90bb2c8 --- /dev/null +++ b/apps/yaak-client/components/ConfirmLargeResponse.tsx @@ -0,0 +1,61 @@ +import type { HttpResponse } from "@yaakapp-internal/models"; +import { Banner, HStack, InlineCode } from "@yaakapp-internal/ui"; +import { type ReactNode, useMemo } from "react"; +import { useSaveResponse } from "../hooks/useSaveResponse"; +import { useToggle } from "../hooks/useToggle"; +import { isProbablyTextContentType } from "../lib/contentType"; +import { getContentTypeFromHeaders } from "../lib/model_util"; +import { getResponseBodyText } from "../lib/responseBody"; +import { CopyButton } from "./CopyButton"; +import { Button } from "./core/Button"; +import { SizeTag } from "./core/SizeTag"; + +interface Props { + children: ReactNode; + response: HttpResponse; +} + +const LARGE_BYTES = 2 * 1000 * 1000; + +export function ConfirmLargeResponse({ children, response }: Props) { + const { mutate: saveResponse } = useSaveResponse(response); + const [showLargeResponse, toggleShowLargeResponse] = useToggle(); + const isProbablyText = useMemo(() => { + const contentType = getContentTypeFromHeaders(response.headers); + return isProbablyTextContentType(contentType); + }, [response.headers]); + + const contentLength = response.contentLength ?? 0; + const isLarge = contentLength > LARGE_BYTES; + if (!showLargeResponse && isLarge) { + return ( + +

+ Showing responses over{" "} + + + {" "} + may impact performance +

+ + + + {isProbablyText && ( + getResponseBodyText({ response, filter: null })} + /> + )} + +
+ ); + } + + return <>{children}; +} diff --git a/apps/yaak-client/components/ConfirmLargeResponseRequest.tsx b/apps/yaak-client/components/ConfirmLargeResponseRequest.tsx new file mode 100644 index 0000000..92525f7 --- /dev/null +++ b/apps/yaak-client/components/ConfirmLargeResponseRequest.tsx @@ -0,0 +1,56 @@ +import type { HttpResponse } from "@yaakapp-internal/models"; +import { Banner, HStack, InlineCode } from "@yaakapp-internal/ui"; +import { type ReactNode, useMemo } from "react"; +import { getRequestBodyText as getHttpResponseRequestBodyText } from "../hooks/useHttpRequestBody"; +import { useToggle } from "../hooks/useToggle"; +import { isProbablyTextContentType } from "../lib/contentType"; +import { getContentTypeFromHeaders } from "../lib/model_util"; +import { CopyButton } from "./CopyButton"; +import { Button } from "./core/Button"; +import { SizeTag } from "./core/SizeTag"; + +interface Props { + children: ReactNode; + response: HttpResponse; +} + +const LARGE_BYTES = 2 * 1000 * 1000; + +export function ConfirmLargeResponseRequest({ children, response }: Props) { + const [showLargeResponse, toggleShowLargeResponse] = useToggle(); + const isProbablyText = useMemo(() => { + const contentType = getContentTypeFromHeaders(response.headers); + return isProbablyTextContentType(contentType); + }, [response.headers]); + + const contentLength = response.requestContentLength ?? 0; + const isLarge = contentLength > LARGE_BYTES; + if (!showLargeResponse && isLarge) { + return ( + +

+ Showing content over{" "} + + + {" "} + may impact performance +

+ + + {isProbablyText && ( + getHttpResponseRequestBodyText(response).then((d) => d?.bodyText ?? "")} + /> + )} + +
+ ); + } + + return <>{children}; +} diff --git a/apps/yaak-client/components/ContextMenus.tsx b/apps/yaak-client/components/ContextMenus.tsx new file mode 100644 index 0000000..dd8bad8 --- /dev/null +++ b/apps/yaak-client/components/ContextMenus.tsx @@ -0,0 +1,26 @@ +import { useAtomValue } from "jotai"; +import { contextMenusAtom, hideContextMenu } from "../lib/contextMenu"; +import { ContextMenu } from "./core/Dropdown"; +import { ErrorBoundary } from "./ErrorBoundary"; + +/** Renders menus opened by {@link showContextMenu}, the way {@link Dialogs} renders dialogs. */ +export function ContextMenus() { + const menus = useAtomValue(contextMenusAtom); + return ( + <> + {menus.map(({ id, items, triggerPosition, triggerRect, triggerEl }) => ( + + hideContextMenu(id)} + /> + + ))} + + ); +} diff --git a/apps/yaak-client/components/CookieDialog.tsx b/apps/yaak-client/components/CookieDialog.tsx new file mode 100644 index 0000000..31c9091 --- /dev/null +++ b/apps/yaak-client/components/CookieDialog.tsx @@ -0,0 +1,731 @@ +import type { Cookie } from "@yaakapp-internal/models"; +import { cookieJarsAtom, patchModel } from "@yaakapp-internal/models"; +import { formatDate } from "date-fns/format"; +import { useAtomValue } from "jotai"; +import { + type ComponentProps, + type CSSProperties, + type FormEvent, + type ReactNode, + type RefObject, + useMemo, + useRef, + useState, +} from "react"; +import { showDialog } from "../lib/dialog"; +import { jotaiStore } from "../lib/jotai"; +import { cookieDomain } from "../lib/model_util"; +import { + Icon, + SplitLayout, + Table, + TableBody, + TableCell, + TableHead, + TableHeaderCell, + TableRow, + TruncatedWideTableCell, +} from "@yaakapp-internal/ui"; +import { IconButton } from "./core/IconButton"; +import { Checkbox } from "./core/Checkbox"; +import classNames from "classnames"; +import { EventDetailHeader } from "./core/EventViewer"; +import { KeyValueRow, KeyValueRows } from "./core/KeyValueRow"; +import { EmptyStateText } from "./EmptyStateText"; +import { PlainInput } from "./core/PlainInput"; +import { Select } from "./core/Select"; +import { showAlert } from "../lib/alert"; + +interface Props { + cookieJarId: string | null; +} + +export const CookieDialog = ({ cookieJarId }: Props) => { + const cookieJars = useAtomValue(cookieJarsAtom); + const cookieJar = cookieJars?.find((c) => c.id === cookieJarId); + const [filter, setFilter] = useState(""); + const [filterUpdateKey, setFilterUpdateKey] = useState(0); + const [selectedCookieKey, setSelectedCookieKey] = useState(null); + const [editingCookieKey, setEditingCookieKey] = useState(null); + const [draftCookie, setDraftCookie] = useState(null); + const [draftExpiresInput, setDraftExpiresInput] = useState(""); + const editorFormRef = useRef(null); + const filteredCookies = useMemo(() => { + return cookieJar?.cookies.filter((cookie) => cookieMatchesFilter(cookie, filter)) ?? []; + }, [cookieJar?.cookies, filter]); + const selectedCookie = useMemo( + () => + selectedCookieKey == null + ? null + : (filteredCookies.find((cookie) => cookieKey(cookie) === selectedCookieKey) ?? null), + [filteredCookies, selectedCookieKey], + ); + const detailCookie = draftCookie ?? selectedCookie; + const isCreatingCookie = editingCookieKey === NEW_COOKIE_KEY; + const isEditingCookie = draftCookie != null; + + const handleAddCookie = () => { + setSelectedCookieKey(null); + setEditingCookieKey(NEW_COOKIE_KEY); + setDraftCookie(newCookieDraft()); + setDraftExpiresInput(""); + }; + + const handleEditCookie = () => { + if (selectedCookie == null) { + return; + } + + setEditingCookieKey(cookieKey(selectedCookie)); + setDraftCookie(selectedCookie); + setDraftExpiresInput(cookieExpiresInputValue(selectedCookie)); + }; + + const handleCancelEdit = () => { + if (isCreatingCookie) { + setSelectedCookieKey(null); + } + setEditingCookieKey(null); + setDraftCookie(null); + setDraftExpiresInput(""); + }; + + const handleCloseDetails = () => { + if (isEditingCookie) { + handleCancelEdit(); + return; + } + + setSelectedCookieKey(null); + }; + + const handleSaveCookie = (event: FormEvent) => { + event.preventDefault(); + + if (cookieJar == null || draftCookie == null) { + return; + } + + let nextCookie = normalizeCookie(draftCookie); + if (nextCookie.expires !== "SessionEnd") { + const expires = cookieExpiresFromInput(draftExpiresInput); + if (expires == null) { + showAlert({ + id: "invalid-cookie-expires", + title: "Invalid Cookie", + body: "Cookie expiration must be a valid date.", + }); + return; + } + + nextCookie = { ...nextCookie, expires }; + } + + const nextCookieKey = cookieKey(nextCookie); + const nextCookies = cookieJar.cookies.filter((cookie) => { + const key = cookieKey(cookie); + if (editingCookieKey != null && key === editingCookieKey) { + return false; + } + return key !== nextCookieKey; + }); + + void patchModel(cookieJar, { cookies: [...nextCookies, nextCookie] }); + setSelectedCookieKey(nextCookieKey); + setEditingCookieKey(null); + setDraftCookie(null); + setDraftExpiresInput(""); + }; + + if (cookieJar == null) { + return
No cookie jar selected
; + } + + return ( +
+
+ 0 && ( + { + setFilter(""); + setFilterUpdateKey((key) => key + 1); + }} + /> + ) + } + /> + +
+ {cookieJar.cookies.length === 0 && detailCookie == null ? ( + + Cookies will appear when a response includes a Set-Cookie header. + + ) : filteredCookies.length === 0 && detailCookie == null ? ( + No cookies match the current filter. + ) : ( + + filteredCookies.length === 0 ? ( +
+ No cookies match the current filter. +
+ ) : ( + + + + Name + Value + Domain + Path + Expires + Size + HTTP Only + Secure + Same Site + + { + setSelectedCookieKey(null); + setEditingCookieKey(null); + setDraftCookie(null); + setDraftExpiresInput(""); + void patchModel(cookieJar, { cookies: [] }); + }} + /> + + + + + {filteredCookies.map((c: Cookie) => { + const key = cookieKey(c); + const isSelected = key === selectedCookieKey; + + return ( + { + setSelectedCookieKey(key); + setEditingCookieKey(null); + setDraftCookie(null); + setDraftExpiresInput(""); + }} + > + + {c.name} + + + {c.value} + + {cookieDomain(c)} + {c.path} + {cookieExpires(c)} + {cookieSize(c)} + + + + + + + {c.sameSite} + + { + event.stopPropagation(); + if (isSelected) { + setSelectedCookieKey(null); + } + if (editingCookieKey === key) { + setEditingCookieKey(null); + setDraftCookie(null); + setDraftExpiresInput(""); + } + void patchModel(cookieJar, { + cookies: cookieJar.cookies.filter( + (c2: Cookie) => cookieKey(c2) !== key, + ), + }); + }} + /> + + + ); + })} + +
+ ) + } + secondSlot={ + detailCookie == null + ? null + : ({ style }) => ( + + editorFormRef.current?.requestSubmit(), + }, + { + key: "cancel", + label: "Cancel", + onClick: handleCancelEdit, + }, + ] + : [ + { + key: "edit", + label: "Edit", + onClick: handleEditCookie, + }, + ] + } + onClose={handleCloseDetails} + /> + {isEditingCookie ? ( + + ) : ( + + )} + + ) + } + /> + )} +
+ ); +}; + +function CookieDetailsPane({ + children, + formRef, + isEditing, + onSubmit, + style, +}: { + children: ReactNode; + formRef: RefObject; + isEditing: boolean; + onSubmit: (event: FormEvent) => void; + style: CSSProperties; +}) { + const className = "grid grid-rows-[auto_minmax(0,1fr)] bg-surface border-t border-border pt-2"; + + if (isEditing) { + return ( +
+ {children} +
+ ); + } + + return ( +
+ {children} +
+ ); +} + +CookieDialog.show = (cookieJarId: string | null) => { + const cookieJar = jotaiStore.get(cookieJarsAtom)?.find((jar) => jar.id === cookieJarId); + if (cookieJar == null) { + showAlert({ + id: "invalid-jar", + body: `Failed to find cookie jar for ID: ${cookieJarId}`, + title: "Invalid Cookie Jar", + }); + return; + } + + showDialog({ + id: "cookies", + title: `${cookieJar.name} Cookies`, + size: "full", + render: () => , + }); +}; + +function CookieDetails({ cookie }: { cookie: Cookie }) { + return ( +
+ + {cookie.name} + +
{cookie.value}
+
+ {cookieDomain(cookie)} + {cookie.path} + {cookieExpires(cookie)} + {cookieSize(cookie)} + {cookie.httpOnly ? "Yes" : "No"} + {cookie.secure ? "Yes" : "No"} + {cookie.sameSite && ( + {cookie.sameSite} + )} +
+
+ ); +} + +function CookieEditor({ + cookie, + expiresInputValue, + onChange, + onExpiresInputChange, +}: { + cookie: Cookie; + expiresInputValue: string; + onChange: (cookie: Cookie) => void; + onExpiresInputChange: (value: string) => void; +}) { + const sessionCookie = cookie.expires === "SessionEnd"; + + return ( +
+ + + onChange({ ...cookie, name })} + /> + + + onChange({ ...cookie, value })} + /> + + + onChange(cookieWithDomain(cookie, domain))} + /> + + + onChange({ ...cookie, path })} + /> + + +
+ { + if (checked) { + onChange({ ...cookie, expires: "SessionEnd" }); + return; + } + + const expiresInput = + cookieExpiresFromInput(expiresInputValue) == null + ? defaultCookieExpiresInputValue() + : expiresInputValue; + + onExpiresInputChange(expiresInput); + onChange({ + ...cookie, + expires: cookieExpiresFromInput(expiresInput)!, + }); + }} + /> + { + onExpiresInputChange(value); + + const expires = cookieExpiresFromInput(value); + if (expires != null) { + onChange({ ...cookie, expires }); + } + }} + /> +
+
+ {cookieSize(cookie)} + + onChange({ ...cookie, httpOnly })} + /> + + + onChange({ ...cookie, secure })} + /> + + + onChange(event.target.value)} + pattern={pattern} + placeholder={placeholder} + required={required} + type="text" + value={value} + /> + ); +} + +function CookieTextarea({ onChange, value }: { onChange: (value: string) => void; value: string }) { + return ( +