From f1757ae427e5b990b8458c7360fafef5f281086a Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Mon, 31 Mar 2025 11:56:17 -0700 Subject: [PATCH] Generalized frontend model store (#193) --- package-lock.json | 10 +- package.json | 3 + src-tauri/gen/schemas/acl-manifests.json | 2 +- src-tauri/gen/schemas/desktop-schema.json | 50 ++ src-tauri/gen/schemas/macOS-schema.json | 50 ++ .../20250326193143_key-value-id.sql | 43 ++ src-tauri/src/http_request.rs | 5 +- src-tauri/src/lib.rs | 479 +----------------- src-tauri/src/updates.rs | 3 +- src-tauri/yaak-license/src/license.rs | 2 +- src-tauri/yaak-models/bindings/gen_models.ts | 2 +- src-tauri/yaak-models/build.rs | 10 +- src-tauri/yaak-models/guest-js/atoms.ts | 80 +++ src-tauri/yaak-models/guest-js/index.ts | 10 + src-tauri/yaak-models/guest-js/store.ts | 199 ++++++++ src-tauri/yaak-models/guest-js/types.ts | 8 + src-tauri/yaak-models/guest-js/util.ts | 23 + src-tauri/yaak-models/index.ts | 8 - src-tauri/yaak-models/package.json | 2 +- .../autogenerated/commands/duplicate.toml | 13 + .../autogenerated/commands/get_settings.toml | 13 + .../autogenerated/commands/grpc_events.toml | 13 + .../commands/websocket_events.toml | 13 + .../commands/workspace_models.toml | 13 + .../permissions/autogenerated/reference.md | 137 ++++- .../yaak-models/permissions/default.toml | 7 +- .../permissions/schemas/schema.json | 50 ++ src-tauri/yaak-models/src/commands.rs | 121 ++++- src-tauri/yaak-models/src/db_context.rs | 6 +- src-tauri/yaak-models/src/lib.rs | 16 +- src-tauri/yaak-models/src/models.rs | 82 ++- .../yaak-models/src/queries/cookie_jars.rs | 13 +- .../yaak-models/src/queries/environments.rs | 59 ++- src-tauri/yaak-models/src/queries/folders.rs | 73 +-- .../src/queries/grpc_connections.rs | 14 +- .../yaak-models/src/queries/http_responses.rs | 2 +- .../yaak-models/src/queries/key_values.rs | 67 +-- src-tauri/yaak-models/src/queries/mod.rs | 2 +- src-tauri/yaak-models/src/queries/settings.rs | 31 +- .../src/queries/websocket_connections.rs | 4 +- .../src/queries/workspace_metas.rs | 27 +- .../yaak-models/src/queries/workspaces.rs | 46 +- src-tauri/yaak-models/src/query_manager.rs | 10 +- src-tauri/yaak-models/src/util.rs | 6 +- src-tauri/yaak-sync/src/sync.rs | 4 +- src-tauri/yaak-ws/src/commands.rs | 2 +- src-web/commands/commands.tsx | 15 +- src-web/commands/deleteWebsocketConnection.ts | 10 - src-web/commands/deleteWebsocketRequest.tsx | 26 - src-web/commands/duplicateWebsocketRequest.ts | 17 - src-web/commands/openSettings.ts | 5 +- src-web/commands/openWorkspaceSettings.tsx | 5 +- src-web/commands/upsertWebsocketRequest.ts | 25 - src-web/commands/upsertWorkspace.ts | 12 - src-web/commands/upsertWorkspaceMeta.ts | 19 - src-web/components/CommandPaletteDialog.tsx | 28 +- src-web/components/CookieDialog.tsx | 20 +- src-web/components/CookieDropdown.tsx | 15 +- src-web/components/CreateWorkspaceDialog.tsx | 14 +- src-web/components/DynamicForm.tsx | 8 +- .../components/EnvironmentActionsDropdown.tsx | 4 +- src-web/components/EnvironmentEditDialog.tsx | 32 +- src-web/components/ExportDataDialog.tsx | 13 +- src-web/components/FolderSettingsDialog.tsx | 20 +- src-web/components/GitDropdown.tsx | 8 +- src-web/components/GlobalHooks.tsx | 2 - src-web/components/GraphQLEditor.tsx | 28 +- src-web/components/GrpcConnectionLayout.tsx | 42 +- src-web/components/GrpcEditor.tsx | 19 +- ...ction.tsx => GrpcProtoSelectionDialog.tsx} | 18 +- ...ctionSetupPane.tsx => GrpcRequestPane.tsx} | 60 +-- ...nMessagesPane.tsx => GrpcResponsePane.tsx} | 21 +- src-web/components/HeaderSize.tsx | 5 +- .../components/HttpAuthenticationEditor.tsx | 24 +- src-web/components/HttpRequestPane.tsx | 84 ++- src-web/components/LicenseBadge.tsx | 9 +- src-web/components/MoveToWorkspaceDialog.tsx | 28 +- .../RecentGrpcConnectionsDropdown.tsx | 9 +- .../RecentHttpResponsesDropdown.tsx | 7 +- src-web/components/RecentRequestsDropdown.tsx | 10 +- .../RecentWebsocketConnectionsDropdown.tsx | 10 +- .../components/RedirectToLatestWorkspace.tsx | 10 +- .../Settings/SettingsAppearance.tsx | 27 +- .../components/Settings/SettingsGeneral.tsx | 31 +- .../components/Settings/SettingsLicense.tsx | 2 +- .../components/Settings/SettingsPlugins.tsx | 15 +- src-web/components/Settings/SettingsProxy.tsx | 35 +- src-web/components/SwitchWorkspaceDialog.tsx | 15 +- src-web/components/WebsocketRequestPane.tsx | 64 +-- src-web/components/WebsocketResponsePane.tsx | 16 +- src-web/components/Workspace.tsx | 46 +- .../components/WorkspaceActionsDropdown.tsx | 21 +- .../components/WorkspaceSettingsDialog.tsx | 30 +- src-web/components/core/Editor/Editor.tsx | 7 +- src-web/components/core/Select.tsx | 7 +- src-web/components/core/SplitLayout.tsx | 5 +- src-web/components/sidebar/Sidebar.tsx | 84 +-- src-web/components/sidebar/SidebarAtoms.ts | 13 +- src-web/components/sidebar/SidebarItem.tsx | 39 +- .../sidebar/SidebarItemContextMenu.tsx | 69 ++- src-web/components/sidebar/SidebarItems.tsx | 15 +- src-web/font-size.ts | 6 +- src-web/hooks/useActiveCookieJar.ts | 7 +- src-web/hooks/useActiveEnvironment.ts | 4 +- .../hooks/useActiveEnvironmentVariables.ts | 40 +- src-web/hooks/useActiveRequest.ts | 19 +- src-web/hooks/useActiveWorkspace.ts | 41 +- .../hooks/useActiveWorkspaceChangedToast.tsx | 5 +- src-web/hooks/useAllRequests.ts | 14 + src-web/hooks/useCookieJars.ts | 17 - src-web/hooks/useCreateCookieJar.ts | 17 +- src-web/hooks/useCreateDropdownItems.tsx | 30 +- src-web/hooks/useCreateEnvironment.ts | 23 +- src-web/hooks/useCreateGrpcRequest.ts | 31 +- src-web/hooks/useCreateHttpRequest.ts | 25 +- src-web/hooks/useDeleteActiveWorkspace.tsx | 31 -- src-web/hooks/useDeleteAnyGrpcRequest.tsx | 27 - src-web/hooks/useDeleteAnyHttpRequest.tsx | 27 - src-web/hooks/useDeleteAnyRequest.tsx | 29 -- src-web/hooks/useDeleteCookieJar.tsx | 24 - src-web/hooks/useDeleteEnvironment.tsx | 24 - src-web/hooks/useDeleteFolder.tsx | 26 - src-web/hooks/useDeleteGrpcConnection.ts | 12 - src-web/hooks/useDeleteGrpcConnections.ts | 8 +- src-web/hooks/useDeleteHttpResponse.ts | 12 - src-web/hooks/useDeleteHttpResponses.ts | 8 +- src-web/hooks/useDeleteSendHistory.tsx | 28 +- src-web/hooks/useDuplicateFolder.ts | 9 - src-web/hooks/useDuplicateGrpcRequest.ts | 36 -- src-web/hooks/useDuplicateHttpRequest.ts | 29 -- src-web/hooks/useEnvironments.ts | 30 -- src-web/hooks/useEnvironmentsBreakdown.ts | 13 + src-web/hooks/useExportData.tsx | 6 +- src-web/hooks/useFloatingSidebarHidden.ts | 5 +- src-web/hooks/useFolders.ts | 14 - src-web/hooks/useGrpcConnections.ts | 8 - src-web/hooks/useGrpcEvents.ts | 23 - src-web/hooks/useGrpcProtoFiles.ts | 9 - src-web/hooks/useGrpcRequest.ts | 7 - src-web/hooks/useGrpcRequests.ts | 13 - src-web/hooks/useHotKey.ts | 6 +- src-web/hooks/useHttpAuthenticationConfig.ts | 5 +- src-web/hooks/useHttpRequest.ts | 7 - src-web/hooks/useHttpRequests.ts | 13 - src-web/hooks/useHttpResponses.ts | 9 - src-web/hooks/useImportCurl.ts | 43 +- src-web/hooks/useImportData.tsx | 5 +- src-web/hooks/useKeyValue.ts | 15 +- src-web/hooks/useLatestGrpcConnection.ts | 7 +- src-web/hooks/useLatestHttpResponse.ts | 7 +- src-web/hooks/useMoveToWorkspace.tsx | 8 +- src-web/hooks/usePinnedGrpcConnection.ts | 85 +++- src-web/hooks/usePinnedHttpResponse.ts | 7 +- src-web/hooks/usePinnedWebsocketConnection.ts | 77 ++- src-web/hooks/usePluginInfo.ts | 11 +- src-web/hooks/usePlugins.ts | 29 +- src-web/hooks/useRecentCookieJars.ts | 15 +- src-web/hooks/useRecentEnvironments.ts | 11 +- src-web/hooks/useRecentRequests.ts | 13 +- src-web/hooks/useRecentWorkspaces.ts | 7 +- src-web/hooks/useRenameRequest.tsx | 46 -- src-web/hooks/useRenderTemplate.ts | 5 +- src-web/hooks/useRequestUpdateKey.ts | 32 +- src-web/hooks/useRequests.ts | 14 - src-web/hooks/useResolvedAppearance.ts | 5 +- src-web/hooks/useResolvedTheme.ts | 5 +- src-web/hooks/useSaveResponse.tsx | 4 +- src-web/hooks/useSendAnyHttpRequest.ts | 4 +- src-web/hooks/useSettings.ts | 16 - src-web/hooks/useSidebarHidden.ts | 7 +- src-web/hooks/useSidebarItemCollapsed.ts | 12 +- src-web/hooks/useSidebarWidth.ts | 7 +- src-web/hooks/useStateWithDeps.ts | 2 +- src-web/hooks/useSyncFontSizeSetting.ts | 5 +- src-web/hooks/useSyncModelStores.ts | 202 -------- src-web/hooks/useSyncWorkspaceChildModels.ts | 41 +- src-web/hooks/useSyncWorkspaceRequestTitle.ts | 10 +- src-web/hooks/useUpdateAnyFolder.ts | 18 - src-web/hooks/useUpdateAnyGrpcRequest.ts | 24 - src-web/hooks/useUpdateAnyHttpRequest.ts | 24 - src-web/hooks/useUpdateCookieJar.ts | 19 - src-web/hooks/useUpdateEnvironment.ts | 23 - src-web/hooks/useUpdateSettings.ts | 20 - src-web/hooks/useWebsocketConnections.ts | 17 - src-web/hooks/useWebsocketEvents.ts | 21 - src-web/hooks/useWebsocketRequests.ts | 13 - src-web/hooks/useWorkspaceMeta.ts | 13 - src-web/hooks/useWorkspaces.ts | 20 - src-web/hooks/useZoom.ts | 25 +- src-web/init/sync.ts | 11 +- src-web/lib/atoms/atomWithKVStorage.ts | 25 + src-web/lib/deleteModelWithConfirm.tsx | 29 ++ src-web/lib/deleteRequestAndNavigate.tsx | 23 + src-web/lib/keyValueStore.ts | 39 +- src-web/lib/renameModelWithPrompt.tsx | 31 ++ src-web/lib/resolvedModelName.ts | 4 +- src-web/lib/settings.ts | 6 + src-web/lib/tauri.ts | 41 +- src-web/main.tsx | 4 + src-web/package.json | 1 - src-web/theme.ts | 9 +- 201 files changed, 2185 insertions(+), 2865 deletions(-) create mode 100644 src-tauri/migrations/20250326193143_key-value-id.sql create mode 100644 src-tauri/yaak-models/guest-js/atoms.ts create mode 100644 src-tauri/yaak-models/guest-js/index.ts create mode 100644 src-tauri/yaak-models/guest-js/store.ts create mode 100644 src-tauri/yaak-models/guest-js/types.ts create mode 100644 src-tauri/yaak-models/guest-js/util.ts delete mode 100644 src-tauri/yaak-models/index.ts create mode 100644 src-tauri/yaak-models/permissions/autogenerated/commands/duplicate.toml create mode 100644 src-tauri/yaak-models/permissions/autogenerated/commands/get_settings.toml create mode 100644 src-tauri/yaak-models/permissions/autogenerated/commands/grpc_events.toml create mode 100644 src-tauri/yaak-models/permissions/autogenerated/commands/websocket_events.toml create mode 100644 src-tauri/yaak-models/permissions/autogenerated/commands/workspace_models.toml delete mode 100644 src-web/commands/deleteWebsocketConnection.ts delete mode 100644 src-web/commands/deleteWebsocketRequest.tsx delete mode 100644 src-web/commands/duplicateWebsocketRequest.ts delete mode 100644 src-web/commands/upsertWebsocketRequest.ts delete mode 100644 src-web/commands/upsertWorkspace.ts delete mode 100644 src-web/commands/upsertWorkspaceMeta.ts rename src-web/components/{GrpcProtoSelection.tsx => GrpcProtoSelectionDialog.tsx} (90%) rename src-web/components/{GrpcConnectionSetupPane.tsx => GrpcRequestPane.tsx} (86%) rename src-web/components/{GrpcConnectionMessagesPane.tsx => GrpcResponsePane.tsx} (93%) create mode 100644 src-web/hooks/useAllRequests.ts delete mode 100644 src-web/hooks/useCookieJars.ts delete mode 100644 src-web/hooks/useDeleteActiveWorkspace.tsx delete mode 100644 src-web/hooks/useDeleteAnyGrpcRequest.tsx delete mode 100644 src-web/hooks/useDeleteAnyHttpRequest.tsx delete mode 100644 src-web/hooks/useDeleteAnyRequest.tsx delete mode 100644 src-web/hooks/useDeleteCookieJar.tsx delete mode 100644 src-web/hooks/useDeleteEnvironment.tsx delete mode 100644 src-web/hooks/useDeleteFolder.tsx delete mode 100644 src-web/hooks/useDeleteGrpcConnection.ts delete mode 100644 src-web/hooks/useDeleteHttpResponse.ts delete mode 100644 src-web/hooks/useDuplicateFolder.ts delete mode 100644 src-web/hooks/useDuplicateGrpcRequest.ts delete mode 100644 src-web/hooks/useDuplicateHttpRequest.ts delete mode 100644 src-web/hooks/useEnvironments.ts create mode 100644 src-web/hooks/useEnvironmentsBreakdown.ts delete mode 100644 src-web/hooks/useFolders.ts delete mode 100644 src-web/hooks/useGrpcConnections.ts delete mode 100644 src-web/hooks/useGrpcEvents.ts delete mode 100644 src-web/hooks/useGrpcRequest.ts delete mode 100644 src-web/hooks/useGrpcRequests.ts delete mode 100644 src-web/hooks/useHttpRequest.ts delete mode 100644 src-web/hooks/useHttpRequests.ts delete mode 100644 src-web/hooks/useHttpResponses.ts delete mode 100644 src-web/hooks/useRenameRequest.tsx delete mode 100644 src-web/hooks/useRequests.ts delete mode 100644 src-web/hooks/useSettings.ts delete mode 100644 src-web/hooks/useSyncModelStores.ts delete mode 100644 src-web/hooks/useUpdateAnyFolder.ts delete mode 100644 src-web/hooks/useUpdateAnyGrpcRequest.ts delete mode 100644 src-web/hooks/useUpdateAnyHttpRequest.ts delete mode 100644 src-web/hooks/useUpdateCookieJar.ts delete mode 100644 src-web/hooks/useUpdateEnvironment.ts delete mode 100644 src-web/hooks/useUpdateSettings.ts delete mode 100644 src-web/hooks/useWebsocketConnections.ts delete mode 100644 src-web/hooks/useWebsocketEvents.ts delete mode 100644 src-web/hooks/useWebsocketRequests.ts delete mode 100644 src-web/hooks/useWorkspaceMeta.ts delete mode 100644 src-web/hooks/useWorkspaces.ts create mode 100644 src-web/lib/atoms/atomWithKVStorage.ts create mode 100644 src-web/lib/deleteModelWithConfirm.tsx create mode 100644 src-web/lib/deleteRequestAndNavigate.tsx create mode 100644 src-web/lib/renameModelWithPrompt.tsx create mode 100644 src-web/lib/settings.ts diff --git a/package-lock.json b/package-lock.json index 15ce1299..b22d4e83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,9 @@ "src-tauri/yaak-ws", "src-web" ], + "dependencies": { + "jotai": "^2.12.2" + }, "devDependencies": { "@tauri-apps/cli": "^2.4.0", "@typescript-eslint/eslint-plugin": "^8.27.0", @@ -8558,9 +8561,9 @@ } }, "node_modules/jotai": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.10.0.tgz", - "integrity": "sha512-8W4u0aRlOIwGlLQ0sqfl/c6+eExl5D8lZgAUolirZLktyaj4WnxO/8a0HEPmtriQAB6X5LMhXzZVmw02X0P0qQ==", + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.12.2.tgz", + "integrity": "sha512-oN8715y7MkjXlSrpyjlR887TOuc/NLZMs9gvgtfWH/JP47ChwO0lR2ijSwBvPMYyXRAPT+liIAhuBavluKGgtA==", "license": "MIT", "engines": { "node": ">=12.20.0" @@ -15741,7 +15744,6 @@ "fuzzbunny": "^1.0.1", "hexy": "^0.3.5", "history": "^5.3.0", - "jotai": "^2.9.3", "js-md5": "^0.8.3", "lucide-react": "^0.474.0", "mime": "^4.0.4", diff --git a/package.json b/package.json index 6fbb1aaf..84b690aa 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,9 @@ "tauri-before-build": "npm run bootstrap && npm run --workspaces --if-present build", "tauri-before-dev": "npm run --workspaces --if-present dev" }, + "dependencies": { + "jotai": "^2.12.2" + }, "devDependencies": { "@tauri-apps/cli": "^2.4.0", "@typescript-eslint/eslint-plugin": "^8.27.0", diff --git a/src-tauri/gen/schemas/acl-manifests.json b/src-tauri/gen/schemas/acl-manifests.json index 2f0f127f..c64132a4 100644 --- a/src-tauri/gen/schemas/acl-manifests.json +++ b/src-tauri/gen/schemas/acl-manifests.json @@ -1 +1 @@ -{"clipboard-manager":{"default_permission":{"identifier":"default","description":"No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n","permissions":[]},"permissions":{"allow-clear":{"identifier":"allow-clear","description":"Enables the clear command without any pre-configured scope.","commands":{"allow":["clear"],"deny":[]}},"allow-read-image":{"identifier":"allow-read-image","description":"Enables the read_image command without any pre-configured scope.","commands":{"allow":["read_image"],"deny":[]}},"allow-read-text":{"identifier":"allow-read-text","description":"Enables the read_text command without any pre-configured scope.","commands":{"allow":["read_text"],"deny":[]}},"allow-write-html":{"identifier":"allow-write-html","description":"Enables the write_html command without any pre-configured scope.","commands":{"allow":["write_html"],"deny":[]}},"allow-write-image":{"identifier":"allow-write-image","description":"Enables the write_image command without any pre-configured scope.","commands":{"allow":["write_image"],"deny":[]}},"allow-write-text":{"identifier":"allow-write-text","description":"Enables the write_text command without any pre-configured scope.","commands":{"allow":["write_text"],"deny":[]}},"deny-clear":{"identifier":"deny-clear","description":"Denies the clear command without any pre-configured scope.","commands":{"allow":[],"deny":["clear"]}},"deny-read-image":{"identifier":"deny-read-image","description":"Denies the read_image command without any pre-configured scope.","commands":{"allow":[],"deny":["read_image"]}},"deny-read-text":{"identifier":"deny-read-text","description":"Denies the read_text command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text"]}},"deny-write-html":{"identifier":"deny-write-html","description":"Denies the write_html command without any pre-configured scope.","commands":{"allow":[],"deny":["write_html"]}},"deny-write-image":{"identifier":"deny-write-image","description":"Denies the write_image command without any pre-configured scope.","commands":{"allow":[],"deny":["write_image"]}},"deny-write-text":{"identifier":"deny-write-text","description":"Denies the write_text command without any pre-configured scope.","commands":{"allow":[],"deny":["write_text"]}}},"permission_sets":{},"global_scope_schema":null},"core":{"default_permission":{"identifier":"default","description":"Default core plugins set which includes:\n- 'core:path:default'\n- 'core:event:default'\n- 'core:window:default'\n- 'core:webview:default'\n- 'core:app:default'\n- 'core:image:default'\n- 'core:resources:default'\n- 'core:menu:default'\n- 'core:tray:default'\n","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-internal-toggle-maximize"]},"permissions":{"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"dialog":{"default_permission":{"identifier":"default","description":"This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n","permissions":["allow-ask","allow-confirm","allow-message","allow-save","allow-open"]},"permissions":{"allow-ask":{"identifier":"allow-ask","description":"Enables the ask command without any pre-configured scope.","commands":{"allow":["ask"],"deny":[]}},"allow-confirm":{"identifier":"allow-confirm","description":"Enables the confirm command without any pre-configured scope.","commands":{"allow":["confirm"],"deny":[]}},"allow-message":{"identifier":"allow-message","description":"Enables the message command without any pre-configured scope.","commands":{"allow":["message"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-save":{"identifier":"allow-save","description":"Enables the save command without any pre-configured scope.","commands":{"allow":["save"],"deny":[]}},"deny-ask":{"identifier":"deny-ask","description":"Denies the ask command without any pre-configured scope.","commands":{"allow":[],"deny":["ask"]}},"deny-confirm":{"identifier":"deny-confirm","description":"Denies the confirm command without any pre-configured scope.","commands":{"allow":[],"deny":["confirm"]}},"deny-message":{"identifier":"deny-message","description":"Denies the message command without any pre-configured scope.","commands":{"allow":[],"deny":["message"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-save":{"identifier":"deny-save","description":"Denies the save command without any pre-configured scope.","commands":{"allow":[],"deny":["save"]}}},"permission_sets":{},"global_scope_schema":null},"fs":{"default_permission":{"identifier":"default","description":"This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n","permissions":["create-app-specific-dirs","read-app-specific-dirs-recursive","deny-default"]},"permissions":{"allow-copy-file":{"identifier":"allow-copy-file","description":"Enables the copy_file command without any pre-configured scope.","commands":{"allow":["copy_file"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-exists":{"identifier":"allow-exists","description":"Enables the exists command without any pre-configured scope.","commands":{"allow":["exists"],"deny":[]}},"allow-fstat":{"identifier":"allow-fstat","description":"Enables the fstat command without any pre-configured scope.","commands":{"allow":["fstat"],"deny":[]}},"allow-ftruncate":{"identifier":"allow-ftruncate","description":"Enables the ftruncate command without any pre-configured scope.","commands":{"allow":["ftruncate"],"deny":[]}},"allow-lstat":{"identifier":"allow-lstat","description":"Enables the lstat command without any pre-configured scope.","commands":{"allow":["lstat"],"deny":[]}},"allow-mkdir":{"identifier":"allow-mkdir","description":"Enables the mkdir command without any pre-configured scope.","commands":{"allow":["mkdir"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-read":{"identifier":"allow-read","description":"Enables the read command without any pre-configured scope.","commands":{"allow":["read"],"deny":[]}},"allow-read-dir":{"identifier":"allow-read-dir","description":"Enables the read_dir command without any pre-configured scope.","commands":{"allow":["read_dir"],"deny":[]}},"allow-read-file":{"identifier":"allow-read-file","description":"Enables the read_file command without any pre-configured scope.","commands":{"allow":["read_file"],"deny":[]}},"allow-read-text-file":{"identifier":"allow-read-text-file","description":"Enables the read_text_file command without any pre-configured scope.","commands":{"allow":["read_text_file"],"deny":[]}},"allow-read-text-file-lines":{"identifier":"allow-read-text-file-lines","description":"Enables the read_text_file_lines command without any pre-configured scope.","commands":{"allow":["read_text_file_lines","read_text_file_lines_next"],"deny":[]}},"allow-read-text-file-lines-next":{"identifier":"allow-read-text-file-lines-next","description":"Enables the read_text_file_lines_next command without any pre-configured scope.","commands":{"allow":["read_text_file_lines_next"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-rename":{"identifier":"allow-rename","description":"Enables the rename command without any pre-configured scope.","commands":{"allow":["rename"],"deny":[]}},"allow-seek":{"identifier":"allow-seek","description":"Enables the seek command without any pre-configured scope.","commands":{"allow":["seek"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"allow-stat":{"identifier":"allow-stat","description":"Enables the stat command without any pre-configured scope.","commands":{"allow":["stat"],"deny":[]}},"allow-truncate":{"identifier":"allow-truncate","description":"Enables the truncate command without any pre-configured scope.","commands":{"allow":["truncate"],"deny":[]}},"allow-unwatch":{"identifier":"allow-unwatch","description":"Enables the unwatch command without any pre-configured scope.","commands":{"allow":["unwatch"],"deny":[]}},"allow-watch":{"identifier":"allow-watch","description":"Enables the watch command without any pre-configured scope.","commands":{"allow":["watch"],"deny":[]}},"allow-write":{"identifier":"allow-write","description":"Enables the write command without any pre-configured scope.","commands":{"allow":["write"],"deny":[]}},"allow-write-file":{"identifier":"allow-write-file","description":"Enables the write_file command without any pre-configured scope.","commands":{"allow":["write_file","open","write"],"deny":[]}},"allow-write-text-file":{"identifier":"allow-write-text-file","description":"Enables the write_text_file command without any pre-configured scope.","commands":{"allow":["write_text_file"],"deny":[]}},"create-app-specific-dirs":{"identifier":"create-app-specific-dirs","description":"This permissions allows to create the application specific directories.\n","commands":{"allow":["mkdir","scope-app-index"],"deny":[]}},"deny-copy-file":{"identifier":"deny-copy-file","description":"Denies the copy_file command without any pre-configured scope.","commands":{"allow":[],"deny":["copy_file"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-exists":{"identifier":"deny-exists","description":"Denies the exists command without any pre-configured scope.","commands":{"allow":[],"deny":["exists"]}},"deny-fstat":{"identifier":"deny-fstat","description":"Denies the fstat command without any pre-configured scope.","commands":{"allow":[],"deny":["fstat"]}},"deny-ftruncate":{"identifier":"deny-ftruncate","description":"Denies the ftruncate command without any pre-configured scope.","commands":{"allow":[],"deny":["ftruncate"]}},"deny-lstat":{"identifier":"deny-lstat","description":"Denies the lstat command without any pre-configured scope.","commands":{"allow":[],"deny":["lstat"]}},"deny-mkdir":{"identifier":"deny-mkdir","description":"Denies the mkdir command without any pre-configured scope.","commands":{"allow":[],"deny":["mkdir"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-read":{"identifier":"deny-read","description":"Denies the read command without any pre-configured scope.","commands":{"allow":[],"deny":["read"]}},"deny-read-dir":{"identifier":"deny-read-dir","description":"Denies the read_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["read_dir"]}},"deny-read-file":{"identifier":"deny-read-file","description":"Denies the read_file command without any pre-configured scope.","commands":{"allow":[],"deny":["read_file"]}},"deny-read-text-file":{"identifier":"deny-read-text-file","description":"Denies the read_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text_file"]}},"deny-read-text-file-lines":{"identifier":"deny-read-text-file-lines","description":"Denies the read_text_file_lines command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text_file_lines"]}},"deny-read-text-file-lines-next":{"identifier":"deny-read-text-file-lines-next","description":"Denies the read_text_file_lines_next command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text_file_lines_next"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-rename":{"identifier":"deny-rename","description":"Denies the rename command without any pre-configured scope.","commands":{"allow":[],"deny":["rename"]}},"deny-seek":{"identifier":"deny-seek","description":"Denies the seek command without any pre-configured scope.","commands":{"allow":[],"deny":["seek"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}},"deny-stat":{"identifier":"deny-stat","description":"Denies the stat command without any pre-configured scope.","commands":{"allow":[],"deny":["stat"]}},"deny-truncate":{"identifier":"deny-truncate","description":"Denies the truncate command without any pre-configured scope.","commands":{"allow":[],"deny":["truncate"]}},"deny-unwatch":{"identifier":"deny-unwatch","description":"Denies the unwatch command without any pre-configured scope.","commands":{"allow":[],"deny":["unwatch"]}},"deny-watch":{"identifier":"deny-watch","description":"Denies the watch command without any pre-configured scope.","commands":{"allow":[],"deny":["watch"]}},"deny-webview-data-linux":{"identifier":"deny-webview-data-linux","description":"This denies read access to the\n`$APPLOCALDATA` folder on linux as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered.","commands":{"allow":[],"deny":[]}},"deny-webview-data-windows":{"identifier":"deny-webview-data-windows","description":"This denies read access to the\n`$APPLOCALDATA/EBWebView` folder on windows as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered.","commands":{"allow":[],"deny":[]}},"deny-write":{"identifier":"deny-write","description":"Denies the write command without any pre-configured scope.","commands":{"allow":[],"deny":["write"]}},"deny-write-file":{"identifier":"deny-write-file","description":"Denies the write_file command without any pre-configured scope.","commands":{"allow":[],"deny":["write_file"]}},"deny-write-text-file":{"identifier":"deny-write-text-file","description":"Denies the write_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["write_text_file"]}},"read-all":{"identifier":"read-all","description":"This enables all read related commands without any pre-configured accessible paths.","commands":{"allow":["read_dir","read_file","read","open","read_text_file","read_text_file_lines","read_text_file_lines_next","seek","stat","lstat","fstat","exists","watch","unwatch"],"deny":[]}},"read-app-specific-dirs-recursive":{"identifier":"read-app-specific-dirs-recursive","description":"This permission allows recursive read functionality on the application\nspecific base directories. \n","commands":{"allow":["read_dir","read_file","read_text_file","read_text_file_lines","read_text_file_lines_next","exists","scope-app-recursive"],"deny":[]}},"read-dirs":{"identifier":"read-dirs","description":"This enables directory read and file metadata related commands without any pre-configured accessible paths.","commands":{"allow":["read_dir","stat","lstat","fstat","exists"],"deny":[]}},"read-files":{"identifier":"read-files","description":"This enables file read related commands without any pre-configured accessible paths.","commands":{"allow":["read_file","read","open","read_text_file","read_text_file_lines","read_text_file_lines_next","seek","stat","lstat","fstat","exists"],"deny":[]}},"read-meta":{"identifier":"read-meta","description":"This enables all index or metadata related commands without any pre-configured accessible paths.","commands":{"allow":["read_dir","stat","lstat","fstat","exists","size"],"deny":[]}},"scope":{"identifier":"scope","description":"An empty permission you can use to modify the global scope.","commands":{"allow":[],"deny":[]}},"scope-app":{"identifier":"scope-app","description":"This scope permits access to all files and list content of top level directories in the application folders.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/*"},{"path":"$APPDATA"},{"path":"$APPDATA/*"},{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/*"},{"path":"$APPCACHE"},{"path":"$APPCACHE/*"},{"path":"$APPLOG"},{"path":"$APPLOG/*"}]}},"scope-app-index":{"identifier":"scope-app-index","description":"This scope permits to list all files and folders in the application directories.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPDATA"},{"path":"$APPLOCALDATA"},{"path":"$APPCACHE"},{"path":"$APPLOG"}]}},"scope-app-recursive":{"identifier":"scope-app-recursive","description":"This scope permits recursive access to the complete application folders, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/**"},{"path":"$APPDATA"},{"path":"$APPDATA/**"},{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/**"},{"path":"$APPCACHE"},{"path":"$APPCACHE/**"},{"path":"$APPLOG"},{"path":"$APPLOG/**"}]}},"scope-appcache":{"identifier":"scope-appcache","description":"This scope permits access to all files and list content of top level directories in the `$APPCACHE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCACHE"},{"path":"$APPCACHE/*"}]}},"scope-appcache-index":{"identifier":"scope-appcache-index","description":"This scope permits to list all files and folders in the `$APPCACHE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCACHE"}]}},"scope-appcache-recursive":{"identifier":"scope-appcache-recursive","description":"This scope permits recursive access to the complete `$APPCACHE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCACHE"},{"path":"$APPCACHE/**"}]}},"scope-appconfig":{"identifier":"scope-appconfig","description":"This scope permits access to all files and list content of top level directories in the `$APPCONFIG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/*"}]}},"scope-appconfig-index":{"identifier":"scope-appconfig-index","description":"This scope permits to list all files and folders in the `$APPCONFIG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"}]}},"scope-appconfig-recursive":{"identifier":"scope-appconfig-recursive","description":"This scope permits recursive access to the complete `$APPCONFIG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/**"}]}},"scope-appdata":{"identifier":"scope-appdata","description":"This scope permits access to all files and list content of top level directories in the `$APPDATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPDATA"},{"path":"$APPDATA/*"}]}},"scope-appdata-index":{"identifier":"scope-appdata-index","description":"This scope permits to list all files and folders in the `$APPDATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPDATA"}]}},"scope-appdata-recursive":{"identifier":"scope-appdata-recursive","description":"This scope permits recursive access to the complete `$APPDATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPDATA"},{"path":"$APPDATA/**"}]}},"scope-applocaldata":{"identifier":"scope-applocaldata","description":"This scope permits access to all files and list content of top level directories in the `$APPLOCALDATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/*"}]}},"scope-applocaldata-index":{"identifier":"scope-applocaldata-index","description":"This scope permits to list all files and folders in the `$APPLOCALDATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOCALDATA"}]}},"scope-applocaldata-recursive":{"identifier":"scope-applocaldata-recursive","description":"This scope permits recursive access to the complete `$APPLOCALDATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/**"}]}},"scope-applog":{"identifier":"scope-applog","description":"This scope permits access to all files and list content of top level directories in the `$APPLOG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOG"},{"path":"$APPLOG/*"}]}},"scope-applog-index":{"identifier":"scope-applog-index","description":"This scope permits to list all files and folders in the `$APPLOG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOG"}]}},"scope-applog-recursive":{"identifier":"scope-applog-recursive","description":"This scope permits recursive access to the complete `$APPLOG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOG"},{"path":"$APPLOG/**"}]}},"scope-audio":{"identifier":"scope-audio","description":"This scope permits access to all files and list content of top level directories in the `$AUDIO` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$AUDIO"},{"path":"$AUDIO/*"}]}},"scope-audio-index":{"identifier":"scope-audio-index","description":"This scope permits to list all files and folders in the `$AUDIO`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$AUDIO"}]}},"scope-audio-recursive":{"identifier":"scope-audio-recursive","description":"This scope permits recursive access to the complete `$AUDIO` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$AUDIO"},{"path":"$AUDIO/**"}]}},"scope-cache":{"identifier":"scope-cache","description":"This scope permits access to all files and list content of top level directories in the `$CACHE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CACHE"},{"path":"$CACHE/*"}]}},"scope-cache-index":{"identifier":"scope-cache-index","description":"This scope permits to list all files and folders in the `$CACHE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CACHE"}]}},"scope-cache-recursive":{"identifier":"scope-cache-recursive","description":"This scope permits recursive access to the complete `$CACHE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CACHE"},{"path":"$CACHE/**"}]}},"scope-config":{"identifier":"scope-config","description":"This scope permits access to all files and list content of top level directories in the `$CONFIG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CONFIG"},{"path":"$CONFIG/*"}]}},"scope-config-index":{"identifier":"scope-config-index","description":"This scope permits to list all files and folders in the `$CONFIG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CONFIG"}]}},"scope-config-recursive":{"identifier":"scope-config-recursive","description":"This scope permits recursive access to the complete `$CONFIG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CONFIG"},{"path":"$CONFIG/**"}]}},"scope-data":{"identifier":"scope-data","description":"This scope permits access to all files and list content of top level directories in the `$DATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DATA"},{"path":"$DATA/*"}]}},"scope-data-index":{"identifier":"scope-data-index","description":"This scope permits to list all files and folders in the `$DATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DATA"}]}},"scope-data-recursive":{"identifier":"scope-data-recursive","description":"This scope permits recursive access to the complete `$DATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DATA"},{"path":"$DATA/**"}]}},"scope-desktop":{"identifier":"scope-desktop","description":"This scope permits access to all files and list content of top level directories in the `$DESKTOP` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DESKTOP"},{"path":"$DESKTOP/*"}]}},"scope-desktop-index":{"identifier":"scope-desktop-index","description":"This scope permits to list all files and folders in the `$DESKTOP`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DESKTOP"}]}},"scope-desktop-recursive":{"identifier":"scope-desktop-recursive","description":"This scope permits recursive access to the complete `$DESKTOP` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DESKTOP"},{"path":"$DESKTOP/**"}]}},"scope-document":{"identifier":"scope-document","description":"This scope permits access to all files and list content of top level directories in the `$DOCUMENT` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOCUMENT"},{"path":"$DOCUMENT/*"}]}},"scope-document-index":{"identifier":"scope-document-index","description":"This scope permits to list all files and folders in the `$DOCUMENT`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOCUMENT"}]}},"scope-document-recursive":{"identifier":"scope-document-recursive","description":"This scope permits recursive access to the complete `$DOCUMENT` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOCUMENT"},{"path":"$DOCUMENT/**"}]}},"scope-download":{"identifier":"scope-download","description":"This scope permits access to all files and list content of top level directories in the `$DOWNLOAD` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOWNLOAD"},{"path":"$DOWNLOAD/*"}]}},"scope-download-index":{"identifier":"scope-download-index","description":"This scope permits to list all files and folders in the `$DOWNLOAD`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOWNLOAD"}]}},"scope-download-recursive":{"identifier":"scope-download-recursive","description":"This scope permits recursive access to the complete `$DOWNLOAD` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOWNLOAD"},{"path":"$DOWNLOAD/**"}]}},"scope-exe":{"identifier":"scope-exe","description":"This scope permits access to all files and list content of top level directories in the `$EXE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$EXE"},{"path":"$EXE/*"}]}},"scope-exe-index":{"identifier":"scope-exe-index","description":"This scope permits to list all files and folders in the `$EXE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$EXE"}]}},"scope-exe-recursive":{"identifier":"scope-exe-recursive","description":"This scope permits recursive access to the complete `$EXE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$EXE"},{"path":"$EXE/**"}]}},"scope-font":{"identifier":"scope-font","description":"This scope permits access to all files and list content of top level directories in the `$FONT` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$FONT"},{"path":"$FONT/*"}]}},"scope-font-index":{"identifier":"scope-font-index","description":"This scope permits to list all files and folders in the `$FONT`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$FONT"}]}},"scope-font-recursive":{"identifier":"scope-font-recursive","description":"This scope permits recursive access to the complete `$FONT` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$FONT"},{"path":"$FONT/**"}]}},"scope-home":{"identifier":"scope-home","description":"This scope permits access to all files and list content of top level directories in the `$HOME` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$HOME"},{"path":"$HOME/*"}]}},"scope-home-index":{"identifier":"scope-home-index","description":"This scope permits to list all files and folders in the `$HOME`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$HOME"}]}},"scope-home-recursive":{"identifier":"scope-home-recursive","description":"This scope permits recursive access to the complete `$HOME` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$HOME"},{"path":"$HOME/**"}]}},"scope-localdata":{"identifier":"scope-localdata","description":"This scope permits access to all files and list content of top level directories in the `$LOCALDATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOCALDATA"},{"path":"$LOCALDATA/*"}]}},"scope-localdata-index":{"identifier":"scope-localdata-index","description":"This scope permits to list all files and folders in the `$LOCALDATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOCALDATA"}]}},"scope-localdata-recursive":{"identifier":"scope-localdata-recursive","description":"This scope permits recursive access to the complete `$LOCALDATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOCALDATA"},{"path":"$LOCALDATA/**"}]}},"scope-log":{"identifier":"scope-log","description":"This scope permits access to all files and list content of top level directories in the `$LOG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOG"},{"path":"$LOG/*"}]}},"scope-log-index":{"identifier":"scope-log-index","description":"This scope permits to list all files and folders in the `$LOG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOG"}]}},"scope-log-recursive":{"identifier":"scope-log-recursive","description":"This scope permits recursive access to the complete `$LOG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOG"},{"path":"$LOG/**"}]}},"scope-picture":{"identifier":"scope-picture","description":"This scope permits access to all files and list content of top level directories in the `$PICTURE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PICTURE"},{"path":"$PICTURE/*"}]}},"scope-picture-index":{"identifier":"scope-picture-index","description":"This scope permits to list all files and folders in the `$PICTURE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PICTURE"}]}},"scope-picture-recursive":{"identifier":"scope-picture-recursive","description":"This scope permits recursive access to the complete `$PICTURE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PICTURE"},{"path":"$PICTURE/**"}]}},"scope-public":{"identifier":"scope-public","description":"This scope permits access to all files and list content of top level directories in the `$PUBLIC` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PUBLIC"},{"path":"$PUBLIC/*"}]}},"scope-public-index":{"identifier":"scope-public-index","description":"This scope permits to list all files and folders in the `$PUBLIC`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PUBLIC"}]}},"scope-public-recursive":{"identifier":"scope-public-recursive","description":"This scope permits recursive access to the complete `$PUBLIC` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PUBLIC"},{"path":"$PUBLIC/**"}]}},"scope-resource":{"identifier":"scope-resource","description":"This scope permits access to all files and list content of top level directories in the `$RESOURCE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RESOURCE"},{"path":"$RESOURCE/*"}]}},"scope-resource-index":{"identifier":"scope-resource-index","description":"This scope permits to list all files and folders in the `$RESOURCE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RESOURCE"}]}},"scope-resource-recursive":{"identifier":"scope-resource-recursive","description":"This scope permits recursive access to the complete `$RESOURCE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RESOURCE"},{"path":"$RESOURCE/**"}]}},"scope-runtime":{"identifier":"scope-runtime","description":"This scope permits access to all files and list content of top level directories in the `$RUNTIME` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RUNTIME"},{"path":"$RUNTIME/*"}]}},"scope-runtime-index":{"identifier":"scope-runtime-index","description":"This scope permits to list all files and folders in the `$RUNTIME`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RUNTIME"}]}},"scope-runtime-recursive":{"identifier":"scope-runtime-recursive","description":"This scope permits recursive access to the complete `$RUNTIME` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RUNTIME"},{"path":"$RUNTIME/**"}]}},"scope-temp":{"identifier":"scope-temp","description":"This scope permits access to all files and list content of top level directories in the `$TEMP` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMP"},{"path":"$TEMP/*"}]}},"scope-temp-index":{"identifier":"scope-temp-index","description":"This scope permits to list all files and folders in the `$TEMP`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMP"}]}},"scope-temp-recursive":{"identifier":"scope-temp-recursive","description":"This scope permits recursive access to the complete `$TEMP` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMP"},{"path":"$TEMP/**"}]}},"scope-template":{"identifier":"scope-template","description":"This scope permits access to all files and list content of top level directories in the `$TEMPLATE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMPLATE"},{"path":"$TEMPLATE/*"}]}},"scope-template-index":{"identifier":"scope-template-index","description":"This scope permits to list all files and folders in the `$TEMPLATE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMPLATE"}]}},"scope-template-recursive":{"identifier":"scope-template-recursive","description":"This scope permits recursive access to the complete `$TEMPLATE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMPLATE"},{"path":"$TEMPLATE/**"}]}},"scope-video":{"identifier":"scope-video","description":"This scope permits access to all files and list content of top level directories in the `$VIDEO` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$VIDEO"},{"path":"$VIDEO/*"}]}},"scope-video-index":{"identifier":"scope-video-index","description":"This scope permits to list all files and folders in the `$VIDEO`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$VIDEO"}]}},"scope-video-recursive":{"identifier":"scope-video-recursive","description":"This scope permits recursive access to the complete `$VIDEO` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$VIDEO"},{"path":"$VIDEO/**"}]}},"write-all":{"identifier":"write-all","description":"This enables all write related commands without any pre-configured accessible paths.","commands":{"allow":["mkdir","create","copy_file","remove","rename","truncate","ftruncate","write","write_file","write_text_file"],"deny":[]}},"write-files":{"identifier":"write-files","description":"This enables all file write related commands without any pre-configured accessible paths.","commands":{"allow":["create","copy_file","remove","rename","truncate","ftruncate","write","write_file","write_text_file"],"deny":[]}}},"permission_sets":{"allow-app-meta":{"identifier":"allow-app-meta","description":"This allows non-recursive read access to metadata of the application folders, including file listing and statistics.","permissions":["read-meta","scope-app-index"]},"allow-app-meta-recursive":{"identifier":"allow-app-meta-recursive","description":"This allows full recursive read access to metadata of the application folders, including file listing and statistics.","permissions":["read-meta","scope-app-recursive"]},"allow-app-read":{"identifier":"allow-app-read","description":"This allows non-recursive read access to the application folders.","permissions":["read-all","scope-app"]},"allow-app-read-recursive":{"identifier":"allow-app-read-recursive","description":"This allows full recursive read access to the complete application folders, files and subdirectories.","permissions":["read-all","scope-app-recursive"]},"allow-app-write":{"identifier":"allow-app-write","description":"This allows non-recursive write access to the application folders.","permissions":["write-all","scope-app"]},"allow-app-write-recursive":{"identifier":"allow-app-write-recursive","description":"This allows full recursive write access to the complete application folders, files and subdirectories.","permissions":["write-all","scope-app-recursive"]},"allow-appcache-meta":{"identifier":"allow-appcache-meta","description":"This allows non-recursive read access to metadata of the `$APPCACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-appcache-index"]},"allow-appcache-meta-recursive":{"identifier":"allow-appcache-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPCACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-appcache-recursive"]},"allow-appcache-read":{"identifier":"allow-appcache-read","description":"This allows non-recursive read access to the `$APPCACHE` folder.","permissions":["read-all","scope-appcache"]},"allow-appcache-read-recursive":{"identifier":"allow-appcache-read-recursive","description":"This allows full recursive read access to the complete `$APPCACHE` folder, files and subdirectories.","permissions":["read-all","scope-appcache-recursive"]},"allow-appcache-write":{"identifier":"allow-appcache-write","description":"This allows non-recursive write access to the `$APPCACHE` folder.","permissions":["write-all","scope-appcache"]},"allow-appcache-write-recursive":{"identifier":"allow-appcache-write-recursive","description":"This allows full recursive write access to the complete `$APPCACHE` folder, files and subdirectories.","permissions":["write-all","scope-appcache-recursive"]},"allow-appconfig-meta":{"identifier":"allow-appconfig-meta","description":"This allows non-recursive read access to metadata of the `$APPCONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-appconfig-index"]},"allow-appconfig-meta-recursive":{"identifier":"allow-appconfig-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPCONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-appconfig-recursive"]},"allow-appconfig-read":{"identifier":"allow-appconfig-read","description":"This allows non-recursive read access to the `$APPCONFIG` folder.","permissions":["read-all","scope-appconfig"]},"allow-appconfig-read-recursive":{"identifier":"allow-appconfig-read-recursive","description":"This allows full recursive read access to the complete `$APPCONFIG` folder, files and subdirectories.","permissions":["read-all","scope-appconfig-recursive"]},"allow-appconfig-write":{"identifier":"allow-appconfig-write","description":"This allows non-recursive write access to the `$APPCONFIG` folder.","permissions":["write-all","scope-appconfig"]},"allow-appconfig-write-recursive":{"identifier":"allow-appconfig-write-recursive","description":"This allows full recursive write access to the complete `$APPCONFIG` folder, files and subdirectories.","permissions":["write-all","scope-appconfig-recursive"]},"allow-appdata-meta":{"identifier":"allow-appdata-meta","description":"This allows non-recursive read access to metadata of the `$APPDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-appdata-index"]},"allow-appdata-meta-recursive":{"identifier":"allow-appdata-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-appdata-recursive"]},"allow-appdata-read":{"identifier":"allow-appdata-read","description":"This allows non-recursive read access to the `$APPDATA` folder.","permissions":["read-all","scope-appdata"]},"allow-appdata-read-recursive":{"identifier":"allow-appdata-read-recursive","description":"This allows full recursive read access to the complete `$APPDATA` folder, files and subdirectories.","permissions":["read-all","scope-appdata-recursive"]},"allow-appdata-write":{"identifier":"allow-appdata-write","description":"This allows non-recursive write access to the `$APPDATA` folder.","permissions":["write-all","scope-appdata"]},"allow-appdata-write-recursive":{"identifier":"allow-appdata-write-recursive","description":"This allows full recursive write access to the complete `$APPDATA` folder, files and subdirectories.","permissions":["write-all","scope-appdata-recursive"]},"allow-applocaldata-meta":{"identifier":"allow-applocaldata-meta","description":"This allows non-recursive read access to metadata of the `$APPLOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-applocaldata-index"]},"allow-applocaldata-meta-recursive":{"identifier":"allow-applocaldata-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPLOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-applocaldata-recursive"]},"allow-applocaldata-read":{"identifier":"allow-applocaldata-read","description":"This allows non-recursive read access to the `$APPLOCALDATA` folder.","permissions":["read-all","scope-applocaldata"]},"allow-applocaldata-read-recursive":{"identifier":"allow-applocaldata-read-recursive","description":"This allows full recursive read access to the complete `$APPLOCALDATA` folder, files and subdirectories.","permissions":["read-all","scope-applocaldata-recursive"]},"allow-applocaldata-write":{"identifier":"allow-applocaldata-write","description":"This allows non-recursive write access to the `$APPLOCALDATA` folder.","permissions":["write-all","scope-applocaldata"]},"allow-applocaldata-write-recursive":{"identifier":"allow-applocaldata-write-recursive","description":"This allows full recursive write access to the complete `$APPLOCALDATA` folder, files and subdirectories.","permissions":["write-all","scope-applocaldata-recursive"]},"allow-applog-meta":{"identifier":"allow-applog-meta","description":"This allows non-recursive read access to metadata of the `$APPLOG` folder, including file listing and statistics.","permissions":["read-meta","scope-applog-index"]},"allow-applog-meta-recursive":{"identifier":"allow-applog-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPLOG` folder, including file listing and statistics.","permissions":["read-meta","scope-applog-recursive"]},"allow-applog-read":{"identifier":"allow-applog-read","description":"This allows non-recursive read access to the `$APPLOG` folder.","permissions":["read-all","scope-applog"]},"allow-applog-read-recursive":{"identifier":"allow-applog-read-recursive","description":"This allows full recursive read access to the complete `$APPLOG` folder, files and subdirectories.","permissions":["read-all","scope-applog-recursive"]},"allow-applog-write":{"identifier":"allow-applog-write","description":"This allows non-recursive write access to the `$APPLOG` folder.","permissions":["write-all","scope-applog"]},"allow-applog-write-recursive":{"identifier":"allow-applog-write-recursive","description":"This allows full recursive write access to the complete `$APPLOG` folder, files and subdirectories.","permissions":["write-all","scope-applog-recursive"]},"allow-audio-meta":{"identifier":"allow-audio-meta","description":"This allows non-recursive read access to metadata of the `$AUDIO` folder, including file listing and statistics.","permissions":["read-meta","scope-audio-index"]},"allow-audio-meta-recursive":{"identifier":"allow-audio-meta-recursive","description":"This allows full recursive read access to metadata of the `$AUDIO` folder, including file listing and statistics.","permissions":["read-meta","scope-audio-recursive"]},"allow-audio-read":{"identifier":"allow-audio-read","description":"This allows non-recursive read access to the `$AUDIO` folder.","permissions":["read-all","scope-audio"]},"allow-audio-read-recursive":{"identifier":"allow-audio-read-recursive","description":"This allows full recursive read access to the complete `$AUDIO` folder, files and subdirectories.","permissions":["read-all","scope-audio-recursive"]},"allow-audio-write":{"identifier":"allow-audio-write","description":"This allows non-recursive write access to the `$AUDIO` folder.","permissions":["write-all","scope-audio"]},"allow-audio-write-recursive":{"identifier":"allow-audio-write-recursive","description":"This allows full recursive write access to the complete `$AUDIO` folder, files and subdirectories.","permissions":["write-all","scope-audio-recursive"]},"allow-cache-meta":{"identifier":"allow-cache-meta","description":"This allows non-recursive read access to metadata of the `$CACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-cache-index"]},"allow-cache-meta-recursive":{"identifier":"allow-cache-meta-recursive","description":"This allows full recursive read access to metadata of the `$CACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-cache-recursive"]},"allow-cache-read":{"identifier":"allow-cache-read","description":"This allows non-recursive read access to the `$CACHE` folder.","permissions":["read-all","scope-cache"]},"allow-cache-read-recursive":{"identifier":"allow-cache-read-recursive","description":"This allows full recursive read access to the complete `$CACHE` folder, files and subdirectories.","permissions":["read-all","scope-cache-recursive"]},"allow-cache-write":{"identifier":"allow-cache-write","description":"This allows non-recursive write access to the `$CACHE` folder.","permissions":["write-all","scope-cache"]},"allow-cache-write-recursive":{"identifier":"allow-cache-write-recursive","description":"This allows full recursive write access to the complete `$CACHE` folder, files and subdirectories.","permissions":["write-all","scope-cache-recursive"]},"allow-config-meta":{"identifier":"allow-config-meta","description":"This allows non-recursive read access to metadata of the `$CONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-config-index"]},"allow-config-meta-recursive":{"identifier":"allow-config-meta-recursive","description":"This allows full recursive read access to metadata of the `$CONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-config-recursive"]},"allow-config-read":{"identifier":"allow-config-read","description":"This allows non-recursive read access to the `$CONFIG` folder.","permissions":["read-all","scope-config"]},"allow-config-read-recursive":{"identifier":"allow-config-read-recursive","description":"This allows full recursive read access to the complete `$CONFIG` folder, files and subdirectories.","permissions":["read-all","scope-config-recursive"]},"allow-config-write":{"identifier":"allow-config-write","description":"This allows non-recursive write access to the `$CONFIG` folder.","permissions":["write-all","scope-config"]},"allow-config-write-recursive":{"identifier":"allow-config-write-recursive","description":"This allows full recursive write access to the complete `$CONFIG` folder, files and subdirectories.","permissions":["write-all","scope-config-recursive"]},"allow-data-meta":{"identifier":"allow-data-meta","description":"This allows non-recursive read access to metadata of the `$DATA` folder, including file listing and statistics.","permissions":["read-meta","scope-data-index"]},"allow-data-meta-recursive":{"identifier":"allow-data-meta-recursive","description":"This allows full recursive read access to metadata of the `$DATA` folder, including file listing and statistics.","permissions":["read-meta","scope-data-recursive"]},"allow-data-read":{"identifier":"allow-data-read","description":"This allows non-recursive read access to the `$DATA` folder.","permissions":["read-all","scope-data"]},"allow-data-read-recursive":{"identifier":"allow-data-read-recursive","description":"This allows full recursive read access to the complete `$DATA` folder, files and subdirectories.","permissions":["read-all","scope-data-recursive"]},"allow-data-write":{"identifier":"allow-data-write","description":"This allows non-recursive write access to the `$DATA` folder.","permissions":["write-all","scope-data"]},"allow-data-write-recursive":{"identifier":"allow-data-write-recursive","description":"This allows full recursive write access to the complete `$DATA` folder, files and subdirectories.","permissions":["write-all","scope-data-recursive"]},"allow-desktop-meta":{"identifier":"allow-desktop-meta","description":"This allows non-recursive read access to metadata of the `$DESKTOP` folder, including file listing and statistics.","permissions":["read-meta","scope-desktop-index"]},"allow-desktop-meta-recursive":{"identifier":"allow-desktop-meta-recursive","description":"This allows full recursive read access to metadata of the `$DESKTOP` folder, including file listing and statistics.","permissions":["read-meta","scope-desktop-recursive"]},"allow-desktop-read":{"identifier":"allow-desktop-read","description":"This allows non-recursive read access to the `$DESKTOP` folder.","permissions":["read-all","scope-desktop"]},"allow-desktop-read-recursive":{"identifier":"allow-desktop-read-recursive","description":"This allows full recursive read access to the complete `$DESKTOP` folder, files and subdirectories.","permissions":["read-all","scope-desktop-recursive"]},"allow-desktop-write":{"identifier":"allow-desktop-write","description":"This allows non-recursive write access to the `$DESKTOP` folder.","permissions":["write-all","scope-desktop"]},"allow-desktop-write-recursive":{"identifier":"allow-desktop-write-recursive","description":"This allows full recursive write access to the complete `$DESKTOP` folder, files and subdirectories.","permissions":["write-all","scope-desktop-recursive"]},"allow-document-meta":{"identifier":"allow-document-meta","description":"This allows non-recursive read access to metadata of the `$DOCUMENT` folder, including file listing and statistics.","permissions":["read-meta","scope-document-index"]},"allow-document-meta-recursive":{"identifier":"allow-document-meta-recursive","description":"This allows full recursive read access to metadata of the `$DOCUMENT` folder, including file listing and statistics.","permissions":["read-meta","scope-document-recursive"]},"allow-document-read":{"identifier":"allow-document-read","description":"This allows non-recursive read access to the `$DOCUMENT` folder.","permissions":["read-all","scope-document"]},"allow-document-read-recursive":{"identifier":"allow-document-read-recursive","description":"This allows full recursive read access to the complete `$DOCUMENT` folder, files and subdirectories.","permissions":["read-all","scope-document-recursive"]},"allow-document-write":{"identifier":"allow-document-write","description":"This allows non-recursive write access to the `$DOCUMENT` folder.","permissions":["write-all","scope-document"]},"allow-document-write-recursive":{"identifier":"allow-document-write-recursive","description":"This allows full recursive write access to the complete `$DOCUMENT` folder, files and subdirectories.","permissions":["write-all","scope-document-recursive"]},"allow-download-meta":{"identifier":"allow-download-meta","description":"This allows non-recursive read access to metadata of the `$DOWNLOAD` folder, including file listing and statistics.","permissions":["read-meta","scope-download-index"]},"allow-download-meta-recursive":{"identifier":"allow-download-meta-recursive","description":"This allows full recursive read access to metadata of the `$DOWNLOAD` folder, including file listing and statistics.","permissions":["read-meta","scope-download-recursive"]},"allow-download-read":{"identifier":"allow-download-read","description":"This allows non-recursive read access to the `$DOWNLOAD` folder.","permissions":["read-all","scope-download"]},"allow-download-read-recursive":{"identifier":"allow-download-read-recursive","description":"This allows full recursive read access to the complete `$DOWNLOAD` folder, files and subdirectories.","permissions":["read-all","scope-download-recursive"]},"allow-download-write":{"identifier":"allow-download-write","description":"This allows non-recursive write access to the `$DOWNLOAD` folder.","permissions":["write-all","scope-download"]},"allow-download-write-recursive":{"identifier":"allow-download-write-recursive","description":"This allows full recursive write access to the complete `$DOWNLOAD` folder, files and subdirectories.","permissions":["write-all","scope-download-recursive"]},"allow-exe-meta":{"identifier":"allow-exe-meta","description":"This allows non-recursive read access to metadata of the `$EXE` folder, including file listing and statistics.","permissions":["read-meta","scope-exe-index"]},"allow-exe-meta-recursive":{"identifier":"allow-exe-meta-recursive","description":"This allows full recursive read access to metadata of the `$EXE` folder, including file listing and statistics.","permissions":["read-meta","scope-exe-recursive"]},"allow-exe-read":{"identifier":"allow-exe-read","description":"This allows non-recursive read access to the `$EXE` folder.","permissions":["read-all","scope-exe"]},"allow-exe-read-recursive":{"identifier":"allow-exe-read-recursive","description":"This allows full recursive read access to the complete `$EXE` folder, files and subdirectories.","permissions":["read-all","scope-exe-recursive"]},"allow-exe-write":{"identifier":"allow-exe-write","description":"This allows non-recursive write access to the `$EXE` folder.","permissions":["write-all","scope-exe"]},"allow-exe-write-recursive":{"identifier":"allow-exe-write-recursive","description":"This allows full recursive write access to the complete `$EXE` folder, files and subdirectories.","permissions":["write-all","scope-exe-recursive"]},"allow-font-meta":{"identifier":"allow-font-meta","description":"This allows non-recursive read access to metadata of the `$FONT` folder, including file listing and statistics.","permissions":["read-meta","scope-font-index"]},"allow-font-meta-recursive":{"identifier":"allow-font-meta-recursive","description":"This allows full recursive read access to metadata of the `$FONT` folder, including file listing and statistics.","permissions":["read-meta","scope-font-recursive"]},"allow-font-read":{"identifier":"allow-font-read","description":"This allows non-recursive read access to the `$FONT` folder.","permissions":["read-all","scope-font"]},"allow-font-read-recursive":{"identifier":"allow-font-read-recursive","description":"This allows full recursive read access to the complete `$FONT` folder, files and subdirectories.","permissions":["read-all","scope-font-recursive"]},"allow-font-write":{"identifier":"allow-font-write","description":"This allows non-recursive write access to the `$FONT` folder.","permissions":["write-all","scope-font"]},"allow-font-write-recursive":{"identifier":"allow-font-write-recursive","description":"This allows full recursive write access to the complete `$FONT` folder, files and subdirectories.","permissions":["write-all","scope-font-recursive"]},"allow-home-meta":{"identifier":"allow-home-meta","description":"This allows non-recursive read access to metadata of the `$HOME` folder, including file listing and statistics.","permissions":["read-meta","scope-home-index"]},"allow-home-meta-recursive":{"identifier":"allow-home-meta-recursive","description":"This allows full recursive read access to metadata of the `$HOME` folder, including file listing and statistics.","permissions":["read-meta","scope-home-recursive"]},"allow-home-read":{"identifier":"allow-home-read","description":"This allows non-recursive read access to the `$HOME` folder.","permissions":["read-all","scope-home"]},"allow-home-read-recursive":{"identifier":"allow-home-read-recursive","description":"This allows full recursive read access to the complete `$HOME` folder, files and subdirectories.","permissions":["read-all","scope-home-recursive"]},"allow-home-write":{"identifier":"allow-home-write","description":"This allows non-recursive write access to the `$HOME` folder.","permissions":["write-all","scope-home"]},"allow-home-write-recursive":{"identifier":"allow-home-write-recursive","description":"This allows full recursive write access to the complete `$HOME` folder, files and subdirectories.","permissions":["write-all","scope-home-recursive"]},"allow-localdata-meta":{"identifier":"allow-localdata-meta","description":"This allows non-recursive read access to metadata of the `$LOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-localdata-index"]},"allow-localdata-meta-recursive":{"identifier":"allow-localdata-meta-recursive","description":"This allows full recursive read access to metadata of the `$LOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-localdata-recursive"]},"allow-localdata-read":{"identifier":"allow-localdata-read","description":"This allows non-recursive read access to the `$LOCALDATA` folder.","permissions":["read-all","scope-localdata"]},"allow-localdata-read-recursive":{"identifier":"allow-localdata-read-recursive","description":"This allows full recursive read access to the complete `$LOCALDATA` folder, files and subdirectories.","permissions":["read-all","scope-localdata-recursive"]},"allow-localdata-write":{"identifier":"allow-localdata-write","description":"This allows non-recursive write access to the `$LOCALDATA` folder.","permissions":["write-all","scope-localdata"]},"allow-localdata-write-recursive":{"identifier":"allow-localdata-write-recursive","description":"This allows full recursive write access to the complete `$LOCALDATA` folder, files and subdirectories.","permissions":["write-all","scope-localdata-recursive"]},"allow-log-meta":{"identifier":"allow-log-meta","description":"This allows non-recursive read access to metadata of the `$LOG` folder, including file listing and statistics.","permissions":["read-meta","scope-log-index"]},"allow-log-meta-recursive":{"identifier":"allow-log-meta-recursive","description":"This allows full recursive read access to metadata of the `$LOG` folder, including file listing and statistics.","permissions":["read-meta","scope-log-recursive"]},"allow-log-read":{"identifier":"allow-log-read","description":"This allows non-recursive read access to the `$LOG` folder.","permissions":["read-all","scope-log"]},"allow-log-read-recursive":{"identifier":"allow-log-read-recursive","description":"This allows full recursive read access to the complete `$LOG` folder, files and subdirectories.","permissions":["read-all","scope-log-recursive"]},"allow-log-write":{"identifier":"allow-log-write","description":"This allows non-recursive write access to the `$LOG` folder.","permissions":["write-all","scope-log"]},"allow-log-write-recursive":{"identifier":"allow-log-write-recursive","description":"This allows full recursive write access to the complete `$LOG` folder, files and subdirectories.","permissions":["write-all","scope-log-recursive"]},"allow-picture-meta":{"identifier":"allow-picture-meta","description":"This allows non-recursive read access to metadata of the `$PICTURE` folder, including file listing and statistics.","permissions":["read-meta","scope-picture-index"]},"allow-picture-meta-recursive":{"identifier":"allow-picture-meta-recursive","description":"This allows full recursive read access to metadata of the `$PICTURE` folder, including file listing and statistics.","permissions":["read-meta","scope-picture-recursive"]},"allow-picture-read":{"identifier":"allow-picture-read","description":"This allows non-recursive read access to the `$PICTURE` folder.","permissions":["read-all","scope-picture"]},"allow-picture-read-recursive":{"identifier":"allow-picture-read-recursive","description":"This allows full recursive read access to the complete `$PICTURE` folder, files and subdirectories.","permissions":["read-all","scope-picture-recursive"]},"allow-picture-write":{"identifier":"allow-picture-write","description":"This allows non-recursive write access to the `$PICTURE` folder.","permissions":["write-all","scope-picture"]},"allow-picture-write-recursive":{"identifier":"allow-picture-write-recursive","description":"This allows full recursive write access to the complete `$PICTURE` folder, files and subdirectories.","permissions":["write-all","scope-picture-recursive"]},"allow-public-meta":{"identifier":"allow-public-meta","description":"This allows non-recursive read access to metadata of the `$PUBLIC` folder, including file listing and statistics.","permissions":["read-meta","scope-public-index"]},"allow-public-meta-recursive":{"identifier":"allow-public-meta-recursive","description":"This allows full recursive read access to metadata of the `$PUBLIC` folder, including file listing and statistics.","permissions":["read-meta","scope-public-recursive"]},"allow-public-read":{"identifier":"allow-public-read","description":"This allows non-recursive read access to the `$PUBLIC` folder.","permissions":["read-all","scope-public"]},"allow-public-read-recursive":{"identifier":"allow-public-read-recursive","description":"This allows full recursive read access to the complete `$PUBLIC` folder, files and subdirectories.","permissions":["read-all","scope-public-recursive"]},"allow-public-write":{"identifier":"allow-public-write","description":"This allows non-recursive write access to the `$PUBLIC` folder.","permissions":["write-all","scope-public"]},"allow-public-write-recursive":{"identifier":"allow-public-write-recursive","description":"This allows full recursive write access to the complete `$PUBLIC` folder, files and subdirectories.","permissions":["write-all","scope-public-recursive"]},"allow-resource-meta":{"identifier":"allow-resource-meta","description":"This allows non-recursive read access to metadata of the `$RESOURCE` folder, including file listing and statistics.","permissions":["read-meta","scope-resource-index"]},"allow-resource-meta-recursive":{"identifier":"allow-resource-meta-recursive","description":"This allows full recursive read access to metadata of the `$RESOURCE` folder, including file listing and statistics.","permissions":["read-meta","scope-resource-recursive"]},"allow-resource-read":{"identifier":"allow-resource-read","description":"This allows non-recursive read access to the `$RESOURCE` folder.","permissions":["read-all","scope-resource"]},"allow-resource-read-recursive":{"identifier":"allow-resource-read-recursive","description":"This allows full recursive read access to the complete `$RESOURCE` folder, files and subdirectories.","permissions":["read-all","scope-resource-recursive"]},"allow-resource-write":{"identifier":"allow-resource-write","description":"This allows non-recursive write access to the `$RESOURCE` folder.","permissions":["write-all","scope-resource"]},"allow-resource-write-recursive":{"identifier":"allow-resource-write-recursive","description":"This allows full recursive write access to the complete `$RESOURCE` folder, files and subdirectories.","permissions":["write-all","scope-resource-recursive"]},"allow-runtime-meta":{"identifier":"allow-runtime-meta","description":"This allows non-recursive read access to metadata of the `$RUNTIME` folder, including file listing and statistics.","permissions":["read-meta","scope-runtime-index"]},"allow-runtime-meta-recursive":{"identifier":"allow-runtime-meta-recursive","description":"This allows full recursive read access to metadata of the `$RUNTIME` folder, including file listing and statistics.","permissions":["read-meta","scope-runtime-recursive"]},"allow-runtime-read":{"identifier":"allow-runtime-read","description":"This allows non-recursive read access to the `$RUNTIME` folder.","permissions":["read-all","scope-runtime"]},"allow-runtime-read-recursive":{"identifier":"allow-runtime-read-recursive","description":"This allows full recursive read access to the complete `$RUNTIME` folder, files and subdirectories.","permissions":["read-all","scope-runtime-recursive"]},"allow-runtime-write":{"identifier":"allow-runtime-write","description":"This allows non-recursive write access to the `$RUNTIME` folder.","permissions":["write-all","scope-runtime"]},"allow-runtime-write-recursive":{"identifier":"allow-runtime-write-recursive","description":"This allows full recursive write access to the complete `$RUNTIME` folder, files and subdirectories.","permissions":["write-all","scope-runtime-recursive"]},"allow-temp-meta":{"identifier":"allow-temp-meta","description":"This allows non-recursive read access to metadata of the `$TEMP` folder, including file listing and statistics.","permissions":["read-meta","scope-temp-index"]},"allow-temp-meta-recursive":{"identifier":"allow-temp-meta-recursive","description":"This allows full recursive read access to metadata of the `$TEMP` folder, including file listing and statistics.","permissions":["read-meta","scope-temp-recursive"]},"allow-temp-read":{"identifier":"allow-temp-read","description":"This allows non-recursive read access to the `$TEMP` folder.","permissions":["read-all","scope-temp"]},"allow-temp-read-recursive":{"identifier":"allow-temp-read-recursive","description":"This allows full recursive read access to the complete `$TEMP` folder, files and subdirectories.","permissions":["read-all","scope-temp-recursive"]},"allow-temp-write":{"identifier":"allow-temp-write","description":"This allows non-recursive write access to the `$TEMP` folder.","permissions":["write-all","scope-temp"]},"allow-temp-write-recursive":{"identifier":"allow-temp-write-recursive","description":"This allows full recursive write access to the complete `$TEMP` folder, files and subdirectories.","permissions":["write-all","scope-temp-recursive"]},"allow-template-meta":{"identifier":"allow-template-meta","description":"This allows non-recursive read access to metadata of the `$TEMPLATE` folder, including file listing and statistics.","permissions":["read-meta","scope-template-index"]},"allow-template-meta-recursive":{"identifier":"allow-template-meta-recursive","description":"This allows full recursive read access to metadata of the `$TEMPLATE` folder, including file listing and statistics.","permissions":["read-meta","scope-template-recursive"]},"allow-template-read":{"identifier":"allow-template-read","description":"This allows non-recursive read access to the `$TEMPLATE` folder.","permissions":["read-all","scope-template"]},"allow-template-read-recursive":{"identifier":"allow-template-read-recursive","description":"This allows full recursive read access to the complete `$TEMPLATE` folder, files and subdirectories.","permissions":["read-all","scope-template-recursive"]},"allow-template-write":{"identifier":"allow-template-write","description":"This allows non-recursive write access to the `$TEMPLATE` folder.","permissions":["write-all","scope-template"]},"allow-template-write-recursive":{"identifier":"allow-template-write-recursive","description":"This allows full recursive write access to the complete `$TEMPLATE` folder, files and subdirectories.","permissions":["write-all","scope-template-recursive"]},"allow-video-meta":{"identifier":"allow-video-meta","description":"This allows non-recursive read access to metadata of the `$VIDEO` folder, including file listing and statistics.","permissions":["read-meta","scope-video-index"]},"allow-video-meta-recursive":{"identifier":"allow-video-meta-recursive","description":"This allows full recursive read access to metadata of the `$VIDEO` folder, including file listing and statistics.","permissions":["read-meta","scope-video-recursive"]},"allow-video-read":{"identifier":"allow-video-read","description":"This allows non-recursive read access to the `$VIDEO` folder.","permissions":["read-all","scope-video"]},"allow-video-read-recursive":{"identifier":"allow-video-read-recursive","description":"This allows full recursive read access to the complete `$VIDEO` folder, files and subdirectories.","permissions":["read-all","scope-video-recursive"]},"allow-video-write":{"identifier":"allow-video-write","description":"This allows non-recursive write access to the `$VIDEO` folder.","permissions":["write-all","scope-video"]},"allow-video-write-recursive":{"identifier":"allow-video-write-recursive","description":"This allows full recursive write access to the complete `$VIDEO` folder, files and subdirectories.","permissions":["write-all","scope-video-recursive"]},"deny-default":{"identifier":"deny-default","description":"This denies access to dangerous Tauri relevant files and folders by default.","permissions":["deny-webview-data-linux","deny-webview-data-windows"]}},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"description":"A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},{"properties":{"path":{"description":"A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"}},"required":["path"],"type":"object"}],"description":"FS scope entry.","title":"FsScopeEntry"}},"log":{"default_permission":{"identifier":"default","description":"Allows the log command","permissions":["allow-log"]},"permissions":{"allow-log":{"identifier":"allow-log","description":"Enables the log command without any pre-configured scope.","commands":{"allow":["log"],"deny":[]}},"deny-log":{"identifier":"deny-log","description":"Denies the log command without any pre-configured scope.","commands":{"allow":[],"deny":["log"]}}},"permission_sets":{},"global_scope_schema":null},"opener":{"default_permission":{"identifier":"default","description":"This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer","permissions":["allow-open-url","allow-reveal-item-in-dir","allow-default-urls"]},"permissions":{"allow-default-urls":{"identifier":"allow-default-urls","description":"This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"url":"mailto:*"},{"url":"tel:*"},{"url":"http://*"},{"url":"https://*"}]}},"allow-open-path":{"identifier":"allow-open-path","description":"Enables the open_path command without any pre-configured scope.","commands":{"allow":["open_path"],"deny":[]}},"allow-open-url":{"identifier":"allow-open-url","description":"Enables the open_url command without any pre-configured scope.","commands":{"allow":["open_url"],"deny":[]}},"allow-reveal-item-in-dir":{"identifier":"allow-reveal-item-in-dir","description":"Enables the reveal_item_in_dir command without any pre-configured scope.","commands":{"allow":["reveal_item_in_dir"],"deny":[]}},"deny-open-path":{"identifier":"deny-open-path","description":"Denies the open_path command without any pre-configured scope.","commands":{"allow":[],"deny":["open_path"]}},"deny-open-url":{"identifier":"deny-open-url","description":"Denies the open_url command without any pre-configured scope.","commands":{"allow":[],"deny":["open_url"]}},"deny-reveal-item-in-dir":{"identifier":"deny-reveal-item-in-dir","description":"Denies the reveal_item_in_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["reveal_item_in_dir"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"properties":{"app":{"allOf":[{"$ref":"#/definitions/Application"}],"description":"An application to open this url with, for example: firefox."},"url":{"description":"A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"","type":"string"}},"required":["url"],"type":"object"},{"properties":{"app":{"allOf":[{"$ref":"#/definitions/Application"}],"description":"An application to open this path with, for example: xdg-open."},"path":{"description":"A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"}},"required":["path"],"type":"object"}],"definitions":{"Application":{"anyOf":[{"description":"Open in default application.","type":"null"},{"description":"If true, allow open with any application.","type":"boolean"},{"description":"Allow specific application to open with.","type":"string"}],"description":"Opener scope application."}},"description":"Opener scope entry.","title":"OpenerScopeEntry"}},"os":{"default_permission":{"identifier":"default","description":"This permission set configures which\noperating system information are available\nto gather from the frontend.\n\n#### Granted Permissions\n\nAll information except the host name are available.\n\n","permissions":["allow-arch","allow-exe-extension","allow-family","allow-locale","allow-os-type","allow-platform","allow-version"]},"permissions":{"allow-arch":{"identifier":"allow-arch","description":"Enables the arch command without any pre-configured scope.","commands":{"allow":["arch"],"deny":[]}},"allow-exe-extension":{"identifier":"allow-exe-extension","description":"Enables the exe_extension command without any pre-configured scope.","commands":{"allow":["exe_extension"],"deny":[]}},"allow-family":{"identifier":"allow-family","description":"Enables the family command without any pre-configured scope.","commands":{"allow":["family"],"deny":[]}},"allow-hostname":{"identifier":"allow-hostname","description":"Enables the hostname command without any pre-configured scope.","commands":{"allow":["hostname"],"deny":[]}},"allow-locale":{"identifier":"allow-locale","description":"Enables the locale command without any pre-configured scope.","commands":{"allow":["locale"],"deny":[]}},"allow-os-type":{"identifier":"allow-os-type","description":"Enables the os_type command without any pre-configured scope.","commands":{"allow":["os_type"],"deny":[]}},"allow-platform":{"identifier":"allow-platform","description":"Enables the platform command without any pre-configured scope.","commands":{"allow":["platform"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-arch":{"identifier":"deny-arch","description":"Denies the arch command without any pre-configured scope.","commands":{"allow":[],"deny":["arch"]}},"deny-exe-extension":{"identifier":"deny-exe-extension","description":"Denies the exe_extension command without any pre-configured scope.","commands":{"allow":[],"deny":["exe_extension"]}},"deny-family":{"identifier":"deny-family","description":"Denies the family command without any pre-configured scope.","commands":{"allow":[],"deny":["family"]}},"deny-hostname":{"identifier":"deny-hostname","description":"Denies the hostname command without any pre-configured scope.","commands":{"allow":[],"deny":["hostname"]}},"deny-locale":{"identifier":"deny-locale","description":"Denies the locale command without any pre-configured scope.","commands":{"allow":[],"deny":["locale"]}},"deny-os-type":{"identifier":"deny-os-type","description":"Denies the os_type command without any pre-configured scope.","commands":{"allow":[],"deny":["os_type"]}},"deny-platform":{"identifier":"deny-platform","description":"Denies the platform command without any pre-configured scope.","commands":{"allow":[],"deny":["platform"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"shell":{"default_permission":{"identifier":"default","description":"This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality without any specific\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n","permissions":["allow-open"]},"permissions":{"allow-execute":{"identifier":"allow-execute","description":"Enables the execute command without any pre-configured scope.","commands":{"allow":["execute"],"deny":[]}},"allow-kill":{"identifier":"allow-kill","description":"Enables the kill command without any pre-configured scope.","commands":{"allow":["kill"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-spawn":{"identifier":"allow-spawn","description":"Enables the spawn command without any pre-configured scope.","commands":{"allow":["spawn"],"deny":[]}},"allow-stdin-write":{"identifier":"allow-stdin-write","description":"Enables the stdin_write command without any pre-configured scope.","commands":{"allow":["stdin_write"],"deny":[]}},"deny-execute":{"identifier":"deny-execute","description":"Denies the execute command without any pre-configured scope.","commands":{"allow":[],"deny":["execute"]}},"deny-kill":{"identifier":"deny-kill","description":"Denies the kill command without any pre-configured scope.","commands":{"allow":[],"deny":["kill"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-spawn":{"identifier":"deny-spawn","description":"Denies the spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["spawn"]}},"deny-stdin-write":{"identifier":"deny-stdin-write","description":"Denies the stdin_write command without any pre-configured scope.","commands":{"allow":[],"deny":["stdin_write"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"cmd":{"description":"The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"}},"required":["cmd","name"],"type":"object"},{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"},"sidecar":{"description":"If this command is a sidecar command.","type":"boolean"}},"required":["name","sidecar"],"type":"object"}],"definitions":{"ShellScopeEntryAllowedArg":{"anyOf":[{"description":"A non-configurable argument that is passed to the command in the order it was specified.","type":"string"},{"additionalProperties":false,"description":"A variable that is set while calling the command from the webview API.","properties":{"raw":{"default":false,"description":"Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.","type":"boolean"},"validator":{"description":"[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\nThe regex string is by default surrounded by `^...$` to match the full string. For example the `https?://\\w+` regex would be registered as `^https?://\\w+$`.\n\n[regex]: ","type":"string"}},"required":["validator"],"type":"object"}],"description":"A command argument allowed to be executed by the webview API."},"ShellScopeEntryAllowedArgs":{"anyOf":[{"description":"Use a simple boolean to allow all or disable all arguments to this command configuration.","type":"boolean"},{"description":"A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration.","items":{"$ref":"#/definitions/ShellScopeEntryAllowedArg"},"type":"array"}],"description":"A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration."}},"description":"Shell scope entry.","title":"ShellScopeEntry"}},"updater":{"default_permission":{"identifier":"default","description":"This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n","permissions":["allow-check","allow-download","allow-install","allow-download-and-install"]},"permissions":{"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"allow-download":{"identifier":"allow-download","description":"Enables the download command without any pre-configured scope.","commands":{"allow":["download"],"deny":[]}},"allow-download-and-install":{"identifier":"allow-download-and-install","description":"Enables the download_and_install command without any pre-configured scope.","commands":{"allow":["download_and_install"],"deny":[]}},"allow-install":{"identifier":"allow-install","description":"Enables the install command without any pre-configured scope.","commands":{"allow":["install"],"deny":[]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}},"deny-download":{"identifier":"deny-download","description":"Denies the download command without any pre-configured scope.","commands":{"allow":[],"deny":["download"]}},"deny-download-and-install":{"identifier":"deny-download-and-install","description":"Denies the download_and_install command without any pre-configured scope.","commands":{"allow":[],"deny":["download_and_install"]}},"deny-install":{"identifier":"deny-install","description":"Denies the install command without any pre-configured scope.","commands":{"allow":[],"deny":["install"]}}},"permission_sets":{},"global_scope_schema":null},"window-state":{"default_permission":{"identifier":"default","description":"This permission set configures what kind of\noperations are available from the window state plugin.\n\n#### Granted Permissions\n\nAll operations are enabled by default.\n\n","permissions":["allow-filename","allow-restore-state","allow-save-window-state"]},"permissions":{"allow-filename":{"identifier":"allow-filename","description":"Enables the filename command without any pre-configured scope.","commands":{"allow":["filename"],"deny":[]}},"allow-restore-state":{"identifier":"allow-restore-state","description":"Enables the restore_state command without any pre-configured scope.","commands":{"allow":["restore_state"],"deny":[]}},"allow-save-window-state":{"identifier":"allow-save-window-state","description":"Enables the save_window_state command without any pre-configured scope.","commands":{"allow":["save_window_state"],"deny":[]}},"deny-filename":{"identifier":"deny-filename","description":"Denies the filename command without any pre-configured scope.","commands":{"allow":[],"deny":["filename"]}},"deny-restore-state":{"identifier":"deny-restore-state","description":"Denies the restore_state command without any pre-configured scope.","commands":{"allow":[],"deny":["restore_state"]}},"deny-save-window-state":{"identifier":"deny-save-window-state","description":"Denies the save_window_state command without any pre-configured scope.","commands":{"allow":[],"deny":["save_window_state"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-git":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-add","allow-branch","allow-checkout","allow-commit","allow-delete-branch","allow-fetch-all","allow-initialize","allow-log","allow-merge-branch","allow-pull","allow-push","allow-status","allow-unstage"]},"permissions":{"allow-add":{"identifier":"allow-add","description":"Enables the add command without any pre-configured scope.","commands":{"allow":["add"],"deny":[]}},"allow-branch":{"identifier":"allow-branch","description":"Enables the branch command without any pre-configured scope.","commands":{"allow":["branch"],"deny":[]}},"allow-checkout":{"identifier":"allow-checkout","description":"Enables the checkout command without any pre-configured scope.","commands":{"allow":["checkout"],"deny":[]}},"allow-checkout-remote":{"identifier":"allow-checkout-remote","description":"Enables the checkout_remote command without any pre-configured scope.","commands":{"allow":["checkout_remote"],"deny":[]}},"allow-commit":{"identifier":"allow-commit","description":"Enables the commit command without any pre-configured scope.","commands":{"allow":["commit"],"deny":[]}},"allow-delete-branch":{"identifier":"allow-delete-branch","description":"Enables the delete_branch command without any pre-configured scope.","commands":{"allow":["delete_branch"],"deny":[]}},"allow-fetch-all":{"identifier":"allow-fetch-all","description":"Enables the fetch_all command without any pre-configured scope.","commands":{"allow":["fetch_all"],"deny":[]}},"allow-initialize":{"identifier":"allow-initialize","description":"Enables the initialize command without any pre-configured scope.","commands":{"allow":["initialize"],"deny":[]}},"allow-log":{"identifier":"allow-log","description":"Enables the log command without any pre-configured scope.","commands":{"allow":["log"],"deny":[]}},"allow-merge-branch":{"identifier":"allow-merge-branch","description":"Enables the merge_branch command without any pre-configured scope.","commands":{"allow":["merge_branch"],"deny":[]}},"allow-pull":{"identifier":"allow-pull","description":"Enables the pull command without any pre-configured scope.","commands":{"allow":["pull"],"deny":[]}},"allow-push":{"identifier":"allow-push","description":"Enables the push command without any pre-configured scope.","commands":{"allow":["push"],"deny":[]}},"allow-status":{"identifier":"allow-status","description":"Enables the status command without any pre-configured scope.","commands":{"allow":["status"],"deny":[]}},"allow-unstage":{"identifier":"allow-unstage","description":"Enables the unstage command without any pre-configured scope.","commands":{"allow":["unstage"],"deny":[]}},"deny-add":{"identifier":"deny-add","description":"Denies the add command without any pre-configured scope.","commands":{"allow":[],"deny":["add"]}},"deny-branch":{"identifier":"deny-branch","description":"Denies the branch command without any pre-configured scope.","commands":{"allow":[],"deny":["branch"]}},"deny-checkout":{"identifier":"deny-checkout","description":"Denies the checkout command without any pre-configured scope.","commands":{"allow":[],"deny":["checkout"]}},"deny-checkout-remote":{"identifier":"deny-checkout-remote","description":"Denies the checkout_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["checkout_remote"]}},"deny-commit":{"identifier":"deny-commit","description":"Denies the commit command without any pre-configured scope.","commands":{"allow":[],"deny":["commit"]}},"deny-delete-branch":{"identifier":"deny-delete-branch","description":"Denies the delete_branch command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_branch"]}},"deny-fetch-all":{"identifier":"deny-fetch-all","description":"Denies the fetch_all command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_all"]}},"deny-initialize":{"identifier":"deny-initialize","description":"Denies the initialize command without any pre-configured scope.","commands":{"allow":[],"deny":["initialize"]}},"deny-log":{"identifier":"deny-log","description":"Denies the log command without any pre-configured scope.","commands":{"allow":[],"deny":["log"]}},"deny-merge-branch":{"identifier":"deny-merge-branch","description":"Denies the merge_branch command without any pre-configured scope.","commands":{"allow":[],"deny":["merge_branch"]}},"deny-pull":{"identifier":"deny-pull","description":"Denies the pull command without any pre-configured scope.","commands":{"allow":[],"deny":["pull"]}},"deny-push":{"identifier":"deny-push","description":"Denies the push command without any pre-configured scope.","commands":{"allow":[],"deny":["push"]}},"deny-status":{"identifier":"deny-status","description":"Denies the status command without any pre-configured scope.","commands":{"allow":[],"deny":["status"]}},"deny-unstage":{"identifier":"deny-unstage","description":"Denies the unstage command without any pre-configured scope.","commands":{"allow":[],"deny":["unstage"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-license":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-check","allow-activate","allow-deactivate"]},"permissions":{"allow-activate":{"identifier":"allow-activate","description":"Enables the activate command without any pre-configured scope.","commands":{"allow":["activate"],"deny":[]}},"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"allow-deactivate":{"identifier":"allow-deactivate","description":"Enables the deactivate command without any pre-configured scope.","commands":{"allow":["deactivate"],"deny":[]}},"deny-activate":{"identifier":"deny-activate","description":"Denies the activate command without any pre-configured scope.","commands":{"allow":[],"deny":["activate"]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}},"deny-deactivate":{"identifier":"deny-deactivate","description":"Denies the deactivate command without any pre-configured scope.","commands":{"allow":[],"deny":["deactivate"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-models":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-upsert","allow-delete"]},"permissions":{"allow-delete":{"identifier":"allow-delete","description":"Enables the delete command without any pre-configured scope.","commands":{"allow":["delete"],"deny":[]}},"allow-upsert":{"identifier":"allow-upsert","description":"Enables the upsert command without any pre-configured scope.","commands":{"allow":["upsert"],"deny":[]}},"deny-delete":{"identifier":"deny-delete","description":"Denies the delete command without any pre-configured scope.","commands":{"allow":[],"deny":["delete"]}},"deny-upsert":{"identifier":"deny-upsert","description":"Denies the upsert command without any pre-configured scope.","commands":{"allow":[],"deny":["upsert"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-sync":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-calculate","allow-calculate-fs","allow-apply","allow-watch"]},"permissions":{"allow-apply":{"identifier":"allow-apply","description":"Enables the apply command without any pre-configured scope.","commands":{"allow":["apply"],"deny":[]}},"allow-calculate":{"identifier":"allow-calculate","description":"Enables the calculate command without any pre-configured scope.","commands":{"allow":["calculate"],"deny":[]}},"allow-calculate-fs":{"identifier":"allow-calculate-fs","description":"Enables the calculate_fs command without any pre-configured scope.","commands":{"allow":["calculate_fs"],"deny":[]}},"allow-watch":{"identifier":"allow-watch","description":"Enables the watch command without any pre-configured scope.","commands":{"allow":["watch"],"deny":[]}},"deny-apply":{"identifier":"deny-apply","description":"Denies the apply command without any pre-configured scope.","commands":{"allow":[],"deny":["apply"]}},"deny-calculate":{"identifier":"deny-calculate","description":"Denies the calculate command without any pre-configured scope.","commands":{"allow":[],"deny":["calculate"]}},"deny-calculate-fs":{"identifier":"deny-calculate-fs","description":"Denies the calculate_fs command without any pre-configured scope.","commands":{"allow":[],"deny":["calculate_fs"]}},"deny-watch":{"identifier":"deny-watch","description":"Denies the watch command without any pre-configured scope.","commands":{"allow":[],"deny":["watch"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-ws":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-close","allow-connect","allow-delete-connection","allow-delete-connections","allow-delete-request","allow-duplicate-request","allow-list-connections","allow-list-events","allow-list-requests","allow-send","allow-upsert-request"]},"permissions":{"allow-cancel":{"identifier":"allow-cancel","description":"Enables the cancel command without any pre-configured scope.","commands":{"allow":["cancel"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-connect":{"identifier":"allow-connect","description":"Enables the connect command without any pre-configured scope.","commands":{"allow":["connect"],"deny":[]}},"allow-delete-connection":{"identifier":"allow-delete-connection","description":"Enables the delete_connection command without any pre-configured scope.","commands":{"allow":["delete_connection"],"deny":[]}},"allow-delete-connections":{"identifier":"allow-delete-connections","description":"Enables the delete_connections command without any pre-configured scope.","commands":{"allow":["delete_connections"],"deny":[]}},"allow-delete-request":{"identifier":"allow-delete-request","description":"Enables the delete_request command without any pre-configured scope.","commands":{"allow":["delete_request"],"deny":[]}},"allow-duplicate-request":{"identifier":"allow-duplicate-request","description":"Enables the duplicate_request command without any pre-configured scope.","commands":{"allow":["duplicate_request"],"deny":[]}},"allow-list-connections":{"identifier":"allow-list-connections","description":"Enables the list_connections command without any pre-configured scope.","commands":{"allow":["list_connections"],"deny":[]}},"allow-list-events":{"identifier":"allow-list-events","description":"Enables the list_events command without any pre-configured scope.","commands":{"allow":["list_events"],"deny":[]}},"allow-list-requests":{"identifier":"allow-list-requests","description":"Enables the list_requests command without any pre-configured scope.","commands":{"allow":["list_requests"],"deny":[]}},"allow-list-websocket-connections":{"identifier":"allow-list-websocket-connections","description":"Enables the list_websocket_connections command without any pre-configured scope.","commands":{"allow":["list_websocket_connections"],"deny":[]}},"allow-list-websocket-requests":{"identifier":"allow-list-websocket-requests","description":"Enables the list_websocket_requests command without any pre-configured scope.","commands":{"allow":["list_websocket_requests"],"deny":[]}},"allow-send":{"identifier":"allow-send","description":"Enables the send command without any pre-configured scope.","commands":{"allow":["send"],"deny":[]}},"allow-upsert-request":{"identifier":"allow-upsert-request","description":"Enables the upsert_request command without any pre-configured scope.","commands":{"allow":["upsert_request"],"deny":[]}},"allow-upsert-websocket-request":{"identifier":"allow-upsert-websocket-request","description":"Enables the upsert_websocket_request command without any pre-configured scope.","commands":{"allow":["upsert_websocket_request"],"deny":[]}},"deny-cancel":{"identifier":"deny-cancel","description":"Denies the cancel command without any pre-configured scope.","commands":{"allow":[],"deny":["cancel"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-connect":{"identifier":"deny-connect","description":"Denies the connect command without any pre-configured scope.","commands":{"allow":[],"deny":["connect"]}},"deny-delete-connection":{"identifier":"deny-delete-connection","description":"Denies the delete_connection command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_connection"]}},"deny-delete-connections":{"identifier":"deny-delete-connections","description":"Denies the delete_connections command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_connections"]}},"deny-delete-request":{"identifier":"deny-delete-request","description":"Denies the delete_request command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_request"]}},"deny-duplicate-request":{"identifier":"deny-duplicate-request","description":"Denies the duplicate_request command without any pre-configured scope.","commands":{"allow":[],"deny":["duplicate_request"]}},"deny-list-connections":{"identifier":"deny-list-connections","description":"Denies the list_connections command without any pre-configured scope.","commands":{"allow":[],"deny":["list_connections"]}},"deny-list-events":{"identifier":"deny-list-events","description":"Denies the list_events command without any pre-configured scope.","commands":{"allow":[],"deny":["list_events"]}},"deny-list-requests":{"identifier":"deny-list-requests","description":"Denies the list_requests command without any pre-configured scope.","commands":{"allow":[],"deny":["list_requests"]}},"deny-list-websocket-connections":{"identifier":"deny-list-websocket-connections","description":"Denies the list_websocket_connections command without any pre-configured scope.","commands":{"allow":[],"deny":["list_websocket_connections"]}},"deny-list-websocket-requests":{"identifier":"deny-list-websocket-requests","description":"Denies the list_websocket_requests command without any pre-configured scope.","commands":{"allow":[],"deny":["list_websocket_requests"]}},"deny-send":{"identifier":"deny-send","description":"Denies the send command without any pre-configured scope.","commands":{"allow":[],"deny":["send"]}},"deny-upsert-request":{"identifier":"deny-upsert-request","description":"Denies the upsert_request command without any pre-configured scope.","commands":{"allow":[],"deny":["upsert_request"]}},"deny-upsert-websocket-request":{"identifier":"deny-upsert-websocket-request","description":"Denies the upsert_websocket_request command without any pre-configured scope.","commands":{"allow":[],"deny":["upsert_websocket_request"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file +{"clipboard-manager":{"default_permission":{"identifier":"default","description":"No features are enabled by default, as we believe\nthe clipboard can be inherently dangerous and it is \napplication specific if read and/or write access is needed.\n\nClipboard interaction needs to be explicitly enabled.\n","permissions":[]},"permissions":{"allow-clear":{"identifier":"allow-clear","description":"Enables the clear command without any pre-configured scope.","commands":{"allow":["clear"],"deny":[]}},"allow-read-image":{"identifier":"allow-read-image","description":"Enables the read_image command without any pre-configured scope.","commands":{"allow":["read_image"],"deny":[]}},"allow-read-text":{"identifier":"allow-read-text","description":"Enables the read_text command without any pre-configured scope.","commands":{"allow":["read_text"],"deny":[]}},"allow-write-html":{"identifier":"allow-write-html","description":"Enables the write_html command without any pre-configured scope.","commands":{"allow":["write_html"],"deny":[]}},"allow-write-image":{"identifier":"allow-write-image","description":"Enables the write_image command without any pre-configured scope.","commands":{"allow":["write_image"],"deny":[]}},"allow-write-text":{"identifier":"allow-write-text","description":"Enables the write_text command without any pre-configured scope.","commands":{"allow":["write_text"],"deny":[]}},"deny-clear":{"identifier":"deny-clear","description":"Denies the clear command without any pre-configured scope.","commands":{"allow":[],"deny":["clear"]}},"deny-read-image":{"identifier":"deny-read-image","description":"Denies the read_image command without any pre-configured scope.","commands":{"allow":[],"deny":["read_image"]}},"deny-read-text":{"identifier":"deny-read-text","description":"Denies the read_text command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text"]}},"deny-write-html":{"identifier":"deny-write-html","description":"Denies the write_html command without any pre-configured scope.","commands":{"allow":[],"deny":["write_html"]}},"deny-write-image":{"identifier":"deny-write-image","description":"Denies the write_image command without any pre-configured scope.","commands":{"allow":[],"deny":["write_image"]}},"deny-write-text":{"identifier":"deny-write-text","description":"Denies the write_text command without any pre-configured scope.","commands":{"allow":[],"deny":["write_text"]}}},"permission_sets":{},"global_scope_schema":null},"core":{"default_permission":{"identifier":"default","description":"Default core plugins set which includes:\n- 'core:path:default'\n- 'core:event:default'\n- 'core:window:default'\n- 'core:webview:default'\n- 'core:app:default'\n- 'core:image:default'\n- 'core:resources:default'\n- 'core:menu:default'\n- 'core:tray:default'\n","permissions":["core:path:default","core:event:default","core:window:default","core:webview:default","core:app:default","core:image:default","core:resources:default","core:menu:default","core:tray:default"]},"permissions":{},"permission_sets":{},"global_scope_schema":null},"core:app":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-version","allow-name","allow-tauri-version","allow-identifier"]},"permissions":{"allow-app-hide":{"identifier":"allow-app-hide","description":"Enables the app_hide command without any pre-configured scope.","commands":{"allow":["app_hide"],"deny":[]}},"allow-app-show":{"identifier":"allow-app-show","description":"Enables the app_show command without any pre-configured scope.","commands":{"allow":["app_show"],"deny":[]}},"allow-default-window-icon":{"identifier":"allow-default-window-icon","description":"Enables the default_window_icon command without any pre-configured scope.","commands":{"allow":["default_window_icon"],"deny":[]}},"allow-fetch-data-store-identifiers":{"identifier":"allow-fetch-data-store-identifiers","description":"Enables the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":["fetch_data_store_identifiers"],"deny":[]}},"allow-identifier":{"identifier":"allow-identifier","description":"Enables the identifier command without any pre-configured scope.","commands":{"allow":["identifier"],"deny":[]}},"allow-name":{"identifier":"allow-name","description":"Enables the name command without any pre-configured scope.","commands":{"allow":["name"],"deny":[]}},"allow-remove-data-store":{"identifier":"allow-remove-data-store","description":"Enables the remove_data_store command without any pre-configured scope.","commands":{"allow":["remove_data_store"],"deny":[]}},"allow-set-app-theme":{"identifier":"allow-set-app-theme","description":"Enables the set_app_theme command without any pre-configured scope.","commands":{"allow":["set_app_theme"],"deny":[]}},"allow-tauri-version":{"identifier":"allow-tauri-version","description":"Enables the tauri_version command without any pre-configured scope.","commands":{"allow":["tauri_version"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-app-hide":{"identifier":"deny-app-hide","description":"Denies the app_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["app_hide"]}},"deny-app-show":{"identifier":"deny-app-show","description":"Denies the app_show command without any pre-configured scope.","commands":{"allow":[],"deny":["app_show"]}},"deny-default-window-icon":{"identifier":"deny-default-window-icon","description":"Denies the default_window_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["default_window_icon"]}},"deny-fetch-data-store-identifiers":{"identifier":"deny-fetch-data-store-identifiers","description":"Denies the fetch_data_store_identifiers command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_data_store_identifiers"]}},"deny-identifier":{"identifier":"deny-identifier","description":"Denies the identifier command without any pre-configured scope.","commands":{"allow":[],"deny":["identifier"]}},"deny-name":{"identifier":"deny-name","description":"Denies the name command without any pre-configured scope.","commands":{"allow":[],"deny":["name"]}},"deny-remove-data-store":{"identifier":"deny-remove-data-store","description":"Denies the remove_data_store command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_data_store"]}},"deny-set-app-theme":{"identifier":"deny-set-app-theme","description":"Denies the set_app_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_app_theme"]}},"deny-tauri-version":{"identifier":"deny-tauri-version","description":"Denies the tauri_version command without any pre-configured scope.","commands":{"allow":[],"deny":["tauri_version"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"core:event":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-listen","allow-unlisten","allow-emit","allow-emit-to"]},"permissions":{"allow-emit":{"identifier":"allow-emit","description":"Enables the emit command without any pre-configured scope.","commands":{"allow":["emit"],"deny":[]}},"allow-emit-to":{"identifier":"allow-emit-to","description":"Enables the emit_to command without any pre-configured scope.","commands":{"allow":["emit_to"],"deny":[]}},"allow-listen":{"identifier":"allow-listen","description":"Enables the listen command without any pre-configured scope.","commands":{"allow":["listen"],"deny":[]}},"allow-unlisten":{"identifier":"allow-unlisten","description":"Enables the unlisten command without any pre-configured scope.","commands":{"allow":["unlisten"],"deny":[]}},"deny-emit":{"identifier":"deny-emit","description":"Denies the emit command without any pre-configured scope.","commands":{"allow":[],"deny":["emit"]}},"deny-emit-to":{"identifier":"deny-emit-to","description":"Denies the emit_to command without any pre-configured scope.","commands":{"allow":[],"deny":["emit_to"]}},"deny-listen":{"identifier":"deny-listen","description":"Denies the listen command without any pre-configured scope.","commands":{"allow":[],"deny":["listen"]}},"deny-unlisten":{"identifier":"deny-unlisten","description":"Denies the unlisten command without any pre-configured scope.","commands":{"allow":[],"deny":["unlisten"]}}},"permission_sets":{},"global_scope_schema":null},"core:image":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-from-bytes","allow-from-path","allow-rgba","allow-size"]},"permissions":{"allow-from-bytes":{"identifier":"allow-from-bytes","description":"Enables the from_bytes command without any pre-configured scope.","commands":{"allow":["from_bytes"],"deny":[]}},"allow-from-path":{"identifier":"allow-from-path","description":"Enables the from_path command without any pre-configured scope.","commands":{"allow":["from_path"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-rgba":{"identifier":"allow-rgba","description":"Enables the rgba command without any pre-configured scope.","commands":{"allow":["rgba"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"deny-from-bytes":{"identifier":"deny-from-bytes","description":"Denies the from_bytes command without any pre-configured scope.","commands":{"allow":[],"deny":["from_bytes"]}},"deny-from-path":{"identifier":"deny-from-path","description":"Denies the from_path command without any pre-configured scope.","commands":{"allow":[],"deny":["from_path"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-rgba":{"identifier":"deny-rgba","description":"Denies the rgba command without any pre-configured scope.","commands":{"allow":[],"deny":["rgba"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}}},"permission_sets":{},"global_scope_schema":null},"core:menu":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-append","allow-prepend","allow-insert","allow-remove","allow-remove-at","allow-items","allow-get","allow-popup","allow-create-default","allow-set-as-app-menu","allow-set-as-window-menu","allow-text","allow-set-text","allow-is-enabled","allow-set-enabled","allow-set-accelerator","allow-set-as-windows-menu-for-nsapp","allow-set-as-help-menu-for-nsapp","allow-is-checked","allow-set-checked","allow-set-icon"]},"permissions":{"allow-append":{"identifier":"allow-append","description":"Enables the append command without any pre-configured scope.","commands":{"allow":["append"],"deny":[]}},"allow-create-default":{"identifier":"allow-create-default","description":"Enables the create_default command without any pre-configured scope.","commands":{"allow":["create_default"],"deny":[]}},"allow-get":{"identifier":"allow-get","description":"Enables the get command without any pre-configured scope.","commands":{"allow":["get"],"deny":[]}},"allow-insert":{"identifier":"allow-insert","description":"Enables the insert command without any pre-configured scope.","commands":{"allow":["insert"],"deny":[]}},"allow-is-checked":{"identifier":"allow-is-checked","description":"Enables the is_checked command without any pre-configured scope.","commands":{"allow":["is_checked"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-items":{"identifier":"allow-items","description":"Enables the items command without any pre-configured scope.","commands":{"allow":["items"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-popup":{"identifier":"allow-popup","description":"Enables the popup command without any pre-configured scope.","commands":{"allow":["popup"],"deny":[]}},"allow-prepend":{"identifier":"allow-prepend","description":"Enables the prepend command without any pre-configured scope.","commands":{"allow":["prepend"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-remove-at":{"identifier":"allow-remove-at","description":"Enables the remove_at command without any pre-configured scope.","commands":{"allow":["remove_at"],"deny":[]}},"allow-set-accelerator":{"identifier":"allow-set-accelerator","description":"Enables the set_accelerator command without any pre-configured scope.","commands":{"allow":["set_accelerator"],"deny":[]}},"allow-set-as-app-menu":{"identifier":"allow-set-as-app-menu","description":"Enables the set_as_app_menu command without any pre-configured scope.","commands":{"allow":["set_as_app_menu"],"deny":[]}},"allow-set-as-help-menu-for-nsapp":{"identifier":"allow-set-as-help-menu-for-nsapp","description":"Enables the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_help_menu_for_nsapp"],"deny":[]}},"allow-set-as-window-menu":{"identifier":"allow-set-as-window-menu","description":"Enables the set_as_window_menu command without any pre-configured scope.","commands":{"allow":["set_as_window_menu"],"deny":[]}},"allow-set-as-windows-menu-for-nsapp":{"identifier":"allow-set-as-windows-menu-for-nsapp","description":"Enables the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":["set_as_windows_menu_for_nsapp"],"deny":[]}},"allow-set-checked":{"identifier":"allow-set-checked","description":"Enables the set_checked command without any pre-configured scope.","commands":{"allow":["set_checked"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-text":{"identifier":"allow-set-text","description":"Enables the set_text command without any pre-configured scope.","commands":{"allow":["set_text"],"deny":[]}},"allow-text":{"identifier":"allow-text","description":"Enables the text command without any pre-configured scope.","commands":{"allow":["text"],"deny":[]}},"deny-append":{"identifier":"deny-append","description":"Denies the append command without any pre-configured scope.","commands":{"allow":[],"deny":["append"]}},"deny-create-default":{"identifier":"deny-create-default","description":"Denies the create_default command without any pre-configured scope.","commands":{"allow":[],"deny":["create_default"]}},"deny-get":{"identifier":"deny-get","description":"Denies the get command without any pre-configured scope.","commands":{"allow":[],"deny":["get"]}},"deny-insert":{"identifier":"deny-insert","description":"Denies the insert command without any pre-configured scope.","commands":{"allow":[],"deny":["insert"]}},"deny-is-checked":{"identifier":"deny-is-checked","description":"Denies the is_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["is_checked"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-items":{"identifier":"deny-items","description":"Denies the items command without any pre-configured scope.","commands":{"allow":[],"deny":["items"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-popup":{"identifier":"deny-popup","description":"Denies the popup command without any pre-configured scope.","commands":{"allow":[],"deny":["popup"]}},"deny-prepend":{"identifier":"deny-prepend","description":"Denies the prepend command without any pre-configured scope.","commands":{"allow":[],"deny":["prepend"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-remove-at":{"identifier":"deny-remove-at","description":"Denies the remove_at command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_at"]}},"deny-set-accelerator":{"identifier":"deny-set-accelerator","description":"Denies the set_accelerator command without any pre-configured scope.","commands":{"allow":[],"deny":["set_accelerator"]}},"deny-set-as-app-menu":{"identifier":"deny-set-as-app-menu","description":"Denies the set_as_app_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_app_menu"]}},"deny-set-as-help-menu-for-nsapp":{"identifier":"deny-set-as-help-menu-for-nsapp","description":"Denies the set_as_help_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_help_menu_for_nsapp"]}},"deny-set-as-window-menu":{"identifier":"deny-set-as-window-menu","description":"Denies the set_as_window_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_window_menu"]}},"deny-set-as-windows-menu-for-nsapp":{"identifier":"deny-set-as-windows-menu-for-nsapp","description":"Denies the set_as_windows_menu_for_nsapp command without any pre-configured scope.","commands":{"allow":[],"deny":["set_as_windows_menu_for_nsapp"]}},"deny-set-checked":{"identifier":"deny-set-checked","description":"Denies the set_checked command without any pre-configured scope.","commands":{"allow":[],"deny":["set_checked"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-text":{"identifier":"deny-set-text","description":"Denies the set_text command without any pre-configured scope.","commands":{"allow":[],"deny":["set_text"]}},"deny-text":{"identifier":"deny-text","description":"Denies the text command without any pre-configured scope.","commands":{"allow":[],"deny":["text"]}}},"permission_sets":{},"global_scope_schema":null},"core:path":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-resolve-directory","allow-resolve","allow-normalize","allow-join","allow-dirname","allow-extname","allow-basename","allow-is-absolute"]},"permissions":{"allow-basename":{"identifier":"allow-basename","description":"Enables the basename command without any pre-configured scope.","commands":{"allow":["basename"],"deny":[]}},"allow-dirname":{"identifier":"allow-dirname","description":"Enables the dirname command without any pre-configured scope.","commands":{"allow":["dirname"],"deny":[]}},"allow-extname":{"identifier":"allow-extname","description":"Enables the extname command without any pre-configured scope.","commands":{"allow":["extname"],"deny":[]}},"allow-is-absolute":{"identifier":"allow-is-absolute","description":"Enables the is_absolute command without any pre-configured scope.","commands":{"allow":["is_absolute"],"deny":[]}},"allow-join":{"identifier":"allow-join","description":"Enables the join command without any pre-configured scope.","commands":{"allow":["join"],"deny":[]}},"allow-normalize":{"identifier":"allow-normalize","description":"Enables the normalize command without any pre-configured scope.","commands":{"allow":["normalize"],"deny":[]}},"allow-resolve":{"identifier":"allow-resolve","description":"Enables the resolve command without any pre-configured scope.","commands":{"allow":["resolve"],"deny":[]}},"allow-resolve-directory":{"identifier":"allow-resolve-directory","description":"Enables the resolve_directory command without any pre-configured scope.","commands":{"allow":["resolve_directory"],"deny":[]}},"deny-basename":{"identifier":"deny-basename","description":"Denies the basename command without any pre-configured scope.","commands":{"allow":[],"deny":["basename"]}},"deny-dirname":{"identifier":"deny-dirname","description":"Denies the dirname command without any pre-configured scope.","commands":{"allow":[],"deny":["dirname"]}},"deny-extname":{"identifier":"deny-extname","description":"Denies the extname command without any pre-configured scope.","commands":{"allow":[],"deny":["extname"]}},"deny-is-absolute":{"identifier":"deny-is-absolute","description":"Denies the is_absolute command without any pre-configured scope.","commands":{"allow":[],"deny":["is_absolute"]}},"deny-join":{"identifier":"deny-join","description":"Denies the join command without any pre-configured scope.","commands":{"allow":[],"deny":["join"]}},"deny-normalize":{"identifier":"deny-normalize","description":"Denies the normalize command without any pre-configured scope.","commands":{"allow":[],"deny":["normalize"]}},"deny-resolve":{"identifier":"deny-resolve","description":"Denies the resolve command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve"]}},"deny-resolve-directory":{"identifier":"deny-resolve-directory","description":"Denies the resolve_directory command without any pre-configured scope.","commands":{"allow":[],"deny":["resolve_directory"]}}},"permission_sets":{},"global_scope_schema":null},"core:resources":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-close"]},"permissions":{"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}}},"permission_sets":{},"global_scope_schema":null},"core:tray":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-new","allow-get-by-id","allow-remove-by-id","allow-set-icon","allow-set-menu","allow-set-tooltip","allow-set-title","allow-set-visible","allow-set-temp-dir-path","allow-set-icon-as-template","allow-set-show-menu-on-left-click"]},"permissions":{"allow-get-by-id":{"identifier":"allow-get-by-id","description":"Enables the get_by_id command without any pre-configured scope.","commands":{"allow":["get_by_id"],"deny":[]}},"allow-new":{"identifier":"allow-new","description":"Enables the new command without any pre-configured scope.","commands":{"allow":["new"],"deny":[]}},"allow-remove-by-id":{"identifier":"allow-remove-by-id","description":"Enables the remove_by_id command without any pre-configured scope.","commands":{"allow":["remove_by_id"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-icon-as-template":{"identifier":"allow-set-icon-as-template","description":"Enables the set_icon_as_template command without any pre-configured scope.","commands":{"allow":["set_icon_as_template"],"deny":[]}},"allow-set-menu":{"identifier":"allow-set-menu","description":"Enables the set_menu command without any pre-configured scope.","commands":{"allow":["set_menu"],"deny":[]}},"allow-set-show-menu-on-left-click":{"identifier":"allow-set-show-menu-on-left-click","description":"Enables the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":["set_show_menu_on_left_click"],"deny":[]}},"allow-set-temp-dir-path":{"identifier":"allow-set-temp-dir-path","description":"Enables the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":["set_temp_dir_path"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-tooltip":{"identifier":"allow-set-tooltip","description":"Enables the set_tooltip command without any pre-configured scope.","commands":{"allow":["set_tooltip"],"deny":[]}},"allow-set-visible":{"identifier":"allow-set-visible","description":"Enables the set_visible command without any pre-configured scope.","commands":{"allow":["set_visible"],"deny":[]}},"deny-get-by-id":{"identifier":"deny-get-by-id","description":"Denies the get_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["get_by_id"]}},"deny-new":{"identifier":"deny-new","description":"Denies the new command without any pre-configured scope.","commands":{"allow":[],"deny":["new"]}},"deny-remove-by-id":{"identifier":"deny-remove-by-id","description":"Denies the remove_by_id command without any pre-configured scope.","commands":{"allow":[],"deny":["remove_by_id"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-icon-as-template":{"identifier":"deny-set-icon-as-template","description":"Denies the set_icon_as_template command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon_as_template"]}},"deny-set-menu":{"identifier":"deny-set-menu","description":"Denies the set_menu command without any pre-configured scope.","commands":{"allow":[],"deny":["set_menu"]}},"deny-set-show-menu-on-left-click":{"identifier":"deny-set-show-menu-on-left-click","description":"Denies the set_show_menu_on_left_click command without any pre-configured scope.","commands":{"allow":[],"deny":["set_show_menu_on_left_click"]}},"deny-set-temp-dir-path":{"identifier":"deny-set-temp-dir-path","description":"Denies the set_temp_dir_path command without any pre-configured scope.","commands":{"allow":[],"deny":["set_temp_dir_path"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-tooltip":{"identifier":"deny-set-tooltip","description":"Denies the set_tooltip command without any pre-configured scope.","commands":{"allow":[],"deny":["set_tooltip"]}},"deny-set-visible":{"identifier":"deny-set-visible","description":"Denies the set_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible"]}}},"permission_sets":{},"global_scope_schema":null},"core:webview":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-webviews","allow-webview-position","allow-webview-size","allow-internal-toggle-devtools"]},"permissions":{"allow-clear-all-browsing-data":{"identifier":"allow-clear-all-browsing-data","description":"Enables the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":["clear_all_browsing_data"],"deny":[]}},"allow-create-webview":{"identifier":"allow-create-webview","description":"Enables the create_webview command without any pre-configured scope.","commands":{"allow":["create_webview"],"deny":[]}},"allow-create-webview-window":{"identifier":"allow-create-webview-window","description":"Enables the create_webview_window command without any pre-configured scope.","commands":{"allow":["create_webview_window"],"deny":[]}},"allow-get-all-webviews":{"identifier":"allow-get-all-webviews","description":"Enables the get_all_webviews command without any pre-configured scope.","commands":{"allow":["get_all_webviews"],"deny":[]}},"allow-internal-toggle-devtools":{"identifier":"allow-internal-toggle-devtools","description":"Enables the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":["internal_toggle_devtools"],"deny":[]}},"allow-print":{"identifier":"allow-print","description":"Enables the print command without any pre-configured scope.","commands":{"allow":["print"],"deny":[]}},"allow-reparent":{"identifier":"allow-reparent","description":"Enables the reparent command without any pre-configured scope.","commands":{"allow":["reparent"],"deny":[]}},"allow-set-webview-background-color":{"identifier":"allow-set-webview-background-color","description":"Enables the set_webview_background_color command without any pre-configured scope.","commands":{"allow":["set_webview_background_color"],"deny":[]}},"allow-set-webview-focus":{"identifier":"allow-set-webview-focus","description":"Enables the set_webview_focus command without any pre-configured scope.","commands":{"allow":["set_webview_focus"],"deny":[]}},"allow-set-webview-position":{"identifier":"allow-set-webview-position","description":"Enables the set_webview_position command without any pre-configured scope.","commands":{"allow":["set_webview_position"],"deny":[]}},"allow-set-webview-size":{"identifier":"allow-set-webview-size","description":"Enables the set_webview_size command without any pre-configured scope.","commands":{"allow":["set_webview_size"],"deny":[]}},"allow-set-webview-zoom":{"identifier":"allow-set-webview-zoom","description":"Enables the set_webview_zoom command without any pre-configured scope.","commands":{"allow":["set_webview_zoom"],"deny":[]}},"allow-webview-close":{"identifier":"allow-webview-close","description":"Enables the webview_close command without any pre-configured scope.","commands":{"allow":["webview_close"],"deny":[]}},"allow-webview-hide":{"identifier":"allow-webview-hide","description":"Enables the webview_hide command without any pre-configured scope.","commands":{"allow":["webview_hide"],"deny":[]}},"allow-webview-position":{"identifier":"allow-webview-position","description":"Enables the webview_position command without any pre-configured scope.","commands":{"allow":["webview_position"],"deny":[]}},"allow-webview-show":{"identifier":"allow-webview-show","description":"Enables the webview_show command without any pre-configured scope.","commands":{"allow":["webview_show"],"deny":[]}},"allow-webview-size":{"identifier":"allow-webview-size","description":"Enables the webview_size command without any pre-configured scope.","commands":{"allow":["webview_size"],"deny":[]}},"deny-clear-all-browsing-data":{"identifier":"deny-clear-all-browsing-data","description":"Denies the clear_all_browsing_data command without any pre-configured scope.","commands":{"allow":[],"deny":["clear_all_browsing_data"]}},"deny-create-webview":{"identifier":"deny-create-webview","description":"Denies the create_webview command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview"]}},"deny-create-webview-window":{"identifier":"deny-create-webview-window","description":"Denies the create_webview_window command without any pre-configured scope.","commands":{"allow":[],"deny":["create_webview_window"]}},"deny-get-all-webviews":{"identifier":"deny-get-all-webviews","description":"Denies the get_all_webviews command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_webviews"]}},"deny-internal-toggle-devtools":{"identifier":"deny-internal-toggle-devtools","description":"Denies the internal_toggle_devtools command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_devtools"]}},"deny-print":{"identifier":"deny-print","description":"Denies the print command without any pre-configured scope.","commands":{"allow":[],"deny":["print"]}},"deny-reparent":{"identifier":"deny-reparent","description":"Denies the reparent command without any pre-configured scope.","commands":{"allow":[],"deny":["reparent"]}},"deny-set-webview-background-color":{"identifier":"deny-set-webview-background-color","description":"Denies the set_webview_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_background_color"]}},"deny-set-webview-focus":{"identifier":"deny-set-webview-focus","description":"Denies the set_webview_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_focus"]}},"deny-set-webview-position":{"identifier":"deny-set-webview-position","description":"Denies the set_webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_position"]}},"deny-set-webview-size":{"identifier":"deny-set-webview-size","description":"Denies the set_webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_size"]}},"deny-set-webview-zoom":{"identifier":"deny-set-webview-zoom","description":"Denies the set_webview_zoom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_webview_zoom"]}},"deny-webview-close":{"identifier":"deny-webview-close","description":"Denies the webview_close command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_close"]}},"deny-webview-hide":{"identifier":"deny-webview-hide","description":"Denies the webview_hide command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_hide"]}},"deny-webview-position":{"identifier":"deny-webview-position","description":"Denies the webview_position command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_position"]}},"deny-webview-show":{"identifier":"deny-webview-show","description":"Denies the webview_show command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_show"]}},"deny-webview-size":{"identifier":"deny-webview-size","description":"Denies the webview_size command without any pre-configured scope.","commands":{"allow":[],"deny":["webview_size"]}}},"permission_sets":{},"global_scope_schema":null},"core:window":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin.","permissions":["allow-get-all-windows","allow-scale-factor","allow-inner-position","allow-outer-position","allow-inner-size","allow-outer-size","allow-is-fullscreen","allow-is-minimized","allow-is-maximized","allow-is-focused","allow-is-decorated","allow-is-resizable","allow-is-maximizable","allow-is-minimizable","allow-is-closable","allow-is-visible","allow-is-enabled","allow-title","allow-current-monitor","allow-primary-monitor","allow-monitor-from-point","allow-available-monitors","allow-cursor-position","allow-theme","allow-is-always-on-top","allow-internal-toggle-maximize"]},"permissions":{"allow-available-monitors":{"identifier":"allow-available-monitors","description":"Enables the available_monitors command without any pre-configured scope.","commands":{"allow":["available_monitors"],"deny":[]}},"allow-center":{"identifier":"allow-center","description":"Enables the center command without any pre-configured scope.","commands":{"allow":["center"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-current-monitor":{"identifier":"allow-current-monitor","description":"Enables the current_monitor command without any pre-configured scope.","commands":{"allow":["current_monitor"],"deny":[]}},"allow-cursor-position":{"identifier":"allow-cursor-position","description":"Enables the cursor_position command without any pre-configured scope.","commands":{"allow":["cursor_position"],"deny":[]}},"allow-destroy":{"identifier":"allow-destroy","description":"Enables the destroy command without any pre-configured scope.","commands":{"allow":["destroy"],"deny":[]}},"allow-get-all-windows":{"identifier":"allow-get-all-windows","description":"Enables the get_all_windows command without any pre-configured scope.","commands":{"allow":["get_all_windows"],"deny":[]}},"allow-hide":{"identifier":"allow-hide","description":"Enables the hide command without any pre-configured scope.","commands":{"allow":["hide"],"deny":[]}},"allow-inner-position":{"identifier":"allow-inner-position","description":"Enables the inner_position command without any pre-configured scope.","commands":{"allow":["inner_position"],"deny":[]}},"allow-inner-size":{"identifier":"allow-inner-size","description":"Enables the inner_size command without any pre-configured scope.","commands":{"allow":["inner_size"],"deny":[]}},"allow-internal-toggle-maximize":{"identifier":"allow-internal-toggle-maximize","description":"Enables the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":["internal_toggle_maximize"],"deny":[]}},"allow-is-always-on-top":{"identifier":"allow-is-always-on-top","description":"Enables the is_always_on_top command without any pre-configured scope.","commands":{"allow":["is_always_on_top"],"deny":[]}},"allow-is-closable":{"identifier":"allow-is-closable","description":"Enables the is_closable command without any pre-configured scope.","commands":{"allow":["is_closable"],"deny":[]}},"allow-is-decorated":{"identifier":"allow-is-decorated","description":"Enables the is_decorated command without any pre-configured scope.","commands":{"allow":["is_decorated"],"deny":[]}},"allow-is-enabled":{"identifier":"allow-is-enabled","description":"Enables the is_enabled command without any pre-configured scope.","commands":{"allow":["is_enabled"],"deny":[]}},"allow-is-focused":{"identifier":"allow-is-focused","description":"Enables the is_focused command without any pre-configured scope.","commands":{"allow":["is_focused"],"deny":[]}},"allow-is-fullscreen":{"identifier":"allow-is-fullscreen","description":"Enables the is_fullscreen command without any pre-configured scope.","commands":{"allow":["is_fullscreen"],"deny":[]}},"allow-is-maximizable":{"identifier":"allow-is-maximizable","description":"Enables the is_maximizable command without any pre-configured scope.","commands":{"allow":["is_maximizable"],"deny":[]}},"allow-is-maximized":{"identifier":"allow-is-maximized","description":"Enables the is_maximized command without any pre-configured scope.","commands":{"allow":["is_maximized"],"deny":[]}},"allow-is-minimizable":{"identifier":"allow-is-minimizable","description":"Enables the is_minimizable command without any pre-configured scope.","commands":{"allow":["is_minimizable"],"deny":[]}},"allow-is-minimized":{"identifier":"allow-is-minimized","description":"Enables the is_minimized command without any pre-configured scope.","commands":{"allow":["is_minimized"],"deny":[]}},"allow-is-resizable":{"identifier":"allow-is-resizable","description":"Enables the is_resizable command without any pre-configured scope.","commands":{"allow":["is_resizable"],"deny":[]}},"allow-is-visible":{"identifier":"allow-is-visible","description":"Enables the is_visible command without any pre-configured scope.","commands":{"allow":["is_visible"],"deny":[]}},"allow-maximize":{"identifier":"allow-maximize","description":"Enables the maximize command without any pre-configured scope.","commands":{"allow":["maximize"],"deny":[]}},"allow-minimize":{"identifier":"allow-minimize","description":"Enables the minimize command without any pre-configured scope.","commands":{"allow":["minimize"],"deny":[]}},"allow-monitor-from-point":{"identifier":"allow-monitor-from-point","description":"Enables the monitor_from_point command without any pre-configured scope.","commands":{"allow":["monitor_from_point"],"deny":[]}},"allow-outer-position":{"identifier":"allow-outer-position","description":"Enables the outer_position command without any pre-configured scope.","commands":{"allow":["outer_position"],"deny":[]}},"allow-outer-size":{"identifier":"allow-outer-size","description":"Enables the outer_size command without any pre-configured scope.","commands":{"allow":["outer_size"],"deny":[]}},"allow-primary-monitor":{"identifier":"allow-primary-monitor","description":"Enables the primary_monitor command without any pre-configured scope.","commands":{"allow":["primary_monitor"],"deny":[]}},"allow-request-user-attention":{"identifier":"allow-request-user-attention","description":"Enables the request_user_attention command without any pre-configured scope.","commands":{"allow":["request_user_attention"],"deny":[]}},"allow-scale-factor":{"identifier":"allow-scale-factor","description":"Enables the scale_factor command without any pre-configured scope.","commands":{"allow":["scale_factor"],"deny":[]}},"allow-set-always-on-bottom":{"identifier":"allow-set-always-on-bottom","description":"Enables the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":["set_always_on_bottom"],"deny":[]}},"allow-set-always-on-top":{"identifier":"allow-set-always-on-top","description":"Enables the set_always_on_top command without any pre-configured scope.","commands":{"allow":["set_always_on_top"],"deny":[]}},"allow-set-background-color":{"identifier":"allow-set-background-color","description":"Enables the set_background_color command without any pre-configured scope.","commands":{"allow":["set_background_color"],"deny":[]}},"allow-set-badge-count":{"identifier":"allow-set-badge-count","description":"Enables the set_badge_count command without any pre-configured scope.","commands":{"allow":["set_badge_count"],"deny":[]}},"allow-set-badge-label":{"identifier":"allow-set-badge-label","description":"Enables the set_badge_label command without any pre-configured scope.","commands":{"allow":["set_badge_label"],"deny":[]}},"allow-set-closable":{"identifier":"allow-set-closable","description":"Enables the set_closable command without any pre-configured scope.","commands":{"allow":["set_closable"],"deny":[]}},"allow-set-content-protected":{"identifier":"allow-set-content-protected","description":"Enables the set_content_protected command without any pre-configured scope.","commands":{"allow":["set_content_protected"],"deny":[]}},"allow-set-cursor-grab":{"identifier":"allow-set-cursor-grab","description":"Enables the set_cursor_grab command without any pre-configured scope.","commands":{"allow":["set_cursor_grab"],"deny":[]}},"allow-set-cursor-icon":{"identifier":"allow-set-cursor-icon","description":"Enables the set_cursor_icon command without any pre-configured scope.","commands":{"allow":["set_cursor_icon"],"deny":[]}},"allow-set-cursor-position":{"identifier":"allow-set-cursor-position","description":"Enables the set_cursor_position command without any pre-configured scope.","commands":{"allow":["set_cursor_position"],"deny":[]}},"allow-set-cursor-visible":{"identifier":"allow-set-cursor-visible","description":"Enables the set_cursor_visible command without any pre-configured scope.","commands":{"allow":["set_cursor_visible"],"deny":[]}},"allow-set-decorations":{"identifier":"allow-set-decorations","description":"Enables the set_decorations command without any pre-configured scope.","commands":{"allow":["set_decorations"],"deny":[]}},"allow-set-effects":{"identifier":"allow-set-effects","description":"Enables the set_effects command without any pre-configured scope.","commands":{"allow":["set_effects"],"deny":[]}},"allow-set-enabled":{"identifier":"allow-set-enabled","description":"Enables the set_enabled command without any pre-configured scope.","commands":{"allow":["set_enabled"],"deny":[]}},"allow-set-focus":{"identifier":"allow-set-focus","description":"Enables the set_focus command without any pre-configured scope.","commands":{"allow":["set_focus"],"deny":[]}},"allow-set-fullscreen":{"identifier":"allow-set-fullscreen","description":"Enables the set_fullscreen command without any pre-configured scope.","commands":{"allow":["set_fullscreen"],"deny":[]}},"allow-set-icon":{"identifier":"allow-set-icon","description":"Enables the set_icon command without any pre-configured scope.","commands":{"allow":["set_icon"],"deny":[]}},"allow-set-ignore-cursor-events":{"identifier":"allow-set-ignore-cursor-events","description":"Enables the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":["set_ignore_cursor_events"],"deny":[]}},"allow-set-max-size":{"identifier":"allow-set-max-size","description":"Enables the set_max_size command without any pre-configured scope.","commands":{"allow":["set_max_size"],"deny":[]}},"allow-set-maximizable":{"identifier":"allow-set-maximizable","description":"Enables the set_maximizable command without any pre-configured scope.","commands":{"allow":["set_maximizable"],"deny":[]}},"allow-set-min-size":{"identifier":"allow-set-min-size","description":"Enables the set_min_size command without any pre-configured scope.","commands":{"allow":["set_min_size"],"deny":[]}},"allow-set-minimizable":{"identifier":"allow-set-minimizable","description":"Enables the set_minimizable command without any pre-configured scope.","commands":{"allow":["set_minimizable"],"deny":[]}},"allow-set-overlay-icon":{"identifier":"allow-set-overlay-icon","description":"Enables the set_overlay_icon command without any pre-configured scope.","commands":{"allow":["set_overlay_icon"],"deny":[]}},"allow-set-position":{"identifier":"allow-set-position","description":"Enables the set_position command without any pre-configured scope.","commands":{"allow":["set_position"],"deny":[]}},"allow-set-progress-bar":{"identifier":"allow-set-progress-bar","description":"Enables the set_progress_bar command without any pre-configured scope.","commands":{"allow":["set_progress_bar"],"deny":[]}},"allow-set-resizable":{"identifier":"allow-set-resizable","description":"Enables the set_resizable command without any pre-configured scope.","commands":{"allow":["set_resizable"],"deny":[]}},"allow-set-shadow":{"identifier":"allow-set-shadow","description":"Enables the set_shadow command without any pre-configured scope.","commands":{"allow":["set_shadow"],"deny":[]}},"allow-set-size":{"identifier":"allow-set-size","description":"Enables the set_size command without any pre-configured scope.","commands":{"allow":["set_size"],"deny":[]}},"allow-set-size-constraints":{"identifier":"allow-set-size-constraints","description":"Enables the set_size_constraints command without any pre-configured scope.","commands":{"allow":["set_size_constraints"],"deny":[]}},"allow-set-skip-taskbar":{"identifier":"allow-set-skip-taskbar","description":"Enables the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":["set_skip_taskbar"],"deny":[]}},"allow-set-theme":{"identifier":"allow-set-theme","description":"Enables the set_theme command without any pre-configured scope.","commands":{"allow":["set_theme"],"deny":[]}},"allow-set-title":{"identifier":"allow-set-title","description":"Enables the set_title command without any pre-configured scope.","commands":{"allow":["set_title"],"deny":[]}},"allow-set-title-bar-style":{"identifier":"allow-set-title-bar-style","description":"Enables the set_title_bar_style command without any pre-configured scope.","commands":{"allow":["set_title_bar_style"],"deny":[]}},"allow-set-visible-on-all-workspaces":{"identifier":"allow-set-visible-on-all-workspaces","description":"Enables the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":["set_visible_on_all_workspaces"],"deny":[]}},"allow-show":{"identifier":"allow-show","description":"Enables the show command without any pre-configured scope.","commands":{"allow":["show"],"deny":[]}},"allow-start-dragging":{"identifier":"allow-start-dragging","description":"Enables the start_dragging command without any pre-configured scope.","commands":{"allow":["start_dragging"],"deny":[]}},"allow-start-resize-dragging":{"identifier":"allow-start-resize-dragging","description":"Enables the start_resize_dragging command without any pre-configured scope.","commands":{"allow":["start_resize_dragging"],"deny":[]}},"allow-theme":{"identifier":"allow-theme","description":"Enables the theme command without any pre-configured scope.","commands":{"allow":["theme"],"deny":[]}},"allow-title":{"identifier":"allow-title","description":"Enables the title command without any pre-configured scope.","commands":{"allow":["title"],"deny":[]}},"allow-toggle-maximize":{"identifier":"allow-toggle-maximize","description":"Enables the toggle_maximize command without any pre-configured scope.","commands":{"allow":["toggle_maximize"],"deny":[]}},"allow-unmaximize":{"identifier":"allow-unmaximize","description":"Enables the unmaximize command without any pre-configured scope.","commands":{"allow":["unmaximize"],"deny":[]}},"allow-unminimize":{"identifier":"allow-unminimize","description":"Enables the unminimize command without any pre-configured scope.","commands":{"allow":["unminimize"],"deny":[]}},"deny-available-monitors":{"identifier":"deny-available-monitors","description":"Denies the available_monitors command without any pre-configured scope.","commands":{"allow":[],"deny":["available_monitors"]}},"deny-center":{"identifier":"deny-center","description":"Denies the center command without any pre-configured scope.","commands":{"allow":[],"deny":["center"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-current-monitor":{"identifier":"deny-current-monitor","description":"Denies the current_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["current_monitor"]}},"deny-cursor-position":{"identifier":"deny-cursor-position","description":"Denies the cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["cursor_position"]}},"deny-destroy":{"identifier":"deny-destroy","description":"Denies the destroy command without any pre-configured scope.","commands":{"allow":[],"deny":["destroy"]}},"deny-get-all-windows":{"identifier":"deny-get-all-windows","description":"Denies the get_all_windows command without any pre-configured scope.","commands":{"allow":[],"deny":["get_all_windows"]}},"deny-hide":{"identifier":"deny-hide","description":"Denies the hide command without any pre-configured scope.","commands":{"allow":[],"deny":["hide"]}},"deny-inner-position":{"identifier":"deny-inner-position","description":"Denies the inner_position command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_position"]}},"deny-inner-size":{"identifier":"deny-inner-size","description":"Denies the inner_size command without any pre-configured scope.","commands":{"allow":[],"deny":["inner_size"]}},"deny-internal-toggle-maximize":{"identifier":"deny-internal-toggle-maximize","description":"Denies the internal_toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["internal_toggle_maximize"]}},"deny-is-always-on-top":{"identifier":"deny-is-always-on-top","description":"Denies the is_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["is_always_on_top"]}},"deny-is-closable":{"identifier":"deny-is-closable","description":"Denies the is_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_closable"]}},"deny-is-decorated":{"identifier":"deny-is-decorated","description":"Denies the is_decorated command without any pre-configured scope.","commands":{"allow":[],"deny":["is_decorated"]}},"deny-is-enabled":{"identifier":"deny-is-enabled","description":"Denies the is_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["is_enabled"]}},"deny-is-focused":{"identifier":"deny-is-focused","description":"Denies the is_focused command without any pre-configured scope.","commands":{"allow":[],"deny":["is_focused"]}},"deny-is-fullscreen":{"identifier":"deny-is-fullscreen","description":"Denies the is_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["is_fullscreen"]}},"deny-is-maximizable":{"identifier":"deny-is-maximizable","description":"Denies the is_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximizable"]}},"deny-is-maximized":{"identifier":"deny-is-maximized","description":"Denies the is_maximized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_maximized"]}},"deny-is-minimizable":{"identifier":"deny-is-minimizable","description":"Denies the is_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimizable"]}},"deny-is-minimized":{"identifier":"deny-is-minimized","description":"Denies the is_minimized command without any pre-configured scope.","commands":{"allow":[],"deny":["is_minimized"]}},"deny-is-resizable":{"identifier":"deny-is-resizable","description":"Denies the is_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["is_resizable"]}},"deny-is-visible":{"identifier":"deny-is-visible","description":"Denies the is_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["is_visible"]}},"deny-maximize":{"identifier":"deny-maximize","description":"Denies the maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["maximize"]}},"deny-minimize":{"identifier":"deny-minimize","description":"Denies the minimize command without any pre-configured scope.","commands":{"allow":[],"deny":["minimize"]}},"deny-monitor-from-point":{"identifier":"deny-monitor-from-point","description":"Denies the monitor_from_point command without any pre-configured scope.","commands":{"allow":[],"deny":["monitor_from_point"]}},"deny-outer-position":{"identifier":"deny-outer-position","description":"Denies the outer_position command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_position"]}},"deny-outer-size":{"identifier":"deny-outer-size","description":"Denies the outer_size command without any pre-configured scope.","commands":{"allow":[],"deny":["outer_size"]}},"deny-primary-monitor":{"identifier":"deny-primary-monitor","description":"Denies the primary_monitor command without any pre-configured scope.","commands":{"allow":[],"deny":["primary_monitor"]}},"deny-request-user-attention":{"identifier":"deny-request-user-attention","description":"Denies the request_user_attention command without any pre-configured scope.","commands":{"allow":[],"deny":["request_user_attention"]}},"deny-scale-factor":{"identifier":"deny-scale-factor","description":"Denies the scale_factor command without any pre-configured scope.","commands":{"allow":[],"deny":["scale_factor"]}},"deny-set-always-on-bottom":{"identifier":"deny-set-always-on-bottom","description":"Denies the set_always_on_bottom command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_bottom"]}},"deny-set-always-on-top":{"identifier":"deny-set-always-on-top","description":"Denies the set_always_on_top command without any pre-configured scope.","commands":{"allow":[],"deny":["set_always_on_top"]}},"deny-set-background-color":{"identifier":"deny-set-background-color","description":"Denies the set_background_color command without any pre-configured scope.","commands":{"allow":[],"deny":["set_background_color"]}},"deny-set-badge-count":{"identifier":"deny-set-badge-count","description":"Denies the set_badge_count command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_count"]}},"deny-set-badge-label":{"identifier":"deny-set-badge-label","description":"Denies the set_badge_label command without any pre-configured scope.","commands":{"allow":[],"deny":["set_badge_label"]}},"deny-set-closable":{"identifier":"deny-set-closable","description":"Denies the set_closable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_closable"]}},"deny-set-content-protected":{"identifier":"deny-set-content-protected","description":"Denies the set_content_protected command without any pre-configured scope.","commands":{"allow":[],"deny":["set_content_protected"]}},"deny-set-cursor-grab":{"identifier":"deny-set-cursor-grab","description":"Denies the set_cursor_grab command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_grab"]}},"deny-set-cursor-icon":{"identifier":"deny-set-cursor-icon","description":"Denies the set_cursor_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_icon"]}},"deny-set-cursor-position":{"identifier":"deny-set-cursor-position","description":"Denies the set_cursor_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_position"]}},"deny-set-cursor-visible":{"identifier":"deny-set-cursor-visible","description":"Denies the set_cursor_visible command without any pre-configured scope.","commands":{"allow":[],"deny":["set_cursor_visible"]}},"deny-set-decorations":{"identifier":"deny-set-decorations","description":"Denies the set_decorations command without any pre-configured scope.","commands":{"allow":[],"deny":["set_decorations"]}},"deny-set-effects":{"identifier":"deny-set-effects","description":"Denies the set_effects command without any pre-configured scope.","commands":{"allow":[],"deny":["set_effects"]}},"deny-set-enabled":{"identifier":"deny-set-enabled","description":"Denies the set_enabled command without any pre-configured scope.","commands":{"allow":[],"deny":["set_enabled"]}},"deny-set-focus":{"identifier":"deny-set-focus","description":"Denies the set_focus command without any pre-configured scope.","commands":{"allow":[],"deny":["set_focus"]}},"deny-set-fullscreen":{"identifier":"deny-set-fullscreen","description":"Denies the set_fullscreen command without any pre-configured scope.","commands":{"allow":[],"deny":["set_fullscreen"]}},"deny-set-icon":{"identifier":"deny-set-icon","description":"Denies the set_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_icon"]}},"deny-set-ignore-cursor-events":{"identifier":"deny-set-ignore-cursor-events","description":"Denies the set_ignore_cursor_events command without any pre-configured scope.","commands":{"allow":[],"deny":["set_ignore_cursor_events"]}},"deny-set-max-size":{"identifier":"deny-set-max-size","description":"Denies the set_max_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_max_size"]}},"deny-set-maximizable":{"identifier":"deny-set-maximizable","description":"Denies the set_maximizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_maximizable"]}},"deny-set-min-size":{"identifier":"deny-set-min-size","description":"Denies the set_min_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_min_size"]}},"deny-set-minimizable":{"identifier":"deny-set-minimizable","description":"Denies the set_minimizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_minimizable"]}},"deny-set-overlay-icon":{"identifier":"deny-set-overlay-icon","description":"Denies the set_overlay_icon command without any pre-configured scope.","commands":{"allow":[],"deny":["set_overlay_icon"]}},"deny-set-position":{"identifier":"deny-set-position","description":"Denies the set_position command without any pre-configured scope.","commands":{"allow":[],"deny":["set_position"]}},"deny-set-progress-bar":{"identifier":"deny-set-progress-bar","description":"Denies the set_progress_bar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_progress_bar"]}},"deny-set-resizable":{"identifier":"deny-set-resizable","description":"Denies the set_resizable command without any pre-configured scope.","commands":{"allow":[],"deny":["set_resizable"]}},"deny-set-shadow":{"identifier":"deny-set-shadow","description":"Denies the set_shadow command without any pre-configured scope.","commands":{"allow":[],"deny":["set_shadow"]}},"deny-set-size":{"identifier":"deny-set-size","description":"Denies the set_size command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size"]}},"deny-set-size-constraints":{"identifier":"deny-set-size-constraints","description":"Denies the set_size_constraints command without any pre-configured scope.","commands":{"allow":[],"deny":["set_size_constraints"]}},"deny-set-skip-taskbar":{"identifier":"deny-set-skip-taskbar","description":"Denies the set_skip_taskbar command without any pre-configured scope.","commands":{"allow":[],"deny":["set_skip_taskbar"]}},"deny-set-theme":{"identifier":"deny-set-theme","description":"Denies the set_theme command without any pre-configured scope.","commands":{"allow":[],"deny":["set_theme"]}},"deny-set-title":{"identifier":"deny-set-title","description":"Denies the set_title command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title"]}},"deny-set-title-bar-style":{"identifier":"deny-set-title-bar-style","description":"Denies the set_title_bar_style command without any pre-configured scope.","commands":{"allow":[],"deny":["set_title_bar_style"]}},"deny-set-visible-on-all-workspaces":{"identifier":"deny-set-visible-on-all-workspaces","description":"Denies the set_visible_on_all_workspaces command without any pre-configured scope.","commands":{"allow":[],"deny":["set_visible_on_all_workspaces"]}},"deny-show":{"identifier":"deny-show","description":"Denies the show command without any pre-configured scope.","commands":{"allow":[],"deny":["show"]}},"deny-start-dragging":{"identifier":"deny-start-dragging","description":"Denies the start_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_dragging"]}},"deny-start-resize-dragging":{"identifier":"deny-start-resize-dragging","description":"Denies the start_resize_dragging command without any pre-configured scope.","commands":{"allow":[],"deny":["start_resize_dragging"]}},"deny-theme":{"identifier":"deny-theme","description":"Denies the theme command without any pre-configured scope.","commands":{"allow":[],"deny":["theme"]}},"deny-title":{"identifier":"deny-title","description":"Denies the title command without any pre-configured scope.","commands":{"allow":[],"deny":["title"]}},"deny-toggle-maximize":{"identifier":"deny-toggle-maximize","description":"Denies the toggle_maximize command without any pre-configured scope.","commands":{"allow":[],"deny":["toggle_maximize"]}},"deny-unmaximize":{"identifier":"deny-unmaximize","description":"Denies the unmaximize command without any pre-configured scope.","commands":{"allow":[],"deny":["unmaximize"]}},"deny-unminimize":{"identifier":"deny-unminimize","description":"Denies the unminimize command without any pre-configured scope.","commands":{"allow":[],"deny":["unminimize"]}}},"permission_sets":{},"global_scope_schema":null},"dialog":{"default_permission":{"identifier":"default","description":"This permission set configures the types of dialogs\navailable from the dialog plugin.\n\n#### Granted Permissions\n\nAll dialog types are enabled.\n\n\n","permissions":["allow-ask","allow-confirm","allow-message","allow-save","allow-open"]},"permissions":{"allow-ask":{"identifier":"allow-ask","description":"Enables the ask command without any pre-configured scope.","commands":{"allow":["ask"],"deny":[]}},"allow-confirm":{"identifier":"allow-confirm","description":"Enables the confirm command without any pre-configured scope.","commands":{"allow":["confirm"],"deny":[]}},"allow-message":{"identifier":"allow-message","description":"Enables the message command without any pre-configured scope.","commands":{"allow":["message"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-save":{"identifier":"allow-save","description":"Enables the save command without any pre-configured scope.","commands":{"allow":["save"],"deny":[]}},"deny-ask":{"identifier":"deny-ask","description":"Denies the ask command without any pre-configured scope.","commands":{"allow":[],"deny":["ask"]}},"deny-confirm":{"identifier":"deny-confirm","description":"Denies the confirm command without any pre-configured scope.","commands":{"allow":[],"deny":["confirm"]}},"deny-message":{"identifier":"deny-message","description":"Denies the message command without any pre-configured scope.","commands":{"allow":[],"deny":["message"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-save":{"identifier":"deny-save","description":"Denies the save command without any pre-configured scope.","commands":{"allow":[],"deny":["save"]}}},"permission_sets":{},"global_scope_schema":null},"fs":{"default_permission":{"identifier":"default","description":"This set of permissions describes the what kind of\nfile system access the `fs` plugin has enabled or denied by default.\n\n#### Granted Permissions\n\nThis default permission set enables read access to the\napplication specific directories (AppConfig, AppData, AppLocalData, AppCache,\nAppLog) and all files and sub directories created in it.\nThe location of these directories depends on the operating system,\nwhere the application is run.\n\nIn general these directories need to be manually created\nby the application at runtime, before accessing files or folders\nin it is possible.\n\nTherefore, it is also allowed to create all of these folders via\nthe `mkdir` command.\n\n#### Denied Permissions\n\nThis default permission set prevents access to critical components\nof the Tauri application by default.\nOn Windows the webview data folder access is denied.\n\n#### Included permissions within this default permission set:\n","permissions":["create-app-specific-dirs","read-app-specific-dirs-recursive","deny-default"]},"permissions":{"allow-copy-file":{"identifier":"allow-copy-file","description":"Enables the copy_file command without any pre-configured scope.","commands":{"allow":["copy_file"],"deny":[]}},"allow-create":{"identifier":"allow-create","description":"Enables the create command without any pre-configured scope.","commands":{"allow":["create"],"deny":[]}},"allow-exists":{"identifier":"allow-exists","description":"Enables the exists command without any pre-configured scope.","commands":{"allow":["exists"],"deny":[]}},"allow-fstat":{"identifier":"allow-fstat","description":"Enables the fstat command without any pre-configured scope.","commands":{"allow":["fstat"],"deny":[]}},"allow-ftruncate":{"identifier":"allow-ftruncate","description":"Enables the ftruncate command without any pre-configured scope.","commands":{"allow":["ftruncate"],"deny":[]}},"allow-lstat":{"identifier":"allow-lstat","description":"Enables the lstat command without any pre-configured scope.","commands":{"allow":["lstat"],"deny":[]}},"allow-mkdir":{"identifier":"allow-mkdir","description":"Enables the mkdir command without any pre-configured scope.","commands":{"allow":["mkdir"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-read":{"identifier":"allow-read","description":"Enables the read command without any pre-configured scope.","commands":{"allow":["read"],"deny":[]}},"allow-read-dir":{"identifier":"allow-read-dir","description":"Enables the read_dir command without any pre-configured scope.","commands":{"allow":["read_dir"],"deny":[]}},"allow-read-file":{"identifier":"allow-read-file","description":"Enables the read_file command without any pre-configured scope.","commands":{"allow":["read_file"],"deny":[]}},"allow-read-text-file":{"identifier":"allow-read-text-file","description":"Enables the read_text_file command without any pre-configured scope.","commands":{"allow":["read_text_file"],"deny":[]}},"allow-read-text-file-lines":{"identifier":"allow-read-text-file-lines","description":"Enables the read_text_file_lines command without any pre-configured scope.","commands":{"allow":["read_text_file_lines","read_text_file_lines_next"],"deny":[]}},"allow-read-text-file-lines-next":{"identifier":"allow-read-text-file-lines-next","description":"Enables the read_text_file_lines_next command without any pre-configured scope.","commands":{"allow":["read_text_file_lines_next"],"deny":[]}},"allow-remove":{"identifier":"allow-remove","description":"Enables the remove command without any pre-configured scope.","commands":{"allow":["remove"],"deny":[]}},"allow-rename":{"identifier":"allow-rename","description":"Enables the rename command without any pre-configured scope.","commands":{"allow":["rename"],"deny":[]}},"allow-seek":{"identifier":"allow-seek","description":"Enables the seek command without any pre-configured scope.","commands":{"allow":["seek"],"deny":[]}},"allow-size":{"identifier":"allow-size","description":"Enables the size command without any pre-configured scope.","commands":{"allow":["size"],"deny":[]}},"allow-stat":{"identifier":"allow-stat","description":"Enables the stat command without any pre-configured scope.","commands":{"allow":["stat"],"deny":[]}},"allow-truncate":{"identifier":"allow-truncate","description":"Enables the truncate command without any pre-configured scope.","commands":{"allow":["truncate"],"deny":[]}},"allow-unwatch":{"identifier":"allow-unwatch","description":"Enables the unwatch command without any pre-configured scope.","commands":{"allow":["unwatch"],"deny":[]}},"allow-watch":{"identifier":"allow-watch","description":"Enables the watch command without any pre-configured scope.","commands":{"allow":["watch"],"deny":[]}},"allow-write":{"identifier":"allow-write","description":"Enables the write command without any pre-configured scope.","commands":{"allow":["write"],"deny":[]}},"allow-write-file":{"identifier":"allow-write-file","description":"Enables the write_file command without any pre-configured scope.","commands":{"allow":["write_file","open","write"],"deny":[]}},"allow-write-text-file":{"identifier":"allow-write-text-file","description":"Enables the write_text_file command without any pre-configured scope.","commands":{"allow":["write_text_file"],"deny":[]}},"create-app-specific-dirs":{"identifier":"create-app-specific-dirs","description":"This permissions allows to create the application specific directories.\n","commands":{"allow":["mkdir","scope-app-index"],"deny":[]}},"deny-copy-file":{"identifier":"deny-copy-file","description":"Denies the copy_file command without any pre-configured scope.","commands":{"allow":[],"deny":["copy_file"]}},"deny-create":{"identifier":"deny-create","description":"Denies the create command without any pre-configured scope.","commands":{"allow":[],"deny":["create"]}},"deny-exists":{"identifier":"deny-exists","description":"Denies the exists command without any pre-configured scope.","commands":{"allow":[],"deny":["exists"]}},"deny-fstat":{"identifier":"deny-fstat","description":"Denies the fstat command without any pre-configured scope.","commands":{"allow":[],"deny":["fstat"]}},"deny-ftruncate":{"identifier":"deny-ftruncate","description":"Denies the ftruncate command without any pre-configured scope.","commands":{"allow":[],"deny":["ftruncate"]}},"deny-lstat":{"identifier":"deny-lstat","description":"Denies the lstat command without any pre-configured scope.","commands":{"allow":[],"deny":["lstat"]}},"deny-mkdir":{"identifier":"deny-mkdir","description":"Denies the mkdir command without any pre-configured scope.","commands":{"allow":[],"deny":["mkdir"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-read":{"identifier":"deny-read","description":"Denies the read command without any pre-configured scope.","commands":{"allow":[],"deny":["read"]}},"deny-read-dir":{"identifier":"deny-read-dir","description":"Denies the read_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["read_dir"]}},"deny-read-file":{"identifier":"deny-read-file","description":"Denies the read_file command without any pre-configured scope.","commands":{"allow":[],"deny":["read_file"]}},"deny-read-text-file":{"identifier":"deny-read-text-file","description":"Denies the read_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text_file"]}},"deny-read-text-file-lines":{"identifier":"deny-read-text-file-lines","description":"Denies the read_text_file_lines command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text_file_lines"]}},"deny-read-text-file-lines-next":{"identifier":"deny-read-text-file-lines-next","description":"Denies the read_text_file_lines_next command without any pre-configured scope.","commands":{"allow":[],"deny":["read_text_file_lines_next"]}},"deny-remove":{"identifier":"deny-remove","description":"Denies the remove command without any pre-configured scope.","commands":{"allow":[],"deny":["remove"]}},"deny-rename":{"identifier":"deny-rename","description":"Denies the rename command without any pre-configured scope.","commands":{"allow":[],"deny":["rename"]}},"deny-seek":{"identifier":"deny-seek","description":"Denies the seek command without any pre-configured scope.","commands":{"allow":[],"deny":["seek"]}},"deny-size":{"identifier":"deny-size","description":"Denies the size command without any pre-configured scope.","commands":{"allow":[],"deny":["size"]}},"deny-stat":{"identifier":"deny-stat","description":"Denies the stat command without any pre-configured scope.","commands":{"allow":[],"deny":["stat"]}},"deny-truncate":{"identifier":"deny-truncate","description":"Denies the truncate command without any pre-configured scope.","commands":{"allow":[],"deny":["truncate"]}},"deny-unwatch":{"identifier":"deny-unwatch","description":"Denies the unwatch command without any pre-configured scope.","commands":{"allow":[],"deny":["unwatch"]}},"deny-watch":{"identifier":"deny-watch","description":"Denies the watch command without any pre-configured scope.","commands":{"allow":[],"deny":["watch"]}},"deny-webview-data-linux":{"identifier":"deny-webview-data-linux","description":"This denies read access to the\n`$APPLOCALDATA` folder on linux as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered.","commands":{"allow":[],"deny":[]}},"deny-webview-data-windows":{"identifier":"deny-webview-data-windows","description":"This denies read access to the\n`$APPLOCALDATA/EBWebView` folder on windows as the webview data and configuration values are stored here.\nAllowing access can lead to sensitive information disclosure and should be well considered.","commands":{"allow":[],"deny":[]}},"deny-write":{"identifier":"deny-write","description":"Denies the write command without any pre-configured scope.","commands":{"allow":[],"deny":["write"]}},"deny-write-file":{"identifier":"deny-write-file","description":"Denies the write_file command without any pre-configured scope.","commands":{"allow":[],"deny":["write_file"]}},"deny-write-text-file":{"identifier":"deny-write-text-file","description":"Denies the write_text_file command without any pre-configured scope.","commands":{"allow":[],"deny":["write_text_file"]}},"read-all":{"identifier":"read-all","description":"This enables all read related commands without any pre-configured accessible paths.","commands":{"allow":["read_dir","read_file","read","open","read_text_file","read_text_file_lines","read_text_file_lines_next","seek","stat","lstat","fstat","exists","watch","unwatch"],"deny":[]}},"read-app-specific-dirs-recursive":{"identifier":"read-app-specific-dirs-recursive","description":"This permission allows recursive read functionality on the application\nspecific base directories. \n","commands":{"allow":["read_dir","read_file","read_text_file","read_text_file_lines","read_text_file_lines_next","exists","scope-app-recursive"],"deny":[]}},"read-dirs":{"identifier":"read-dirs","description":"This enables directory read and file metadata related commands without any pre-configured accessible paths.","commands":{"allow":["read_dir","stat","lstat","fstat","exists"],"deny":[]}},"read-files":{"identifier":"read-files","description":"This enables file read related commands without any pre-configured accessible paths.","commands":{"allow":["read_file","read","open","read_text_file","read_text_file_lines","read_text_file_lines_next","seek","stat","lstat","fstat","exists"],"deny":[]}},"read-meta":{"identifier":"read-meta","description":"This enables all index or metadata related commands without any pre-configured accessible paths.","commands":{"allow":["read_dir","stat","lstat","fstat","exists","size"],"deny":[]}},"scope":{"identifier":"scope","description":"An empty permission you can use to modify the global scope.","commands":{"allow":[],"deny":[]}},"scope-app":{"identifier":"scope-app","description":"This scope permits access to all files and list content of top level directories in the application folders.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/*"},{"path":"$APPDATA"},{"path":"$APPDATA/*"},{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/*"},{"path":"$APPCACHE"},{"path":"$APPCACHE/*"},{"path":"$APPLOG"},{"path":"$APPLOG/*"}]}},"scope-app-index":{"identifier":"scope-app-index","description":"This scope permits to list all files and folders in the application directories.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPDATA"},{"path":"$APPLOCALDATA"},{"path":"$APPCACHE"},{"path":"$APPLOG"}]}},"scope-app-recursive":{"identifier":"scope-app-recursive","description":"This scope permits recursive access to the complete application folders, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/**"},{"path":"$APPDATA"},{"path":"$APPDATA/**"},{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/**"},{"path":"$APPCACHE"},{"path":"$APPCACHE/**"},{"path":"$APPLOG"},{"path":"$APPLOG/**"}]}},"scope-appcache":{"identifier":"scope-appcache","description":"This scope permits access to all files and list content of top level directories in the `$APPCACHE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCACHE"},{"path":"$APPCACHE/*"}]}},"scope-appcache-index":{"identifier":"scope-appcache-index","description":"This scope permits to list all files and folders in the `$APPCACHE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCACHE"}]}},"scope-appcache-recursive":{"identifier":"scope-appcache-recursive","description":"This scope permits recursive access to the complete `$APPCACHE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCACHE"},{"path":"$APPCACHE/**"}]}},"scope-appconfig":{"identifier":"scope-appconfig","description":"This scope permits access to all files and list content of top level directories in the `$APPCONFIG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/*"}]}},"scope-appconfig-index":{"identifier":"scope-appconfig-index","description":"This scope permits to list all files and folders in the `$APPCONFIG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"}]}},"scope-appconfig-recursive":{"identifier":"scope-appconfig-recursive","description":"This scope permits recursive access to the complete `$APPCONFIG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPCONFIG"},{"path":"$APPCONFIG/**"}]}},"scope-appdata":{"identifier":"scope-appdata","description":"This scope permits access to all files and list content of top level directories in the `$APPDATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPDATA"},{"path":"$APPDATA/*"}]}},"scope-appdata-index":{"identifier":"scope-appdata-index","description":"This scope permits to list all files and folders in the `$APPDATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPDATA"}]}},"scope-appdata-recursive":{"identifier":"scope-appdata-recursive","description":"This scope permits recursive access to the complete `$APPDATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPDATA"},{"path":"$APPDATA/**"}]}},"scope-applocaldata":{"identifier":"scope-applocaldata","description":"This scope permits access to all files and list content of top level directories in the `$APPLOCALDATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/*"}]}},"scope-applocaldata-index":{"identifier":"scope-applocaldata-index","description":"This scope permits to list all files and folders in the `$APPLOCALDATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOCALDATA"}]}},"scope-applocaldata-recursive":{"identifier":"scope-applocaldata-recursive","description":"This scope permits recursive access to the complete `$APPLOCALDATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOCALDATA"},{"path":"$APPLOCALDATA/**"}]}},"scope-applog":{"identifier":"scope-applog","description":"This scope permits access to all files and list content of top level directories in the `$APPLOG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOG"},{"path":"$APPLOG/*"}]}},"scope-applog-index":{"identifier":"scope-applog-index","description":"This scope permits to list all files and folders in the `$APPLOG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOG"}]}},"scope-applog-recursive":{"identifier":"scope-applog-recursive","description":"This scope permits recursive access to the complete `$APPLOG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$APPLOG"},{"path":"$APPLOG/**"}]}},"scope-audio":{"identifier":"scope-audio","description":"This scope permits access to all files and list content of top level directories in the `$AUDIO` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$AUDIO"},{"path":"$AUDIO/*"}]}},"scope-audio-index":{"identifier":"scope-audio-index","description":"This scope permits to list all files and folders in the `$AUDIO`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$AUDIO"}]}},"scope-audio-recursive":{"identifier":"scope-audio-recursive","description":"This scope permits recursive access to the complete `$AUDIO` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$AUDIO"},{"path":"$AUDIO/**"}]}},"scope-cache":{"identifier":"scope-cache","description":"This scope permits access to all files and list content of top level directories in the `$CACHE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CACHE"},{"path":"$CACHE/*"}]}},"scope-cache-index":{"identifier":"scope-cache-index","description":"This scope permits to list all files and folders in the `$CACHE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CACHE"}]}},"scope-cache-recursive":{"identifier":"scope-cache-recursive","description":"This scope permits recursive access to the complete `$CACHE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CACHE"},{"path":"$CACHE/**"}]}},"scope-config":{"identifier":"scope-config","description":"This scope permits access to all files and list content of top level directories in the `$CONFIG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CONFIG"},{"path":"$CONFIG/*"}]}},"scope-config-index":{"identifier":"scope-config-index","description":"This scope permits to list all files and folders in the `$CONFIG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CONFIG"}]}},"scope-config-recursive":{"identifier":"scope-config-recursive","description":"This scope permits recursive access to the complete `$CONFIG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$CONFIG"},{"path":"$CONFIG/**"}]}},"scope-data":{"identifier":"scope-data","description":"This scope permits access to all files and list content of top level directories in the `$DATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DATA"},{"path":"$DATA/*"}]}},"scope-data-index":{"identifier":"scope-data-index","description":"This scope permits to list all files and folders in the `$DATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DATA"}]}},"scope-data-recursive":{"identifier":"scope-data-recursive","description":"This scope permits recursive access to the complete `$DATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DATA"},{"path":"$DATA/**"}]}},"scope-desktop":{"identifier":"scope-desktop","description":"This scope permits access to all files and list content of top level directories in the `$DESKTOP` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DESKTOP"},{"path":"$DESKTOP/*"}]}},"scope-desktop-index":{"identifier":"scope-desktop-index","description":"This scope permits to list all files and folders in the `$DESKTOP`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DESKTOP"}]}},"scope-desktop-recursive":{"identifier":"scope-desktop-recursive","description":"This scope permits recursive access to the complete `$DESKTOP` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DESKTOP"},{"path":"$DESKTOP/**"}]}},"scope-document":{"identifier":"scope-document","description":"This scope permits access to all files and list content of top level directories in the `$DOCUMENT` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOCUMENT"},{"path":"$DOCUMENT/*"}]}},"scope-document-index":{"identifier":"scope-document-index","description":"This scope permits to list all files and folders in the `$DOCUMENT`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOCUMENT"}]}},"scope-document-recursive":{"identifier":"scope-document-recursive","description":"This scope permits recursive access to the complete `$DOCUMENT` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOCUMENT"},{"path":"$DOCUMENT/**"}]}},"scope-download":{"identifier":"scope-download","description":"This scope permits access to all files and list content of top level directories in the `$DOWNLOAD` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOWNLOAD"},{"path":"$DOWNLOAD/*"}]}},"scope-download-index":{"identifier":"scope-download-index","description":"This scope permits to list all files and folders in the `$DOWNLOAD`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOWNLOAD"}]}},"scope-download-recursive":{"identifier":"scope-download-recursive","description":"This scope permits recursive access to the complete `$DOWNLOAD` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$DOWNLOAD"},{"path":"$DOWNLOAD/**"}]}},"scope-exe":{"identifier":"scope-exe","description":"This scope permits access to all files and list content of top level directories in the `$EXE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$EXE"},{"path":"$EXE/*"}]}},"scope-exe-index":{"identifier":"scope-exe-index","description":"This scope permits to list all files and folders in the `$EXE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$EXE"}]}},"scope-exe-recursive":{"identifier":"scope-exe-recursive","description":"This scope permits recursive access to the complete `$EXE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$EXE"},{"path":"$EXE/**"}]}},"scope-font":{"identifier":"scope-font","description":"This scope permits access to all files and list content of top level directories in the `$FONT` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$FONT"},{"path":"$FONT/*"}]}},"scope-font-index":{"identifier":"scope-font-index","description":"This scope permits to list all files and folders in the `$FONT`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$FONT"}]}},"scope-font-recursive":{"identifier":"scope-font-recursive","description":"This scope permits recursive access to the complete `$FONT` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$FONT"},{"path":"$FONT/**"}]}},"scope-home":{"identifier":"scope-home","description":"This scope permits access to all files and list content of top level directories in the `$HOME` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$HOME"},{"path":"$HOME/*"}]}},"scope-home-index":{"identifier":"scope-home-index","description":"This scope permits to list all files and folders in the `$HOME`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$HOME"}]}},"scope-home-recursive":{"identifier":"scope-home-recursive","description":"This scope permits recursive access to the complete `$HOME` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$HOME"},{"path":"$HOME/**"}]}},"scope-localdata":{"identifier":"scope-localdata","description":"This scope permits access to all files and list content of top level directories in the `$LOCALDATA` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOCALDATA"},{"path":"$LOCALDATA/*"}]}},"scope-localdata-index":{"identifier":"scope-localdata-index","description":"This scope permits to list all files and folders in the `$LOCALDATA`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOCALDATA"}]}},"scope-localdata-recursive":{"identifier":"scope-localdata-recursive","description":"This scope permits recursive access to the complete `$LOCALDATA` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOCALDATA"},{"path":"$LOCALDATA/**"}]}},"scope-log":{"identifier":"scope-log","description":"This scope permits access to all files and list content of top level directories in the `$LOG` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOG"},{"path":"$LOG/*"}]}},"scope-log-index":{"identifier":"scope-log-index","description":"This scope permits to list all files and folders in the `$LOG`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOG"}]}},"scope-log-recursive":{"identifier":"scope-log-recursive","description":"This scope permits recursive access to the complete `$LOG` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$LOG"},{"path":"$LOG/**"}]}},"scope-picture":{"identifier":"scope-picture","description":"This scope permits access to all files and list content of top level directories in the `$PICTURE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PICTURE"},{"path":"$PICTURE/*"}]}},"scope-picture-index":{"identifier":"scope-picture-index","description":"This scope permits to list all files and folders in the `$PICTURE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PICTURE"}]}},"scope-picture-recursive":{"identifier":"scope-picture-recursive","description":"This scope permits recursive access to the complete `$PICTURE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PICTURE"},{"path":"$PICTURE/**"}]}},"scope-public":{"identifier":"scope-public","description":"This scope permits access to all files and list content of top level directories in the `$PUBLIC` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PUBLIC"},{"path":"$PUBLIC/*"}]}},"scope-public-index":{"identifier":"scope-public-index","description":"This scope permits to list all files and folders in the `$PUBLIC`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PUBLIC"}]}},"scope-public-recursive":{"identifier":"scope-public-recursive","description":"This scope permits recursive access to the complete `$PUBLIC` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$PUBLIC"},{"path":"$PUBLIC/**"}]}},"scope-resource":{"identifier":"scope-resource","description":"This scope permits access to all files and list content of top level directories in the `$RESOURCE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RESOURCE"},{"path":"$RESOURCE/*"}]}},"scope-resource-index":{"identifier":"scope-resource-index","description":"This scope permits to list all files and folders in the `$RESOURCE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RESOURCE"}]}},"scope-resource-recursive":{"identifier":"scope-resource-recursive","description":"This scope permits recursive access to the complete `$RESOURCE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RESOURCE"},{"path":"$RESOURCE/**"}]}},"scope-runtime":{"identifier":"scope-runtime","description":"This scope permits access to all files and list content of top level directories in the `$RUNTIME` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RUNTIME"},{"path":"$RUNTIME/*"}]}},"scope-runtime-index":{"identifier":"scope-runtime-index","description":"This scope permits to list all files and folders in the `$RUNTIME`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RUNTIME"}]}},"scope-runtime-recursive":{"identifier":"scope-runtime-recursive","description":"This scope permits recursive access to the complete `$RUNTIME` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$RUNTIME"},{"path":"$RUNTIME/**"}]}},"scope-temp":{"identifier":"scope-temp","description":"This scope permits access to all files and list content of top level directories in the `$TEMP` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMP"},{"path":"$TEMP/*"}]}},"scope-temp-index":{"identifier":"scope-temp-index","description":"This scope permits to list all files and folders in the `$TEMP`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMP"}]}},"scope-temp-recursive":{"identifier":"scope-temp-recursive","description":"This scope permits recursive access to the complete `$TEMP` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMP"},{"path":"$TEMP/**"}]}},"scope-template":{"identifier":"scope-template","description":"This scope permits access to all files and list content of top level directories in the `$TEMPLATE` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMPLATE"},{"path":"$TEMPLATE/*"}]}},"scope-template-index":{"identifier":"scope-template-index","description":"This scope permits to list all files and folders in the `$TEMPLATE`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMPLATE"}]}},"scope-template-recursive":{"identifier":"scope-template-recursive","description":"This scope permits recursive access to the complete `$TEMPLATE` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$TEMPLATE"},{"path":"$TEMPLATE/**"}]}},"scope-video":{"identifier":"scope-video","description":"This scope permits access to all files and list content of top level directories in the `$VIDEO` folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$VIDEO"},{"path":"$VIDEO/*"}]}},"scope-video-index":{"identifier":"scope-video-index","description":"This scope permits to list all files and folders in the `$VIDEO`folder.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$VIDEO"}]}},"scope-video-recursive":{"identifier":"scope-video-recursive","description":"This scope permits recursive access to the complete `$VIDEO` folder, including sub directories and files.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"path":"$VIDEO"},{"path":"$VIDEO/**"}]}},"write-all":{"identifier":"write-all","description":"This enables all write related commands without any pre-configured accessible paths.","commands":{"allow":["mkdir","create","copy_file","remove","rename","truncate","ftruncate","write","write_file","write_text_file"],"deny":[]}},"write-files":{"identifier":"write-files","description":"This enables all file write related commands without any pre-configured accessible paths.","commands":{"allow":["create","copy_file","remove","rename","truncate","ftruncate","write","write_file","write_text_file"],"deny":[]}}},"permission_sets":{"allow-app-meta":{"identifier":"allow-app-meta","description":"This allows non-recursive read access to metadata of the application folders, including file listing and statistics.","permissions":["read-meta","scope-app-index"]},"allow-app-meta-recursive":{"identifier":"allow-app-meta-recursive","description":"This allows full recursive read access to metadata of the application folders, including file listing and statistics.","permissions":["read-meta","scope-app-recursive"]},"allow-app-read":{"identifier":"allow-app-read","description":"This allows non-recursive read access to the application folders.","permissions":["read-all","scope-app"]},"allow-app-read-recursive":{"identifier":"allow-app-read-recursive","description":"This allows full recursive read access to the complete application folders, files and subdirectories.","permissions":["read-all","scope-app-recursive"]},"allow-app-write":{"identifier":"allow-app-write","description":"This allows non-recursive write access to the application folders.","permissions":["write-all","scope-app"]},"allow-app-write-recursive":{"identifier":"allow-app-write-recursive","description":"This allows full recursive write access to the complete application folders, files and subdirectories.","permissions":["write-all","scope-app-recursive"]},"allow-appcache-meta":{"identifier":"allow-appcache-meta","description":"This allows non-recursive read access to metadata of the `$APPCACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-appcache-index"]},"allow-appcache-meta-recursive":{"identifier":"allow-appcache-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPCACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-appcache-recursive"]},"allow-appcache-read":{"identifier":"allow-appcache-read","description":"This allows non-recursive read access to the `$APPCACHE` folder.","permissions":["read-all","scope-appcache"]},"allow-appcache-read-recursive":{"identifier":"allow-appcache-read-recursive","description":"This allows full recursive read access to the complete `$APPCACHE` folder, files and subdirectories.","permissions":["read-all","scope-appcache-recursive"]},"allow-appcache-write":{"identifier":"allow-appcache-write","description":"This allows non-recursive write access to the `$APPCACHE` folder.","permissions":["write-all","scope-appcache"]},"allow-appcache-write-recursive":{"identifier":"allow-appcache-write-recursive","description":"This allows full recursive write access to the complete `$APPCACHE` folder, files and subdirectories.","permissions":["write-all","scope-appcache-recursive"]},"allow-appconfig-meta":{"identifier":"allow-appconfig-meta","description":"This allows non-recursive read access to metadata of the `$APPCONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-appconfig-index"]},"allow-appconfig-meta-recursive":{"identifier":"allow-appconfig-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPCONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-appconfig-recursive"]},"allow-appconfig-read":{"identifier":"allow-appconfig-read","description":"This allows non-recursive read access to the `$APPCONFIG` folder.","permissions":["read-all","scope-appconfig"]},"allow-appconfig-read-recursive":{"identifier":"allow-appconfig-read-recursive","description":"This allows full recursive read access to the complete `$APPCONFIG` folder, files and subdirectories.","permissions":["read-all","scope-appconfig-recursive"]},"allow-appconfig-write":{"identifier":"allow-appconfig-write","description":"This allows non-recursive write access to the `$APPCONFIG` folder.","permissions":["write-all","scope-appconfig"]},"allow-appconfig-write-recursive":{"identifier":"allow-appconfig-write-recursive","description":"This allows full recursive write access to the complete `$APPCONFIG` folder, files and subdirectories.","permissions":["write-all","scope-appconfig-recursive"]},"allow-appdata-meta":{"identifier":"allow-appdata-meta","description":"This allows non-recursive read access to metadata of the `$APPDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-appdata-index"]},"allow-appdata-meta-recursive":{"identifier":"allow-appdata-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-appdata-recursive"]},"allow-appdata-read":{"identifier":"allow-appdata-read","description":"This allows non-recursive read access to the `$APPDATA` folder.","permissions":["read-all","scope-appdata"]},"allow-appdata-read-recursive":{"identifier":"allow-appdata-read-recursive","description":"This allows full recursive read access to the complete `$APPDATA` folder, files and subdirectories.","permissions":["read-all","scope-appdata-recursive"]},"allow-appdata-write":{"identifier":"allow-appdata-write","description":"This allows non-recursive write access to the `$APPDATA` folder.","permissions":["write-all","scope-appdata"]},"allow-appdata-write-recursive":{"identifier":"allow-appdata-write-recursive","description":"This allows full recursive write access to the complete `$APPDATA` folder, files and subdirectories.","permissions":["write-all","scope-appdata-recursive"]},"allow-applocaldata-meta":{"identifier":"allow-applocaldata-meta","description":"This allows non-recursive read access to metadata of the `$APPLOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-applocaldata-index"]},"allow-applocaldata-meta-recursive":{"identifier":"allow-applocaldata-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPLOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-applocaldata-recursive"]},"allow-applocaldata-read":{"identifier":"allow-applocaldata-read","description":"This allows non-recursive read access to the `$APPLOCALDATA` folder.","permissions":["read-all","scope-applocaldata"]},"allow-applocaldata-read-recursive":{"identifier":"allow-applocaldata-read-recursive","description":"This allows full recursive read access to the complete `$APPLOCALDATA` folder, files and subdirectories.","permissions":["read-all","scope-applocaldata-recursive"]},"allow-applocaldata-write":{"identifier":"allow-applocaldata-write","description":"This allows non-recursive write access to the `$APPLOCALDATA` folder.","permissions":["write-all","scope-applocaldata"]},"allow-applocaldata-write-recursive":{"identifier":"allow-applocaldata-write-recursive","description":"This allows full recursive write access to the complete `$APPLOCALDATA` folder, files and subdirectories.","permissions":["write-all","scope-applocaldata-recursive"]},"allow-applog-meta":{"identifier":"allow-applog-meta","description":"This allows non-recursive read access to metadata of the `$APPLOG` folder, including file listing and statistics.","permissions":["read-meta","scope-applog-index"]},"allow-applog-meta-recursive":{"identifier":"allow-applog-meta-recursive","description":"This allows full recursive read access to metadata of the `$APPLOG` folder, including file listing and statistics.","permissions":["read-meta","scope-applog-recursive"]},"allow-applog-read":{"identifier":"allow-applog-read","description":"This allows non-recursive read access to the `$APPLOG` folder.","permissions":["read-all","scope-applog"]},"allow-applog-read-recursive":{"identifier":"allow-applog-read-recursive","description":"This allows full recursive read access to the complete `$APPLOG` folder, files and subdirectories.","permissions":["read-all","scope-applog-recursive"]},"allow-applog-write":{"identifier":"allow-applog-write","description":"This allows non-recursive write access to the `$APPLOG` folder.","permissions":["write-all","scope-applog"]},"allow-applog-write-recursive":{"identifier":"allow-applog-write-recursive","description":"This allows full recursive write access to the complete `$APPLOG` folder, files and subdirectories.","permissions":["write-all","scope-applog-recursive"]},"allow-audio-meta":{"identifier":"allow-audio-meta","description":"This allows non-recursive read access to metadata of the `$AUDIO` folder, including file listing and statistics.","permissions":["read-meta","scope-audio-index"]},"allow-audio-meta-recursive":{"identifier":"allow-audio-meta-recursive","description":"This allows full recursive read access to metadata of the `$AUDIO` folder, including file listing and statistics.","permissions":["read-meta","scope-audio-recursive"]},"allow-audio-read":{"identifier":"allow-audio-read","description":"This allows non-recursive read access to the `$AUDIO` folder.","permissions":["read-all","scope-audio"]},"allow-audio-read-recursive":{"identifier":"allow-audio-read-recursive","description":"This allows full recursive read access to the complete `$AUDIO` folder, files and subdirectories.","permissions":["read-all","scope-audio-recursive"]},"allow-audio-write":{"identifier":"allow-audio-write","description":"This allows non-recursive write access to the `$AUDIO` folder.","permissions":["write-all","scope-audio"]},"allow-audio-write-recursive":{"identifier":"allow-audio-write-recursive","description":"This allows full recursive write access to the complete `$AUDIO` folder, files and subdirectories.","permissions":["write-all","scope-audio-recursive"]},"allow-cache-meta":{"identifier":"allow-cache-meta","description":"This allows non-recursive read access to metadata of the `$CACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-cache-index"]},"allow-cache-meta-recursive":{"identifier":"allow-cache-meta-recursive","description":"This allows full recursive read access to metadata of the `$CACHE` folder, including file listing and statistics.","permissions":["read-meta","scope-cache-recursive"]},"allow-cache-read":{"identifier":"allow-cache-read","description":"This allows non-recursive read access to the `$CACHE` folder.","permissions":["read-all","scope-cache"]},"allow-cache-read-recursive":{"identifier":"allow-cache-read-recursive","description":"This allows full recursive read access to the complete `$CACHE` folder, files and subdirectories.","permissions":["read-all","scope-cache-recursive"]},"allow-cache-write":{"identifier":"allow-cache-write","description":"This allows non-recursive write access to the `$CACHE` folder.","permissions":["write-all","scope-cache"]},"allow-cache-write-recursive":{"identifier":"allow-cache-write-recursive","description":"This allows full recursive write access to the complete `$CACHE` folder, files and subdirectories.","permissions":["write-all","scope-cache-recursive"]},"allow-config-meta":{"identifier":"allow-config-meta","description":"This allows non-recursive read access to metadata of the `$CONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-config-index"]},"allow-config-meta-recursive":{"identifier":"allow-config-meta-recursive","description":"This allows full recursive read access to metadata of the `$CONFIG` folder, including file listing and statistics.","permissions":["read-meta","scope-config-recursive"]},"allow-config-read":{"identifier":"allow-config-read","description":"This allows non-recursive read access to the `$CONFIG` folder.","permissions":["read-all","scope-config"]},"allow-config-read-recursive":{"identifier":"allow-config-read-recursive","description":"This allows full recursive read access to the complete `$CONFIG` folder, files and subdirectories.","permissions":["read-all","scope-config-recursive"]},"allow-config-write":{"identifier":"allow-config-write","description":"This allows non-recursive write access to the `$CONFIG` folder.","permissions":["write-all","scope-config"]},"allow-config-write-recursive":{"identifier":"allow-config-write-recursive","description":"This allows full recursive write access to the complete `$CONFIG` folder, files and subdirectories.","permissions":["write-all","scope-config-recursive"]},"allow-data-meta":{"identifier":"allow-data-meta","description":"This allows non-recursive read access to metadata of the `$DATA` folder, including file listing and statistics.","permissions":["read-meta","scope-data-index"]},"allow-data-meta-recursive":{"identifier":"allow-data-meta-recursive","description":"This allows full recursive read access to metadata of the `$DATA` folder, including file listing and statistics.","permissions":["read-meta","scope-data-recursive"]},"allow-data-read":{"identifier":"allow-data-read","description":"This allows non-recursive read access to the `$DATA` folder.","permissions":["read-all","scope-data"]},"allow-data-read-recursive":{"identifier":"allow-data-read-recursive","description":"This allows full recursive read access to the complete `$DATA` folder, files and subdirectories.","permissions":["read-all","scope-data-recursive"]},"allow-data-write":{"identifier":"allow-data-write","description":"This allows non-recursive write access to the `$DATA` folder.","permissions":["write-all","scope-data"]},"allow-data-write-recursive":{"identifier":"allow-data-write-recursive","description":"This allows full recursive write access to the complete `$DATA` folder, files and subdirectories.","permissions":["write-all","scope-data-recursive"]},"allow-desktop-meta":{"identifier":"allow-desktop-meta","description":"This allows non-recursive read access to metadata of the `$DESKTOP` folder, including file listing and statistics.","permissions":["read-meta","scope-desktop-index"]},"allow-desktop-meta-recursive":{"identifier":"allow-desktop-meta-recursive","description":"This allows full recursive read access to metadata of the `$DESKTOP` folder, including file listing and statistics.","permissions":["read-meta","scope-desktop-recursive"]},"allow-desktop-read":{"identifier":"allow-desktop-read","description":"This allows non-recursive read access to the `$DESKTOP` folder.","permissions":["read-all","scope-desktop"]},"allow-desktop-read-recursive":{"identifier":"allow-desktop-read-recursive","description":"This allows full recursive read access to the complete `$DESKTOP` folder, files and subdirectories.","permissions":["read-all","scope-desktop-recursive"]},"allow-desktop-write":{"identifier":"allow-desktop-write","description":"This allows non-recursive write access to the `$DESKTOP` folder.","permissions":["write-all","scope-desktop"]},"allow-desktop-write-recursive":{"identifier":"allow-desktop-write-recursive","description":"This allows full recursive write access to the complete `$DESKTOP` folder, files and subdirectories.","permissions":["write-all","scope-desktop-recursive"]},"allow-document-meta":{"identifier":"allow-document-meta","description":"This allows non-recursive read access to metadata of the `$DOCUMENT` folder, including file listing and statistics.","permissions":["read-meta","scope-document-index"]},"allow-document-meta-recursive":{"identifier":"allow-document-meta-recursive","description":"This allows full recursive read access to metadata of the `$DOCUMENT` folder, including file listing and statistics.","permissions":["read-meta","scope-document-recursive"]},"allow-document-read":{"identifier":"allow-document-read","description":"This allows non-recursive read access to the `$DOCUMENT` folder.","permissions":["read-all","scope-document"]},"allow-document-read-recursive":{"identifier":"allow-document-read-recursive","description":"This allows full recursive read access to the complete `$DOCUMENT` folder, files and subdirectories.","permissions":["read-all","scope-document-recursive"]},"allow-document-write":{"identifier":"allow-document-write","description":"This allows non-recursive write access to the `$DOCUMENT` folder.","permissions":["write-all","scope-document"]},"allow-document-write-recursive":{"identifier":"allow-document-write-recursive","description":"This allows full recursive write access to the complete `$DOCUMENT` folder, files and subdirectories.","permissions":["write-all","scope-document-recursive"]},"allow-download-meta":{"identifier":"allow-download-meta","description":"This allows non-recursive read access to metadata of the `$DOWNLOAD` folder, including file listing and statistics.","permissions":["read-meta","scope-download-index"]},"allow-download-meta-recursive":{"identifier":"allow-download-meta-recursive","description":"This allows full recursive read access to metadata of the `$DOWNLOAD` folder, including file listing and statistics.","permissions":["read-meta","scope-download-recursive"]},"allow-download-read":{"identifier":"allow-download-read","description":"This allows non-recursive read access to the `$DOWNLOAD` folder.","permissions":["read-all","scope-download"]},"allow-download-read-recursive":{"identifier":"allow-download-read-recursive","description":"This allows full recursive read access to the complete `$DOWNLOAD` folder, files and subdirectories.","permissions":["read-all","scope-download-recursive"]},"allow-download-write":{"identifier":"allow-download-write","description":"This allows non-recursive write access to the `$DOWNLOAD` folder.","permissions":["write-all","scope-download"]},"allow-download-write-recursive":{"identifier":"allow-download-write-recursive","description":"This allows full recursive write access to the complete `$DOWNLOAD` folder, files and subdirectories.","permissions":["write-all","scope-download-recursive"]},"allow-exe-meta":{"identifier":"allow-exe-meta","description":"This allows non-recursive read access to metadata of the `$EXE` folder, including file listing and statistics.","permissions":["read-meta","scope-exe-index"]},"allow-exe-meta-recursive":{"identifier":"allow-exe-meta-recursive","description":"This allows full recursive read access to metadata of the `$EXE` folder, including file listing and statistics.","permissions":["read-meta","scope-exe-recursive"]},"allow-exe-read":{"identifier":"allow-exe-read","description":"This allows non-recursive read access to the `$EXE` folder.","permissions":["read-all","scope-exe"]},"allow-exe-read-recursive":{"identifier":"allow-exe-read-recursive","description":"This allows full recursive read access to the complete `$EXE` folder, files and subdirectories.","permissions":["read-all","scope-exe-recursive"]},"allow-exe-write":{"identifier":"allow-exe-write","description":"This allows non-recursive write access to the `$EXE` folder.","permissions":["write-all","scope-exe"]},"allow-exe-write-recursive":{"identifier":"allow-exe-write-recursive","description":"This allows full recursive write access to the complete `$EXE` folder, files and subdirectories.","permissions":["write-all","scope-exe-recursive"]},"allow-font-meta":{"identifier":"allow-font-meta","description":"This allows non-recursive read access to metadata of the `$FONT` folder, including file listing and statistics.","permissions":["read-meta","scope-font-index"]},"allow-font-meta-recursive":{"identifier":"allow-font-meta-recursive","description":"This allows full recursive read access to metadata of the `$FONT` folder, including file listing and statistics.","permissions":["read-meta","scope-font-recursive"]},"allow-font-read":{"identifier":"allow-font-read","description":"This allows non-recursive read access to the `$FONT` folder.","permissions":["read-all","scope-font"]},"allow-font-read-recursive":{"identifier":"allow-font-read-recursive","description":"This allows full recursive read access to the complete `$FONT` folder, files and subdirectories.","permissions":["read-all","scope-font-recursive"]},"allow-font-write":{"identifier":"allow-font-write","description":"This allows non-recursive write access to the `$FONT` folder.","permissions":["write-all","scope-font"]},"allow-font-write-recursive":{"identifier":"allow-font-write-recursive","description":"This allows full recursive write access to the complete `$FONT` folder, files and subdirectories.","permissions":["write-all","scope-font-recursive"]},"allow-home-meta":{"identifier":"allow-home-meta","description":"This allows non-recursive read access to metadata of the `$HOME` folder, including file listing and statistics.","permissions":["read-meta","scope-home-index"]},"allow-home-meta-recursive":{"identifier":"allow-home-meta-recursive","description":"This allows full recursive read access to metadata of the `$HOME` folder, including file listing and statistics.","permissions":["read-meta","scope-home-recursive"]},"allow-home-read":{"identifier":"allow-home-read","description":"This allows non-recursive read access to the `$HOME` folder.","permissions":["read-all","scope-home"]},"allow-home-read-recursive":{"identifier":"allow-home-read-recursive","description":"This allows full recursive read access to the complete `$HOME` folder, files and subdirectories.","permissions":["read-all","scope-home-recursive"]},"allow-home-write":{"identifier":"allow-home-write","description":"This allows non-recursive write access to the `$HOME` folder.","permissions":["write-all","scope-home"]},"allow-home-write-recursive":{"identifier":"allow-home-write-recursive","description":"This allows full recursive write access to the complete `$HOME` folder, files and subdirectories.","permissions":["write-all","scope-home-recursive"]},"allow-localdata-meta":{"identifier":"allow-localdata-meta","description":"This allows non-recursive read access to metadata of the `$LOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-localdata-index"]},"allow-localdata-meta-recursive":{"identifier":"allow-localdata-meta-recursive","description":"This allows full recursive read access to metadata of the `$LOCALDATA` folder, including file listing and statistics.","permissions":["read-meta","scope-localdata-recursive"]},"allow-localdata-read":{"identifier":"allow-localdata-read","description":"This allows non-recursive read access to the `$LOCALDATA` folder.","permissions":["read-all","scope-localdata"]},"allow-localdata-read-recursive":{"identifier":"allow-localdata-read-recursive","description":"This allows full recursive read access to the complete `$LOCALDATA` folder, files and subdirectories.","permissions":["read-all","scope-localdata-recursive"]},"allow-localdata-write":{"identifier":"allow-localdata-write","description":"This allows non-recursive write access to the `$LOCALDATA` folder.","permissions":["write-all","scope-localdata"]},"allow-localdata-write-recursive":{"identifier":"allow-localdata-write-recursive","description":"This allows full recursive write access to the complete `$LOCALDATA` folder, files and subdirectories.","permissions":["write-all","scope-localdata-recursive"]},"allow-log-meta":{"identifier":"allow-log-meta","description":"This allows non-recursive read access to metadata of the `$LOG` folder, including file listing and statistics.","permissions":["read-meta","scope-log-index"]},"allow-log-meta-recursive":{"identifier":"allow-log-meta-recursive","description":"This allows full recursive read access to metadata of the `$LOG` folder, including file listing and statistics.","permissions":["read-meta","scope-log-recursive"]},"allow-log-read":{"identifier":"allow-log-read","description":"This allows non-recursive read access to the `$LOG` folder.","permissions":["read-all","scope-log"]},"allow-log-read-recursive":{"identifier":"allow-log-read-recursive","description":"This allows full recursive read access to the complete `$LOG` folder, files and subdirectories.","permissions":["read-all","scope-log-recursive"]},"allow-log-write":{"identifier":"allow-log-write","description":"This allows non-recursive write access to the `$LOG` folder.","permissions":["write-all","scope-log"]},"allow-log-write-recursive":{"identifier":"allow-log-write-recursive","description":"This allows full recursive write access to the complete `$LOG` folder, files and subdirectories.","permissions":["write-all","scope-log-recursive"]},"allow-picture-meta":{"identifier":"allow-picture-meta","description":"This allows non-recursive read access to metadata of the `$PICTURE` folder, including file listing and statistics.","permissions":["read-meta","scope-picture-index"]},"allow-picture-meta-recursive":{"identifier":"allow-picture-meta-recursive","description":"This allows full recursive read access to metadata of the `$PICTURE` folder, including file listing and statistics.","permissions":["read-meta","scope-picture-recursive"]},"allow-picture-read":{"identifier":"allow-picture-read","description":"This allows non-recursive read access to the `$PICTURE` folder.","permissions":["read-all","scope-picture"]},"allow-picture-read-recursive":{"identifier":"allow-picture-read-recursive","description":"This allows full recursive read access to the complete `$PICTURE` folder, files and subdirectories.","permissions":["read-all","scope-picture-recursive"]},"allow-picture-write":{"identifier":"allow-picture-write","description":"This allows non-recursive write access to the `$PICTURE` folder.","permissions":["write-all","scope-picture"]},"allow-picture-write-recursive":{"identifier":"allow-picture-write-recursive","description":"This allows full recursive write access to the complete `$PICTURE` folder, files and subdirectories.","permissions":["write-all","scope-picture-recursive"]},"allow-public-meta":{"identifier":"allow-public-meta","description":"This allows non-recursive read access to metadata of the `$PUBLIC` folder, including file listing and statistics.","permissions":["read-meta","scope-public-index"]},"allow-public-meta-recursive":{"identifier":"allow-public-meta-recursive","description":"This allows full recursive read access to metadata of the `$PUBLIC` folder, including file listing and statistics.","permissions":["read-meta","scope-public-recursive"]},"allow-public-read":{"identifier":"allow-public-read","description":"This allows non-recursive read access to the `$PUBLIC` folder.","permissions":["read-all","scope-public"]},"allow-public-read-recursive":{"identifier":"allow-public-read-recursive","description":"This allows full recursive read access to the complete `$PUBLIC` folder, files and subdirectories.","permissions":["read-all","scope-public-recursive"]},"allow-public-write":{"identifier":"allow-public-write","description":"This allows non-recursive write access to the `$PUBLIC` folder.","permissions":["write-all","scope-public"]},"allow-public-write-recursive":{"identifier":"allow-public-write-recursive","description":"This allows full recursive write access to the complete `$PUBLIC` folder, files and subdirectories.","permissions":["write-all","scope-public-recursive"]},"allow-resource-meta":{"identifier":"allow-resource-meta","description":"This allows non-recursive read access to metadata of the `$RESOURCE` folder, including file listing and statistics.","permissions":["read-meta","scope-resource-index"]},"allow-resource-meta-recursive":{"identifier":"allow-resource-meta-recursive","description":"This allows full recursive read access to metadata of the `$RESOURCE` folder, including file listing and statistics.","permissions":["read-meta","scope-resource-recursive"]},"allow-resource-read":{"identifier":"allow-resource-read","description":"This allows non-recursive read access to the `$RESOURCE` folder.","permissions":["read-all","scope-resource"]},"allow-resource-read-recursive":{"identifier":"allow-resource-read-recursive","description":"This allows full recursive read access to the complete `$RESOURCE` folder, files and subdirectories.","permissions":["read-all","scope-resource-recursive"]},"allow-resource-write":{"identifier":"allow-resource-write","description":"This allows non-recursive write access to the `$RESOURCE` folder.","permissions":["write-all","scope-resource"]},"allow-resource-write-recursive":{"identifier":"allow-resource-write-recursive","description":"This allows full recursive write access to the complete `$RESOURCE` folder, files and subdirectories.","permissions":["write-all","scope-resource-recursive"]},"allow-runtime-meta":{"identifier":"allow-runtime-meta","description":"This allows non-recursive read access to metadata of the `$RUNTIME` folder, including file listing and statistics.","permissions":["read-meta","scope-runtime-index"]},"allow-runtime-meta-recursive":{"identifier":"allow-runtime-meta-recursive","description":"This allows full recursive read access to metadata of the `$RUNTIME` folder, including file listing and statistics.","permissions":["read-meta","scope-runtime-recursive"]},"allow-runtime-read":{"identifier":"allow-runtime-read","description":"This allows non-recursive read access to the `$RUNTIME` folder.","permissions":["read-all","scope-runtime"]},"allow-runtime-read-recursive":{"identifier":"allow-runtime-read-recursive","description":"This allows full recursive read access to the complete `$RUNTIME` folder, files and subdirectories.","permissions":["read-all","scope-runtime-recursive"]},"allow-runtime-write":{"identifier":"allow-runtime-write","description":"This allows non-recursive write access to the `$RUNTIME` folder.","permissions":["write-all","scope-runtime"]},"allow-runtime-write-recursive":{"identifier":"allow-runtime-write-recursive","description":"This allows full recursive write access to the complete `$RUNTIME` folder, files and subdirectories.","permissions":["write-all","scope-runtime-recursive"]},"allow-temp-meta":{"identifier":"allow-temp-meta","description":"This allows non-recursive read access to metadata of the `$TEMP` folder, including file listing and statistics.","permissions":["read-meta","scope-temp-index"]},"allow-temp-meta-recursive":{"identifier":"allow-temp-meta-recursive","description":"This allows full recursive read access to metadata of the `$TEMP` folder, including file listing and statistics.","permissions":["read-meta","scope-temp-recursive"]},"allow-temp-read":{"identifier":"allow-temp-read","description":"This allows non-recursive read access to the `$TEMP` folder.","permissions":["read-all","scope-temp"]},"allow-temp-read-recursive":{"identifier":"allow-temp-read-recursive","description":"This allows full recursive read access to the complete `$TEMP` folder, files and subdirectories.","permissions":["read-all","scope-temp-recursive"]},"allow-temp-write":{"identifier":"allow-temp-write","description":"This allows non-recursive write access to the `$TEMP` folder.","permissions":["write-all","scope-temp"]},"allow-temp-write-recursive":{"identifier":"allow-temp-write-recursive","description":"This allows full recursive write access to the complete `$TEMP` folder, files and subdirectories.","permissions":["write-all","scope-temp-recursive"]},"allow-template-meta":{"identifier":"allow-template-meta","description":"This allows non-recursive read access to metadata of the `$TEMPLATE` folder, including file listing and statistics.","permissions":["read-meta","scope-template-index"]},"allow-template-meta-recursive":{"identifier":"allow-template-meta-recursive","description":"This allows full recursive read access to metadata of the `$TEMPLATE` folder, including file listing and statistics.","permissions":["read-meta","scope-template-recursive"]},"allow-template-read":{"identifier":"allow-template-read","description":"This allows non-recursive read access to the `$TEMPLATE` folder.","permissions":["read-all","scope-template"]},"allow-template-read-recursive":{"identifier":"allow-template-read-recursive","description":"This allows full recursive read access to the complete `$TEMPLATE` folder, files and subdirectories.","permissions":["read-all","scope-template-recursive"]},"allow-template-write":{"identifier":"allow-template-write","description":"This allows non-recursive write access to the `$TEMPLATE` folder.","permissions":["write-all","scope-template"]},"allow-template-write-recursive":{"identifier":"allow-template-write-recursive","description":"This allows full recursive write access to the complete `$TEMPLATE` folder, files and subdirectories.","permissions":["write-all","scope-template-recursive"]},"allow-video-meta":{"identifier":"allow-video-meta","description":"This allows non-recursive read access to metadata of the `$VIDEO` folder, including file listing and statistics.","permissions":["read-meta","scope-video-index"]},"allow-video-meta-recursive":{"identifier":"allow-video-meta-recursive","description":"This allows full recursive read access to metadata of the `$VIDEO` folder, including file listing and statistics.","permissions":["read-meta","scope-video-recursive"]},"allow-video-read":{"identifier":"allow-video-read","description":"This allows non-recursive read access to the `$VIDEO` folder.","permissions":["read-all","scope-video"]},"allow-video-read-recursive":{"identifier":"allow-video-read-recursive","description":"This allows full recursive read access to the complete `$VIDEO` folder, files and subdirectories.","permissions":["read-all","scope-video-recursive"]},"allow-video-write":{"identifier":"allow-video-write","description":"This allows non-recursive write access to the `$VIDEO` folder.","permissions":["write-all","scope-video"]},"allow-video-write-recursive":{"identifier":"allow-video-write-recursive","description":"This allows full recursive write access to the complete `$VIDEO` folder, files and subdirectories.","permissions":["write-all","scope-video-recursive"]},"deny-default":{"identifier":"deny-default","description":"This denies access to dangerous Tauri relevant files and folders by default.","permissions":["deny-webview-data-linux","deny-webview-data-windows"]}},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"description":"A path that can be accessed by the webview when using the fs APIs. FS scope path pattern.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},{"properties":{"path":{"description":"A path that can be accessed by the webview when using the fs APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"}},"required":["path"],"type":"object"}],"description":"FS scope entry.","title":"FsScopeEntry"}},"log":{"default_permission":{"identifier":"default","description":"Allows the log command","permissions":["allow-log"]},"permissions":{"allow-log":{"identifier":"allow-log","description":"Enables the log command without any pre-configured scope.","commands":{"allow":["log"],"deny":[]}},"deny-log":{"identifier":"deny-log","description":"Denies the log command without any pre-configured scope.","commands":{"allow":[],"deny":["log"]}}},"permission_sets":{},"global_scope_schema":null},"opener":{"default_permission":{"identifier":"default","description":"This permission set allows opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application\nas well as reveal file in directories using default file explorer","permissions":["allow-open-url","allow-reveal-item-in-dir","allow-default-urls"]},"permissions":{"allow-default-urls":{"identifier":"allow-default-urls","description":"This enables opening `mailto:`, `tel:`, `https://` and `http://` urls using their default application.","commands":{"allow":[],"deny":[]},"scope":{"allow":[{"url":"mailto:*"},{"url":"tel:*"},{"url":"http://*"},{"url":"https://*"}]}},"allow-open-path":{"identifier":"allow-open-path","description":"Enables the open_path command without any pre-configured scope.","commands":{"allow":["open_path"],"deny":[]}},"allow-open-url":{"identifier":"allow-open-url","description":"Enables the open_url command without any pre-configured scope.","commands":{"allow":["open_url"],"deny":[]}},"allow-reveal-item-in-dir":{"identifier":"allow-reveal-item-in-dir","description":"Enables the reveal_item_in_dir command without any pre-configured scope.","commands":{"allow":["reveal_item_in_dir"],"deny":[]}},"deny-open-path":{"identifier":"deny-open-path","description":"Denies the open_path command without any pre-configured scope.","commands":{"allow":[],"deny":["open_path"]}},"deny-open-url":{"identifier":"deny-open-url","description":"Denies the open_url command without any pre-configured scope.","commands":{"allow":[],"deny":["open_url"]}},"deny-reveal-item-in-dir":{"identifier":"deny-reveal-item-in-dir","description":"Denies the reveal_item_in_dir command without any pre-configured scope.","commands":{"allow":[],"deny":["reveal_item_in_dir"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"properties":{"app":{"allOf":[{"$ref":"#/definitions/Application"}],"description":"An application to open this url with, for example: firefox."},"url":{"description":"A URL that can be opened by the webview when using the Opener APIs.\n\nWildcards can be used following the UNIX glob pattern.\n\nExamples:\n\n- \"https://*\" : allows all HTTPS origin\n\n- \"https://*.github.com/tauri-apps/tauri\": allows any subdomain of \"github.com\" with the \"tauri-apps/api\" path\n\n- \"https://myapi.service.com/users/*\": allows access to any URLs that begins with \"https://myapi.service.com/users/\"","type":"string"}},"required":["url"],"type":"object"},{"properties":{"app":{"allOf":[{"$ref":"#/definitions/Application"}],"description":"An application to open this path with, for example: xdg-open."},"path":{"description":"A path that can be opened by the webview when using the Opener APIs.\n\nThe pattern can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$APP`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"}},"required":["path"],"type":"object"}],"definitions":{"Application":{"anyOf":[{"description":"Open in default application.","type":"null"},{"description":"If true, allow open with any application.","type":"boolean"},{"description":"Allow specific application to open with.","type":"string"}],"description":"Opener scope application."}},"description":"Opener scope entry.","title":"OpenerScopeEntry"}},"os":{"default_permission":{"identifier":"default","description":"This permission set configures which\noperating system information are available\nto gather from the frontend.\n\n#### Granted Permissions\n\nAll information except the host name are available.\n\n","permissions":["allow-arch","allow-exe-extension","allow-family","allow-locale","allow-os-type","allow-platform","allow-version"]},"permissions":{"allow-arch":{"identifier":"allow-arch","description":"Enables the arch command without any pre-configured scope.","commands":{"allow":["arch"],"deny":[]}},"allow-exe-extension":{"identifier":"allow-exe-extension","description":"Enables the exe_extension command without any pre-configured scope.","commands":{"allow":["exe_extension"],"deny":[]}},"allow-family":{"identifier":"allow-family","description":"Enables the family command without any pre-configured scope.","commands":{"allow":["family"],"deny":[]}},"allow-hostname":{"identifier":"allow-hostname","description":"Enables the hostname command without any pre-configured scope.","commands":{"allow":["hostname"],"deny":[]}},"allow-locale":{"identifier":"allow-locale","description":"Enables the locale command without any pre-configured scope.","commands":{"allow":["locale"],"deny":[]}},"allow-os-type":{"identifier":"allow-os-type","description":"Enables the os_type command without any pre-configured scope.","commands":{"allow":["os_type"],"deny":[]}},"allow-platform":{"identifier":"allow-platform","description":"Enables the platform command without any pre-configured scope.","commands":{"allow":["platform"],"deny":[]}},"allow-version":{"identifier":"allow-version","description":"Enables the version command without any pre-configured scope.","commands":{"allow":["version"],"deny":[]}},"deny-arch":{"identifier":"deny-arch","description":"Denies the arch command without any pre-configured scope.","commands":{"allow":[],"deny":["arch"]}},"deny-exe-extension":{"identifier":"deny-exe-extension","description":"Denies the exe_extension command without any pre-configured scope.","commands":{"allow":[],"deny":["exe_extension"]}},"deny-family":{"identifier":"deny-family","description":"Denies the family command without any pre-configured scope.","commands":{"allow":[],"deny":["family"]}},"deny-hostname":{"identifier":"deny-hostname","description":"Denies the hostname command without any pre-configured scope.","commands":{"allow":[],"deny":["hostname"]}},"deny-locale":{"identifier":"deny-locale","description":"Denies the locale command without any pre-configured scope.","commands":{"allow":[],"deny":["locale"]}},"deny-os-type":{"identifier":"deny-os-type","description":"Denies the os_type command without any pre-configured scope.","commands":{"allow":[],"deny":["os_type"]}},"deny-platform":{"identifier":"deny-platform","description":"Denies the platform command without any pre-configured scope.","commands":{"allow":[],"deny":["platform"]}},"deny-version":{"identifier":"deny-version","description":"Denies the version command without any pre-configured scope.","commands":{"allow":[],"deny":["version"]}}},"permission_sets":{},"global_scope_schema":null},"shell":{"default_permission":{"identifier":"default","description":"This permission set configures which\nshell functionality is exposed by default.\n\n#### Granted Permissions\n\nIt allows to use the `open` functionality without any specific\nscope pre-configured. It will allow opening `http(s)://`,\n`tel:` and `mailto:` links.\n","permissions":["allow-open"]},"permissions":{"allow-execute":{"identifier":"allow-execute","description":"Enables the execute command without any pre-configured scope.","commands":{"allow":["execute"],"deny":[]}},"allow-kill":{"identifier":"allow-kill","description":"Enables the kill command without any pre-configured scope.","commands":{"allow":["kill"],"deny":[]}},"allow-open":{"identifier":"allow-open","description":"Enables the open command without any pre-configured scope.","commands":{"allow":["open"],"deny":[]}},"allow-spawn":{"identifier":"allow-spawn","description":"Enables the spawn command without any pre-configured scope.","commands":{"allow":["spawn"],"deny":[]}},"allow-stdin-write":{"identifier":"allow-stdin-write","description":"Enables the stdin_write command without any pre-configured scope.","commands":{"allow":["stdin_write"],"deny":[]}},"deny-execute":{"identifier":"deny-execute","description":"Denies the execute command without any pre-configured scope.","commands":{"allow":[],"deny":["execute"]}},"deny-kill":{"identifier":"deny-kill","description":"Denies the kill command without any pre-configured scope.","commands":{"allow":[],"deny":["kill"]}},"deny-open":{"identifier":"deny-open","description":"Denies the open command without any pre-configured scope.","commands":{"allow":[],"deny":["open"]}},"deny-spawn":{"identifier":"deny-spawn","description":"Denies the spawn command without any pre-configured scope.","commands":{"allow":[],"deny":["spawn"]}},"deny-stdin-write":{"identifier":"deny-stdin-write","description":"Denies the stdin_write command without any pre-configured scope.","commands":{"allow":[],"deny":["stdin_write"]}}},"permission_sets":{},"global_scope_schema":{"$schema":"http://json-schema.org/draft-07/schema#","anyOf":[{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"cmd":{"description":"The command name. It can start with a variable that resolves to a system base directory. The variables are: `$AUDIO`, `$CACHE`, `$CONFIG`, `$DATA`, `$LOCALDATA`, `$DESKTOP`, `$DOCUMENT`, `$DOWNLOAD`, `$EXE`, `$FONT`, `$HOME`, `$PICTURE`, `$PUBLIC`, `$RUNTIME`, `$TEMPLATE`, `$VIDEO`, `$RESOURCE`, `$LOG`, `$TEMP`, `$APPCONFIG`, `$APPDATA`, `$APPLOCALDATA`, `$APPCACHE`, `$APPLOG`.","type":"string"},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"}},"required":["cmd","name"],"type":"object"},{"additionalProperties":false,"properties":{"args":{"allOf":[{"$ref":"#/definitions/ShellScopeEntryAllowedArgs"}],"description":"The allowed arguments for the command execution."},"name":{"description":"The name for this allowed shell command configuration.\n\nThis name will be used inside of the webview API to call this command along with any specified arguments.","type":"string"},"sidecar":{"description":"If this command is a sidecar command.","type":"boolean"}},"required":["name","sidecar"],"type":"object"}],"definitions":{"ShellScopeEntryAllowedArg":{"anyOf":[{"description":"A non-configurable argument that is passed to the command in the order it was specified.","type":"string"},{"additionalProperties":false,"description":"A variable that is set while calling the command from the webview API.","properties":{"raw":{"default":false,"description":"Marks the validator as a raw regex, meaning the plugin should not make any modification at runtime.\n\nThis means the regex will not match on the entire string by default, which might be exploited if your regex allow unexpected input to be considered valid. When using this option, make sure your regex is correct.","type":"boolean"},"validator":{"description":"[regex] validator to require passed values to conform to an expected input.\n\nThis will require the argument value passed to this variable to match the `validator` regex before it will be executed.\n\nThe regex string is by default surrounded by `^...$` to match the full string. For example the `https?://\\w+` regex would be registered as `^https?://\\w+$`.\n\n[regex]: ","type":"string"}},"required":["validator"],"type":"object"}],"description":"A command argument allowed to be executed by the webview API."},"ShellScopeEntryAllowedArgs":{"anyOf":[{"description":"Use a simple boolean to allow all or disable all arguments to this command configuration.","type":"boolean"},{"description":"A specific set of [`ShellScopeEntryAllowedArg`] that are valid to call for the command configuration.","items":{"$ref":"#/definitions/ShellScopeEntryAllowedArg"},"type":"array"}],"description":"A set of command arguments allowed to be executed by the webview API.\n\nA value of `true` will allow any arguments to be passed to the command. `false` will disable all arguments. A list of [`ShellScopeEntryAllowedArg`] will set those arguments as the only valid arguments to be passed to the attached command configuration."}},"description":"Shell scope entry.","title":"ShellScopeEntry"}},"updater":{"default_permission":{"identifier":"default","description":"This permission set configures which kind of\nupdater functions are exposed to the frontend.\n\n#### Granted Permissions\n\nThe full workflow from checking for updates to installing them\nis enabled.\n\n","permissions":["allow-check","allow-download","allow-install","allow-download-and-install"]},"permissions":{"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"allow-download":{"identifier":"allow-download","description":"Enables the download command without any pre-configured scope.","commands":{"allow":["download"],"deny":[]}},"allow-download-and-install":{"identifier":"allow-download-and-install","description":"Enables the download_and_install command without any pre-configured scope.","commands":{"allow":["download_and_install"],"deny":[]}},"allow-install":{"identifier":"allow-install","description":"Enables the install command without any pre-configured scope.","commands":{"allow":["install"],"deny":[]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}},"deny-download":{"identifier":"deny-download","description":"Denies the download command without any pre-configured scope.","commands":{"allow":[],"deny":["download"]}},"deny-download-and-install":{"identifier":"deny-download-and-install","description":"Denies the download_and_install command without any pre-configured scope.","commands":{"allow":[],"deny":["download_and_install"]}},"deny-install":{"identifier":"deny-install","description":"Denies the install command without any pre-configured scope.","commands":{"allow":[],"deny":["install"]}}},"permission_sets":{},"global_scope_schema":null},"window-state":{"default_permission":{"identifier":"default","description":"This permission set configures what kind of\noperations are available from the window state plugin.\n\n#### Granted Permissions\n\nAll operations are enabled by default.\n\n","permissions":["allow-filename","allow-restore-state","allow-save-window-state"]},"permissions":{"allow-filename":{"identifier":"allow-filename","description":"Enables the filename command without any pre-configured scope.","commands":{"allow":["filename"],"deny":[]}},"allow-restore-state":{"identifier":"allow-restore-state","description":"Enables the restore_state command without any pre-configured scope.","commands":{"allow":["restore_state"],"deny":[]}},"allow-save-window-state":{"identifier":"allow-save-window-state","description":"Enables the save_window_state command without any pre-configured scope.","commands":{"allow":["save_window_state"],"deny":[]}},"deny-filename":{"identifier":"deny-filename","description":"Denies the filename command without any pre-configured scope.","commands":{"allow":[],"deny":["filename"]}},"deny-restore-state":{"identifier":"deny-restore-state","description":"Denies the restore_state command without any pre-configured scope.","commands":{"allow":[],"deny":["restore_state"]}},"deny-save-window-state":{"identifier":"deny-save-window-state","description":"Denies the save_window_state command without any pre-configured scope.","commands":{"allow":[],"deny":["save_window_state"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-git":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-add","allow-branch","allow-checkout","allow-commit","allow-delete-branch","allow-fetch-all","allow-initialize","allow-log","allow-merge-branch","allow-pull","allow-push","allow-status","allow-unstage"]},"permissions":{"allow-add":{"identifier":"allow-add","description":"Enables the add command without any pre-configured scope.","commands":{"allow":["add"],"deny":[]}},"allow-branch":{"identifier":"allow-branch","description":"Enables the branch command without any pre-configured scope.","commands":{"allow":["branch"],"deny":[]}},"allow-checkout":{"identifier":"allow-checkout","description":"Enables the checkout command without any pre-configured scope.","commands":{"allow":["checkout"],"deny":[]}},"allow-checkout-remote":{"identifier":"allow-checkout-remote","description":"Enables the checkout_remote command without any pre-configured scope.","commands":{"allow":["checkout_remote"],"deny":[]}},"allow-commit":{"identifier":"allow-commit","description":"Enables the commit command without any pre-configured scope.","commands":{"allow":["commit"],"deny":[]}},"allow-delete-branch":{"identifier":"allow-delete-branch","description":"Enables the delete_branch command without any pre-configured scope.","commands":{"allow":["delete_branch"],"deny":[]}},"allow-fetch-all":{"identifier":"allow-fetch-all","description":"Enables the fetch_all command without any pre-configured scope.","commands":{"allow":["fetch_all"],"deny":[]}},"allow-initialize":{"identifier":"allow-initialize","description":"Enables the initialize command without any pre-configured scope.","commands":{"allow":["initialize"],"deny":[]}},"allow-log":{"identifier":"allow-log","description":"Enables the log command without any pre-configured scope.","commands":{"allow":["log"],"deny":[]}},"allow-merge-branch":{"identifier":"allow-merge-branch","description":"Enables the merge_branch command without any pre-configured scope.","commands":{"allow":["merge_branch"],"deny":[]}},"allow-pull":{"identifier":"allow-pull","description":"Enables the pull command without any pre-configured scope.","commands":{"allow":["pull"],"deny":[]}},"allow-push":{"identifier":"allow-push","description":"Enables the push command without any pre-configured scope.","commands":{"allow":["push"],"deny":[]}},"allow-status":{"identifier":"allow-status","description":"Enables the status command without any pre-configured scope.","commands":{"allow":["status"],"deny":[]}},"allow-unstage":{"identifier":"allow-unstage","description":"Enables the unstage command without any pre-configured scope.","commands":{"allow":["unstage"],"deny":[]}},"deny-add":{"identifier":"deny-add","description":"Denies the add command without any pre-configured scope.","commands":{"allow":[],"deny":["add"]}},"deny-branch":{"identifier":"deny-branch","description":"Denies the branch command without any pre-configured scope.","commands":{"allow":[],"deny":["branch"]}},"deny-checkout":{"identifier":"deny-checkout","description":"Denies the checkout command without any pre-configured scope.","commands":{"allow":[],"deny":["checkout"]}},"deny-checkout-remote":{"identifier":"deny-checkout-remote","description":"Denies the checkout_remote command without any pre-configured scope.","commands":{"allow":[],"deny":["checkout_remote"]}},"deny-commit":{"identifier":"deny-commit","description":"Denies the commit command without any pre-configured scope.","commands":{"allow":[],"deny":["commit"]}},"deny-delete-branch":{"identifier":"deny-delete-branch","description":"Denies the delete_branch command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_branch"]}},"deny-fetch-all":{"identifier":"deny-fetch-all","description":"Denies the fetch_all command without any pre-configured scope.","commands":{"allow":[],"deny":["fetch_all"]}},"deny-initialize":{"identifier":"deny-initialize","description":"Denies the initialize command without any pre-configured scope.","commands":{"allow":[],"deny":["initialize"]}},"deny-log":{"identifier":"deny-log","description":"Denies the log command without any pre-configured scope.","commands":{"allow":[],"deny":["log"]}},"deny-merge-branch":{"identifier":"deny-merge-branch","description":"Denies the merge_branch command without any pre-configured scope.","commands":{"allow":[],"deny":["merge_branch"]}},"deny-pull":{"identifier":"deny-pull","description":"Denies the pull command without any pre-configured scope.","commands":{"allow":[],"deny":["pull"]}},"deny-push":{"identifier":"deny-push","description":"Denies the push command without any pre-configured scope.","commands":{"allow":[],"deny":["push"]}},"deny-status":{"identifier":"deny-status","description":"Denies the status command without any pre-configured scope.","commands":{"allow":[],"deny":["status"]}},"deny-unstage":{"identifier":"deny-unstage","description":"Denies the unstage command without any pre-configured scope.","commands":{"allow":[],"deny":["unstage"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-license":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-check","allow-activate","allow-deactivate"]},"permissions":{"allow-activate":{"identifier":"allow-activate","description":"Enables the activate command without any pre-configured scope.","commands":{"allow":["activate"],"deny":[]}},"allow-check":{"identifier":"allow-check","description":"Enables the check command without any pre-configured scope.","commands":{"allow":["check"],"deny":[]}},"allow-deactivate":{"identifier":"allow-deactivate","description":"Enables the deactivate command without any pre-configured scope.","commands":{"allow":["deactivate"],"deny":[]}},"deny-activate":{"identifier":"deny-activate","description":"Denies the activate command without any pre-configured scope.","commands":{"allow":[],"deny":["activate"]}},"deny-check":{"identifier":"deny-check","description":"Denies the check command without any pre-configured scope.","commands":{"allow":[],"deny":["check"]}},"deny-deactivate":{"identifier":"deny-deactivate","description":"Denies the deactivate command without any pre-configured scope.","commands":{"allow":[],"deny":["deactivate"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-models":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-delete","allow-duplicate","allow-get-settings","allow-grpc-events","allow-upsert","allow-websocket-events","allow-workspace-models"]},"permissions":{"allow-delete":{"identifier":"allow-delete","description":"Enables the delete command without any pre-configured scope.","commands":{"allow":["delete"],"deny":[]}},"allow-duplicate":{"identifier":"allow-duplicate","description":"Enables the duplicate command without any pre-configured scope.","commands":{"allow":["duplicate"],"deny":[]}},"allow-get-settings":{"identifier":"allow-get-settings","description":"Enables the get_settings command without any pre-configured scope.","commands":{"allow":["get_settings"],"deny":[]}},"allow-grpc-events":{"identifier":"allow-grpc-events","description":"Enables the grpc_events command without any pre-configured scope.","commands":{"allow":["grpc_events"],"deny":[]}},"allow-upsert":{"identifier":"allow-upsert","description":"Enables the upsert command without any pre-configured scope.","commands":{"allow":["upsert"],"deny":[]}},"allow-websocket-events":{"identifier":"allow-websocket-events","description":"Enables the websocket_events command without any pre-configured scope.","commands":{"allow":["websocket_events"],"deny":[]}},"allow-workspace-models":{"identifier":"allow-workspace-models","description":"Enables the workspace_models command without any pre-configured scope.","commands":{"allow":["workspace_models"],"deny":[]}},"deny-delete":{"identifier":"deny-delete","description":"Denies the delete command without any pre-configured scope.","commands":{"allow":[],"deny":["delete"]}},"deny-duplicate":{"identifier":"deny-duplicate","description":"Denies the duplicate command without any pre-configured scope.","commands":{"allow":[],"deny":["duplicate"]}},"deny-get-settings":{"identifier":"deny-get-settings","description":"Denies the get_settings command without any pre-configured scope.","commands":{"allow":[],"deny":["get_settings"]}},"deny-grpc-events":{"identifier":"deny-grpc-events","description":"Denies the grpc_events command without any pre-configured scope.","commands":{"allow":[],"deny":["grpc_events"]}},"deny-upsert":{"identifier":"deny-upsert","description":"Denies the upsert command without any pre-configured scope.","commands":{"allow":[],"deny":["upsert"]}},"deny-websocket-events":{"identifier":"deny-websocket-events","description":"Denies the websocket_events command without any pre-configured scope.","commands":{"allow":[],"deny":["websocket_events"]}},"deny-workspace-models":{"identifier":"deny-workspace-models","description":"Denies the workspace_models command without any pre-configured scope.","commands":{"allow":[],"deny":["workspace_models"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-sync":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-calculate","allow-calculate-fs","allow-apply","allow-watch"]},"permissions":{"allow-apply":{"identifier":"allow-apply","description":"Enables the apply command without any pre-configured scope.","commands":{"allow":["apply"],"deny":[]}},"allow-calculate":{"identifier":"allow-calculate","description":"Enables the calculate command without any pre-configured scope.","commands":{"allow":["calculate"],"deny":[]}},"allow-calculate-fs":{"identifier":"allow-calculate-fs","description":"Enables the calculate_fs command without any pre-configured scope.","commands":{"allow":["calculate_fs"],"deny":[]}},"allow-watch":{"identifier":"allow-watch","description":"Enables the watch command without any pre-configured scope.","commands":{"allow":["watch"],"deny":[]}},"deny-apply":{"identifier":"deny-apply","description":"Denies the apply command without any pre-configured scope.","commands":{"allow":[],"deny":["apply"]}},"deny-calculate":{"identifier":"deny-calculate","description":"Denies the calculate command without any pre-configured scope.","commands":{"allow":[],"deny":["calculate"]}},"deny-calculate-fs":{"identifier":"deny-calculate-fs","description":"Denies the calculate_fs command without any pre-configured scope.","commands":{"allow":[],"deny":["calculate_fs"]}},"deny-watch":{"identifier":"deny-watch","description":"Denies the watch command without any pre-configured scope.","commands":{"allow":[],"deny":["watch"]}}},"permission_sets":{},"global_scope_schema":null},"yaak-ws":{"default_permission":{"identifier":"default","description":"Default permissions for the plugin","permissions":["allow-close","allow-connect","allow-delete-connection","allow-delete-connections","allow-delete-request","allow-duplicate-request","allow-list-connections","allow-list-events","allow-list-requests","allow-send","allow-upsert-request"]},"permissions":{"allow-cancel":{"identifier":"allow-cancel","description":"Enables the cancel command without any pre-configured scope.","commands":{"allow":["cancel"],"deny":[]}},"allow-close":{"identifier":"allow-close","description":"Enables the close command without any pre-configured scope.","commands":{"allow":["close"],"deny":[]}},"allow-connect":{"identifier":"allow-connect","description":"Enables the connect command without any pre-configured scope.","commands":{"allow":["connect"],"deny":[]}},"allow-delete-connection":{"identifier":"allow-delete-connection","description":"Enables the delete_connection command without any pre-configured scope.","commands":{"allow":["delete_connection"],"deny":[]}},"allow-delete-connections":{"identifier":"allow-delete-connections","description":"Enables the delete_connections command without any pre-configured scope.","commands":{"allow":["delete_connections"],"deny":[]}},"allow-delete-request":{"identifier":"allow-delete-request","description":"Enables the delete_request command without any pre-configured scope.","commands":{"allow":["delete_request"],"deny":[]}},"allow-duplicate-request":{"identifier":"allow-duplicate-request","description":"Enables the duplicate_request command without any pre-configured scope.","commands":{"allow":["duplicate_request"],"deny":[]}},"allow-list-connections":{"identifier":"allow-list-connections","description":"Enables the list_connections command without any pre-configured scope.","commands":{"allow":["list_connections"],"deny":[]}},"allow-list-events":{"identifier":"allow-list-events","description":"Enables the list_events command without any pre-configured scope.","commands":{"allow":["list_events"],"deny":[]}},"allow-list-requests":{"identifier":"allow-list-requests","description":"Enables the list_requests command without any pre-configured scope.","commands":{"allow":["list_requests"],"deny":[]}},"allow-list-websocket-connections":{"identifier":"allow-list-websocket-connections","description":"Enables the list_websocket_connections command without any pre-configured scope.","commands":{"allow":["list_websocket_connections"],"deny":[]}},"allow-list-websocket-requests":{"identifier":"allow-list-websocket-requests","description":"Enables the list_websocket_requests command without any pre-configured scope.","commands":{"allow":["list_websocket_requests"],"deny":[]}},"allow-send":{"identifier":"allow-send","description":"Enables the send command without any pre-configured scope.","commands":{"allow":["send"],"deny":[]}},"allow-upsert-request":{"identifier":"allow-upsert-request","description":"Enables the upsert_request command without any pre-configured scope.","commands":{"allow":["upsert_request"],"deny":[]}},"allow-upsert-websocket-request":{"identifier":"allow-upsert-websocket-request","description":"Enables the upsert_websocket_request command without any pre-configured scope.","commands":{"allow":["upsert_websocket_request"],"deny":[]}},"deny-cancel":{"identifier":"deny-cancel","description":"Denies the cancel command without any pre-configured scope.","commands":{"allow":[],"deny":["cancel"]}},"deny-close":{"identifier":"deny-close","description":"Denies the close command without any pre-configured scope.","commands":{"allow":[],"deny":["close"]}},"deny-connect":{"identifier":"deny-connect","description":"Denies the connect command without any pre-configured scope.","commands":{"allow":[],"deny":["connect"]}},"deny-delete-connection":{"identifier":"deny-delete-connection","description":"Denies the delete_connection command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_connection"]}},"deny-delete-connections":{"identifier":"deny-delete-connections","description":"Denies the delete_connections command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_connections"]}},"deny-delete-request":{"identifier":"deny-delete-request","description":"Denies the delete_request command without any pre-configured scope.","commands":{"allow":[],"deny":["delete_request"]}},"deny-duplicate-request":{"identifier":"deny-duplicate-request","description":"Denies the duplicate_request command without any pre-configured scope.","commands":{"allow":[],"deny":["duplicate_request"]}},"deny-list-connections":{"identifier":"deny-list-connections","description":"Denies the list_connections command without any pre-configured scope.","commands":{"allow":[],"deny":["list_connections"]}},"deny-list-events":{"identifier":"deny-list-events","description":"Denies the list_events command without any pre-configured scope.","commands":{"allow":[],"deny":["list_events"]}},"deny-list-requests":{"identifier":"deny-list-requests","description":"Denies the list_requests command without any pre-configured scope.","commands":{"allow":[],"deny":["list_requests"]}},"deny-list-websocket-connections":{"identifier":"deny-list-websocket-connections","description":"Denies the list_websocket_connections command without any pre-configured scope.","commands":{"allow":[],"deny":["list_websocket_connections"]}},"deny-list-websocket-requests":{"identifier":"deny-list-websocket-requests","description":"Denies the list_websocket_requests command without any pre-configured scope.","commands":{"allow":[],"deny":["list_websocket_requests"]}},"deny-send":{"identifier":"deny-send","description":"Denies the send command without any pre-configured scope.","commands":{"allow":[],"deny":["send"]}},"deny-upsert-request":{"identifier":"deny-upsert-request","description":"Denies the upsert_request command without any pre-configured scope.","commands":{"allow":[],"deny":["upsert_request"]}},"deny-upsert-websocket-request":{"identifier":"deny-upsert-websocket-request","description":"Denies the upsert_websocket_request command without any pre-configured scope.","commands":{"allow":[],"deny":["upsert_websocket_request"]}}},"permission_sets":{},"global_scope_schema":null}} \ No newline at end of file diff --git a/src-tauri/gen/schemas/desktop-schema.json b/src-tauri/gen/schemas/desktop-schema.json index bf32452a..81ba3fe4 100644 --- a/src-tauri/gen/schemas/desktop-schema.json +++ b/src-tauri/gen/schemas/desktop-schema.json @@ -5642,21 +5642,71 @@ "type": "string", "const": "yaak-models:allow-delete" }, + { + "description": "Enables the duplicate command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:allow-duplicate" + }, + { + "description": "Enables the get_settings command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:allow-get-settings" + }, + { + "description": "Enables the grpc_events command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:allow-grpc-events" + }, { "description": "Enables the upsert command without any pre-configured scope.", "type": "string", "const": "yaak-models:allow-upsert" }, + { + "description": "Enables the websocket_events command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:allow-websocket-events" + }, + { + "description": "Enables the workspace_models command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:allow-workspace-models" + }, { "description": "Denies the delete command without any pre-configured scope.", "type": "string", "const": "yaak-models:deny-delete" }, + { + "description": "Denies the duplicate command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:deny-duplicate" + }, + { + "description": "Denies the get_settings command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:deny-get-settings" + }, + { + "description": "Denies the grpc_events command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:deny-grpc-events" + }, { "description": "Denies the upsert command without any pre-configured scope.", "type": "string", "const": "yaak-models:deny-upsert" }, + { + "description": "Denies the websocket_events command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:deny-websocket-events" + }, + { + "description": "Denies the workspace_models command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:deny-workspace-models" + }, { "description": "Default permissions for the plugin", "type": "string", diff --git a/src-tauri/gen/schemas/macOS-schema.json b/src-tauri/gen/schemas/macOS-schema.json index bf32452a..81ba3fe4 100644 --- a/src-tauri/gen/schemas/macOS-schema.json +++ b/src-tauri/gen/schemas/macOS-schema.json @@ -5642,21 +5642,71 @@ "type": "string", "const": "yaak-models:allow-delete" }, + { + "description": "Enables the duplicate command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:allow-duplicate" + }, + { + "description": "Enables the get_settings command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:allow-get-settings" + }, + { + "description": "Enables the grpc_events command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:allow-grpc-events" + }, { "description": "Enables the upsert command without any pre-configured scope.", "type": "string", "const": "yaak-models:allow-upsert" }, + { + "description": "Enables the websocket_events command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:allow-websocket-events" + }, + { + "description": "Enables the workspace_models command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:allow-workspace-models" + }, { "description": "Denies the delete command without any pre-configured scope.", "type": "string", "const": "yaak-models:deny-delete" }, + { + "description": "Denies the duplicate command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:deny-duplicate" + }, + { + "description": "Denies the get_settings command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:deny-get-settings" + }, + { + "description": "Denies the grpc_events command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:deny-grpc-events" + }, { "description": "Denies the upsert command without any pre-configured scope.", "type": "string", "const": "yaak-models:deny-upsert" }, + { + "description": "Denies the websocket_events command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:deny-websocket-events" + }, + { + "description": "Denies the workspace_models command without any pre-configured scope.", + "type": "string", + "const": "yaak-models:deny-workspace-models" + }, { "description": "Default permissions for the plugin", "type": "string", diff --git a/src-tauri/migrations/20250326193143_key-value-id.sql b/src-tauri/migrations/20250326193143_key-value-id.sql new file mode 100644 index 00000000..a045c052 --- /dev/null +++ b/src-tauri/migrations/20250326193143_key-value-id.sql @@ -0,0 +1,43 @@ +-- 1. Create the new table with `id` as the primary key +CREATE TABLE key_values_new +( + id TEXT PRIMARY KEY, + model TEXT DEFAULT 'key_value' NOT NULL, + created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + updated_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL, + deleted_at DATETIME, + namespace TEXT NOT NULL, + key TEXT NOT NULL, + value TEXT NOT NULL +); + +-- 2. Copy data from the old table +INSERT INTO key_values_new (id, model, created_at, updated_at, deleted_at, namespace, key, value) +SELECT ( + -- This is the best way to generate a random string in SQLite, apparently + 'kv_' || SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) || + SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) || + SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) || + SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) || + SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) || + SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) || + SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) || + SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) || + SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) || + SUBSTR('abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23457789', (ABS(RANDOM()) % 57) + 1, 1) + ) AS id, + model, + created_at, + updated_at, + deleted_at, + namespace, + key, + value +FROM key_values; + +-- 3. Drop the old table +DROP TABLE key_values; + +-- 4. Rename the new table +ALTER TABLE key_values_new + RENAME TO key_values; diff --git a/src-tauri/src/http_request.rs b/src-tauri/src/http_request.rs index 03bf08ca..e9f2fa73 100644 --- a/src-tauri/src/http_request.rs +++ b/src-tauri/src/http_request.rs @@ -24,11 +24,11 @@ use tokio::fs::{create_dir_all, File}; use tokio::io::AsyncWriteExt; use tokio::sync::watch::Receiver; use tokio::sync::{oneshot, Mutex}; -use yaak_models::query_manager::QueryManagerExt; use yaak_models::models::{ Cookie, CookieJar, Environment, HttpRequest, HttpResponse, HttpResponseHeader, HttpResponseState, ProxySetting, ProxySettingAuth, }; +use yaak_models::query_manager::QueryManagerExt; use yaak_models::util::UpdateSource; use yaak_plugins::events::{ CallHttpAuthenticationRequest, HttpHeader, RenderPurpose, WindowContext, @@ -46,10 +46,9 @@ pub async fn send_http_request( ) -> Result { let app_handle = window.app_handle().clone(); let plugin_manager = app_handle.state::(); - let update_source = &UpdateSource::from_window(&window); let (settings, workspace) = { let db = window.db(); - let settings = db.get_or_create_settings(update_source); + let settings = db.get_settings(); let workspace = db.get_workspace(&unrendered_request.workspace_id)?; (settings, workspace) }; diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 30fc91fd..70a25e79 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -13,12 +13,12 @@ use error::Result as YaakResult; use eventsource_client::{EventParser, SSE}; use log::{debug, error, warn}; use std::collections::{BTreeMap, HashMap}; -use std::fs::{create_dir_all, File}; +use std::fs::{File, create_dir_all}; use std::path::PathBuf; use std::str::FromStr; use std::time::Duration; use std::{fs, panic}; -use tauri::{is_dev, AppHandle, Emitter, RunEvent, State, WebviewWindow}; +use tauri::{AppHandle, Emitter, RunEvent, State, WebviewWindow, is_dev}; use tauri::{Listener, Runtime}; use tauri::{Manager, WindowEvent}; use tauri_plugin_log::fern::colors::ColoredLevelConfig; @@ -29,15 +29,15 @@ use tokio::sync::Mutex; use tokio::task::block_in_place; use yaak_common::window::WorkspaceWindowTrait; use yaak_grpc::manager::{DynamicMessage, GrpcHandle}; -use yaak_grpc::{deserialize_message, serialize_message, Code, ServiceDefinition}; +use yaak_grpc::{Code, ServiceDefinition, deserialize_message, serialize_message}; use yaak_models::models::{ - CookieJar, Environment, EnvironmentVariable, Folder, GrpcConnection, GrpcConnectionState, - GrpcEvent, GrpcEventType, GrpcRequest, HttpRequest, HttpResponse, HttpResponseState, KeyValue, - Plugin, Settings, WebsocketRequest, Workspace, WorkspaceMeta, + CookieJar, Environment, Folder, GrpcConnection, GrpcConnectionState, GrpcEvent, GrpcEventType, + GrpcRequest, HttpRequest, HttpResponse, HttpResponseState, Plugin, WebsocketRequest, Workspace, + WorkspaceMeta, }; use yaak_models::query_manager::QueryManagerExt; use yaak_models::util::{ - get_workspace_export_resources, maybe_gen_id, maybe_gen_id_opt, BatchUpsertResult, UpdateSource, + BatchUpsertResult, UpdateSource, get_workspace_export_resources, maybe_gen_id, maybe_gen_id_opt, }; use yaak_plugins::events::{ BootResponse, CallHttpAuthenticationRequest, CallHttpRequestActionRequest, FilterResponse, @@ -1064,47 +1064,6 @@ fn response_err( response } -#[tauri::command] -async fn cmd_set_update_mode( - update_mode: &str, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult { - let (key_value, _created) = app_handle.db().set_key_value_raw( - "app", - "update_mode", - update_mode, - &UpdateSource::from_window(&window), - ); - Ok(key_value) -} - -#[tauri::command] -async fn cmd_get_key_value( - namespace: &str, - key: &str, - app_handle: AppHandle, -) -> YaakResult> { - Ok(app_handle.db().get_key_value_raw(namespace, key)) -} - -#[tauri::command] -async fn cmd_set_key_value( - app_handle: AppHandle, - window: WebviewWindow, - namespace: &str, - key: &str, - value: &str, -) -> YaakResult { - let (key_value, _created) = app_handle.db().set_key_value_raw( - namespace, - key, - value, - &UpdateSource::from_window(&window), - ); - Ok(key_value) -} - #[tauri::command] async fn cmd_install_plugin( directory: &str, @@ -1144,64 +1103,6 @@ async fn cmd_uninstall_plugin( Ok(plugin) } -#[tauri::command] -async fn cmd_update_cookie_jar( - cookie_jar: CookieJar, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult { - Ok(app_handle.db().upsert_cookie_jar(&cookie_jar, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_delete_cookie_jar( - app_handle: AppHandle, - window: WebviewWindow, - cookie_jar_id: &str, -) -> YaakResult { - Ok(app_handle - .db() - .delete_cookie_jar_by_id(cookie_jar_id, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_create_cookie_jar( - workspace_id: &str, - name: &str, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult { - Ok(app_handle.db().upsert_cookie_jar( - &CookieJar { - name: name.to_string(), - workspace_id: workspace_id.to_string(), - ..Default::default() - }, - &UpdateSource::from_window(&window), - )?) -} - -#[tauri::command] -async fn cmd_create_environment( - workspace_id: &str, - environment_id: Option<&str>, - name: &str, - variables: Vec, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult { - Ok(app_handle.db().upsert_environment( - &Environment { - workspace_id: workspace_id.to_string(), - environment_id: environment_id.map(|s| s.to_string()), - name: name.to_string(), - variables, - ..Default::default() - }, - &UpdateSource::from_window(&window), - )?) -} - #[tauri::command] async fn cmd_create_grpc_request( workspace_id: &str, @@ -1223,193 +1124,6 @@ async fn cmd_create_grpc_request( )?) } -#[tauri::command] -async fn cmd_duplicate_grpc_request( - id: &str, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult { - let db = app_handle.db(); - let request = db.get_grpc_request(id)?; - Ok(db.duplicate_grpc_request(&request, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_duplicate_folder( - app_handle: AppHandle, - window: WebviewWindow, - id: &str, -) -> YaakResult { - let db = app_handle.db(); - let folder = db.get_folder(id)?; - Ok(db.duplicate_folder(&folder, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_duplicate_http_request( - id: &str, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult { - let db = app_handle.db(); - let request = db.get_http_request(id)?; - Ok(db.duplicate_http_request(&request, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_update_workspace( - workspace: Workspace, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult { - Ok(app_handle.db().upsert_workspace(&workspace, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_update_workspace_meta( - workspace_meta: WorkspaceMeta, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult { - Ok(app_handle - .db() - .upsert_workspace_meta(&workspace_meta, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_update_environment( - environment: Environment, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult { - Ok(app_handle.db().upsert_environment(&environment, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_update_grpc_request( - request: GrpcRequest, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult { - Ok(app_handle.db().upsert_grpc_request(&request, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_upsert_http_request( - request: HttpRequest, - window: WebviewWindow, - app_handle: AppHandle, -) -> YaakResult { - Ok(app_handle.db().upsert(&request, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_delete_grpc_request( - app_handle: AppHandle, - request_id: &str, - window: WebviewWindow, -) -> YaakResult { - Ok(app_handle - .db() - .delete_grpc_request_by_id(request_id, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_delete_http_request( - app_handle: AppHandle, - request_id: &str, - window: WebviewWindow, -) -> YaakResult { - Ok(app_handle - .db() - .delete_http_request_by_id(request_id, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_list_folders( - workspace_id: &str, - app_handle: AppHandle, -) -> YaakResult> { - Ok(app_handle.db().list_folders(workspace_id)?) -} - -#[tauri::command] -async fn cmd_update_folder( - folder: Folder, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult { - Ok(app_handle.db().upsert_folder(&folder, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_delete_folder( - app_handle: AppHandle, - window: WebviewWindow, - folder_id: &str, -) -> YaakResult { - Ok(app_handle.db().delete_folder_by_id(folder_id, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_delete_environment( - app_handle: AppHandle, - window: WebviewWindow, - environment_id: &str, -) -> YaakResult { - Ok(app_handle - .db() - .delete_environment_by_id(environment_id, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_list_grpc_connections( - workspace_id: &str, - app_handle: AppHandle, -) -> YaakResult> { - Ok(app_handle.db().list_grpc_connections_for_workspace(workspace_id, None)?) -} - -#[tauri::command] -async fn cmd_list_grpc_events( - connection_id: &str, - app_handle: AppHandle, -) -> YaakResult> { - Ok(app_handle.db().list_grpc_events(connection_id)?) -} - -#[tauri::command] -async fn cmd_list_grpc_requests( - workspace_id: &str, - app_handle: AppHandle, -) -> YaakResult> { - Ok(app_handle.db().list_grpc_requests(workspace_id)?) -} - -#[tauri::command] -async fn cmd_list_http_requests( - workspace_id: &str, - app_handle: AppHandle, -) -> YaakResult> { - Ok(app_handle.db().list_http_requests(workspace_id)?) -} - -#[tauri::command] -async fn cmd_list_environments( - workspace_id: &str, - app_handle: AppHandle, -) -> YaakResult> { - // Not sure of a better place to put this... - let db = app_handle.db(); - db.ensure_base_environment(workspace_id)?; - Ok(db.list_environments(workspace_id)?) -} - -#[tauri::command] -async fn cmd_list_plugins(app_handle: AppHandle) -> YaakResult> { - Ok(app_handle.db().list_plugins()?) -} - #[tauri::command] async fn cmd_reload_plugins( app_handle: AppHandle, @@ -1438,99 +1152,6 @@ async fn cmd_plugin_info( .await) } -#[tauri::command] -async fn cmd_get_settings(window: WebviewWindow) -> YaakResult { - Ok(window.db().get_or_create_settings(&UpdateSource::from_window(&window))) -} - -#[tauri::command] -async fn cmd_update_settings( - settings: Settings, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult { - Ok(app_handle.db().upsert_settings(&settings, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_get_folder(id: &str, app_handle: AppHandle) -> YaakResult { - Ok(app_handle.db().get_folder(id)?) -} - -#[tauri::command] -async fn cmd_list_cookie_jars( - workspace_id: &str, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult> { - let db = app_handle.db(); - let cookie_jars = db.list_cookie_jars(workspace_id)?; - - if cookie_jars.is_empty() { - let cookie_jar = db.upsert_cookie_jar( - &CookieJar { - name: "Default".to_string(), - workspace_id: workspace_id.to_string(), - ..Default::default() - }, - &UpdateSource::from_window(&window), - )?; - Ok(vec![cookie_jar]) - } else { - Ok(cookie_jars) - } -} - -#[tauri::command] -async fn cmd_list_key_values(app_handle: AppHandle) -> YaakResult> { - Ok(app_handle.db().list_key_values_raw()?) -} - -#[tauri::command] -async fn cmd_get_environment( - id: &str, - app_handle: AppHandle, -) -> YaakResult { - Ok(app_handle.db().get_environment(id)?) -} - -#[tauri::command] -async fn cmd_get_workspace( - id: &str, - app_handle: AppHandle, -) -> YaakResult { - Ok(app_handle.db().get_workspace(id)?) -} - -#[tauri::command] -async fn cmd_list_http_responses( - workspace_id: &str, - limit: Option, - app_handle: AppHandle, -) -> YaakResult> { - Ok(app_handle.db().list_http_responses_for_workspace(workspace_id, limit.map(|l| l as u64))?) -} - -#[tauri::command] -async fn cmd_delete_http_response( - id: &str, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult { - let db = app_handle.db(); - let http_response = db.get_http_response(id)?; - Ok(db.delete_http_response(&http_response, &UpdateSource::from_window(&window))?) -} - -#[tauri::command] -async fn cmd_delete_grpc_connection( - id: &str, - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult { - Ok(app_handle.db().delete_grpc_connection_by_id(id, &UpdateSource::from_window(&window))?) -} - #[tauri::command] async fn cmd_delete_all_grpc_connections( request_id: &str, @@ -1568,29 +1189,6 @@ async fn cmd_delete_all_http_responses( .delete_all_http_responses_for_request(request_id, &UpdateSource::from_window(&window))?) } -#[tauri::command] -async fn cmd_list_workspaces( - app_handle: AppHandle, - window: WebviewWindow, -) -> YaakResult> { - let db = app_handle.db(); - let mut workspaces = db.find_all::()?; - - if workspaces.is_empty() { - workspaces.push(db.upsert_workspace( - &Workspace { - name: "Yaak".to_string(), - setting_follow_redirects: true, - setting_validate_certificates: true, - ..Default::default() - }, - &UpdateSource::from_window(&window), - )?); - } - - Ok(workspaces) -} - #[tauri::command] async fn cmd_get_workspace_meta( app_handle: AppHandle, @@ -1599,7 +1197,7 @@ async fn cmd_get_workspace_meta( ) -> YaakResult { let db = app_handle.db(); let workspace = db.get_workspace(workspace_id)?; - Ok(db.get_or_create_workspace_meta(&workspace, &UpdateSource::from_window(&window))?) + Ok(db.get_or_create_workspace_meta(&workspace.id, &UpdateSource::from_window(&window))?) } #[tauri::command] @@ -1620,15 +1218,6 @@ async fn cmd_new_main_window(app_handle: AppHandle, url: &str) -> Result<(), Str Ok(()) } -#[tauri::command] -async fn cmd_delete_workspace( - app_handle: AppHandle, - window: WebviewWindow, - workspace_id: &str, -) -> YaakResult { - Ok(app_handle.db().delete_workspace_by_id(workspace_id, &UpdateSource::from_window(&window))?) -} - #[tauri::command] async fn cmd_check_for_updates( window: WebviewWindow, @@ -1722,53 +1311,24 @@ pub fn run() { cmd_call_http_authentication_action, cmd_call_http_request_action, cmd_check_for_updates, - cmd_create_cookie_jar, - cmd_create_environment, cmd_create_grpc_request, cmd_curl_to_request, cmd_delete_all_grpc_connections, cmd_delete_all_http_responses, - cmd_delete_cookie_jar, - cmd_delete_environment, - cmd_delete_folder, - cmd_delete_grpc_connection, - cmd_delete_grpc_request, - cmd_delete_http_request, - cmd_delete_http_response, cmd_delete_send_history, - cmd_delete_workspace, cmd_dismiss_notification, - cmd_duplicate_folder, - cmd_duplicate_grpc_request, - cmd_duplicate_http_request, cmd_export_data, cmd_filter_response, cmd_format_json, - cmd_get_environment, - cmd_get_folder, cmd_get_http_authentication_summaries, cmd_get_http_authentication_config, - cmd_get_key_value, - cmd_get_settings, cmd_get_sse_events, - cmd_get_workspace, cmd_get_workspace_meta, cmd_grpc_go, cmd_grpc_reflect, cmd_http_request_actions, cmd_import_data, cmd_install_plugin, - cmd_list_cookie_jars, - cmd_list_environments, - cmd_list_folders, - cmd_list_grpc_connections, - cmd_list_grpc_events, - cmd_list_grpc_requests, - cmd_list_key_values, - cmd_list_http_requests, - cmd_list_http_responses, - cmd_list_plugins, - cmd_list_workspaces, cmd_metadata, cmd_new_child_window, cmd_new_main_window, @@ -1779,19 +1339,9 @@ pub fn run() { cmd_save_response, cmd_send_ephemeral_request, cmd_send_http_request, - cmd_set_key_value, - cmd_set_update_mode, cmd_template_functions, cmd_template_tokens_to_string, cmd_uninstall_plugin, - cmd_update_cookie_jar, - cmd_update_environment, - cmd_update_folder, - cmd_update_grpc_request, - cmd_upsert_http_request, - cmd_update_settings, - cmd_update_workspace, - cmd_update_workspace_meta, ]) .register_uri_scheme_protocol("yaak", handle_uri_scheme) .build(tauri::generate_context!()) @@ -1859,7 +1409,7 @@ pub fn run() { } async fn get_update_mode(window: &WebviewWindow) -> YaakResult { - let settings = window.db().get_or_create_settings(&UpdateSource::from_window(window)); + let settings = window.db().get_settings(); Ok(UpdateMode::new(settings.update_channel.as_str())) } @@ -1934,13 +1484,10 @@ fn get_window_from_window_context( } }; - let window = app_handle.webview_windows().iter().find_map(|(_, w)| { - if w.label() == label { - Some(w.to_owned()) - } else { - None - } - }); + let window = app_handle + .webview_windows() + .iter() + .find_map(|(_, w)| if w.label() == label { Some(w.to_owned()) } else { None }); if window.is_none() { error!("Failed to find window by {window_context:?}"); diff --git a/src-tauri/src/updates.rs b/src-tauri/src/updates.rs index 0e7ac844..dcbeb66d 100644 --- a/src-tauri/src/updates.rs +++ b/src-tauri/src/updates.rs @@ -8,7 +8,6 @@ use tauri_plugin_dialog::{DialogExt, MessageDialogButtons}; use tauri_plugin_updater::UpdaterExt; use tokio::task::block_in_place; use yaak_models::query_manager::QueryManagerExt; -use yaak_models::util::UpdateSource; use yaak_plugins::manager::PluginManager; use crate::is_dev; @@ -67,7 +66,7 @@ impl YaakUpdater { mode: UpdateMode, update_trigger: UpdateTrigger, ) -> Result { - let settings = window.db().get_or_create_settings(&UpdateSource::from_window(window)); + let settings = window.db().get_settings(); let update_key = format!("{:x}", md5::compute(settings.id)); self.last_update_check = SystemTime::now(); diff --git a/src-tauri/yaak-license/src/license.rs b/src-tauri/yaak-license/src/license.rs index 58323772..e36caa07 100644 --- a/src-tauri/yaak-license/src/license.rs +++ b/src-tauri/yaak-license/src/license.rs @@ -146,7 +146,7 @@ pub async fn check_license( payload: CheckActivationRequestPayload, ) -> Result { let activation_id = get_activation_id(window.app_handle()).await; - let settings = window.db().get_or_create_settings(&UpdateSource::from_window(window)); + let settings = window.db().get_settings(); let trial_end = settings.created_at.add(Duration::from_secs(TRIAL_SECONDS)); debug!("Trial ending at {trial_end:?}"); diff --git a/src-tauri/yaak-models/bindings/gen_models.ts b/src-tauri/yaak-models/bindings/gen_models.ts index 6cb2a62a..d154e7af 100644 --- a/src-tauri/yaak-models/bindings/gen_models.ts +++ b/src-tauri/yaak-models/bindings/gen_models.ts @@ -42,7 +42,7 @@ export type HttpResponseState = "initialized" | "connected" | "closed"; export type HttpUrlParameter = { enabled?: boolean, name: string, value: string, id?: string, }; -export type KeyValue = { model: "key_value", createdAt: string, updatedAt: string, key: string, namespace: string, value: string, }; +export type KeyValue = { model: "key_value", id: string, createdAt: string, updatedAt: string, key: string, namespace: string, value: string, }; export type ModelChangeEvent = { "type": "upsert" } | { "type": "delete" }; diff --git a/src-tauri/yaak-models/build.rs b/src-tauri/yaak-models/build.rs index 12b6b524..ca467281 100644 --- a/src-tauri/yaak-models/build.rs +++ b/src-tauri/yaak-models/build.rs @@ -1,4 +1,12 @@ -const COMMANDS: &[&str] = &["upsert", "delete"]; +const COMMANDS: &[&str] = &[ + "delete", + "duplicate", + "get_settings", + "grpc_events", + "upsert", + "websocket_events", + "workspace_models", +]; fn main() { tauri_plugin::Builder::new(COMMANDS).build(); diff --git a/src-tauri/yaak-models/guest-js/atoms.ts b/src-tauri/yaak-models/guest-js/atoms.ts new file mode 100644 index 00000000..eed36111 --- /dev/null +++ b/src-tauri/yaak-models/guest-js/atoms.ts @@ -0,0 +1,80 @@ +import { atom } from 'jotai'; + +import { selectAtom } from 'jotai/utils'; +import type { AnyModel } from '../bindings/gen_models'; +import { ExtractModel } from './types'; +import { newStoreData } from './util'; + +export const modelStoreDataAtom = atom(newStoreData()); + +export const cookieJarsAtom = createOrderedModelAtom('cookie_jar', 'name', 'asc'); +export const environmentsAtom = createOrderedModelAtom('environment', 'name', 'asc'); +export const foldersAtom = createModelAtom('folder'); +export const grpcConnectionsAtom = createOrderedModelAtom('grpc_connection', 'createdAt', 'desc'); +export const grpcEventsAtom = createOrderedModelAtom('grpc_event', 'createdAt', 'asc'); +export const grpcRequestsAtom = createModelAtom('grpc_request'); +export const httpRequestsAtom = createModelAtom('http_request'); +export const httpResponsesAtom = createOrderedModelAtom('http_response', 'createdAt', 'desc'); +export const keyValuesAtom = createModelAtom('key_value'); +export const pluginsAtom = createModelAtom('plugin'); +export const settingsAtom = createSingularModelAtom('settings'); +export const websocketRequestsAtom = createModelAtom('websocket_request'); +export const websocketEventsAtom = createOrderedModelAtom('websocket_event', 'createdAt', 'asc'); +export const websocketConnectionsAtom = createOrderedModelAtom( + 'websocket_connection', + 'createdAt', + 'desc', +); +export const workspaceMetasAtom = createModelAtom('workspace_meta'); +export const workspacesAtom = createOrderedModelAtom('workspace', 'name', 'asc'); + +export function createModelAtom(modelType: M) { + return selectAtom( + modelStoreDataAtom, + (data) => Object.values(data[modelType] ?? {}), + shallowEqual, + ); +} + +export function createSingularModelAtom(modelType: M) { + return selectAtom(modelStoreDataAtom, (data) => { + const modelData = Object.values(data[modelType] ?? {}); + const item = modelData[0]; + if (item == null) throw new Error('Failed creating singular model with no data: ' + modelType); + return item; + }); +} + +export function createOrderedModelAtom( + modelType: M, + field: keyof ExtractModel, + order: 'asc' | 'desc', +) { + return selectAtom( + modelStoreDataAtom, + (data) => { + const modelData = data[modelType] ?? {}; + return Object.values(modelData).sort( + (a: ExtractModel, b: ExtractModel) => { + const n = a[field] > b[field] ? 1 : -1; + return order === 'desc' ? n * -1 : n; + }, + ); + }, + shallowEqual, + ); +} + +function shallowEqual(a: T[], b: T[]): boolean { + if (a.length !== b.length) { + return false; + } + + for (let i = 0; i < a.length; i++) { + if (a[i] !== b[i]) { + return false; + } + } + + return true; +} diff --git a/src-tauri/yaak-models/guest-js/index.ts b/src-tauri/yaak-models/guest-js/index.ts new file mode 100644 index 00000000..7cc74aec --- /dev/null +++ b/src-tauri/yaak-models/guest-js/index.ts @@ -0,0 +1,10 @@ +import { AnyModel } from '../bindings/gen_models'; + +export * from '../bindings/gen_models'; +export * from './store'; +export * from './atoms'; + +export function modelTypeLabel(m: AnyModel): string { + const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1); + return m.model.split('_').map(capitalize).join(' '); +} diff --git a/src-tauri/yaak-models/guest-js/store.ts b/src-tauri/yaak-models/guest-js/store.ts new file mode 100644 index 00000000..572c1f74 --- /dev/null +++ b/src-tauri/yaak-models/guest-js/store.ts @@ -0,0 +1,199 @@ +import { invoke } from '@tauri-apps/api/core'; +import { getCurrentWebviewWindow } from '@tauri-apps/api/webviewWindow'; +import { AnyModel, ModelPayload } from '../bindings/gen_models'; +import { modelStoreDataAtom } from './atoms'; +import { ExtractModel, JotaiStore, ModelStoreData } from './types'; +import { newStoreData } from './util'; + +let _store: JotaiStore | null = null; + +export function initModelStore(store: JotaiStore) { + _store = store; + + getCurrentWebviewWindow() + .listen('upserted_model', ({ payload }) => { + if (shouldIgnoreModel(payload)) return; + + mustStore().set(modelStoreDataAtom, (prev: ModelStoreData) => { + return { + ...prev, + [payload.model.model]: { + ...prev[payload.model.model], + [payload.model.id]: payload.model, + }, + }; + }); + }) + .catch(console.error); + + getCurrentWebviewWindow() + .listen('deleted_model', ({ payload }) => { + if (shouldIgnoreModel(payload)) return; + + console.log('Delete model', payload); + + mustStore().set(modelStoreDataAtom, (prev: ModelStoreData) => { + const modelData = { ...prev[payload.model.model] }; + delete modelData[payload.model.id]; + return { ...prev, [payload.model.model]: modelData }; + }); + }) + .catch(console.error); +} + +function mustStore(): JotaiStore { + if (_store == null) { + throw new Error('Model store was not initialized'); + } + + return _store; +} + +let _activeWorkspaceId: string | null = null; + +export async function changeModelStoreWorkspace(workspaceId: string | null) { + console.log('Syncing models with new workspace', workspaceId); + const workspaceModels = await invoke('plugin:yaak-models|workspace_models', { + workspaceId, // NOTE: if no workspace id provided, it will just fetch global models + }); + const data = newStoreData(); + for (const model of workspaceModels) { + data[model.model][model.id] = model; + } + + mustStore().set(modelStoreDataAtom, data); + + console.log('Synced model store with workspace', workspaceId, data); + + _activeWorkspaceId = workspaceId; +} + +export function getAnyModel(id: string): AnyModel | null { + let data = mustStore().get(modelStoreDataAtom); + for (const modelData of Object.values(data)) { + let model = modelData[id]; + if (model != null) { + return model; + } + } + return null; +} + +export function getModel>( + modelType: M | M[], + id: string, +): T | null { + let data = mustStore().get(modelStoreDataAtom); + for (const t of Array.isArray(modelType) ? modelType : [modelType]) { + let v = data[t][id]; + if (v?.model === t) return v as T; + } + return null; +} + +export function patchModelById>( + model: M, + id: string, + patch: Partial | ((prev: T) => T), +): Promise { + let prev = getModel(model, id); + if (prev == null) { + throw new Error(`Failed to get model to patch id=${id} model=${model}`); + } + + const newModel = typeof patch === 'function' ? patch(prev) : { ...prev, ...patch }; + return invoke('plugin:yaak-models|upsert', { model: newModel }); +} + +export async function patchModel>( + base: Pick, + patch: Partial, +): Promise { + return patchModelById(base.model, base.id, patch); +} + +export async function deleteModelById< + M extends AnyModel['model'], + T extends ExtractModel, +>(modelType: M | M[], id: string) { + let model = getModel(modelType, id); + await deleteModel(model); +} + +export async function deleteModel>( + model: T | null, +) { + if (model == null) { + throw new Error('Failed to delete null model'); + } + await invoke('plugin:yaak-models|delete', { model }); +} + +export function duplicateModelById< + M extends AnyModel['model'], + T extends ExtractModel, +>(modelType: M | M[], id: string) { + let model = getModel(modelType, id); + return duplicateModel(model); +} + +export function duplicateModel>( + model: T | null, +) { + if (model == null) { + throw new Error('Failed to delete null model'); + } + return invoke('plugin:yaak-models|duplicate', { model }); +} + +export async function createGlobalModel>( + patch: Partial & Pick, +): Promise { + return invoke('plugin:yaak-models|upsert', { model: patch }); +} + +export async function createWorkspaceModel>( + patch: Partial & Pick, +): Promise { + return invoke('plugin:yaak-models|upsert', { model: patch }); +} + +export function replaceModelsInStore< + M extends AnyModel['model'], + T extends Extract, +>(model: M, models: T[]) { + const newModels: Record = {}; + for (const model of models) { + newModels[model.id] = model; + } + + mustStore().set(modelStoreDataAtom, (prev: ModelStoreData) => { + return { + ...prev, + [model]: newModels, + }; + }); +} + +function shouldIgnoreModel({ model, updateSource }: ModelPayload) { + // Never ignore updates from non-user sources + if (updateSource.type !== 'window') { + return false; + } + + // Never ignore same-window updates + if (updateSource.label === getCurrentWebviewWindow().label) { + return false; + } + + // Only sync models that belong to this workspace, if a workspace ID is present + if ('workspaceId' in model && model.workspaceId !== _activeWorkspaceId) { + return true; + } + + if (model.model === 'key_value' && model.namespace === 'no_sync') { + return true; + } + + return false; +} diff --git a/src-tauri/yaak-models/guest-js/types.ts b/src-tauri/yaak-models/guest-js/types.ts new file mode 100644 index 00000000..0c1488bc --- /dev/null +++ b/src-tauri/yaak-models/guest-js/types.ts @@ -0,0 +1,8 @@ +import { createStore } from 'jotai/index'; +import { AnyModel } from '../bindings/gen_models'; + +export type ExtractModel = T extends { model: M } ? T : never; +export type ModelStoreData = { + [M in T['model']]: Record>; +}; +export type JotaiStore = ReturnType; diff --git a/src-tauri/yaak-models/guest-js/util.ts b/src-tauri/yaak-models/guest-js/util.ts new file mode 100644 index 00000000..b75efcff --- /dev/null +++ b/src-tauri/yaak-models/guest-js/util.ts @@ -0,0 +1,23 @@ +import { ModelStoreData } from './types'; + +export function newStoreData(): ModelStoreData { + return { + cookie_jar: {}, + environment: {}, + folder: {}, + grpc_connection: {}, + grpc_event: {}, + grpc_request: {}, + http_request: {}, + http_response: {}, + key_value: {}, + plugin: {}, + settings: {}, + sync_state: {}, + websocket_connection: {}, + websocket_event: {}, + websocket_request: {}, + workspace: {}, + workspace_meta: {}, + }; +} diff --git a/src-tauri/yaak-models/index.ts b/src-tauri/yaak-models/index.ts deleted file mode 100644 index e6157a26..00000000 --- a/src-tauri/yaak-models/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { invoke } from '@tauri-apps/api/core'; -import type { AnyModel } from './bindings/gen_models'; - -export * from './bindings/gen_models'; - -export async function upsertAnyModel(model: AnyModel): Promise { - return invoke('plugin:yaak-models|upsert', { model }); -} diff --git a/src-tauri/yaak-models/package.json b/src-tauri/yaak-models/package.json index 290cf741..c7258427 100644 --- a/src-tauri/yaak-models/package.json +++ b/src-tauri/yaak-models/package.json @@ -2,5 +2,5 @@ "name": "@yaakapp-internal/models", "private": true, "version": "1.0.0", - "main": "index.ts" + "main": "guest-js/index.ts" } diff --git a/src-tauri/yaak-models/permissions/autogenerated/commands/duplicate.toml b/src-tauri/yaak-models/permissions/autogenerated/commands/duplicate.toml new file mode 100644 index 00000000..35a8d663 --- /dev/null +++ b/src-tauri/yaak-models/permissions/autogenerated/commands/duplicate.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-duplicate" +description = "Enables the duplicate command without any pre-configured scope." +commands.allow = ["duplicate"] + +[[permission]] +identifier = "deny-duplicate" +description = "Denies the duplicate command without any pre-configured scope." +commands.deny = ["duplicate"] diff --git a/src-tauri/yaak-models/permissions/autogenerated/commands/get_settings.toml b/src-tauri/yaak-models/permissions/autogenerated/commands/get_settings.toml new file mode 100644 index 00000000..5f257956 --- /dev/null +++ b/src-tauri/yaak-models/permissions/autogenerated/commands/get_settings.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-get-settings" +description = "Enables the get_settings command without any pre-configured scope." +commands.allow = ["get_settings"] + +[[permission]] +identifier = "deny-get-settings" +description = "Denies the get_settings command without any pre-configured scope." +commands.deny = ["get_settings"] diff --git a/src-tauri/yaak-models/permissions/autogenerated/commands/grpc_events.toml b/src-tauri/yaak-models/permissions/autogenerated/commands/grpc_events.toml new file mode 100644 index 00000000..19e1628b --- /dev/null +++ b/src-tauri/yaak-models/permissions/autogenerated/commands/grpc_events.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-grpc-events" +description = "Enables the grpc_events command without any pre-configured scope." +commands.allow = ["grpc_events"] + +[[permission]] +identifier = "deny-grpc-events" +description = "Denies the grpc_events command without any pre-configured scope." +commands.deny = ["grpc_events"] diff --git a/src-tauri/yaak-models/permissions/autogenerated/commands/websocket_events.toml b/src-tauri/yaak-models/permissions/autogenerated/commands/websocket_events.toml new file mode 100644 index 00000000..598f4345 --- /dev/null +++ b/src-tauri/yaak-models/permissions/autogenerated/commands/websocket_events.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-websocket-events" +description = "Enables the websocket_events command without any pre-configured scope." +commands.allow = ["websocket_events"] + +[[permission]] +identifier = "deny-websocket-events" +description = "Denies the websocket_events command without any pre-configured scope." +commands.deny = ["websocket_events"] diff --git a/src-tauri/yaak-models/permissions/autogenerated/commands/workspace_models.toml b/src-tauri/yaak-models/permissions/autogenerated/commands/workspace_models.toml new file mode 100644 index 00000000..061efddd --- /dev/null +++ b/src-tauri/yaak-models/permissions/autogenerated/commands/workspace_models.toml @@ -0,0 +1,13 @@ +# Automatically generated - DO NOT EDIT! + +"$schema" = "../../schemas/schema.json" + +[[permission]] +identifier = "allow-workspace-models" +description = "Enables the workspace_models command without any pre-configured scope." +commands.allow = ["workspace_models"] + +[[permission]] +identifier = "deny-workspace-models" +description = "Denies the workspace_models command without any pre-configured scope." +commands.deny = ["workspace_models"] diff --git a/src-tauri/yaak-models/permissions/autogenerated/reference.md b/src-tauri/yaak-models/permissions/autogenerated/reference.md index 933b925a..01156bf8 100644 --- a/src-tauri/yaak-models/permissions/autogenerated/reference.md +++ b/src-tauri/yaak-models/permissions/autogenerated/reference.md @@ -2,8 +2,13 @@ Default permissions for the plugin -- `allow-upsert` - `allow-delete` +- `allow-duplicate` +- `allow-get-settings` +- `allow-grpc-events` +- `allow-upsert` +- `allow-websocket-events` +- `allow-workspace-models` ## Permission Table @@ -43,6 +48,84 @@ Denies the delete command without any pre-configured scope. +`yaak-models:allow-duplicate` + + + + +Enables the duplicate command without any pre-configured scope. + + + + + + + +`yaak-models:deny-duplicate` + + + + +Denies the duplicate command without any pre-configured scope. + + + + + + + +`yaak-models:allow-get-settings` + + + + +Enables the get_settings command without any pre-configured scope. + + + + + + + +`yaak-models:deny-get-settings` + + + + +Denies the get_settings command without any pre-configured scope. + + + + + + + +`yaak-models:allow-grpc-events` + + + + +Enables the grpc_events command without any pre-configured scope. + + + + + + + +`yaak-models:deny-grpc-events` + + + + +Denies the grpc_events command without any pre-configured scope. + + + + + + + `yaak-models:allow-upsert` @@ -63,6 +146,58 @@ Enables the upsert command without any pre-configured scope. Denies the upsert command without any pre-configured scope. + + + + + + +`yaak-models:allow-websocket-events` + + + + +Enables the websocket_events command without any pre-configured scope. + + + + + + + +`yaak-models:deny-websocket-events` + + + + +Denies the websocket_events command without any pre-configured scope. + + + + + + + +`yaak-models:allow-workspace-models` + + + + +Enables the workspace_models command without any pre-configured scope. + + + + + + + +`yaak-models:deny-workspace-models` + + + + +Denies the workspace_models command without any pre-configured scope. + diff --git a/src-tauri/yaak-models/permissions/default.toml b/src-tauri/yaak-models/permissions/default.toml index 5a93edfb..691305a7 100644 --- a/src-tauri/yaak-models/permissions/default.toml +++ b/src-tauri/yaak-models/permissions/default.toml @@ -1,6 +1,11 @@ [default] description = "Default permissions for the plugin" permissions = [ - "allow-upsert", "allow-delete", + "allow-duplicate", + "allow-get-settings", + "allow-grpc-events", + "allow-upsert", + "allow-websocket-events", + "allow-workspace-models", ] diff --git a/src-tauri/yaak-models/permissions/schemas/schema.json b/src-tauri/yaak-models/permissions/schemas/schema.json index 7092cea5..33914ebf 100644 --- a/src-tauri/yaak-models/permissions/schemas/schema.json +++ b/src-tauri/yaak-models/permissions/schemas/schema.json @@ -304,6 +304,36 @@ "type": "string", "const": "deny-delete" }, + { + "description": "Enables the duplicate command without any pre-configured scope.", + "type": "string", + "const": "allow-duplicate" + }, + { + "description": "Denies the duplicate command without any pre-configured scope.", + "type": "string", + "const": "deny-duplicate" + }, + { + "description": "Enables the get_settings command without any pre-configured scope.", + "type": "string", + "const": "allow-get-settings" + }, + { + "description": "Denies the get_settings command without any pre-configured scope.", + "type": "string", + "const": "deny-get-settings" + }, + { + "description": "Enables the grpc_events command without any pre-configured scope.", + "type": "string", + "const": "allow-grpc-events" + }, + { + "description": "Denies the grpc_events command without any pre-configured scope.", + "type": "string", + "const": "deny-grpc-events" + }, { "description": "Enables the upsert command without any pre-configured scope.", "type": "string", @@ -314,6 +344,26 @@ "type": "string", "const": "deny-upsert" }, + { + "description": "Enables the websocket_events command without any pre-configured scope.", + "type": "string", + "const": "allow-websocket-events" + }, + { + "description": "Denies the websocket_events command without any pre-configured scope.", + "type": "string", + "const": "deny-websocket-events" + }, + { + "description": "Enables the workspace_models command without any pre-configured scope.", + "type": "string", + "const": "allow-workspace-models" + }, + { + "description": "Denies the workspace_models command without any pre-configured scope.", + "type": "string", + "const": "deny-workspace-models" + }, { "description": "Default permissions for the plugin", "type": "string", diff --git a/src-tauri/yaak-models/src/commands.rs b/src-tauri/yaak-models/src/commands.rs index e640c668..66f6af27 100644 --- a/src-tauri/yaak-models/src/commands.rs +++ b/src-tauri/yaak-models/src/commands.rs @@ -1,24 +1,22 @@ use crate::error::Error::GenericError; use crate::error::Result; -use crate::models::AnyModel; +use crate::models::{AnyModel, GrpcEvent, Settings, WebsocketEvent}; use crate::query_manager::QueryManagerExt; use crate::util::UpdateSource; -use tauri::{Runtime, WebviewWindow}; +use tauri::{AppHandle, Runtime, WebviewWindow}; #[tauri::command] -pub(crate) async fn upsert( - window: WebviewWindow, - model: AnyModel, -) -> Result { +pub(crate) fn upsert(window: WebviewWindow, model: AnyModel) -> Result { let db = window.db(); let source = &UpdateSource::from_window(&window); let id = match model { - AnyModel::HttpRequest(m) => db.upsert_http_request(&m, source)?.id, AnyModel::CookieJar(m) => db.upsert_cookie_jar(&m, source)?.id, AnyModel::Environment(m) => db.upsert_environment(&m, source)?.id, AnyModel::Folder(m) => db.upsert_folder(&m, source)?.id, AnyModel::GrpcRequest(m) => db.upsert_grpc_request(&m, source)?.id, + AnyModel::HttpRequest(m) => db.upsert_http_request(&m, source)?.id, AnyModel::HttpResponse(m) => db.upsert_http_response(&m, source)?.id, + AnyModel::KeyValue(m) => db.upsert_key_value(&m, source)?.id, AnyModel::Plugin(m) => db.upsert_plugin(&m, source)?.id, AnyModel::Settings(m) => db.upsert_settings(&m, source)?.id, AnyModel::WebsocketRequest(m) => db.upsert_websocket_request(&m, source)?.id, @@ -32,22 +30,95 @@ pub(crate) async fn upsert( #[tauri::command] pub(crate) fn delete(window: WebviewWindow, model: AnyModel) -> Result { - let db = window.db(); - let source = &UpdateSource::from_window(&window); - let id = match model { - AnyModel::HttpRequest(m) => db.delete_http_request(&m, source)?.id, - AnyModel::CookieJar(m) => db.delete_cookie_jar(&m, source)?.id, - AnyModel::Environment(m) => db.delete_environment(&m, source)?.id, - AnyModel::Folder(m) => db.delete_folder(&m, source)?.id, - AnyModel::GrpcConnection(m) => db.delete_grpc_connection(&m, source)?.id, - AnyModel::GrpcRequest(m) => db.delete_grpc_request(&m, source)?.id, - AnyModel::HttpResponse(m) => db.delete_http_response(&m, source)?.id, - AnyModel::Plugin(m) => db.delete_plugin(&m, source)?.id, - AnyModel::WebsocketConnection(m) => db.delete_websocket_connection(&m, source)?.id, - AnyModel::WebsocketRequest(m) => db.delete_websocket_request(&m, source)?.id, - AnyModel::Workspace(m) => db.delete_workspace(&m, source)?.id, - a => return Err(GenericError(format!("Cannot delete AnyModel {a:?})"))), - }; - - Ok(id) + // Use transaction for deletions because it might recurse + window.with_tx(|tx| { + let source = &UpdateSource::from_window(&window); + let id = match model { + AnyModel::CookieJar(m) => tx.delete_cookie_jar(&m, source)?.id, + AnyModel::Environment(m) => tx.delete_environment(&m, source)?.id, + AnyModel::Folder(m) => tx.delete_folder(&m, source)?.id, + AnyModel::GrpcConnection(m) => tx.delete_grpc_connection(&m, source)?.id, + AnyModel::GrpcRequest(m) => tx.delete_grpc_request(&m, source)?.id, + AnyModel::HttpRequest(m) => tx.delete_http_request(&m, source)?.id, + AnyModel::HttpResponse(m) => tx.delete_http_response(&m, source)?.id, + AnyModel::Plugin(m) => tx.delete_plugin(&m, source)?.id, + AnyModel::WebsocketConnection(m) => tx.delete_websocket_connection(&m, source)?.id, + AnyModel::WebsocketRequest(m) => tx.delete_websocket_request(&m, source)?.id, + AnyModel::Workspace(m) => tx.delete_workspace(&m, source)?.id, + a => return Err(GenericError(format!("Cannot delete AnyModel {a:?})"))), + }; + Ok(id) + }) +} + +#[tauri::command] +pub(crate) fn duplicate(window: WebviewWindow, model: AnyModel) -> Result { + // Use transaction for duplications because it might recurse + window.with_tx(|tx| { + let source = &UpdateSource::from_window(&window); + let id = match model { + AnyModel::Environment(m) => tx.duplicate_environment(&m, source)?.id, + AnyModel::Folder(m) => tx.duplicate_folder(&m, source)?.id, + AnyModel::GrpcRequest(m) => tx.duplicate_grpc_request(&m, source)?.id, + AnyModel::HttpRequest(m) => tx.duplicate_http_request(&m, source)?.id, + AnyModel::WebsocketRequest(m) => tx.duplicate_websocket_request(&m, source)?.id, + a => return Err(GenericError(format!("Cannot duplicate AnyModel {a:?})"))), + }; + + Ok(id) + }) +} + +#[tauri::command] +pub(crate) fn websocket_events( + app_handle: AppHandle, + connection_id: &str, +) -> Result> { + Ok(app_handle.db().list_websocket_events(connection_id)?) +} + +#[tauri::command] +pub(crate) fn grpc_events( + app_handle: AppHandle, + connection_id: &str, +) -> Result> { + Ok(app_handle.db().list_grpc_events(connection_id)?) +} + +#[tauri::command] +pub(crate) fn get_settings(app_handle: AppHandle) -> Result { + Ok(app_handle.db().get_settings()) +} + +#[tauri::command] +pub(crate) fn workspace_models( + window: WebviewWindow, + workspace_id: Option<&str>, +) -> Result> { + let db = window.db(); + let mut l: Vec = Vec::new(); + + // Add the settings + l.push(db.get_settings().into()); + + // Add global models + l.append(&mut db.list_workspaces()?.into_iter().map(Into::into).collect()); + l.append(&mut db.list_key_values()?.into_iter().map(Into::into).collect()); + l.append(&mut db.list_plugins()?.into_iter().map(Into::into).collect()); + + // Add the workspace children + if let Some(wid) = workspace_id { + l.append(&mut db.list_cookie_jars(wid)?.into_iter().map(Into::into).collect()); + l.append(&mut db.list_environments(wid)?.into_iter().map(Into::into).collect()); + l.append(&mut db.list_folders(wid)?.into_iter().map(Into::into).collect()); + l.append(&mut db.list_grpc_connections(wid)?.into_iter().map(Into::into).collect()); + l.append(&mut db.list_grpc_requests(wid)?.into_iter().map(Into::into).collect()); + l.append(&mut db.list_http_requests(wid)?.into_iter().map(Into::into).collect()); + l.append(&mut db.list_http_responses(wid, None)?.into_iter().map(Into::into).collect()); + l.append(&mut db.list_websocket_connections(wid)?.into_iter().map(Into::into).collect()); + l.append(&mut db.list_websocket_requests(wid)?.into_iter().map(Into::into).collect()); + l.append(&mut db.list_workspace_metas(wid)?.into_iter().map(Into::into).collect()); + } + + Ok(l) } diff --git a/src-tauri/yaak-models/src/db_context.rs b/src-tauri/yaak-models/src/db_context.rs index 3548a0c8..ba00c122 100644 --- a/src-tauri/yaak-models/src/db_context.rs +++ b/src-tauri/yaak-models/src/db_context.rs @@ -11,7 +11,7 @@ use sea_query_rusqlite::RusqliteBinder; use tokio::sync::mpsc; pub struct DbContext<'a> { - pub(crate) tx: mpsc::Sender, + pub(crate) events_tx: mpsc::Sender, pub(crate) conn: ConnectionOrTx<'a>, } @@ -145,7 +145,7 @@ impl<'a> DbContext<'a> { update_source: source.clone(), change: ModelChangeEvent::Upsert, }; - self.tx.try_send(payload).unwrap(); + self.events_tx.try_send(payload).unwrap(); Ok(m) } @@ -170,7 +170,7 @@ impl<'a> DbContext<'a> { change: ModelChangeEvent::Delete, }; - self.tx.try_send(payload).unwrap(); + self.events_tx.try_send(payload).unwrap(); Ok(m.clone()) } } diff --git a/src-tauri/yaak-models/src/lib.rs b/src-tauri/yaak-models/src/lib.rs index 2a0b7550..6b261a05 100644 --- a/src-tauri/yaak-models/src/lib.rs +++ b/src-tauri/yaak-models/src/lib.rs @@ -1,4 +1,4 @@ -use crate::commands::{delete, upsert}; +use crate::commands::*; use crate::query_manager::QueryManager; use crate::util::ModelChangeEvent; use log::info; @@ -22,11 +22,11 @@ mod commands; mod connection_or_tx; mod db_context; pub mod error; -pub mod query_manager; pub mod models; pub mod queries; -pub mod util; +pub mod query_manager; pub mod render; +pub mod util; pub struct SqliteConnection(pub Mutex>); @@ -38,7 +38,15 @@ impl SqliteConnection { pub fn init() -> TauriPlugin { tauri::plugin::Builder::new("yaak-models") - .invoke_handler(generate_handler![upsert, delete]) + .invoke_handler(generate_handler![ + upsert, + delete, + duplicate, + workspace_models, + grpc_events, + websocket_events, + get_settings, + ]) .setup(|app_handle, _api| { let app_path = app_handle.path().app_data_dir().unwrap(); create_dir_all(app_path.clone()).expect("Problem creating App directory!"); diff --git a/src-tauri/yaak-models/src/models.rs b/src-tauri/yaak-models/src/models.rs index 1a02cb4c..45223535 100644 --- a/src-tauri/yaak-models/src/models.rs +++ b/src-tauri/yaak-models/src/models.rs @@ -105,7 +105,6 @@ pub struct Settings { pub interface_scale: f32, pub open_workspace_new_window: Option, pub proxy: Option, - pub theme: String, pub theme_dark: String, pub theme_light: String, pub update_channel: String, @@ -148,7 +147,6 @@ impl UpsertModelInfo for Settings { (InterfaceFontSize, self.interface_font_size.into()), (InterfaceScale, self.interface_scale.into()), (OpenWorkspaceNewWindow, self.open_workspace_new_window.into()), - (Theme, self.theme.as_str().into()), (ThemeDark, self.theme_dark.as_str().into()), (ThemeLight, self.theme_light.as_str().into()), (UpdateChannel, self.update_channel.into()), @@ -167,7 +165,6 @@ impl UpsertModelInfo for Settings { SettingsIden::InterfaceScale, SettingsIden::OpenWorkspaceNewWindow, SettingsIden::Proxy, - SettingsIden::Theme, SettingsIden::ThemeDark, SettingsIden::ThemeLight, SettingsIden::UpdateChannel, @@ -193,7 +190,6 @@ impl UpsertModelInfo for Settings { interface_scale: row.get("interface_scale")?, open_workspace_new_window: row.get("open_workspace_new_window")?, proxy: proxy.map(|p| -> ProxySetting { serde_json::from_str(p.as_str()).unwrap() }), - theme: row.get("theme")?, theme_dark: row.get("theme_dark")?, theme_light: row.get("theme_light")?, update_channel: row.get("update_channel")?, @@ -1751,6 +1747,7 @@ impl UpsertModelInfo for SyncState { pub struct KeyValue { #[ts(type = "\"key_value\"")] pub model: String, + pub id: String, pub created_at: NaiveDateTime, pub updated_at: NaiveDateTime, @@ -1759,17 +1756,53 @@ pub struct KeyValue { pub value: String, } -impl<'s> TryFrom<&Row<'s>> for KeyValue { - type Error = rusqlite::Error; +impl UpsertModelInfo for KeyValue { + fn table_name() -> impl IntoTableRef { + KeyValueIden::Table + } - fn try_from(r: &Row<'s>) -> std::result::Result { + fn id_column() -> impl IntoIden + Eq + Clone { + KeyValueIden::Id + } + + fn generate_id() -> String { + generate_prefixed_id("kv") + } + + fn get_id(&self) -> String { + self.id.clone() + } + + fn insert_values( + self, + source: &UpdateSource, + ) -> Result)>> { + use KeyValueIden::*; + Ok(vec![ + (CreatedAt, upsert_date(source, self.created_at)), + (UpdatedAt, upsert_date(source, self.updated_at)), + (Namespace, self.namespace.clone().into()), + (Key, self.key.clone().into()), + (Value, self.value.clone().into()), + ]) + } + + fn update_columns() -> Vec { + vec![KeyValueIden::UpdatedAt, KeyValueIden::Value] + } + + fn from_row(row: &Row) -> rusqlite::Result + where + Self: Sized, + { Ok(Self { - model: r.get("model")?, - created_at: r.get("created_at")?, - updated_at: r.get("updated_at")?, - namespace: r.get("namespace")?, - key: r.get("key")?, - value: r.get("value")?, + id: row.get("id")?, + model: row.get("model")?, + created_at: row.get("created_at")?, + updated_at: row.get("updated_at")?, + namespace: row.get("namespace")?, + key: row.get("key")?, + value: row.get("value")?, }) } } @@ -1876,18 +1909,23 @@ impl<'de> Deserialize<'de> for AnyModel { use serde_json::from_value as fv; let model = match model.get("model") { - Some(m) if m == "http_request" => AnyModel::HttpRequest(fv(value).unwrap()), - Some(m) if m == "grpc_request" => AnyModel::GrpcRequest(fv(value).unwrap()), - Some(m) if m == "workspace" => AnyModel::Workspace(fv(value).unwrap()), + Some(m) if m == "cookie_jar" => AnyModel::CookieJar(fv(value).unwrap()), Some(m) if m == "environment" => AnyModel::Environment(fv(value).unwrap()), Some(m) if m == "folder" => AnyModel::Folder(fv(value).unwrap()), - Some(m) if m == "key_value" => AnyModel::KeyValue(fv(value).unwrap()), Some(m) if m == "grpc_connection" => AnyModel::GrpcConnection(fv(value).unwrap()), Some(m) if m == "grpc_event" => AnyModel::GrpcEvent(fv(value).unwrap()), - Some(m) if m == "cookie_jar" => AnyModel::CookieJar(fv(value).unwrap()), + Some(m) if m == "grpc_request" => AnyModel::GrpcRequest(fv(value).unwrap()), + Some(m) if m == "http_request" => AnyModel::HttpRequest(fv(value).unwrap()), + Some(m) if m == "key_value" => AnyModel::KeyValue(fv(value).unwrap()), Some(m) if m == "plugin" => AnyModel::Plugin(fv(value).unwrap()), + Some(m) if m == "settings" => AnyModel::Settings(fv(value).unwrap()), + Some(m) if m == "websocket_connection" => AnyModel::WebsocketConnection(fv(value).unwrap()), + Some(m) if m == "websocket_event" => AnyModel::WebsocketEvent(fv(value).unwrap()), + Some(m) if m == "websocket_request" => AnyModel::WebsocketRequest(fv(value).unwrap()), + Some(m) if m == "workspace" => AnyModel::Workspace(fv(value).unwrap()), + Some(m) if m == "workspace_meta" => AnyModel::WorkspaceMeta(fv(value).unwrap()), Some(m) => { - return Err(serde::de::Error::custom(format!("Unknown model {}", m))); + return Err(serde::de::Error::custom(format!("Failed to deserialize AnyModel {}", m))); } None => { return Err(serde::de::Error::custom("Missing or invalid model")); @@ -1905,11 +1943,7 @@ impl AnyModel { return name.to_string(); } let without_variables = url.replace(r"\$\{\[\s*([^\]\s]+)\s*]}", "$1"); - if without_variables.is_empty() { - fallback.to_string() - } else { - without_variables - } + if without_variables.is_empty() { fallback.to_string() } else { without_variables } }; match self.clone() { diff --git a/src-tauri/yaak-models/src/queries/cookie_jars.rs b/src-tauri/yaak-models/src/queries/cookie_jars.rs index 525e90ce..7d656176 100644 --- a/src-tauri/yaak-models/src/queries/cookie_jars.rs +++ b/src-tauri/yaak-models/src/queries/cookie_jars.rs @@ -9,7 +9,18 @@ impl<'a> DbContext<'a> { } pub fn list_cookie_jars(&self, workspace_id: &str) -> Result> { - self.find_many(CookieJarIden::WorkspaceId, workspace_id, None) + let mut cookie_jars = self.find_many(CookieJarIden::WorkspaceId, workspace_id, None)?; + + if cookie_jars.is_empty() { + let jar = CookieJar { + name: "Default".to_string(), + workspace_id: workspace_id.to_string(), + ..Default::default() + }; + cookie_jars.push(self.upsert_cookie_jar(&jar, &UpdateSource::Background)?); + } + + Ok(cookie_jars) } pub fn delete_cookie_jar( diff --git a/src-tauri/yaak-models/src/queries/environments.rs b/src-tauri/yaak-models/src/queries/environments.rs index 333157d6..691cf41e 100644 --- a/src-tauri/yaak-models/src/queries/environments.rs +++ b/src-tauri/yaak-models/src/queries/environments.rs @@ -1,11 +1,8 @@ -use crate::error::Result; -use crate::models::{Environment, EnvironmentIden, UpsertModelInfo}; -use crate::util::UpdateSource; -use log::info; -use sea_query::ColumnRef::Asterisk; -use sea_query::{Cond, Expr, Query, SqliteQueryBuilder}; -use sea_query_rusqlite::RusqliteBinder; use crate::db_context::DbContext; +use crate::error::Error::GenericError; +use crate::error::Result; +use crate::models::{Environment, EnvironmentIden}; +use crate::util::UpdateSource; impl<'a> DbContext<'a> { pub fn get_environment(&self, id: &str) -> Result { @@ -13,42 +10,38 @@ impl<'a> DbContext<'a> { } pub fn get_base_environment(&self, workspace_id: &str) -> Result { - let (sql, params) = Query::select() - .from(EnvironmentIden::Table) - .column(Asterisk) - .cond_where( - Cond::all() - .add(Expr::col(EnvironmentIden::WorkspaceId).eq(workspace_id)) - .add(Expr::col(EnvironmentIden::EnvironmentId).is_null()), - ) - .build_rusqlite(SqliteQueryBuilder); - let mut stmt = self.conn.prepare(sql.as_str())?; - Ok(stmt.query_row(&*params.as_params(), Environment::from_row)?) + // Will create base environment if it doesn't exist + let environments = self.list_environments(workspace_id)?; + + let base_environment = environments + .into_iter() + .find(|e| e.environment_id == None && e.workspace_id == workspace_id) + .ok_or(GenericError(format!("No base environment found for {workspace_id}")))?; + + Ok(base_environment) } - pub fn ensure_base_environment(&self, workspace_id: &str) -> Result<()> { - let environments = self.list_environments(workspace_id)?; + pub fn list_environments(&self, workspace_id: &str) -> Result> { + let mut environments = + self.find_many::(EnvironmentIden::WorkspaceId, workspace_id, None)?; + let base_environment = environments .iter() .find(|e| e.environment_id == None && e.workspace_id == workspace_id); if let None = base_environment { - info!("Creating base environment for {workspace_id}"); - self.upsert_environment( + environments.push(self.upsert_environment( &Environment { workspace_id: workspace_id.to_string(), + environment_id: None, name: "Global Variables".to_string(), ..Default::default() }, &UpdateSource::Background, - )?; + )?); } - Ok(()) - } - - pub fn list_environments(&self, workspace_id: &str) -> Result> { - self.find_many(EnvironmentIden::WorkspaceId, workspace_id, None) + Ok(environments) } pub fn delete_environment( @@ -69,6 +62,16 @@ impl<'a> DbContext<'a> { self.delete_environment(&environment, source) } + pub fn duplicate_environment( + &self, + environment: &Environment, + source: &UpdateSource, + ) -> Result { + let mut environment = environment.clone(); + environment.id = "".to_string(); + self.upsert(&environment, source) + } + pub fn upsert_environment( &self, environment: &Environment, diff --git a/src-tauri/yaak-models/src/queries/folders.rs b/src-tauri/yaak-models/src/queries/folders.rs index bd9d17f0..1d9e508b 100644 --- a/src-tauri/yaak-models/src/queries/folders.rs +++ b/src-tauri/yaak-models/src/queries/folders.rs @@ -1,3 +1,4 @@ +use crate::connection_or_tx::ConnectionOrTx; use crate::db_context::DbContext; use crate::error::Result; use crate::models::{ @@ -16,20 +17,29 @@ impl<'a> DbContext<'a> { } pub fn delete_folder(&self, folder: &Folder, source: &UpdateSource) -> Result { - for folder in self.find_many::(FolderIden::FolderId, &folder.id, None)? { + match self.conn { + ConnectionOrTx::Connection(_) => {} + ConnectionOrTx::Transaction(_) => {} + } + + let fid = &folder.id; + for m in self.find_many::(HttpRequestIden::FolderId, fid, None)? { + self.delete_http_request(&m, source)?; + } + + for m in self.find_many::(GrpcRequestIden::FolderId, fid, None)? { + self.delete_grpc_request(&m, source)?; + } + + for m in self.find_many::(WebsocketRequestIden::FolderId, fid, None)? { + self.delete_websocket_request(&m, source)?; + } + + // Recurse down into child folders + for folder in self.find_many::(FolderIden::FolderId, fid, None)? { self.delete_folder(&folder, source)?; } - for request in self.find_many::(HttpRequestIden::FolderId, &folder.id, None)? { - self.delete_http_request(&request, source)?; - } - for request in self.find_many::(GrpcRequestIden::FolderId, &folder.id, None)? { - self.delete_grpc_request(&request, source)?; - } - for request in - self.find_many::(WebsocketRequestIden::FolderId, &folder.id, None)? - { - self.delete_websocket_request(&request, source)?; - } + self.delete(folder, source) } @@ -43,22 +53,7 @@ impl<'a> DbContext<'a> { } pub fn duplicate_folder(&self, src_folder: &Folder, source: &UpdateSource) -> Result { - let workspace_id = src_folder.workspace_id.as_str(); - - let http_requests = self - .find_many::(HttpRequestIden::WorkspaceId, workspace_id, None)? - .into_iter() - .filter(|m| m.folder_id.as_ref() == Some(&src_folder.id)); - - let grpc_requests = self - .find_many::(GrpcRequestIden::WorkspaceId, workspace_id, None)? - .into_iter() - .filter(|m| m.folder_id.as_ref() == Some(&src_folder.id)); - - let folders = self - .find_many::(FolderIden::WorkspaceId, workspace_id, None)? - .into_iter() - .filter(|m| m.folder_id.as_ref() == Some(&src_folder.id)); + let fid = &src_folder.id; let new_folder = self.upsert_folder( &Folder { @@ -69,29 +64,40 @@ impl<'a> DbContext<'a> { source, )?; - for m in http_requests { + for m in self.find_many::(HttpRequestIden::FolderId, fid, None)? { self.upsert_http_request( &HttpRequest { id: "".into(), folder_id: Some(new_folder.id.clone()), - sort_priority: m.sort_priority + 0.001, ..m }, source, )?; } - for m in grpc_requests { + + for m in self.find_many::(WebsocketRequestIden::FolderId, fid, None)? { + self.upsert_websocket_request( + &WebsocketRequest { + id: "".into(), + folder_id: Some(new_folder.id.clone()), + ..m + }, + source, + )?; + } + + for m in self.find_many::(GrpcRequestIden::FolderId, fid, None)? { self.upsert_grpc_request( &GrpcRequest { id: "".into(), folder_id: Some(new_folder.id.clone()), - sort_priority: m.sort_priority + 0.001, ..m }, source, )?; } - for m in folders { + + for m in self.find_many::(FolderIden::FolderId, fid, None)? { // Recurse down self.duplicate_folder( &Folder { @@ -101,6 +107,7 @@ impl<'a> DbContext<'a> { source, )?; } + Ok(new_folder) } } diff --git a/src-tauri/yaak-models/src/queries/grpc_connections.rs b/src-tauri/yaak-models/src/queries/grpc_connections.rs index a8e9dfeb..49d75351 100644 --- a/src-tauri/yaak-models/src/queries/grpc_connections.rs +++ b/src-tauri/yaak-models/src/queries/grpc_connections.rs @@ -1,11 +1,11 @@ +use crate::db_context::DbContext; use crate::error::Result; use crate::models::{GrpcConnection, GrpcConnectionIden, GrpcConnectionState}; +use crate::queries::MAX_HISTORY_ITEMS; use crate::util::UpdateSource; use log::debug; use sea_query::{Expr, Query, SqliteQueryBuilder}; use sea_query_rusqlite::RusqliteBinder; -use crate::db_context::DbContext; -use crate::queries::MAX_HISTORY_ITEMS; impl<'a> DbContext<'a> { pub fn get_grpc_connection(&self, id: &str) -> Result { @@ -29,7 +29,7 @@ impl<'a> DbContext<'a> { workspace_id: &str, source: &UpdateSource, ) -> Result<()> { - for m in self.list_grpc_connections_for_workspace(workspace_id, None)? { + for m in self.list_grpc_connections(workspace_id)? { self.delete(&m, source)?; } Ok(()) @@ -60,12 +60,8 @@ impl<'a> DbContext<'a> { self.find_many(GrpcConnectionIden::RequestId, request_id, limit) } - pub fn list_grpc_connections_for_workspace( - &self, - workspace_id: &str, - limit: Option, - ) -> Result> { - self.find_many(GrpcConnectionIden::WorkspaceId, workspace_id, limit) + pub fn list_grpc_connections(&self, workspace_id: &str) -> Result> { + self.find_many(GrpcConnectionIden::WorkspaceId, workspace_id, None) } pub fn cancel_pending_grpc_connections(&self) -> Result<()> { diff --git a/src-tauri/yaak-models/src/queries/http_responses.rs b/src-tauri/yaak-models/src/queries/http_responses.rs index 48008e35..8ee39160 100644 --- a/src-tauri/yaak-models/src/queries/http_responses.rs +++ b/src-tauri/yaak-models/src/queries/http_responses.rs @@ -21,7 +21,7 @@ impl<'a> DbContext<'a> { self.find_many(HttpResponseIden::RequestId, request_id, limit) } - pub fn list_http_responses_for_workspace( + pub fn list_http_responses( &self, workspace_id: &str, limit: Option, diff --git a/src-tauri/yaak-models/src/queries/key_values.rs b/src-tauri/yaak-models/src/queries/key_values.rs index af9a0cd8..b7ee6f4a 100644 --- a/src-tauri/yaak-models/src/queries/key_values.rs +++ b/src-tauri/yaak-models/src/queries/key_values.rs @@ -1,20 +1,19 @@ use crate::db_context::DbContext; use crate::error::Result; -use crate::models::{KeyValue, KeyValueIden}; -use crate::util::{ModelChangeEvent, ModelPayload, UpdateSource}; +use crate::models::{KeyValue, KeyValueIden, UpsertModelInfo}; +use crate::util::UpdateSource; use log::error; -use sea_query::Keyword::CurrentTimestamp; -use sea_query::{Asterisk, Cond, Expr, OnConflict, Query, SqliteQueryBuilder}; +use sea_query::{Asterisk, Cond, Expr, Query, SqliteQueryBuilder}; use sea_query_rusqlite::RusqliteBinder; impl<'a> DbContext<'a> { - pub fn list_key_values_raw(&self) -> Result> { + pub fn list_key_values(&self) -> Result> { let (sql, params) = Query::select() .from(KeyValueIden::Table) .column(Asterisk) .build_rusqlite(SqliteQueryBuilder); let mut stmt = self.conn.prepare(sql.as_str())?; - let items = stmt.query_map(&*params.as_params(), |row| row.try_into())?; + let items = stmt.query_map(&*params.as_params(), KeyValue::from_row)?; Ok(items.map(|v| v.unwrap()).collect()) } @@ -60,7 +59,7 @@ impl<'a> DbContext<'a> { .add(Expr::col(KeyValueIden::Key).eq(key)), ) .build_rusqlite(SqliteQueryBuilder); - self.conn.resolve().query_row(sql.as_str(), &*params.as_params(), |row| row.try_into()).ok() + self.conn.resolve().query_row(sql.as_str(), &*params.as_params(), KeyValue::from_row).ok() } pub fn set_key_value_string( @@ -125,43 +124,7 @@ impl<'a> DbContext<'a> { key_value: &KeyValue, source: &UpdateSource, ) -> Result { - let (sql, params) = Query::insert() - .into_table(KeyValueIden::Table) - .columns([ - KeyValueIden::CreatedAt, - KeyValueIden::UpdatedAt, - KeyValueIden::Namespace, - KeyValueIden::Key, - KeyValueIden::Value, - ]) - .values_panic([ - CurrentTimestamp.into(), - CurrentTimestamp.into(), - key_value.namespace.clone().into(), - key_value.key.clone().into(), - key_value.value.clone().into(), - ]) - .on_conflict( - OnConflict::new() - .update_columns([KeyValueIden::UpdatedAt, KeyValueIden::Value]) - .to_owned(), - ) - .returning_all() - .build_rusqlite(SqliteQueryBuilder); - - let mut stmt = self.conn.prepare(sql.as_str()).expect("Failed to prepare KeyValue upsert"); - let m: KeyValue = stmt - .query_row(&*params.as_params(), |row| row.try_into()) - .expect("Failed to upsert KeyValue"); - - let payload = ModelPayload { - model: m.clone().into(), - update_source: source.clone(), - change: ModelChangeEvent::Upsert, - }; - self.tx.try_send(payload).unwrap(); - - Ok(m) + self.upsert(key_value, source) } pub fn delete_key_value( @@ -175,21 +138,7 @@ impl<'a> DbContext<'a> { Some(m) => m, }; - let (sql, params) = Query::delete() - .from_table(KeyValueIden::Table) - .cond_where( - Cond::all() - .add(Expr::col(KeyValueIden::Namespace).eq(namespace)) - .add(Expr::col(KeyValueIden::Key).eq(key)), - ) - .build_rusqlite(SqliteQueryBuilder); - self.conn.execute(sql.as_str(), &*params.as_params())?; - let payload = ModelPayload { - model: kv.clone().into(), - update_source: source.clone(), - change: ModelChangeEvent::Delete, - }; - self.tx.try_send(payload).unwrap(); + self.delete(&kv, source)?; Ok(()) } } diff --git a/src-tauri/yaak-models/src/queries/mod.rs b/src-tauri/yaak-models/src/queries/mod.rs index d05c40a4..19c583cc 100644 --- a/src-tauri/yaak-models/src/queries/mod.rs +++ b/src-tauri/yaak-models/src/queries/mod.rs @@ -18,4 +18,4 @@ mod websocket_requests; mod workspace_metas; mod workspaces; -const MAX_HISTORY_ITEMS: usize = 20; \ No newline at end of file +const MAX_HISTORY_ITEMS: usize = 20; diff --git a/src-tauri/yaak-models/src/queries/settings.rs b/src-tauri/yaak-models/src/queries/settings.rs index ff4d3246..2bc7504a 100644 --- a/src-tauri/yaak-models/src/queries/settings.rs +++ b/src-tauri/yaak-models/src/queries/settings.rs @@ -1,24 +1,35 @@ use crate::db_context::DbContext; use crate::error::Result; -use crate::models::{Settings, SettingsIden}; +use crate::models::{EditorKeymap, Settings, SettingsIden}; use crate::util::UpdateSource; impl<'a> DbContext<'a> { - pub fn get_or_create_settings(&self, source: &UpdateSource) -> Settings { + pub fn get_settings(&self) -> Settings { let id = "default".to_string(); if let Some(s) = self.find_optional::(SettingsIden::Id, &id) { return s; }; - self.upsert( - &Settings { - id, - ..Default::default() - }, - source, - ) - .expect("Failed to upsert settings") + let settings = Settings { + model: "settings".to_string(), + id, + created_at: Default::default(), + updated_at: Default::default(), + + appearance: "system".to_string(), + editor_font_size: 13, + editor_keymap: EditorKeymap::Default, + editor_soft_wrap: true, + interface_font_size: 15, + interface_scale: 1.0, + open_workspace_new_window: None, + proxy: None, + theme_dark: "yaak-dark".to_string(), + theme_light: "yaak-light".to_string(), + update_channel: "stable".to_string(), + }; + self.upsert(&settings, &UpdateSource::Background).expect("Failed to upsert settings") } pub fn upsert_settings(&self, settings: &Settings, source: &UpdateSource) -> Result { diff --git a/src-tauri/yaak-models/src/queries/websocket_connections.rs b/src-tauri/yaak-models/src/queries/websocket_connections.rs index c105139e..0799c7ff 100644 --- a/src-tauri/yaak-models/src/queries/websocket_connections.rs +++ b/src-tauri/yaak-models/src/queries/websocket_connections.rs @@ -29,14 +29,14 @@ impl<'a> DbContext<'a> { workspace_id: &str, source: &UpdateSource, ) -> Result<()> { - let responses = self.list_websocket_connections_for_workspace(workspace_id)?; + let responses = self.list_websocket_connections(workspace_id)?; for m in responses { self.delete(&m, source)?; } Ok(()) } - pub fn list_websocket_connections_for_workspace( + pub fn list_websocket_connections( &self, workspace_id: &str, ) -> Result> { diff --git a/src-tauri/yaak-models/src/queries/workspace_metas.rs b/src-tauri/yaak-models/src/queries/workspace_metas.rs index 614b54b1..6e29242b 100644 --- a/src-tauri/yaak-models/src/queries/workspace_metas.rs +++ b/src-tauri/yaak-models/src/queries/workspace_metas.rs @@ -1,25 +1,40 @@ use crate::db_context::DbContext; use crate::error::Result; -use crate::models::{Workspace, WorkspaceMeta, WorkspaceMetaIden}; +use crate::models::{WorkspaceMeta, WorkspaceMetaIden}; use crate::util::UpdateSource; impl<'a> DbContext<'a> { - pub fn get_workspace_meta(&self, workspace: &Workspace) -> Option { - self.find_optional(WorkspaceMetaIden::WorkspaceId, &workspace.id) + pub fn get_workspace_meta(&self, workspace_id: &str) -> Option { + self.find_optional(WorkspaceMetaIden::WorkspaceId, workspace_id) + } + + pub fn list_workspace_metas(&self, workspace_id: &str) -> Result> { + let mut workspace_metas = + self.find_many(WorkspaceMetaIden::WorkspaceId, workspace_id, None)?; + + if workspace_metas.is_empty() { + let wm = WorkspaceMeta { + workspace_id: workspace_id.to_string(), + ..Default::default() + }; + workspace_metas.push(self.upsert_workspace_meta(&wm, &UpdateSource::Background)?) + } + + Ok(workspace_metas) } pub fn get_or_create_workspace_meta( &self, - workspace: &Workspace, + workspace_id: &str, source: &UpdateSource, ) -> Result { - let workspace_meta = self.get_workspace_meta(workspace); + let workspace_meta = self.get_workspace_meta(workspace_id); if let Some(workspace_meta) = workspace_meta { return Ok(workspace_meta); } let workspace_meta = WorkspaceMeta { - workspace_id: workspace.to_owned().id, + workspace_id: workspace_id.to_string(), ..Default::default() }; diff --git a/src-tauri/yaak-models/src/queries/workspaces.rs b/src-tauri/yaak-models/src/queries/workspaces.rs index 15ceb370..ef35e9f8 100644 --- a/src-tauri/yaak-models/src/queries/workspaces.rs +++ b/src-tauri/yaak-models/src/queries/workspaces.rs @@ -12,7 +12,21 @@ impl<'a> DbContext<'a> { } pub fn list_workspaces(&self) -> Result> { - self.find_all() + let mut workspaces = self.find_all()?; + + if workspaces.is_empty() { + workspaces.push(self.upsert_workspace( + &Workspace { + name: "Yaak".to_string(), + setting_follow_redirects: true, + setting_validate_certificates: true, + ..Default::default() + }, + &UpdateSource::Background, + )?) + } + + Ok(workspaces) } pub fn delete_workspace( @@ -20,24 +34,24 @@ impl<'a> DbContext<'a> { workspace: &Workspace, source: &UpdateSource, ) -> Result { + for m in self.find_many::(HttpRequestIden::WorkspaceId, &workspace.id, None)? { + self.delete_http_request(&m, source)?; + } + + for m in self.find_many::(GrpcRequestIden::WorkspaceId, &workspace.id, None)? { + self.delete_grpc_request(&m, source)?; + } + + for m in + self.find_many::(WebsocketRequestIden::FolderId, &workspace.id, None)? + { + self.delete_websocket_request(&m, source)?; + } + for folder in self.find_many::(FolderIden::WorkspaceId, &workspace.id, None)? { self.delete_folder(&folder, source)?; } - for request in - self.find_many::(HttpRequestIden::WorkspaceId, &workspace.id, None)? - { - self.delete_http_request(&request, source)?; - } - for request in - self.find_many::(GrpcRequestIden::WorkspaceId, &workspace.id, None)? - { - self.delete_grpc_request(&request, source)?; - } - for request in - self.find_many::(WebsocketRequestIden::FolderId, &workspace.id, None)? - { - self.delete_websocket_request(&request, source)?; - } + self.delete(workspace, source) } diff --git a/src-tauri/yaak-models/src/query_manager.rs b/src-tauri/yaak-models/src/query_manager.rs index 2accfb57..aee0513d 100644 --- a/src-tauri/yaak-models/src/query_manager.rs +++ b/src-tauri/yaak-models/src/query_manager.rs @@ -22,7 +22,7 @@ pub trait QueryManagerExt<'a, R> { impl<'a, R: Runtime, M: Manager> QueryManagerExt<'a, R> for M { fn db(&'a self) -> DbContext<'a> { let qm = self.state::(); - qm.inner().connect_2() + qm.inner().connect() } fn with_db(&'a self, func: F) -> T @@ -59,7 +59,7 @@ impl QueryManager { } } - pub fn connect_2(&self) -> DbContext { + pub fn connect(&self) -> DbContext { let conn = self .pool .lock() @@ -67,7 +67,7 @@ impl QueryManager { .get() .expect("Failed to get a new DB connection from the pool"); DbContext { - tx: self.events_tx.clone(), + events_tx: self.events_tx.clone(), conn: ConnectionOrTx::Connection(conn), } } @@ -84,7 +84,7 @@ impl QueryManager { .expect("Failed to get new DB connection from the pool"); let db_context = DbContext { - tx: self.events_tx.clone(), + events_tx: self.events_tx.clone(), conn: ConnectionOrTx::Connection(conn), }; @@ -106,7 +106,7 @@ impl QueryManager { .expect("Failed to start DB transaction"); let db_context = DbContext { - tx: self.events_tx.clone(), + events_tx: self.events_tx.clone(), conn: ConnectionOrTx::Transaction(&tx), }; diff --git a/src-tauri/yaak-models/src/util.rs b/src-tauri/yaak-models/src/util.rs index 926a844d..1f44834a 100644 --- a/src-tauri/yaak-models/src/util.rs +++ b/src-tauri/yaak-models/src/util.rs @@ -45,11 +45,11 @@ pub enum ModelChangeEvent { #[serde(rename_all = "snake_case", tag = "type")] #[ts(export, export_to = "gen_models.ts")] pub enum UpdateSource { - Sync, - Window { label: String }, - Plugin, Background, Import, + Plugin, + Sync, + Window { label: String }, } impl UpdateSource { diff --git a/src-tauri/yaak-sync/src/sync.rs b/src-tauri/yaak-sync/src/sync.rs index d475d5a8..d25461d4 100644 --- a/src-tauri/yaak-sync/src/sync.rs +++ b/src-tauri/yaak-sync/src/sync.rs @@ -13,7 +13,7 @@ use tokio::io::AsyncWriteExt; use ts_rs::TS; use yaak_models::models::{SyncState, WorkspaceMeta}; use yaak_models::query_manager::QueryManagerExt; -use yaak_models::util::{get_workspace_export_resources, UpdateSource}; +use yaak_models::util::{UpdateSource, get_workspace_export_resources}; #[derive(Debug, Clone, Serialize, Deserialize, TS)] #[serde(rename_all = "camelCase", tag = "type")] @@ -454,7 +454,7 @@ pub(crate) async fn apply_sync_ops( let sync_dir_string = sync_dir.to_string_lossy().to_string(); let db = app_handle.db(); for workspace in upserted_models.workspaces { - let r = match db.get_workspace_meta(&workspace) { + let r = match db.get_workspace_meta(&workspace.id) { Some(m) => { if m.setting_sync_dir == Some(sync_dir_string.clone()) { // We don't need to update if unchanged diff --git a/src-tauri/yaak-ws/src/commands.rs b/src-tauri/yaak-ws/src/commands.rs index 86698eb6..a4da11a6 100644 --- a/src-tauri/yaak-ws/src/commands.rs +++ b/src-tauri/yaak-ws/src/commands.rs @@ -96,7 +96,7 @@ pub(crate) async fn list_connections( workspace_id: &str, app_handle: AppHandle, ) -> Result> { - Ok(app_handle.db().list_websocket_connections_for_workspace(workspace_id)?) + Ok(app_handle.db().list_websocket_connections(workspace_id)?) } #[tauri::command] diff --git a/src-web/commands/commands.tsx b/src-web/commands/commands.tsx index d3d6c869..67082d6c 100644 --- a/src-web/commands/commands.tsx +++ b/src-web/commands/commands.tsx @@ -1,24 +1,25 @@ import type { Folder } from '@yaakapp-internal/models'; +import { createWorkspaceModel } from '@yaakapp-internal/models'; import { applySync, calculateSync } from '@yaakapp-internal/sync'; import { Banner } from '../components/core/Banner'; import { InlineCode } from '../components/core/InlineCode'; import { VStack } from '../components/core/Stacks'; -import { getActiveWorkspaceId } from '../hooks/useActiveWorkspace'; +import { activeWorkspaceIdAtom } from '../hooks/useActiveWorkspace'; import { createFastMutation } from '../hooks/useFastMutation'; import { showConfirm } from '../lib/confirm'; -import { resolvedModelNameWithFolders } from '../lib/resolvedModelName'; +import { jotaiStore } from '../lib/jotai'; import { pluralizeCount } from '../lib/pluralize'; import { showPrompt } from '../lib/prompt'; -import { invokeCmd } from '../lib/tauri'; +import { resolvedModelNameWithFolders } from '../lib/resolvedModelName'; export const createFolder = createFastMutation< - Folder | null, + void, void, Partial> >({ mutationKey: ['create_folder'], mutationFn: async (patch) => { - const workspaceId = getActiveWorkspaceId(); + const workspaceId = jotaiStore.get(activeWorkspaceIdAtom); if (workspaceId == null) { throw new Error("Cannot create folder when there's no active workspace"); } @@ -33,13 +34,13 @@ export const createFolder = createFastMutation< confirmText: 'Create', placeholder: 'Name', }); - if (name == null) return null; + if (name == null) throw new Error('No name provided to create folder'); patch.name = name; } patch.sortPriority = patch.sortPriority || -Date.now(); - return invokeCmd('cmd_update_folder', { folder: { workspaceId, ...patch } }); + await createWorkspaceModel({ model: 'folder', workspaceId, ...patch }); }, }); diff --git a/src-web/commands/deleteWebsocketConnection.ts b/src-web/commands/deleteWebsocketConnection.ts deleted file mode 100644 index 0599c6b9..00000000 --- a/src-web/commands/deleteWebsocketConnection.ts +++ /dev/null @@ -1,10 +0,0 @@ -import type { WebsocketConnection } from '@yaakapp-internal/models'; -import { deleteWebsocketConnection as cmdDeleteWebsocketConnection } from '@yaakapp-internal/ws'; -import { createFastMutation } from '../hooks/useFastMutation'; - -export const deleteWebsocketConnection = createFastMutation({ - mutationKey: ['delete_websocket_connection'], - mutationFn: async function (connection: WebsocketConnection) { - return cmdDeleteWebsocketConnection(connection.id); - }, -}); diff --git a/src-web/commands/deleteWebsocketRequest.tsx b/src-web/commands/deleteWebsocketRequest.tsx deleted file mode 100644 index 8cce263f..00000000 --- a/src-web/commands/deleteWebsocketRequest.tsx +++ /dev/null @@ -1,26 +0,0 @@ -import type { WebsocketRequest } from '@yaakapp-internal/models'; -import { deleteWebsocketRequest as cmdDeleteWebsocketRequest } from '@yaakapp-internal/ws'; -import { InlineCode } from '../components/core/InlineCode'; -import { createFastMutation } from '../hooks/useFastMutation'; -import { showConfirmDelete } from '../lib/confirm'; -import { resolvedModelName } from '../lib/resolvedModelName'; - -export const deleteWebsocketRequest = createFastMutation({ - mutationKey: ['delete_websocket_request'], - mutationFn: async (request: WebsocketRequest) => { - const confirmed = await showConfirmDelete({ - id: 'delete-websocket-request', - title: 'Delete WebSocket Request', - description: ( - <> - Permanently delete {resolvedModelName(request)}? - - ), - }); - if (!confirmed) { - return null; - } - - return cmdDeleteWebsocketRequest(request.id); - }, -}); diff --git a/src-web/commands/duplicateWebsocketRequest.ts b/src-web/commands/duplicateWebsocketRequest.ts deleted file mode 100644 index 867626b5..00000000 --- a/src-web/commands/duplicateWebsocketRequest.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { duplicateWebsocketRequest as cmdDuplicateWebsocketRequest } from '@yaakapp-internal/ws'; -import { createFastMutation } from '../hooks/useFastMutation'; -import { router } from '../lib/router'; - -export const duplicateWebsocketRequest = createFastMutation({ - mutationKey: ['delete_websocket_connection'], - mutationFn: async function (requestId: string) { - return cmdDuplicateWebsocketRequest(requestId); - }, - onSuccess: async (request) => { - await router.navigate({ - to: '/workspaces/$workspaceId', - params: { workspaceId: request.workspaceId }, - search: (prev) => ({ ...prev, request_id: request.id }), - }); - }, -}); diff --git a/src-web/commands/openSettings.ts b/src-web/commands/openSettings.ts index 34e882b3..78cc8115 100644 --- a/src-web/commands/openSettings.ts +++ b/src-web/commands/openSettings.ts @@ -1,13 +1,14 @@ import { SettingsTab } from '../components/Settings/SettingsTab'; -import { getActiveWorkspaceId } from '../hooks/useActiveWorkspace'; +import { activeWorkspaceIdAtom } from '../hooks/useActiveWorkspace'; import { createFastMutation } from '../hooks/useFastMutation'; +import { jotaiStore } from '../lib/jotai'; import { router } from '../lib/router'; import { invokeCmd } from '../lib/tauri'; export const openSettings = createFastMutation({ mutationKey: ['open_settings'], mutationFn: async function (tab) { - const workspaceId = getActiveWorkspaceId(); + const workspaceId = jotaiStore.get(activeWorkspaceIdAtom); if (workspaceId == null) return; const location = router.buildLocation({ diff --git a/src-web/commands/openWorkspaceSettings.tsx b/src-web/commands/openWorkspaceSettings.tsx index 0b90e70d..44b7273d 100644 --- a/src-web/commands/openWorkspaceSettings.tsx +++ b/src-web/commands/openWorkspaceSettings.tsx @@ -1,12 +1,13 @@ import { WorkspaceSettingsDialog } from '../components/WorkspaceSettingsDialog'; -import { getActiveWorkspaceId } from '../hooks/useActiveWorkspace'; +import { activeWorkspaceIdAtom } from '../hooks/useActiveWorkspace'; import { createFastMutation } from '../hooks/useFastMutation'; import { showDialog } from '../lib/dialog'; +import { jotaiStore } from '../lib/jotai'; export const openWorkspaceSettings = createFastMutation({ mutationKey: ['open_workspace_settings'], async mutationFn({ openSyncMenu }) { - const workspaceId = getActiveWorkspaceId(); + const workspaceId = jotaiStore.get(activeWorkspaceIdAtom); showDialog({ id: 'workspace-settings', title: 'Workspace Settings', diff --git a/src-web/commands/upsertWebsocketRequest.ts b/src-web/commands/upsertWebsocketRequest.ts deleted file mode 100644 index 93716939..00000000 --- a/src-web/commands/upsertWebsocketRequest.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { WebsocketRequest } from '@yaakapp-internal/models'; -import { upsertWebsocketRequest as cmdUpsertWebsocketRequest } from '@yaakapp-internal/ws'; -import { differenceInMilliseconds } from 'date-fns'; -import { createFastMutation } from '../hooks/useFastMutation'; -import { router } from '../lib/router'; - -export const upsertWebsocketRequest = createFastMutation< - WebsocketRequest, - void, - Parameters[0] ->({ - mutationKey: ['upsert_websocket_request'], - mutationFn: (request) => cmdUpsertWebsocketRequest(request), - onSuccess: async (request) => { - const isNew = differenceInMilliseconds(new Date(), request.createdAt + 'Z') < 100; - - if (isNew) { - await router.navigate({ - to: '/workspaces/$workspaceId', - params: { workspaceId: request.workspaceId }, - search: (prev) => ({ ...prev, request_id: request.id }), - }); - } - }, -}); diff --git a/src-web/commands/upsertWorkspace.ts b/src-web/commands/upsertWorkspace.ts deleted file mode 100644 index 25ae4025..00000000 --- a/src-web/commands/upsertWorkspace.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { Workspace } from '@yaakapp-internal/models'; -import { createFastMutation } from '../hooks/useFastMutation'; -import { invokeCmd } from '../lib/tauri'; - -export const upsertWorkspace = createFastMutation< - Workspace, - void, - Workspace | Partial> ->({ - mutationKey: ['upsert_workspace'], - mutationFn: (workspace) => invokeCmd('cmd_update_workspace', { workspace }), -}); diff --git a/src-web/commands/upsertWorkspaceMeta.ts b/src-web/commands/upsertWorkspaceMeta.ts deleted file mode 100644 index e98f00e8..00000000 --- a/src-web/commands/upsertWorkspaceMeta.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { WorkspaceMeta } from '@yaakapp-internal/models'; -import { createFastMutation } from '../hooks/useFastMutation'; -import { workspaceMetaAtom } from '../hooks/useWorkspaceMeta'; -import { jotaiStore } from '../lib/jotai'; -import { invokeCmd } from '../lib/tauri'; - -export const upsertWorkspaceMeta = createFastMutation< - WorkspaceMeta, - unknown, - WorkspaceMeta | (Partial> & { workspaceId: string }) ->({ - mutationKey: ['update_workspace_meta'], - mutationFn: async (patch) => { - const workspaceMeta = jotaiStore.get(workspaceMetaAtom); - return invokeCmd('cmd_update_workspace_meta', { - workspaceMeta: { ...workspaceMeta, ...patch }, - }); - }, -}); diff --git a/src-web/components/CommandPaletteDialog.tsx b/src-web/components/CommandPaletteDialog.tsx index 0ff19519..f90c65a9 100644 --- a/src-web/components/CommandPaletteDialog.tsx +++ b/src-web/components/CommandPaletteDialog.tsx @@ -1,5 +1,7 @@ +import { workspacesAtom } from '@yaakapp-internal/models'; import classNames from 'classnames'; import { fuzzyFilter } from 'fuzzbunny'; +import { useAtomValue } from 'jotai/index'; import type { KeyboardEvent, ReactNode } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { createFolder } from '../commands/commands'; @@ -8,26 +10,25 @@ import { switchWorkspace } from '../commands/switchWorkspace'; import { useActiveCookieJar } from '../hooks/useActiveCookieJar'; import { useActiveEnvironment } from '../hooks/useActiveEnvironment'; import { useActiveRequest } from '../hooks/useActiveRequest'; +import { useAllRequests } from '../hooks/useAllRequests'; import { useCreateEnvironment } from '../hooks/useCreateEnvironment'; import { useCreateGrpcRequest } from '../hooks/useCreateGrpcRequest'; import { useCreateHttpRequest } from '../hooks/useCreateHttpRequest'; import { useCreateWorkspace } from '../hooks/useCreateWorkspace'; import { useDebouncedState } from '../hooks/useDebouncedState'; -import { useDeleteAnyRequest } from '../hooks/useDeleteAnyRequest'; -import { useEnvironments } from '../hooks/useEnvironments'; +import { useEnvironmentsBreakdown } from '../hooks/useEnvironmentsBreakdown'; import type { HotkeyAction } from '../hooks/useHotKey'; import { useHotKey } from '../hooks/useHotKey'; import { useHttpRequestActions } from '../hooks/useHttpRequestActions'; import { useRecentEnvironments } from '../hooks/useRecentEnvironments'; import { useRecentRequests } from '../hooks/useRecentRequests'; import { useRecentWorkspaces } from '../hooks/useRecentWorkspaces'; -import { useRenameRequest } from '../hooks/useRenameRequest'; -import { useRequests } from '../hooks/useRequests'; import { useScrollIntoView } from '../hooks/useScrollIntoView'; import { useSendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest'; import { useSidebarHidden } from '../hooks/useSidebarHidden'; -import { useWorkspaces } from '../hooks/useWorkspaces'; +import { deleteModelWithConfirm } from '../lib/deleteModelWithConfirm'; import { showDialog, toggleDialog } from '../lib/dialog'; +import { renameModelWithPrompt } from '../lib/renameModelWithPrompt'; import { resolvedModelNameWithFolders } from '../lib/resolvedModelName'; import { router } from '../lib/router'; import { setWorkspaceSearchParams } from '../lib/setWorkspaceSearchParams'; @@ -60,23 +61,20 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) { const [selectedItemKey, setSelectedItemKey] = useState(null); const activeEnvironment = useActiveEnvironment(); const httpRequestActions = useHttpRequestActions(); - const workspaces = useWorkspaces(); - const { subEnvironments } = useEnvironments(); + const workspaces = useAtomValue(workspacesAtom); + const { baseEnvironment, subEnvironments } = useEnvironmentsBreakdown(); const createWorkspace = useCreateWorkspace(); const recentEnvironments = useRecentEnvironments(); const recentWorkspaces = useRecentWorkspaces(); - const requests = useRequests(); + const requests = useAllRequests(); const activeRequest = useActiveRequest(); const activeCookieJar = useActiveCookieJar(); const [recentRequests] = useRecentRequests(); const [, setSidebarHidden] = useSidebarHidden(); - const { baseEnvironment } = useEnvironments(); const { mutate: createHttpRequest } = useCreateHttpRequest(); const { mutate: createGrpcRequest } = useCreateGrpcRequest(); const { mutate: createEnvironment } = useCreateEnvironment(); const { mutate: sendRequest } = useSendAnyHttpRequest(); - const { mutate: renameRequest } = useRenameRequest(activeRequest?.id ?? null); - const { mutate: deleteRequest } = useDeleteAnyRequest(); const workspaceCommands = useMemo(() => { const commands: CommandPaletteItem[] = [ @@ -166,13 +164,13 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) { commands.push({ key: 'http_request.rename', label: 'Rename Request', - onSelect: renameRequest, + onSelect: () => renameModelWithPrompt(activeRequest), }); commands.push({ - key: 'http_request.delete', + key: 'sidebar.delete_selected_item', label: 'Delete Request', - onSelect: () => deleteRequest(activeRequest.id), + onSelect: () => deleteModelWithConfirm(activeRequest), }); } @@ -190,9 +188,7 @@ export function CommandPaletteDialog({ onClose }: { onClose: () => void }) { createGrpcRequest, createHttpRequest, createWorkspace, - deleteRequest, httpRequestActions, - renameRequest, sendRequest, setSidebarHidden, ]); diff --git a/src-web/components/CookieDialog.tsx b/src-web/components/CookieDialog.tsx index 9fc177f4..5777c033 100644 --- a/src-web/components/CookieDialog.tsx +++ b/src-web/components/CookieDialog.tsx @@ -1,6 +1,6 @@ -import type { Cookie } from '@yaakapp-internal/models'; -import { useCookieJars } from '../hooks/useCookieJars'; -import { useUpdateCookieJar } from '../hooks/useUpdateCookieJar'; +import type { Cookie} from '@yaakapp-internal/models'; +import { cookieJarsAtom, patchModel } from '@yaakapp-internal/models'; +import { useAtomValue } from 'jotai'; import { cookieDomain } from '../lib/model_util'; import { Banner } from './core/Banner'; import { IconButton } from './core/IconButton'; @@ -11,8 +11,7 @@ interface Props { } export const CookieDialog = function ({ cookieJarId }: Props) { - const updateCookieJar = useUpdateCookieJar(cookieJarId ?? null); - const cookieJars = useCookieJars(); + const cookieJars = useAtomValue(cookieJarsAtom); const cookieJar = cookieJars?.find((c) => c.id === cookieJarId); if (cookieJar == null) { @@ -39,7 +38,7 @@ export const CookieDialog = function ({ cookieJarId }: Props) { {cookieJar?.cookies.map((c: Cookie) => ( - + {cookieDomain(c)} @@ -53,12 +52,11 @@ export const CookieDialog = function ({ cookieJarId }: Props) { iconSize="sm" title="Delete" className="ml-auto" - onClick={async () => { - await updateCookieJar.mutateAsync({ - ...cookieJar, + onClick={() => + patchModel(cookieJar, { cookies: cookieJar.cookies.filter((c2: Cookie) => c2 !== c), - }); - }} + }) + } /> diff --git a/src-web/components/CookieDropdown.tsx b/src-web/components/CookieDropdown.tsx index b57a4eb1..1f6708b6 100644 --- a/src-web/components/CookieDropdown.tsx +++ b/src-web/components/CookieDropdown.tsx @@ -1,10 +1,9 @@ +import { cookieJarsAtom, patchModel } from '@yaakapp-internal/models'; import { useAtomValue } from 'jotai'; import { memo, useMemo } from 'react'; import { useActiveCookieJar } from '../hooks/useActiveCookieJar'; -import { cookieJarsAtom } from '../hooks/useCookieJars'; import { useCreateCookieJar } from '../hooks/useCreateCookieJar'; -import { useDeleteCookieJar } from '../hooks/useDeleteCookieJar'; -import { useUpdateCookieJar } from '../hooks/useUpdateCookieJar'; +import { deleteModelWithConfirm } from '../lib/deleteModelWithConfirm'; import { showDialog } from '../lib/dialog'; import { showPrompt } from '../lib/prompt'; import { setWorkspaceSearchParams } from '../lib/setWorkspaceSearchParams'; @@ -16,8 +15,6 @@ import { InlineCode } from './core/InlineCode'; export const CookieDropdown = memo(function CookieDropdown() { const activeCookieJar = useActiveCookieJar(); - const updateCookieJar = useUpdateCookieJar(activeCookieJar?.id ?? null); - const deleteCookieJar = useDeleteCookieJar(activeCookieJar ?? null); const createCookieJar = useCreateCookieJar(); const cookieJars = useAtomValue(cookieJarsAtom); @@ -67,7 +64,7 @@ export const CookieDropdown = memo(function CookieDropdown() { defaultValue: activeCookieJar?.name, }); if (name == null) return; - updateCookieJar.mutate({ name }); + await patchModel(activeCookieJar, { name }); }, }, ...(((cookieJars ?? []).length > 1 // Never delete the last one @@ -76,7 +73,9 @@ export const CookieDropdown = memo(function CookieDropdown() { label: 'Delete', leftSlot: , color: 'danger', - onSelect: deleteCookieJar.mutate, + onSelect: async () => { + await deleteModelWithConfirm(activeCookieJar); + }, }, ] : []) as DropdownItem[]), @@ -90,7 +89,7 @@ export const CookieDropdown = memo(function CookieDropdown() { onSelect: () => createCookieJar.mutate(), }, ]; - }, [activeCookieJar, cookieJars, createCookieJar, deleteCookieJar, updateCookieJar]); + }, [activeCookieJar, cookieJars, createCookieJar]); return ( diff --git a/src-web/components/CreateWorkspaceDialog.tsx b/src-web/components/CreateWorkspaceDialog.tsx index 887f617a..86b376ae 100644 --- a/src-web/components/CreateWorkspaceDialog.tsx +++ b/src-web/components/CreateWorkspaceDialog.tsx @@ -1,8 +1,7 @@ import { useGitInit } from '@yaakapp-internal/git'; import type { WorkspaceMeta } from '@yaakapp-internal/models'; +import { createGlobalModel, patchModel } from '@yaakapp-internal/models'; import { useState } from 'react'; -import { upsertWorkspace } from '../commands/upsertWorkspace'; -import { upsertWorkspaceMeta } from '../commands/upsertWorkspaceMeta'; import { router } from '../lib/router'; import { invokeCmd } from '../lib/tauri'; import { showErrorToast } from '../lib/toast'; @@ -31,16 +30,15 @@ export function CreateWorkspaceDialog({ hide }: Props) { className="pb-3 max-h-[50vh]" onSubmit={async (e) => { e.preventDefault(); - const workspace = await upsertWorkspace.mutateAsync({ name }); - if (workspace == null) return; + const workspaceId = await createGlobalModel({ model: 'workspace', name }); + if (workspaceId == null) return; // Do getWorkspaceMeta instead of naively creating one because it might have // been created already when the store refreshes the workspace meta after const workspaceMeta = await invokeCmd('cmd_get_workspace_meta', { - workspaceId: workspace.id, + workspaceId, }); - await upsertWorkspaceMeta.mutateAsync({ - ...workspaceMeta, + await patchModel(workspaceMeta, { settingSyncDir: syncConfig.filePath, }); @@ -53,7 +51,7 @@ export function CreateWorkspaceDialog({ hide }: Props) { // Navigate to workspace await router.navigate({ to: '/workspaces/$workspaceId', - params: { workspaceId: workspace.id }, + params: { workspaceId }, }); hide(); diff --git a/src-web/components/DynamicForm.tsx b/src-web/components/DynamicForm.tsx index 6609a111..71cc65cc 100644 --- a/src-web/components/DynamicForm.tsx +++ b/src-web/components/DynamicForm.tsx @@ -1,4 +1,5 @@ import type { Folder, HttpRequest } from '@yaakapp-internal/models'; +import { foldersAtom, httpRequestsAtom } from '@yaakapp-internal/models'; import type { FormInput, FormInputCheckbox, @@ -10,10 +11,9 @@ import type { JsonPrimitive, } from '@yaakapp-internal/plugins'; import classNames from 'classnames'; +import { useAtomValue } from 'jotai/index'; import { useCallback } from 'react'; import { useActiveRequest } from '../hooks/useActiveRequest'; -import { useFolders } from '../hooks/useFolders'; -import { useHttpRequests } from '../hooks/useHttpRequests'; import { capitalize } from '../lib/capitalize'; import { resolvedModelName } from '../lib/resolvedModelName'; import { Banner } from './core/Banner'; @@ -354,8 +354,8 @@ function HttpRequestArg({ value: string; onChange: (v: string) => void; }) { - const folders = useFolders(); - const httpRequests = useHttpRequests(); + const folders = useAtomValue(foldersAtom); + const httpRequests = useAtomValue(httpRequestsAtom); const activeRequest = useActiveRequest(); return ( { - if (folderId == null) return; - updateFolder({ id: folderId, update: (folder) => ({ ...folder, name }) }); - }} + onChange={(name) => patchModel(folder, { name })} stateKey={`name.${folder.id}`} /> @@ -33,13 +29,7 @@ export function FolderSettingsDialog({ folderId }: Props) { className="min-h-[10rem] border border-border px-2" defaultValue={folder.description} stateKey={`description.${folder.id}`} - onChange={(description) => { - if (folderId == null) return; - updateFolder({ - id: folderId, - update: (folder) => ({ ...folder, description }), - }); - }} + onChange={(description) => patchModel(folder, { description })} /> ); diff --git a/src-web/components/GitDropdown.tsx b/src-web/components/GitDropdown.tsx index c7e53074..ddd6f1e4 100644 --- a/src-web/components/GitDropdown.tsx +++ b/src-web/components/GitDropdown.tsx @@ -1,12 +1,12 @@ import { useGit } from '@yaakapp-internal/git'; import type { WorkspaceMeta } from '@yaakapp-internal/models'; import classNames from 'classnames'; +import { useAtomValue } from 'jotai'; import type { HTMLAttributes } from 'react'; import { forwardRef } from 'react'; import { openWorkspaceSettings } from '../commands/openWorkspaceSettings'; -import { useActiveWorkspace } from '../hooks/useActiveWorkspace'; +import { activeWorkspaceAtom, activeWorkspaceMetaAtom } from '../hooks/useActiveWorkspace'; import { useKeyValue } from '../hooks/useKeyValue'; -import { useWorkspaceMeta } from '../hooks/useWorkspaceMeta'; import { sync } from '../init/sync'; import { showConfirm, showConfirmDelete } from '../lib/confirm'; import { showDialog } from '../lib/dialog'; @@ -22,7 +22,7 @@ import { HistoryDialog } from './git/HistoryDialog'; import { GitCommitDialog } from './GitCommitDialog'; export function GitDropdown() { - const workspaceMeta = useWorkspaceMeta(); + const workspaceMeta = useAtomValue(activeWorkspaceMetaAtom); if (workspaceMeta == null) return null; if (workspaceMeta.settingSyncDir == null) { @@ -33,7 +33,7 @@ export function GitDropdown() { } function SyncDropdownWithSyncDir({ syncDir }: { syncDir: string }) { - const workspace = useActiveWorkspace(); + const workspace = useAtomValue(activeWorkspaceAtom); const [ { status, log }, { branch, deleteBranch, fetchAll, mergeBranch, push, pull, checkout, init }, diff --git a/src-web/components/GlobalHooks.tsx b/src-web/components/GlobalHooks.tsx index 3db75491..2aff3fa0 100644 --- a/src-web/components/GlobalHooks.tsx +++ b/src-web/components/GlobalHooks.tsx @@ -8,7 +8,6 @@ import { useSubscribeHttpAuthentication } from '../hooks/useHttpAuthentication'; import { useListenToTauriEvent } from '../hooks/useListenToTauriEvent'; import { useNotificationToast } from '../hooks/useNotificationToast'; import { useSyncFontSizeSetting } from '../hooks/useSyncFontSizeSetting'; -import { useSyncModelStores } from '../hooks/useSyncModelStores'; import { useSyncWorkspaceChildModels } from '../hooks/useSyncWorkspaceChildModels'; import { useSyncZoomSetting } from '../hooks/useSyncZoomSetting'; import { useSubscribeTemplateFunctions } from '../hooks/useTemplateFunctions'; @@ -17,7 +16,6 @@ import { showPrompt } from '../lib/prompt'; import { showToast } from '../lib/toast'; export function GlobalHooks() { - useSyncModelStores(); useSyncZoomSetting(); useSyncFontSizeSetting(); useGenerateThemeCss(); diff --git a/src-web/components/GraphQLEditor.tsx b/src-web/components/GraphQLEditor.tsx index aac0b28c..681eec00 100644 --- a/src-web/components/GraphQLEditor.tsx +++ b/src-web/components/GraphQLEditor.tsx @@ -3,9 +3,10 @@ import { updateSchema } from 'cm6-graphql'; import type { EditorView } from 'codemirror'; import { formatSdl } from 'format-graphql'; -import { useEffect, useMemo, useRef, useState } from 'react'; +import { useEffect, useMemo, useRef } from 'react'; import { useLocalStorage } from 'react-use'; import { useIntrospectGraphQL } from '../hooks/useIntrospectGraphQL'; +import { useStateWithDeps } from '../hooks/useStateWithDeps'; import { showDialog } from '../lib/dialog'; import { Banner } from './core/Banner'; import { Button } from './core/Button'; @@ -30,19 +31,20 @@ export function GraphQLEditor({ request, onChange, baseRequest, ...extraEditorPr const { schema, isLoading, error, refetch, clear } = useIntrospectGraphQL(baseRequest, { disabled: autoIntrospectDisabled?.[baseRequest.id], }); - const [currentBody, setCurrentBody] = useState<{ query: string; variables: string | undefined }>( - () => { - // Migrate text bodies to GraphQL format - // NOTE: This is how GraphQL used to be stored - if ('text' in request.body) { - const b = tryParseJson(request.body.text, {}); - const variables = JSON.stringify(b.variables || undefined, null, 2); - return { query: b.query ?? '', variables }; - } + const [currentBody, setCurrentBody] = useStateWithDeps<{ + query: string; + variables: string | undefined; + }>(() => { + // Migrate text bodies to GraphQL format + // NOTE: This is how GraphQL used to be stored + if ('text' in request.body) { + const b = tryParseJson(request.body.text, {}); + const variables = JSON.stringify(b.variables || undefined, null, 2); + return { query: b.query ?? '', variables }; + } - return { query: request.body.query ?? '', variables: request.body.variables ?? '' }; - }, - ); + return { query: request.body.query ?? '', variables: request.body.variables ?? '' }; + }, [extraEditorProps.forceUpdateKey]); const handleChangeQuery = (query: string) => { const newBody = { query, variables: currentBody.variables || undefined }; diff --git a/src-web/components/GrpcConnectionLayout.tsx b/src-web/components/GrpcConnectionLayout.tsx index 32e4d7a1..7004640c 100644 --- a/src-web/components/GrpcConnectionLayout.tsx +++ b/src-web/components/GrpcConnectionLayout.tsx @@ -1,17 +1,17 @@ +import { patchModel } from '@yaakapp-internal/models'; import classNames from 'classnames'; +import { useAtomValue } from 'jotai'; import type { CSSProperties } from 'react'; import React, { useEffect, useMemo } from 'react'; import { useActiveRequest } from '../hooks/useActiveRequest'; import { useGrpc } from '../hooks/useGrpc'; -import { useGrpcConnections } from '../hooks/useGrpcConnections'; -import { useGrpcEvents } from '../hooks/useGrpcEvents'; import { useGrpcProtoFiles } from '../hooks/useGrpcProtoFiles'; -import { useUpdateAnyGrpcRequest } from '../hooks/useUpdateAnyGrpcRequest'; +import { activeGrpcConnectionAtom, useGrpcEvents } from '../hooks/usePinnedGrpcConnection'; import { Banner } from './core/Banner'; import { HotKeyList } from './core/HotKeyList'; import { SplitLayout } from './core/SplitLayout'; -import { GrpcConnectionMessagesPane } from './GrpcConnectionMessagesPane'; -import { GrpcConnectionSetupPane } from './GrpcConnectionSetupPane'; +import { GrpcRequestPane } from './GrpcRequestPane'; +import { GrpcResponsePane } from './GrpcResponsePane'; interface Props { style: CSSProperties; @@ -21,10 +21,8 @@ const emptyArray: string[] = []; export function GrpcConnectionLayout({ style }: Props) { const activeRequest = useActiveRequest('grpc_request'); - const updateRequest = useUpdateAnyGrpcRequest(); - const connections = useGrpcConnections().filter((c) => c.requestId === activeRequest?.id); - const activeConnection = connections[0] ?? null; - const messages = useGrpcEvents(activeConnection?.id ?? null); + const activeConnection = useAtomValue(activeGrpcConnectionAtom); + const grpcEvents = useGrpcEvents(activeConnection?.id ?? null); const protoFilesKv = useGrpcProtoFiles(activeRequest?.id ?? null); const protoFiles = protoFilesKv.value ?? emptyArray; const grpc = useGrpc(activeRequest, activeConnection, protoFiles); @@ -34,25 +32,21 @@ export function GrpcConnectionLayout({ style }: Props) { if (services == null || activeRequest == null) return; const s = services.find((s) => s.name === activeRequest.service); if (s == null) { - updateRequest.mutate({ - id: activeRequest.id, - update: { - service: services[0]?.name ?? null, - method: services[0]?.methods[0]?.name ?? null, - }, - }); + patchModel(activeRequest, { + service: services[0]?.name ?? null, + method: services[0]?.methods[0]?.name ?? null, + }).catch(console.error); return; } const m = s.methods.find((m) => m.name === activeRequest.method); if (m == null) { - updateRequest.mutate({ - id: activeRequest.id, - update: { method: s.methods[0]?.name ?? null }, - }); + patchModel(activeRequest, { + method: s.methods[0]?.name ?? null, + }).catch(console.error); return; } - }, [activeRequest, services, updateRequest]); + }, [activeRequest, services]); const activeMethod = useMemo(() => { if (services == null || activeRequest == null) return null; @@ -87,7 +81,7 @@ export function GrpcConnectionLayout({ style }: Props) { className="p-3 gap-1.5" style={style} firstSlot={({ style }) => ( - {grpc.go.error} - ) : messages.length >= 0 ? ( - + ) : grpcEvents.length >= 0 ? ( + ) : ( )} diff --git a/src-web/components/GrpcEditor.tsx b/src-web/components/GrpcEditor.tsx index f2c8d432..09e111aa 100644 --- a/src-web/components/GrpcEditor.tsx +++ b/src-web/components/GrpcEditor.tsx @@ -21,7 +21,7 @@ import { Editor } from './core/Editor/Editor'; import { FormattedError } from './core/FormattedError'; import { InlineCode } from './core/InlineCode'; import { VStack } from './core/Stacks'; -import { GrpcProtoSelection } from './GrpcProtoSelection'; +import { GrpcProtoSelectionDialog } from './GrpcProtoSelectionDialog'; type Props = Pick & { services: ReflectResponseService[] | null; @@ -143,13 +143,7 @@ export function GrpcEditor({ title: 'Configure Schema', size: 'md', id: 'reflection-failed', - render: ({ hide }) => { - return ( - - - - ); - }, + render: ({ hide }) => , }); }} > @@ -167,14 +161,7 @@ export function GrpcEditor({ , ], - [ - protoFiles.length, - reflectionError, - reflectionLoading, - reflectionUnavailable, - request.id, - services, - ], + [protoFiles.length, reflectionError, reflectionLoading, reflectionUnavailable, services], ); return ( diff --git a/src-web/components/GrpcProtoSelection.tsx b/src-web/components/GrpcProtoSelectionDialog.tsx similarity index 90% rename from src-web/components/GrpcProtoSelection.tsx rename to src-web/components/GrpcProtoSelectionDialog.tsx index b14f6686..8b6a230f 100644 --- a/src-web/components/GrpcProtoSelection.tsx +++ b/src-web/components/GrpcProtoSelectionDialog.tsx @@ -1,7 +1,8 @@ import { open } from '@tauri-apps/plugin-dialog'; +import type { GrpcRequest } from '@yaakapp-internal/models'; +import { useActiveRequest } from '../hooks/useActiveRequest'; import { useGrpc } from '../hooks/useGrpc'; import { useGrpcProtoFiles } from '../hooks/useGrpcProtoFiles'; -import { useGrpcRequest } from '../hooks/useGrpcRequest'; import { pluralizeCount } from '../lib/pluralize'; import { Banner } from './core/Banner'; import { Button } from './core/Button'; @@ -11,13 +12,18 @@ import { Link } from './core/Link'; import { HStack, VStack } from './core/Stacks'; interface Props { - requestId: string; onDone: () => void; } -export function GrpcProtoSelection({ requestId }: Props) { - const request = useGrpcRequest(requestId); - const protoFilesKv = useGrpcProtoFiles(requestId); +export function GrpcProtoSelectionDialog(props: Props) { + const request = useActiveRequest(); + if (request?.model !== 'grpc_request') return null; + + return GrpcProtoSelectionDialogWithRequest({ ...props, request }); +} + +function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: GrpcRequest }) { + const protoFilesKv = useGrpcProtoFiles(request.id); const protoFiles = protoFilesKv.value ?? []; const grpc = useGrpc(request, null, protoFiles); const services = grpc.reflect.data; @@ -34,7 +40,7 @@ export function GrpcProtoSelection({ requestId }: Props) { } return ( - + {/* Buttons on top so they get focus first */} )} diff --git a/src-web/components/Settings/SettingsProxy.tsx b/src-web/components/Settings/SettingsProxy.tsx index 8409c03d..f6c9bf1e 100644 --- a/src-web/components/Settings/SettingsProxy.tsx +++ b/src-web/components/Settings/SettingsProxy.tsx @@ -1,6 +1,6 @@ +import { patchModel, settingsAtom } from '@yaakapp-internal/models'; +import { useAtomValue } from 'jotai'; import React from 'react'; -import { useSettings } from '../../hooks/useSettings'; -import { useUpdateSettings } from '../../hooks/useUpdateSettings'; import { Checkbox } from '../core/Checkbox'; import { PlainInput } from '../core/PlainInput'; import { Select } from '../core/Select'; @@ -8,8 +8,7 @@ import { Separator } from '../core/Separator'; import { HStack, VStack } from '../core/Stacks'; export function SettingsProxy() { - const settings = useSettings(); - const updateSettings = useUpdateSettings(); + const settings = useAtomValue(settingsAtom); return ( @@ -19,11 +18,11 @@ export function SettingsProxy() { hideLabel size="sm" value={settings.proxy?.type ?? 'automatic'} - onChange={(v) => { + onChange={async (v) => { if (v === 'automatic') { - updateSettings.mutate({ proxy: undefined }); + await patchModel(settings, { proxy: undefined }); } else if (v === 'enabled') { - updateSettings.mutate({ + await patchModel(settings, { proxy: { type: 'enabled', http: '', @@ -32,7 +31,7 @@ export function SettingsProxy() { }, }); } else { - updateSettings.mutate({ proxy: { type: 'disabled' } }); + await patchModel(settings, { proxy: { type: 'disabled' } }); } }} options={[ @@ -49,10 +48,10 @@ export function SettingsProxy() { label="HTTP" placeholder="localhost:9090" defaultValue={settings.proxy?.http} - onChange={(http) => { + onChange={async (http) => { const https = settings.proxy?.type === 'enabled' ? settings.proxy.https : ''; const auth = settings.proxy?.type === 'enabled' ? settings.proxy.auth : null; - updateSettings.mutate({ proxy: { type: 'enabled', http, https, auth } }); + await patchModel(settings, { proxy: { type: 'enabled', http, https, auth } }); }} /> { + onChange={async (https) => { const http = settings.proxy?.type === 'enabled' ? settings.proxy.http : ''; const auth = settings.proxy?.type === 'enabled' ? settings.proxy.auth : null; - updateSettings.mutate({ proxy: { type: 'enabled', http, https, auth } }); + await patchModel(settings, { proxy: { type: 'enabled', http, https, auth } }); }} /> @@ -71,11 +70,11 @@ export function SettingsProxy() { { + onChange={async (enabled) => { const http = settings.proxy?.type === 'enabled' ? settings.proxy.http : ''; const https = settings.proxy?.type === 'enabled' ? settings.proxy.https : ''; const auth = enabled ? { user: '', password: '' } : null; - updateSettings.mutate({ proxy: { type: 'enabled', http, https, auth } }); + await patchModel(settings, { proxy: { type: 'enabled', http, https, auth } }); }} /> @@ -87,13 +86,13 @@ export function SettingsProxy() { label="User" placeholder="myUser" defaultValue={settings.proxy.auth.user} - onChange={(user) => { + onChange={async (user) => { const https = settings.proxy?.type === 'enabled' ? settings.proxy.https : ''; const http = settings.proxy?.type === 'enabled' ? settings.proxy.http : ''; const password = settings.proxy?.type === 'enabled' ? (settings.proxy.auth?.password ?? '') : ''; const auth = { user, password }; - updateSettings.mutate({ proxy: { type: 'enabled', http, https, auth } }); + await patchModel(settings, { proxy: { type: 'enabled', http, https, auth } }); }} /> { + onChange={async (password) => { const https = settings.proxy?.type === 'enabled' ? settings.proxy.https : ''; const http = settings.proxy?.type === 'enabled' ? settings.proxy.http : ''; const user = settings.proxy?.type === 'enabled' ? (settings.proxy.auth?.user ?? '') : ''; const auth = { user, password }; - updateSettings.mutate({ proxy: { type: 'enabled', http, https, auth } }); + await patchModel(settings, { proxy: { type: 'enabled', http, https, auth } }); }} /> diff --git a/src-web/components/SwitchWorkspaceDialog.tsx b/src-web/components/SwitchWorkspaceDialog.tsx index aa7b384f..ef1849b6 100644 --- a/src-web/components/SwitchWorkspaceDialog.tsx +++ b/src-web/components/SwitchWorkspaceDialog.tsx @@ -1,8 +1,8 @@ import type { Workspace } from '@yaakapp-internal/models'; +import { patchModel, settingsAtom } from '@yaakapp-internal/models'; +import { useAtomValue } from 'jotai'; import { useState } from 'react'; import { switchWorkspace } from '../commands/switchWorkspace'; -import { useSettings } from '../hooks/useSettings'; -import { useUpdateSettings } from '../hooks/useUpdateSettings'; import { Button } from './core/Button'; import { Checkbox } from './core/Checkbox'; import { Icon } from './core/Icon'; @@ -15,8 +15,7 @@ interface Props { } export function SwitchWorkspaceDialog({ hide, workspace }: Props) { - const settings = useSettings(); - const updateSettings = useUpdateSettings(); + const settings = useAtomValue(settingsAtom); const [remember, setRemember] = useState(false); return ( @@ -28,11 +27,11 @@ export function SwitchWorkspaceDialog({ hide, workspace }: Props) {