@scalar/api-client 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -0
- package/README.md +41 -0
- package/dist/components/HttpMethod/HttpMethod.vue.d.ts +2 -2
- package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.d.ts +2 -2
- package/dist/plugins/posthog/index.d.ts +23 -0
- package/dist/plugins/posthog/index.d.ts.map +1 -0
- package/dist/plugins/posthog/index.js +58 -0
- package/dist/plugins/posthog/index.js.map +1 -0
- package/dist/style.css +121 -61
- package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/OperationBlock.vue.js.map +1 -1
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js +15 -12
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/decode-buffer.d.ts +5 -2
- package/dist/v2/blocks/operation-block/helpers/decode-buffer.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/decode-buffer.js +5 -2
- package/dist/v2/blocks/operation-block/helpers/decode-buffer.js.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/har-to-fetch-request.d.ts +8 -9
- package/dist/v2/blocks/operation-block/helpers/har-to-fetch-request.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/har-to-fetch-request.js +8 -10
- package/dist/v2/blocks/operation-block/helpers/har-to-fetch-request.js.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/response-cache.d.ts +2 -1
- package/dist/v2/blocks/operation-block/helpers/response-cache.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/response-cache.js.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/send-request.d.ts +11 -3
- package/dist/v2/blocks/operation-block/helpers/send-request.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/send-request.js +19 -12
- package/dist/v2/blocks/operation-block/helpers/send-request.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.d.ts.map +1 -1
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.js +1 -1
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.script.js +4 -0
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.script.js +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.js +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js +1 -0
- package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js +1 -0
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/helpers/get-default-headers.js +1 -1
- package/dist/v2/blocks/response-block/ResponseBlock.vue.d.ts +3 -2
- package/dist/v2/blocks/response-block/ResponseBlock.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/ResponseBlock.vue.js +1 -1
- package/dist/v2/blocks/response-block/ResponseBlock.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/ResponseBlock.vue.script.js +12 -6
- package/dist/v2/blocks/response-block/ResponseBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBody.vue.d.ts +2 -0
- package/dist/v2/blocks/response-block/components/ResponseBody.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBody.vue.js +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBody.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBody.vue.script.js +34 -14
- package/dist/v2/blocks/response-block/components/ResponseBody.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/helpers/process-response-body.d.ts +1 -1
- package/dist/v2/blocks/response-block/helpers/process-response-body.js +2 -3
- package/dist/v2/blocks/response-block/helpers/process-response-body.js.map +1 -1
- package/dist/v2/blocks/response-block/helpers/resolve-response-body-handler.d.ts +11 -0
- package/dist/v2/blocks/response-block/helpers/resolve-response-body-handler.d.ts.map +1 -0
- package/dist/v2/blocks/response-block/helpers/resolve-response-body-handler.js +44 -0
- package/dist/v2/blocks/response-block/helpers/resolve-response-body-handler.js.map +1 -0
- package/dist/v2/blocks/response-block/helpers/resolve-response-content-type.d.ts +14 -0
- package/dist/v2/blocks/response-block/helpers/resolve-response-content-type.d.ts.map +1 -0
- package/dist/v2/blocks/response-block/helpers/resolve-response-content-type.js +13 -0
- package/dist/v2/blocks/response-block/helpers/resolve-response-content-type.js.map +1 -0
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.script.js +3 -3
- package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js +131 -48
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.d.ts +2 -2
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/extract-security-scheme-secrets.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts +16 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js +43 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js.map +1 -1
- package/dist/v2/components/code-input/CodeInput.vue.d.ts +6 -2
- package/dist/v2/components/code-input/CodeInput.vue.d.ts.map +1 -1
- package/dist/v2/components/code-input/CodeInput.vue.js +1 -1
- package/dist/v2/components/code-input/CodeInput.vue.js.map +1 -1
- package/dist/v2/components/code-input/CodeInput.vue.script.js +9 -4
- package/dist/v2/components/code-input/CodeInput.vue.script.js.map +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.d.ts +3 -0
- package/dist/v2/components/data-table/DataTableInput.vue.d.ts.map +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.js +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.js.map +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.script.js +7 -1
- package/dist/v2/components/data-table/DataTableInput.vue.script.js.map +1 -1
- package/dist/v2/components/forms/ConfirmationForm.vue.d.ts +2 -2
- package/dist/v2/constants.js +1 -1
- package/dist/v2/features/app/App.vue.d.ts.map +1 -1
- package/dist/v2/features/app/App.vue.js.map +1 -1
- package/dist/v2/features/app/App.vue.script.js +17 -4
- package/dist/v2/features/app/App.vue.script.js.map +1 -1
- package/dist/v2/features/app/app-state.d.ts +6 -1
- package/dist/v2/features/app/app-state.d.ts.map +1 -1
- package/dist/v2/features/app/app-state.js +5 -3
- package/dist/v2/features/app/app-state.js.map +1 -1
- package/dist/v2/features/app/components/DesktopTab.vue.d.ts +2 -2
- package/dist/v2/features/app/helpers/create-api-client-app.d.ts +9 -1
- package/dist/v2/features/app/helpers/create-api-client-app.d.ts.map +1 -1
- package/dist/v2/features/app/helpers/create-api-client-app.js +3 -2
- package/dist/v2/features/app/helpers/create-api-client-app.js.map +1 -1
- package/dist/v2/features/app/helpers/create-temp-operation.d.ts.map +1 -1
- package/dist/v2/features/app/helpers/create-temp-operation.js +4 -1
- package/dist/v2/features/app/helpers/create-temp-operation.js.map +1 -1
- package/dist/v2/features/app/helpers/routes.d.ts +4 -2
- package/dist/v2/features/app/helpers/routes.d.ts.map +1 -1
- package/dist/v2/features/app/helpers/routes.js.map +1 -1
- package/dist/v2/features/collection/DocumentCollection.vue.script.js +2 -1
- package/dist/v2/features/collection/DocumentCollection.vue.script.js.map +1 -1
- package/dist/v2/features/collection/OperationCollection.vue.script.js +2 -1
- package/dist/v2/features/collection/OperationCollection.vue.script.js.map +1 -1
- package/dist/v2/features/collection/WorkspaceCollection.vue.script.js +2 -1
- package/dist/v2/features/collection/WorkspaceCollection.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Authentication.vue.d.ts.map +1 -1
- package/dist/v2/features/collection/components/Authentication.vue.js +1 -1
- package/dist/v2/features/collection/components/Authentication.vue.js.map +1 -1
- package/dist/v2/features/collection/components/Authentication.vue.script.js +10 -1
- package/dist/v2/features/collection/components/Authentication.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Cookies.vue.script.js +1 -0
- package/dist/v2/features/collection/components/Cookies.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Editor/Editor.vue.script.js +1 -0
- package/dist/v2/features/collection/components/Editor/Editor.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Environment.vue.script.js +1 -0
- package/dist/v2/features/collection/components/Environment.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Form.vue.d.ts +2 -0
- package/dist/v2/features/collection/components/Form.vue.d.ts.map +1 -1
- package/dist/v2/features/collection/components/Form.vue.js.map +1 -1
- package/dist/v2/features/collection/components/Form.vue.script.js +4 -1
- package/dist/v2/features/collection/components/Form.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/LabelInput.vue.d.ts +1 -1
- package/dist/v2/features/collection/components/Overview.vue.script.js +1 -0
- package/dist/v2/features/collection/components/Overview.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Runner/components/Runner.vue.d.ts.map +1 -1
- package/dist/v2/features/collection/components/Runner/components/Runner.vue.js.map +1 -1
- package/dist/v2/features/collection/components/Runner/components/Runner.vue.script.js +4 -2
- package/dist/v2/features/collection/components/Runner/components/Runner.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Runner/components/RunnerTree.vue.d.ts +2 -2
- package/dist/v2/features/collection/components/Runner/hooks/use-runner-execution.d.ts +4 -2
- package/dist/v2/features/collection/components/Runner/hooks/use-runner-execution.d.ts.map +1 -1
- package/dist/v2/features/collection/components/Runner/hooks/use-runner-execution.js +3 -2
- package/dist/v2/features/collection/components/Runner/hooks/use-runner-execution.js.map +1 -1
- package/dist/v2/features/collection/components/Scripts.vue.script.js +1 -0
- package/dist/v2/features/collection/components/Scripts.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Servers.vue.d.ts.map +1 -1
- package/dist/v2/features/collection/components/Servers.vue.js.map +1 -1
- package/dist/v2/features/collection/components/Servers.vue.script.js +3 -1
- package/dist/v2/features/collection/components/Servers.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Settings.vue.script.js +1 -0
- package/dist/v2/features/collection/components/Settings.vue.script.js.map +1 -1
- package/dist/v2/features/command-palette/components/CommandActionForm.vue.d.ts +2 -2
- package/dist/v2/features/command-palette/components/CommandPaletteImport.vue.d.ts.map +1 -1
- package/dist/v2/features/command-palette/components/CommandPaletteImport.vue.js.map +1 -1
- package/dist/v2/features/command-palette/components/CommandPaletteImport.vue.script.js +1 -1
- package/dist/v2/features/command-palette/components/CommandPaletteImport.vue.script.js.map +1 -1
- package/dist/v2/features/command-palette/components/CommandPaletteImportPostman.vue.d.ts.map +1 -1
- package/dist/v2/features/command-palette/components/CommandPaletteImportPostman.vue.js.map +1 -1
- package/dist/v2/features/command-palette/components/CommandPaletteImportPostman.vue.script.js +26 -21
- package/dist/v2/features/command-palette/components/CommandPaletteImportPostman.vue.script.js.map +1 -1
- package/dist/v2/features/command-palette/components/PostmanImportPreview.vue.js +1 -1
- package/dist/v2/features/command-palette/components/PostmanImportPreview.vue.js.map +1 -1
- package/dist/v2/features/command-palette/components/PostmanImportPreview.vue.script.js +1 -1
- package/dist/v2/features/command-palette/components/PostmanImportPreview.vue.script.js.map +1 -1
- package/dist/v2/features/command-palette/helpers/get-postman-convert-options.d.ts +14 -0
- package/dist/v2/features/command-palette/helpers/get-postman-convert-options.d.ts.map +1 -0
- package/dist/v2/features/command-palette/helpers/get-postman-convert-options.js +19 -0
- package/dist/v2/features/command-palette/helpers/get-postman-convert-options.js.map +1 -0
- package/dist/v2/features/command-palette/helpers/get-postman-document-details.js +1 -1
- package/dist/v2/features/command-palette/helpers/get-postman-document-details.js.map +1 -1
- package/dist/v2/features/command-palette/helpers/load-document-from-source.d.ts.map +1 -1
- package/dist/v2/features/command-palette/helpers/load-document-from-source.js +1 -1
- package/dist/v2/features/command-palette/helpers/load-document-from-source.js.map +1 -1
- package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.d.ts +2 -2
- package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.d.ts +1 -1
- package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.d.ts.map +1 -1
- package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.js.map +1 -1
- package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.script.js +2 -2
- package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.script.js.map +1 -1
- package/dist/v2/features/global-cookies/components/CookiesTable.vue.d.ts.map +1 -1
- package/dist/v2/features/global-cookies/components/CookiesTable.vue.js +1 -1
- package/dist/v2/features/global-cookies/components/CookiesTable.vue.js.map +1 -1
- package/dist/v2/features/global-cookies/components/CookiesTable.vue.script.js +2 -0
- package/dist/v2/features/global-cookies/components/CookiesTable.vue.script.js.map +1 -1
- package/dist/v2/features/modal/Modal.vue.d.ts +7 -6
- package/dist/v2/features/modal/Modal.vue.d.ts.map +1 -1
- package/dist/v2/features/modal/Modal.vue.js.map +1 -1
- package/dist/v2/features/modal/Modal.vue.script.js.map +1 -1
- package/dist/v2/features/modal/helpers/create-api-client-modal.d.ts +5 -5
- package/dist/v2/features/modal/helpers/create-api-client-modal.d.ts.map +1 -1
- package/dist/v2/features/modal/helpers/create-api-client-modal.js +11 -0
- package/dist/v2/features/modal/helpers/create-api-client-modal.js.map +1 -1
- package/dist/v2/features/modal/helpers/types.d.ts +1 -7
- package/dist/v2/features/modal/helpers/types.d.ts.map +1 -1
- package/dist/v2/features/modal/index.d.ts +1 -1
- package/dist/v2/features/modal/index.d.ts.map +1 -1
- package/dist/v2/features/operation/Operation.vue.d.ts +0 -5
- package/dist/v2/features/operation/Operation.vue.d.ts.map +1 -1
- package/dist/v2/features/operation/Operation.vue.js.map +1 -1
- package/dist/v2/features/operation/Operation.vue.script.js.map +1 -1
- package/dist/v2/types/options.d.ts +15 -0
- package/dist/v2/types/options.d.ts.map +1 -0
- package/package.json +21 -16
- package/dist/v2/features/command-palette/helpers/is-postman-collection.d.ts +0 -11
- package/dist/v2/features/command-palette/helpers/is-postman-collection.d.ts.map +0 -1
- package/dist/v2/features/command-palette/helpers/is-postman-collection.js +0 -24
- package/dist/v2/features/command-palette/helpers/is-postman-collection.js.map +0 -1
- package/dist/v2/posthog.d.ts +0 -3
- package/dist/v2/posthog.d.ts.map +0 -1
- package/dist/v2/posthog.js +0 -20
- package/dist/v2/posthog.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentCollection.vue.script.js","names":[],"sources":["../../../../src/v2/features/collection/DocumentCollection.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Document Collection Page\n *\n * Displays primary document editing and viewing interface, enabling users to:\n * - Choose a document icon\n * - Edit the document title\n * - Navigate among Overview, Servers, Authentication, Environment, Cookies, and Settings tabs\n */\nexport default {\n name: 'DocumentCollection',\n}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarModal,\n ScalarSavePrompt,\n useLoadingState,\n useModal,\n} from '@scalar/components'\nimport {\n ScalarIconCloudArrowDown,\n ScalarIconDownload,\n ScalarIconFloppyDisk,\n ScalarIconSpinner,\n ScalarIconWarning,\n} from '@scalar/icons'\nimport { LibraryIcon } from '@scalar/icons/library'\nimport { apply, type Difference, type merge } from '@scalar/json-magic/diff'\nimport { useToasts } from '@scalar/use-toasts'\nimport { deepClone } from '@scalar/workspace-store/helpers/deep-clone'\nimport { computed, ref } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport IconSelector from '@/components/IconSelector.vue'\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport { downloadAsFile } from '@/v2/helpers/download-document'\n\nimport LabelInput from './components/LabelInput.vue'\nimport SyncConflictResolutionEditor from './components/SyncConflictResolutionEditor.vue'\nimport Tabs from './components/Tabs.vue'\n\nconst props = defineProps<RouteProps>()\n\n/** Snag the title from the info object */\nconst title = computed(() => props.document?.info?.title ?? '')\n\n/** Default to the folder icon */\nconst icon = computed(\n () => props.document?.['x-scalar-icon'] || 'interface-content-folder',\n)\n\nconst syncModal = useModal()\nconst dirtyBeforeSyncModal = useModal()\n\nconst isDocumentDirty = computed(\n () => props.document?.['x-scalar-is-dirty'] === true,\n)\n\nconst saveLoader = useLoadingState()\n\nconst documentSourceUrl = computed(\n () => props.document?.['x-scalar-original-source-url'] as string | undefined,\n)\n\nconst documentRegistryMeta = computed(\n () =>\n props.document?.['x-scalar-registry-meta'] as\n | { namespace: string; slug: string }\n | undefined,\n)\n\n/** Show Sync when the document has a source URL or registry meta (registry can be used if fetchRegistryDocument is set). */\nconst canShowSyncButton = computed(\n () =>\n documentSourceUrl.value !== undefined ||\n documentRegistryMeta.value !== undefined,\n)\n\nconst { toast } = useToasts()\n\nconst undoChanges = () => {\n props.workspaceStore.revertDocumentChanges(props.documentSlug)\n}\n\nconst saveChanges = async () => {\n saveLoader.start()\n const res = await props.workspaceStore.saveDocument(props.documentSlug)\n await (res ? saveLoader.validate() : saveLoader.invalidate({ persist: true }))\n}\n\n/** Downloads the document as a JSON file using the last saved state. */\nconst downloadDocument = () => {\n const content = props.workspaceStore.exportDocument(\n props.documentSlug,\n 'json',\n false,\n )\n if (!content) return\n const baseName = title.value.replace(/[^\\w\\s-]/g, '').trim() || 'document'\n downloadAsFile(content, `${baseName}.json`)\n}\n\nconst handleSaveThenCloseDirtyModal = async () => {\n await props.workspaceStore.saveDocument(props.documentSlug)\n dirtyBeforeSyncModal.hide()\n await handleSyncFlow()\n}\n\nconst handleDiscardThenCloseDirtyModal = async () => {\n await props.workspaceStore.revertDocumentChanges(props.documentSlug)\n dirtyBeforeSyncModal.hide()\n await handleSyncFlow()\n}\n\nconst isSyncInProgress = ref(false)\n\nconst rebaseResult = ref<{\n originalDocument: Record<string, unknown>\n resolvedDocument: Record<string, unknown>\n conflicts: ReturnType<typeof merge>['conflicts']\n applyChanges: (\n applyChangesInput:\n | {\n resolvedConflicts: Difference<unknown>[]\n }\n | {\n resolvedDocument: Record<string, unknown>\n },\n ) => Promise<void>\n} | null>(null)\n\n/**\n * Resolves the source for syncing. Registry meta has priority over x-scalar-original-source-url\n * when fetchRegistryDocument is provided. Returns either a URL or the full document object.\n */\nconst resolveSyncInput = async (): Promise<\n { url: string } | { document: Record<string, unknown> } | null\n> => {\n const registryMeta = documentRegistryMeta.value\n if (registryMeta && props.fetchRegistryDocument) {\n try {\n const result = await props.fetchRegistryDocument(registryMeta)\n if (!result.ok) {\n toast(result.error, 'error')\n return null\n }\n return { document: result.data }\n } catch (err) {\n toast('Failed to resolve document from registry', 'error')\n return null\n }\n }\n const url = documentSourceUrl.value\n if (url) {\n return { url }\n }\n return null\n}\n\n/**\n * Handles actions to perform when synchronization is complete.\n * Hides the sync modal, resets the sync progress flag, and emits the\n * 'hooks:on:rebase:document:complete' event with document metadata.\n */\nconst onSyncComplete = () => {\n syncModal.hide()\n isSyncInProgress.value = false\n // Display the toast to show that the sync is complete\n toast(\n 'Your document has been rebased with the latest version from the source.',\n 'info',\n )\n // Emit the event to notify other components that the sync is complete\n props.eventBus.emit('hooks:on:rebase:document:complete', {\n meta: {\n documentName: props.documentSlug,\n },\n })\n}\n\n/**\n * Handles errors that occur during synchronization.\n * If an error string is provided, it displays the error via toast.\n * Always resets the sync progress flag.\n */\nconst onSyncError = (error: string | null) => {\n if (error !== null) {\n toast(error, 'error')\n }\n isSyncInProgress.value = false\n}\n\n/**\n * Handles the synchronization flow for a document.\n * Checks for unsaved changes, resolves source (registry over URL),\n * initiates rebasing, handles conflicts, and emits completion events.\n * If conflicts are detected, a modal dialog is shown for user resolution.\n */\nconst handleSyncFlow = async () => {\n if (isDocumentDirty.value) {\n dirtyBeforeSyncModal.show()\n return\n }\n\n if (isSyncInProgress.value) {\n return\n }\n\n isSyncInProgress.value = true\n\n const input = await resolveSyncInput()\n if (!input) {\n onSyncError(null)\n return\n }\n\n const result = await props.workspaceStore.rebaseDocument({\n name: props.documentSlug,\n ...input,\n })\n\n if (result?.ok) {\n const originalDocument =\n props.workspaceStore.getOriginalDocument(props.documentSlug) ?? {}\n rebaseResult.value = {\n conflicts: result.conflicts,\n applyChanges: result.applyChanges,\n resolvedDocument: apply(deepClone(originalDocument), result.changes),\n originalDocument,\n }\n\n if (rebaseResult.value.conflicts.length > 0) {\n syncModal.show()\n } else {\n // If there is no conflict just rebase immediately\n await rebaseResult.value?.applyChanges({\n resolvedDocument: rebaseResult.value.resolvedDocument,\n })\n onSyncComplete()\n }\n } else if (result?.ok === false && result.type === 'NO_CHANGES_DETECTED') {\n // Emit the event either way even if there was no need to rebase the document\n onSyncComplete()\n } else {\n onSyncError('Failed to sync document')\n }\n}\n\n/*\n * Handles applying changes to the current document after conflict resolution.\n * Emits a completion event and hides the sync modal dialog.\n */\nconst handleApplyChanges = async ({\n resolvedDocument,\n}: {\n resolvedDocument: Record<string, unknown>\n}) => {\n await rebaseResult.value?.applyChanges({ resolvedDocument })\n props.eventBus.emit('hooks:on:rebase:document:complete', {\n meta: {\n documentName: props.documentSlug,\n },\n })\n syncModal.hide()\n}\n\n/**\n * Resets sync state when the sync conflict modal is closed (dismissed or after\n * applying changes). Ensures the Sync button is re-enabled and conflict state\n * is cleared.\n */\nconst onSyncModalClose = () => {\n isSyncInProgress.value = false\n rebaseResult.value = null\n}\n</script>\n\n<template>\n <div class=\"custom-scroll h-full\">\n <div\n v-if=\"document\"\n class=\"md:max-w-content w-full px-3 md:mx-auto\">\n <!-- Header -->\n <div\n :aria-label=\"`title: ${title}`\"\n class=\"md:max-w-content mx-auto flex h-fit w-full flex-col gap-2 pt-14 pb-3 md:pt-6\">\n <ScalarSavePrompt\n v-model=\"isDocumentDirty\"\n class=\"w-content-padded-4 max-w-full-padded-4 absolute\"\n :loader=\"saveLoader\"\n @discard=\"undoChanges\"\n @save=\"saveChanges\" />\n <div class=\"flex flex-row items-center justify-between gap-2\">\n <div class=\"flex min-w-0 items-center gap-2\">\n <IconSelector\n :modelValue=\"icon\"\n placement=\"bottom-start\"\n @update:modelValue=\"\n (icon) => eventBus.emit('document:update:icon', icon)\n \">\n <ScalarButton\n class=\"hover:bg-b-2 aspect-square h-7 w-7 cursor-pointer rounded border border-transparent p-0 hover:border-inherit\"\n variant=\"ghost\">\n <LibraryIcon\n class=\"text-c-2 size-5\"\n :src=\"icon\"\n stroke-width=\"2\" />\n </ScalarButton>\n </IconSelector>\n\n <div class=\"group relative ml-1.25 min-w-0\">\n <LabelInput\n class=\"text-xl font-bold\"\n inputId=\"documentName\"\n :modelValue=\"title\"\n @update:modelValue=\"\n (title) => eventBus.emit('document:update:info', { title })\n \" />\n </div>\n </div>\n\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex shrink-0 items-center gap-2\"\n size=\"xs\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"downloadDocument\">\n <ScalarIconDownload\n size=\"sm\"\n thickness=\"1.5\" />\n <span>Download document</span>\n </ScalarButton>\n\n <ScalarButton\n v-if=\"canShowSyncButton\"\n class=\"text-c-2 hover:text-c-1 shrink-0 gap-1.5\"\n data-testid=\"document-sync-button\"\n :disabled=\"isSyncInProgress\"\n size=\"xs\"\n :title=\"'Pull the latest version from the document source and merge with your local copy. Save your changes first if you have unsaved edits.'\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"handleSyncFlow\">\n <ScalarIconSpinner\n v-if=\"isSyncInProgress\"\n class=\"size-3.5 animate-spin\"\n size=\"sm\" />\n <ScalarIconCloudArrowDown\n v-else\n class=\"size-3.5\"\n size=\"sm\"\n thickness=\"1.5\" />\n <span>Sync from source</span>\n </ScalarButton>\n </div>\n </div>\n\n <!-- Tabs -->\n <Tabs type=\"document\" />\n\n <!-- Router views -->\n <div class=\"px-1.5 pt-8 pb-20\">\n <RouterView v-slot=\"{ Component }\">\n <component\n :is=\"Component\"\n v-bind=\"props\"\n collectionType=\"document\" />\n </RouterView>\n </div>\n </div>\n\n <!-- Document not found -->\n <div\n v-else\n class=\"flex w-full flex-1 items-center justify-center\">\n <div class=\"flex h-full flex-col items-center justify-center\">\n <h1 class=\"text-2xl font-bold\">Document not found</h1>\n <p class=\"text-gray-500\">\n The document you are looking for does not exist.\n </p>\n </div>\n </div>\n </div>\n <ScalarModal\n bodyClass=\"border-t-0 rounded-t-lg flex flex-col gap-5\"\n size=\"xs\"\n :state=\"dirtyBeforeSyncModal\"\n title=\"Sync requires saved document\"\n @close=\"dirtyBeforeSyncModal.hide()\">\n <div class=\"flex flex-col gap-5\">\n <div class=\"flex gap-3\">\n <div\n aria-hidden=\"true\"\n class=\"bg-b-3 text-c-2 flex size-10 shrink-0 items-center justify-center rounded-lg\">\n <ScalarIconWarning class=\"text-yellow size-5\" />\n </div>\n <div class=\"min-w-0 flex-1 space-y-1\">\n <p class=\"text-c-1 text-sm leading-snug font-medium\">\n You have unsaved changes\n </p>\n <p class=\"text-c-2 text-sm leading-relaxed\">\n Save your work to keep changes, or discard to revert to the last\n saved version. Then you can sync with the source.\n </p>\n </div>\n </div>\n <div class=\"flex flex-wrap items-center justify-end gap-2 border-t pt-4\">\n <ScalarButton\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"dirtyBeforeSyncModal.hide()\">\n Cancel\n </ScalarButton>\n <ScalarButton\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleDiscardThenCloseDirtyModal\">\n Discard changes\n </ScalarButton>\n <ScalarButton\n class=\"flex items-center gap-2\"\n size=\"sm\"\n type=\"button\"\n variant=\"solid\"\n @click=\"handleSaveThenCloseDirtyModal\">\n <ScalarIconFloppyDisk\n size=\"sm\"\n thickness=\"1.5\" />\n Save and continue\n </ScalarButton>\n </div>\n </div>\n </ScalarModal>\n <ScalarModal\n v-if=\"rebaseResult\"\n bodyClass=\"sync-conflict-modal-root flex h-dvh flex-col p-4\"\n maxWidth=\"calc(100dvw - 32px)\"\n size=\"full\"\n :state=\"syncModal\"\n @close=\"onSyncModalClose\">\n <div class=\"flex h-full w-full flex-col gap-4 overflow-hidden\">\n <SyncConflictResolutionEditor\n :baseDocument=\"rebaseResult.originalDocument\"\n :conflicts=\"rebaseResult.conflicts\"\n :resolvedDocument=\"rebaseResult.resolvedDocument\"\n @applyChanges=\"(payload) => handleApplyChanges(payload)\" />\n </div>\n </ScalarModal>\n</template>\n\n<style>\n.full-size-styles:has(.sync-conflict-modal-root) {\n width: 100dvw !important;\n max-width: 100dvw !important;\n border-right: none !important;\n}\n\n.full-size-styles:has(.sync-conflict-modal-root)::after {\n display: none;\n}\n</style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DocumentCollection.vue.script.js","names":[],"sources":["../../../../src/v2/features/collection/DocumentCollection.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Document Collection Page\n *\n * Displays primary document editing and viewing interface, enabling users to:\n * - Choose a document icon\n * - Edit the document title\n * - Navigate among Overview, Servers, Authentication, Environment, Cookies, and Settings tabs\n */\nexport default {\n name: 'DocumentCollection',\n}\n</script>\n\n<script setup lang=\"ts\">\nimport {\n ScalarButton,\n ScalarModal,\n ScalarSavePrompt,\n useLoadingState,\n useModal,\n} from '@scalar/components'\nimport {\n ScalarIconCloudArrowDown,\n ScalarIconDownload,\n ScalarIconFloppyDisk,\n ScalarIconSpinner,\n ScalarIconWarning,\n} from '@scalar/icons'\nimport { LibraryIcon } from '@scalar/icons/library'\nimport { apply, type Difference, type merge } from '@scalar/json-magic/diff'\nimport { useToasts } from '@scalar/use-toasts'\nimport { deepClone } from '@scalar/workspace-store/helpers/deep-clone'\nimport { computed, ref } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport IconSelector from '@/components/IconSelector.vue'\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport { downloadAsFile } from '@/v2/helpers/download-document'\n\nimport LabelInput from './components/LabelInput.vue'\nimport SyncConflictResolutionEditor from './components/SyncConflictResolutionEditor.vue'\nimport Tabs from './components/Tabs.vue'\n\nconst props = defineProps<RouteProps>()\n\n/** Snag the title from the info object */\nconst title = computed(() => props.document?.info?.title ?? '')\n\n/** Default to the folder icon */\nconst icon = computed(\n () => props.document?.['x-scalar-icon'] || 'interface-content-folder',\n)\n\nconst syncModal = useModal()\nconst dirtyBeforeSyncModal = useModal()\n\nconst isDocumentDirty = computed(\n () => props.document?.['x-scalar-is-dirty'] === true,\n)\n\nconst saveLoader = useLoadingState()\n\nconst documentSourceUrl = computed(\n () => props.document?.['x-scalar-original-source-url'] as string | undefined,\n)\n\nconst documentRegistryMeta = computed(\n () =>\n props.document?.['x-scalar-registry-meta'] as\n | { namespace: string; slug: string }\n | undefined,\n)\n\n/** Show Sync when the document has a source URL or registry meta (registry can be used if fetchRegistryDocument is set). */\nconst canShowSyncButton = computed(\n () =>\n documentSourceUrl.value !== undefined ||\n documentRegistryMeta.value !== undefined,\n)\n\nconst { toast } = useToasts()\n\nconst undoChanges = () => {\n props.workspaceStore.revertDocumentChanges(props.documentSlug)\n}\n\nconst saveChanges = async () => {\n saveLoader.start()\n const res = await props.workspaceStore.saveDocument(props.documentSlug)\n await (res ? saveLoader.validate() : saveLoader.invalidate({ persist: true }))\n}\n\n/** Downloads the document as a JSON file using the last saved state. */\nconst downloadDocument = () => {\n const content = props.workspaceStore.exportDocument(\n props.documentSlug,\n 'json',\n false,\n )\n if (!content) return\n const baseName = title.value.replace(/[^\\w\\s-]/g, '').trim() || 'document'\n downloadAsFile(content, `${baseName}.json`)\n}\n\nconst handleSaveThenCloseDirtyModal = async () => {\n await props.workspaceStore.saveDocument(props.documentSlug)\n dirtyBeforeSyncModal.hide()\n await handleSyncFlow()\n}\n\nconst handleDiscardThenCloseDirtyModal = async () => {\n await props.workspaceStore.revertDocumentChanges(props.documentSlug)\n dirtyBeforeSyncModal.hide()\n await handleSyncFlow()\n}\n\nconst isSyncInProgress = ref(false)\n\nconst rebaseResult = ref<{\n originalDocument: Record<string, unknown>\n resolvedDocument: Record<string, unknown>\n conflicts: ReturnType<typeof merge>['conflicts']\n applyChanges: (\n applyChangesInput:\n | {\n resolvedConflicts: Difference<unknown>[]\n }\n | {\n resolvedDocument: Record<string, unknown>\n },\n ) => Promise<void>\n} | null>(null)\n\n/**\n * Resolves the source for syncing. Registry meta has priority over x-scalar-original-source-url\n * when fetchRegistryDocument is provided. Returns either a URL or the full document object.\n */\nconst resolveSyncInput = async (): Promise<\n { url: string } | { document: Record<string, unknown> } | null\n> => {\n const registryMeta = documentRegistryMeta.value\n if (registryMeta && props.fetchRegistryDocument) {\n try {\n const result = await props.fetchRegistryDocument(registryMeta)\n if (!result.ok) {\n toast(result.error, 'error')\n return null\n }\n return { document: result.data }\n } catch (err) {\n toast('Failed to resolve document from registry', 'error')\n return null\n }\n }\n const url = documentSourceUrl.value\n if (url) {\n return { url }\n }\n return null\n}\n\n/**\n * Handles actions to perform when synchronization is complete.\n * Hides the sync modal, resets the sync progress flag, and emits the\n * 'hooks:on:rebase:document:complete' event with document metadata.\n */\nconst onSyncComplete = () => {\n syncModal.hide()\n isSyncInProgress.value = false\n // Display the toast to show that the sync is complete\n toast(\n 'Your document has been rebased with the latest version from the source.',\n 'info',\n )\n // Emit the event to notify other components that the sync is complete\n props.eventBus.emit('hooks:on:rebase:document:complete', {\n meta: {\n documentName: props.documentSlug,\n },\n })\n}\n\n/**\n * Handles errors that occur during synchronization.\n * If an error string is provided, it displays the error via toast.\n * Always resets the sync progress flag.\n */\nconst onSyncError = (error: string | null) => {\n if (error !== null) {\n toast(error, 'error')\n }\n isSyncInProgress.value = false\n}\n\n/**\n * Handles the synchronization flow for a document.\n * Checks for unsaved changes, resolves source (registry over URL),\n * initiates rebasing, handles conflicts, and emits completion events.\n * If conflicts are detected, a modal dialog is shown for user resolution.\n */\nconst handleSyncFlow = async () => {\n if (isDocumentDirty.value) {\n dirtyBeforeSyncModal.show()\n return\n }\n\n if (isSyncInProgress.value) {\n return\n }\n\n isSyncInProgress.value = true\n\n const input = await resolveSyncInput()\n if (!input) {\n onSyncError(null)\n return\n }\n\n const result = await props.workspaceStore.rebaseDocument({\n name: props.documentSlug,\n ...input,\n })\n\n if (result?.ok) {\n const originalDocument =\n props.workspaceStore.getOriginalDocument(props.documentSlug) ?? {}\n rebaseResult.value = {\n conflicts: result.conflicts,\n applyChanges: result.applyChanges,\n resolvedDocument: apply(deepClone(originalDocument), result.changes),\n originalDocument,\n }\n\n if (rebaseResult.value.conflicts.length > 0) {\n syncModal.show()\n } else {\n // If there is no conflict just rebase immediately\n await rebaseResult.value?.applyChanges({\n resolvedDocument: rebaseResult.value.resolvedDocument,\n })\n onSyncComplete()\n }\n } else if (result?.ok === false && result.type === 'NO_CHANGES_DETECTED') {\n // Emit the event either way even if there was no need to rebase the document\n onSyncComplete()\n } else {\n onSyncError('Failed to sync document')\n }\n}\n\n/*\n * Handles applying changes to the current document after conflict resolution.\n * Emits a completion event and hides the sync modal dialog.\n */\nconst handleApplyChanges = async ({\n resolvedDocument,\n}: {\n resolvedDocument: Record<string, unknown>\n}) => {\n await rebaseResult.value?.applyChanges({ resolvedDocument })\n props.eventBus.emit('hooks:on:rebase:document:complete', {\n meta: {\n documentName: props.documentSlug,\n },\n })\n syncModal.hide()\n}\n\n/**\n * Resets sync state when the sync conflict modal is closed (dismissed or after\n * applying changes). Ensures the Sync button is re-enabled and conflict state\n * is cleared.\n */\nconst onSyncModalClose = () => {\n isSyncInProgress.value = false\n rebaseResult.value = null\n}\n</script>\n\n<template>\n <div class=\"custom-scroll h-full\">\n <div\n v-if=\"document\"\n class=\"md:max-w-content w-full px-3 md:mx-auto\">\n <!-- Header -->\n <div\n :aria-label=\"`title: ${title}`\"\n class=\"md:max-w-content mx-auto flex h-fit w-full flex-col gap-2 pt-14 pb-3 md:pt-6\">\n <ScalarSavePrompt\n v-model=\"isDocumentDirty\"\n class=\"w-content-padded-4 max-w-full-padded-4 absolute\"\n :loader=\"saveLoader\"\n @discard=\"undoChanges\"\n @save=\"saveChanges\" />\n <div class=\"flex flex-row items-center justify-between gap-2\">\n <div class=\"flex min-w-0 items-center gap-2\">\n <IconSelector\n :modelValue=\"icon\"\n placement=\"bottom-start\"\n @update:modelValue=\"\n (icon) => eventBus.emit('document:update:icon', icon)\n \">\n <ScalarButton\n class=\"hover:bg-b-2 aspect-square h-7 w-7 cursor-pointer rounded border border-transparent p-0 hover:border-inherit\"\n variant=\"ghost\">\n <LibraryIcon\n class=\"text-c-2 size-5\"\n :src=\"icon\"\n stroke-width=\"2\" />\n </ScalarButton>\n </IconSelector>\n\n <div class=\"group relative ml-1.25 min-w-0\">\n <LabelInput\n class=\"text-xl font-bold\"\n inputId=\"documentName\"\n :modelValue=\"title\"\n @update:modelValue=\"\n (title) => eventBus.emit('document:update:info', { title })\n \" />\n </div>\n </div>\n\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex shrink-0 items-center gap-2\"\n size=\"xs\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"downloadDocument\">\n <ScalarIconDownload\n size=\"sm\"\n thickness=\"1.5\" />\n <span>Download document</span>\n </ScalarButton>\n\n <ScalarButton\n v-if=\"canShowSyncButton\"\n class=\"text-c-2 hover:text-c-1 shrink-0 gap-1.5\"\n data-testid=\"document-sync-button\"\n :disabled=\"isSyncInProgress\"\n size=\"xs\"\n :title=\"'Pull the latest version from the document source and merge with your local copy. Save your changes first if you have unsaved edits.'\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"handleSyncFlow\">\n <ScalarIconSpinner\n v-if=\"isSyncInProgress\"\n class=\"size-3.5 animate-spin\"\n size=\"sm\" />\n <ScalarIconCloudArrowDown\n v-else\n class=\"size-3.5\"\n size=\"sm\"\n thickness=\"1.5\" />\n <span>Sync from source</span>\n </ScalarButton>\n </div>\n </div>\n\n <!-- Tabs -->\n <Tabs type=\"document\" />\n\n <!-- Router views -->\n <div class=\"px-1.5 pt-8 pb-20\">\n <RouterView v-slot=\"{ Component }\">\n <component\n :is=\"Component\"\n v-bind=\"props\"\n collectionType=\"document\" />\n </RouterView>\n </div>\n </div>\n\n <!-- Document not found -->\n <div\n v-else\n class=\"flex w-full flex-1 items-center justify-center\">\n <div class=\"flex h-full flex-col items-center justify-center\">\n <h1 class=\"text-2xl font-bold\">Document not found</h1>\n <p class=\"text-gray-500\">\n The document you are looking for does not exist.\n </p>\n </div>\n </div>\n </div>\n <ScalarModal\n bodyClass=\"border-t-0 rounded-t-lg flex flex-col gap-5\"\n size=\"xs\"\n :state=\"dirtyBeforeSyncModal\"\n title=\"Sync requires saved document\"\n @close=\"dirtyBeforeSyncModal.hide()\">\n <div class=\"flex flex-col gap-5\">\n <div class=\"flex gap-3\">\n <div\n aria-hidden=\"true\"\n class=\"bg-b-3 text-c-2 flex size-10 shrink-0 items-center justify-center rounded-lg\">\n <ScalarIconWarning class=\"text-yellow size-5\" />\n </div>\n <div class=\"min-w-0 flex-1 space-y-1\">\n <p class=\"text-c-1 text-sm leading-snug font-medium\">\n You have unsaved changes\n </p>\n <p class=\"text-c-2 text-sm leading-relaxed\">\n Save your work to keep changes, or discard to revert to the last\n saved version. Then you can sync with the source.\n </p>\n </div>\n </div>\n <div class=\"flex flex-wrap items-center justify-end gap-2 border-t pt-4\">\n <ScalarButton\n size=\"sm\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"dirtyBeforeSyncModal.hide()\">\n Cancel\n </ScalarButton>\n <ScalarButton\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleDiscardThenCloseDirtyModal\">\n Discard changes\n </ScalarButton>\n <ScalarButton\n class=\"flex items-center gap-2\"\n size=\"sm\"\n type=\"button\"\n variant=\"solid\"\n @click=\"handleSaveThenCloseDirtyModal\">\n <ScalarIconFloppyDisk\n size=\"sm\"\n thickness=\"1.5\" />\n Save and continue\n </ScalarButton>\n </div>\n </div>\n </ScalarModal>\n <ScalarModal\n v-if=\"rebaseResult\"\n bodyClass=\"sync-conflict-modal-root flex h-dvh flex-col p-4\"\n maxWidth=\"calc(100dvw - 32px)\"\n size=\"full\"\n :state=\"syncModal\"\n @close=\"onSyncModalClose\">\n <div class=\"flex h-full w-full flex-col gap-4 overflow-hidden\">\n <SyncConflictResolutionEditor\n :baseDocument=\"rebaseResult.originalDocument\"\n :conflicts=\"rebaseResult.conflicts\"\n :resolvedDocument=\"rebaseResult.resolvedDocument\"\n @applyChanges=\"(payload) => handleApplyChanges(payload)\" />\n </div>\n </ScalarModal>\n</template>\n\n<style>\n.full-size-styles:has(.sync-conflict-modal-root) {\n width: 100dvw !important;\n max-width: 100dvw !important;\n border-right: none !important;\n}\n\n.full-size-styles:has(.sync-conflict-modal-root)::after {\n display: none;\n}\n</style>\n"],"mappings":"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"}
|
|
@@ -36,7 +36,8 @@ var OperationCollection_vue_vue_type_script_setup_true_lang_default = /* @__PURE
|
|
|
36
36
|
isDarkMode: { type: Boolean },
|
|
37
37
|
fetchRegistryDocument: { type: Function },
|
|
38
38
|
telemetry: { type: Boolean },
|
|
39
|
-
onUpdateTelemetry: { type: Function }
|
|
39
|
+
onUpdateTelemetry: { type: Function },
|
|
40
|
+
options: {}
|
|
40
41
|
},
|
|
41
42
|
setup(__props) {
|
|
42
43
|
const props = __props;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OperationCollection.vue.script.js","names":[],"sources":["../../../../src/v2/features/collection/OperationCollection.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Document collection page — tabs for Overview, Servers, Auth, Environment, Cookies, and Settings. */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { computed, ref, watch } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport LabelInput from '@/v2/features/collection/components/LabelInput.vue'\n\nimport Tabs from './components/Tabs.vue'\n\nconst props = defineProps<RouteProps>()\n\nconst operation = computed(() => {\n if (!props.path || !props.method) {\n return undefined\n }\n\n return getResolvedRef(props.document?.paths?.[props.path]?.[props.method])\n})\n\n/**\n * Local copy of the label so we can reset on empty-blur rejection and stay in\n * sync when Vue Router reuses this component across workspace navigations.\n */\nconst operationSummary = ref(operation.value?.summary ?? '')\n\nwatch(\n () => operation.value?.summary,\n (newSummary) => {\n operationSummary.value = newSummary ?? ''\n },\n)\n\n/** Emits the rename event on blur, or resets the input if the title is blank. */\nconst handleSummaryUpdate = (payload: string) => {\n const { path, method } = props\n\n if (!path || !method || !isHttpMethod(method)) {\n return\n }\n\n props.eventBus.emit('operation:update:meta', {\n meta: { path, method },\n payload: {\n summary: payload.trim(),\n },\n })\n}\n\nconst operationPlaceholder = computed(() => {\n if (!props.path || !props.method) {\n return 'Untitled Operation'\n }\n return `${props.method.toUpperCase()} ${props.path}`\n})\n</script>\n\n<template>\n <div\n v-if=\"operation !== undefined\"\n class=\"custom-scroll h-full\">\n <div class=\"w-full px-3 md:mx-auto md:max-w-180\">\n <!-- Header -->\n <div\n :aria-label=\"`title: ${operationSummary}`\"\n class=\"mx-auto flex h-fit w-full flex-row items-center gap-2 pt-14 pb-3 md:max-w-180 md:pt-8\">\n <div class=\"group relative ml-1.25\">\n <LabelInput\n v-model=\"operationSummary\"\n class=\"text-xl font-bold\"\n inputId=\"operationSummary\"\n :placeholder=\"operationPlaceholder\"\n @blur=\"handleSummaryUpdate\" />\n </div>\n </div>\n\n <!-- Tabs -->\n <Tabs type=\"operation\" />\n\n <!-- Router views -->\n <div class=\"px-1.5 py-8\">\n <RouterView\n v-bind=\"props\"\n collectionType=\"operation\" />\n </div>\n </div>\n </div>\n\n <!-- Operation not found -->\n <div\n v-else\n class=\"flex w-full flex-1 items-center justify-center\">\n <div class=\"flex h-full flex-col items-center justify-center\">\n <h1 class=\"text-2xl font-bold\">Operation not found</h1>\n <p class=\"text-gray-500\">\n The operation you are looking for does not exist.\n </p>\n </div>\n </div>\n</template>\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"OperationCollection.vue.script.js","names":[],"sources":["../../../../src/v2/features/collection/OperationCollection.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Document collection page — tabs for Overview, Servers, Auth, Environment, Cookies, and Settings. */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { computed, ref, watch } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport LabelInput from '@/v2/features/collection/components/LabelInput.vue'\n\nimport Tabs from './components/Tabs.vue'\n\nconst props = defineProps<RouteProps>()\n\nconst operation = computed(() => {\n if (!props.path || !props.method) {\n return undefined\n }\n\n return getResolvedRef(props.document?.paths?.[props.path]?.[props.method])\n})\n\n/**\n * Local copy of the label so we can reset on empty-blur rejection and stay in\n * sync when Vue Router reuses this component across workspace navigations.\n */\nconst operationSummary = ref(operation.value?.summary ?? '')\n\nwatch(\n () => operation.value?.summary,\n (newSummary) => {\n operationSummary.value = newSummary ?? ''\n },\n)\n\n/** Emits the rename event on blur, or resets the input if the title is blank. */\nconst handleSummaryUpdate = (payload: string) => {\n const { path, method } = props\n\n if (!path || !method || !isHttpMethod(method)) {\n return\n }\n\n props.eventBus.emit('operation:update:meta', {\n meta: { path, method },\n payload: {\n summary: payload.trim(),\n },\n })\n}\n\nconst operationPlaceholder = computed(() => {\n if (!props.path || !props.method) {\n return 'Untitled Operation'\n }\n return `${props.method.toUpperCase()} ${props.path}`\n})\n</script>\n\n<template>\n <div\n v-if=\"operation !== undefined\"\n class=\"custom-scroll h-full\">\n <div class=\"w-full px-3 md:mx-auto md:max-w-180\">\n <!-- Header -->\n <div\n :aria-label=\"`title: ${operationSummary}`\"\n class=\"mx-auto flex h-fit w-full flex-row items-center gap-2 pt-14 pb-3 md:max-w-180 md:pt-8\">\n <div class=\"group relative ml-1.25\">\n <LabelInput\n v-model=\"operationSummary\"\n class=\"text-xl font-bold\"\n inputId=\"operationSummary\"\n :placeholder=\"operationPlaceholder\"\n @blur=\"handleSummaryUpdate\" />\n </div>\n </div>\n\n <!-- Tabs -->\n <Tabs type=\"operation\" />\n\n <!-- Router views -->\n <div class=\"px-1.5 py-8\">\n <RouterView\n v-bind=\"props\"\n collectionType=\"operation\" />\n </div>\n </div>\n </div>\n\n <!-- Operation not found -->\n <div\n v-else\n class=\"flex w-full flex-1 items-center justify-center\">\n <div class=\"flex h-full flex-col items-center justify-center\">\n <h1 class=\"text-2xl font-bold\">Operation not found</h1>\n <p class=\"text-gray-500\">\n The operation you are looking for does not exist.\n </p>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBA,MAAM,QAAQ;EAEd,MAAM,YAAY,eAAe;AAC/B,OAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OACxB;AAGF,UAAO,eAAe,MAAM,UAAU,QAAQ,MAAM,QAAQ,MAAM,QAAO;IAC1E;;;;;EAMD,MAAM,mBAAmB,IAAI,UAAU,OAAO,WAAW,GAAE;AAE3D,cACQ,UAAU,OAAO,UACtB,eAAe;AACd,oBAAiB,QAAQ,cAAc;IAE3C;;EAGA,MAAM,uBAAuB,YAAoB;GAC/C,MAAM,EAAE,MAAM,WAAW;AAEzB,OAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,aAAa,OAAO,CAC3C;AAGF,SAAM,SAAS,KAAK,yBAAyB;IAC3C,MAAM;KAAE;KAAM;KAAQ;IACtB,SAAS,EACP,SAAS,QAAQ,MAAM,EACxB;IACF,CAAA;;EAGH,MAAM,uBAAuB,eAAe;AAC1C,OAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,OACxB,QAAO;AAET,UAAO,GAAG,MAAM,OAAO,aAAa,CAAC,GAAG,MAAM;IAC/C;;UAKS,UAAA,UAAc,KAAA,KAAA,WAAA,EADtB,mBA4BM,OA5BN,YA4BM,CAzBJ,mBAwBM,OAxBN,YAwBM;IAtBJ,mBAWM,OAAA;KAVH,cAAU,UAAY,iBAAA;KACvB,OAAM;QACN,mBAOM,OAPN,YAOM,CANJ,YAKgC,oBAAA;iBAJrB,iBAAA;mFAAgB,QAAA;KACzB,OAAM;KACN,SAAQ;KACP,aAAa,qBAAA;KACb,QAAM;;IAKb,YAAyB,cAAA,EAAnB,MAAK,aAAW,CAAA;IAGtB,mBAIM,OAJN,YAIM,CAHJ,YAE+B,MAAA,WAAA,EAF/B,WACU,OAAK,EACb,gBAAe,aAAW,CAAA,EAAA,MAAA,GAAA,CAAA,CAAA;yBAMlC,mBASM,OATN,YASM,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CANJ,mBAKM,OAAA,EALD,OAAM,oDAAkD,EAAA,CAC3D,mBAAuD,MAAA,EAAnD,OAAM,sBAAoB,EAAC,sBAAmB,EAClD,mBAEI,KAAA,EAFD,OAAM,iBAAe,EAAC,sDAEzB,CAAA,EAAA,GAAA,CAAA,EAAA,CAAA"}
|
|
@@ -27,7 +27,8 @@ var WorkspaceCollection_vue_vue_type_script_setup_true_lang_default = /* @__PURE
|
|
|
27
27
|
isDarkMode: { type: Boolean },
|
|
28
28
|
fetchRegistryDocument: { type: Function },
|
|
29
29
|
telemetry: { type: Boolean },
|
|
30
|
-
onUpdateTelemetry: { type: Function }
|
|
30
|
+
onUpdateTelemetry: { type: Function },
|
|
31
|
+
options: {}
|
|
31
32
|
},
|
|
32
33
|
setup(__props) {
|
|
33
34
|
const props = __props;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorkspaceCollection.vue.script.js","names":[],"sources":["../../../../src/v2/features/collection/WorkspaceCollection.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Document collection page — tabs for Overview, Servers, Auth, Environment, Cookies, and Settings. */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport LabelInput from '@/v2/features/collection/components/LabelInput.vue'\n\nimport Tabs from './components/Tabs.vue'\n\nconst props = defineProps<RouteProps>()\n\n/**\n * Local copy of the label so we can reset on empty-blur rejection and stay in\n * sync when Vue Router reuses this component across workspace navigations.\n */\nconst workspaceTitle = ref(props.activeWorkspace.label)\n\nwatch(\n () => props.activeWorkspace.label,\n (newLabel) => {\n workspaceTitle.value = newLabel\n },\n)\n\n/** Emits the rename event on blur, or resets the input if the title is blank. */\nconst handleUpdateWorkspaceTitle = (title: string) => {\n if (title.trim() === '') {\n // Force defineModel inside LabelInput to re-sync to the original value.\n workspaceTitle.value = props.activeWorkspace.label\n return\n }\n props.eventBus.emit('workspace:update:name', title)\n}\n</script>\n\n<template>\n <div class=\"custom-scroll h-full\">\n <div class=\"w-full px-3 md:mx-auto md:max-w-180\">\n <!-- Header -->\n <div\n :aria-label=\"`title: ${activeWorkspace.label}`\"\n class=\"mx-auto flex h-fit w-full flex-row items-center gap-2 pt-14 pb-3 md:max-w-180 md:pt-6\">\n <div class=\"group relative ml-1.25\">\n <LabelInput\n v-model=\"workspaceTitle\"\n class=\"text-xl font-bold\"\n inputId=\"workspaceName\"\n placeholder=\"Untitled Workspace\"\n @blur=\"handleUpdateWorkspaceTitle\" />\n </div>\n </div>\n\n <!-- Tabs -->\n <Tabs type=\"workspace\" />\n\n <!-- Router views -->\n <div class=\"px-1.5 py-8\">\n <RouterView\n v-bind=\"props\"\n collectionType=\"workspace\" />\n </div>\n </div>\n </div>\n</template>\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"WorkspaceCollection.vue.script.js","names":[],"sources":["../../../../src/v2/features/collection/WorkspaceCollection.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Document collection page — tabs for Overview, Servers, Auth, Environment, Cookies, and Settings. */\nexport default {}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport { RouterView } from 'vue-router'\n\nimport type { RouteProps } from '@/v2/features/app/helpers/routes'\nimport LabelInput from '@/v2/features/collection/components/LabelInput.vue'\n\nimport Tabs from './components/Tabs.vue'\n\nconst props = defineProps<RouteProps>()\n\n/**\n * Local copy of the label so we can reset on empty-blur rejection and stay in\n * sync when Vue Router reuses this component across workspace navigations.\n */\nconst workspaceTitle = ref(props.activeWorkspace.label)\n\nwatch(\n () => props.activeWorkspace.label,\n (newLabel) => {\n workspaceTitle.value = newLabel\n },\n)\n\n/** Emits the rename event on blur, or resets the input if the title is blank. */\nconst handleUpdateWorkspaceTitle = (title: string) => {\n if (title.trim() === '') {\n // Force defineModel inside LabelInput to re-sync to the original value.\n workspaceTitle.value = props.activeWorkspace.label\n return\n }\n props.eventBus.emit('workspace:update:name', title)\n}\n</script>\n\n<template>\n <div class=\"custom-scroll h-full\">\n <div class=\"w-full px-3 md:mx-auto md:max-w-180\">\n <!-- Header -->\n <div\n :aria-label=\"`title: ${activeWorkspace.label}`\"\n class=\"mx-auto flex h-fit w-full flex-row items-center gap-2 pt-14 pb-3 md:max-w-180 md:pt-6\">\n <div class=\"group relative ml-1.25\">\n <LabelInput\n v-model=\"workspaceTitle\"\n class=\"text-xl font-bold\"\n inputId=\"workspaceName\"\n placeholder=\"Untitled Workspace\"\n @blur=\"handleUpdateWorkspaceTitle\" />\n </div>\n </div>\n\n <!-- Tabs -->\n <Tabs type=\"workspace\" />\n\n <!-- Router views -->\n <div class=\"px-1.5 py-8\">\n <RouterView\n v-bind=\"props\"\n collectionType=\"workspace\" />\n </div>\n </div>\n </div>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAcA,MAAM,QAAQ;;;;;EAMd,MAAM,iBAAiB,IAAI,MAAM,gBAAgB,MAAK;AAEtD,cACQ,MAAM,gBAAgB,QAC3B,aAAa;AACZ,kBAAe,QAAQ;IAE3B;;EAGA,MAAM,8BAA8B,UAAkB;AACpD,OAAI,MAAM,MAAM,KAAK,IAAI;AAEvB,mBAAe,QAAQ,MAAM,gBAAgB;AAC7C;;AAEF,SAAM,SAAS,KAAK,yBAAyB,MAAK;;;uBAKlD,mBA0BM,OA1BN,YA0BM,CAzBJ,mBAwBM,OAxBN,YAwBM;IAtBJ,mBAWM,OAAA;KAVH,cAAU,UAAY,QAAA,gBAAgB;KACvC,OAAM;QACN,mBAOM,OAPN,YAOM,CANJ,YAKuC,oBAAA;iBAJ5B,eAAA;iFAAc,QAAA;KACvB,OAAM;KACN,SAAQ;KACR,aAAY;KACX,QAAM;;IAKb,YAAyB,cAAA,EAAnB,MAAK,aAAW,CAAA;IAGtB,mBAIM,OAJN,YAIM,CAHJ,YAE+B,MAAA,WAAA,EAF/B,WACU,OAAK,EACb,gBAAe,aAAW,CAAA,EAAA,MAAA,GAAA,CAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Authentication.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/collection/components/Authentication.vue"],"names":[],"mappings":"AA+
|
|
1
|
+
{"version":3,"file":"Authentication.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/collection/components/Authentication.vue"],"names":[],"mappings":"AA+lBA,QAAA,MAAM,YAAY;;;;;;;;;;;;kGAEhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
|
|
@@ -2,7 +2,7 @@ import _plugin_vue_export_helper_default from "../../../../_virtual/_plugin-vue_
|
|
|
2
2
|
import Authentication_vue_vue_type_script_setup_true_lang_default from "./Authentication.vue.script.js";
|
|
3
3
|
/* empty css */
|
|
4
4
|
//#region src/v2/features/collection/components/Authentication.vue
|
|
5
|
-
var Authentication_default = /* @__PURE__ */ _plugin_vue_export_helper_default(Authentication_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-
|
|
5
|
+
var Authentication_default = /* @__PURE__ */ _plugin_vue_export_helper_default(Authentication_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-d3bc49bd"]]);
|
|
6
6
|
//#endregion
|
|
7
7
|
export { Authentication_default as default };
|
|
8
8
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Authentication.vue.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Authentication.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarToggle } from '@scalar/components'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport type { AuthMeta } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getActiveProxyUrl,\n getSelectedSecurity,\n getServers,\n mergeSecurity,\n} from '@scalar/workspace-store/request-example'\nimport { computed, ref, watchEffect } from 'vue'\n\nimport { AuthSelector } from '@/v2/blocks/scalar-auth-selector-block'\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { getDefaultOperationSecurityToggle } from '@/v2/features/collection/helpers/get-default-operation-security-toggle'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst {\n document,\n eventBus,\n environment,\n workspaceStore,\n documentSlug,\n path,\n method,\n collectionType,\n layout,\n} = defineProps<CollectionProps>()\n\n/**\n * Compute the authentication metadata based on the current collection type.\n * If we're working with an operation, include its path and method; otherwise, use the document scope.\n */\nconst authMeta = computed<AuthMeta>(() => {\n if (collectionType === 'operation') {\n return {\n type: 'operation',\n path: path ?? '',\n method: method ?? 'get',\n }\n }\n return { type: 'document' }\n})\n\n/**\n * Compute the operation object based on the current collection type.\n */\nconst operation = computed(() => {\n if (collectionType === 'operation') {\n // Operation not found\n if (!path || !isHttpMethod(method)) {\n return null\n }\n // Operation found, return the servers\n return getResolvedRef(document?.paths?.[path]?.[method])\n }\n return null\n})\n\n/**\n * If enabled we use/set the selected security schemes on the operation level\n */\nconst useOperationSecurity = ref(false)\nwatchEffect(() => {\n useOperationSecurity.value = getDefaultOperationSecurityToggle({\n authStore: workspaceStore.auth,\n documentName: documentSlug,\n ...authMeta.value,\n })\n})\n\nconst securitySchemes = computed(() =>\n mergeSecurity(\n document?.components?.securitySchemes ?? {},\n {},\n workspaceStore.auth,\n documentSlug,\n ),\n)\n\n/** Resolved selected security for the current collection (operation or document), with defaults applied */\nconst selectedSecurity = computed(() => {\n if (collectionType === 'operation') {\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'operation',\n documentName: documentSlug,\n path: path ?? '',\n method: method ?? 'get',\n })\n return getSelectedSecurity(\n undefined,\n fromStore,\n operation.value?.security ?? [],\n securitySchemes.value,\n )\n }\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'document',\n documentName: documentSlug,\n })\n return getSelectedSecurity(\n fromStore,\n undefined,\n document?.security ?? [],\n securitySchemes.value,\n )\n})\n\n/** Compute the security requirements for the operation or document based on the current collection type */\nconst securityRequirements = computed(() => {\n if (collectionType === 'operation') {\n return operation.value?.security ?? []\n }\n return document?.security ?? []\n})\n\n/** Compute the proxy URL for the current layout (for the electron we don't want to use the proxy by default) */\nconst proxyUrl = computed(\n () =>\n getActiveProxyUrl(\n workspaceStore.workspace['x-scalar-active-proxy'],\n layout === 'web' ? 'web' : 'other',\n ) ?? '',\n)\n\nconst servers = computed(() => {\n return getServers(operation.value?.servers ?? document?.servers, {\n documentUrl: document?.['x-scalar-original-source-url'],\n })\n})\n\n/** Grab the currently selected server for relative auth URIs */\nconst server = computed(() => {\n const documentServer = document?.['x-scalar-selected-server']\n const operationServer = operation.value?.['x-scalar-selected-server']\n const selectedServerUrl = operationServer ?? documentServer\n return (\n servers.value.find(({ url }) => url === selectedServerUrl) ??\n servers.value[0] ??\n null\n )\n})\n\n/**\n * Handles toggling operation-level security authentication. (Only for operation collections)\n * When enabled (`value` is true), overrides document-level authentication for the current operation.\n * When disabled (`value` is false), reverts to using document-level authentication instead.\n */\nconst handleToggleOperationSecurity = (value: boolean) => {\n if (authMeta.value.type !== 'operation') {\n return\n }\n\n useOperationSecurity.value = value\n\n if (value) {\n // Use the same resolved selection as the UI; unpack so the event payload is plain objects\n const { selectedSchemes } = selectedSecurity.value\n return eventBus.emit('auth:update:selected-security-schemes', {\n selectedRequirements: unpackProxyObject(selectedSchemes, { depth: 1 }),\n newSchemes: [],\n meta: authMeta.value,\n })\n }\n\n // Clear the operation security so document level authentication is used\n return eventBus.emit('auth:clear:selected-security-schemes', {\n meta: authMeta.value,\n })\n}\n</script>\n\n<template>\n <Section>\n <template #title>Authentication</template>\n <template #description>\n <template v-if=\"collectionType === 'operation'\">\n <span class=\"block\">\n Override authentication for this operation with the toggle.\n </span>\n <span class=\"mt-1 block\">\n <strong>On</strong> — Authentication below applies only to this\n operation.\n </span>\n <span class=\"mt-1 block\">\n <strong>Off</strong> — This operation uses document-level\n authentication from the OpenAPI spec.\n </span>\n </template>\n <template v-else>\n Configure authentication for this document. Selected authentication\n applies to all operations unless overridden at the operation level.\n </template>\n </template>\n <template\n v-if=\"collectionType === 'operation'\"\n #actions>\n <div class=\"flex h-8 items-center\">\n <ScalarToggle\n class=\"w-4\"\n :modelValue=\"useOperationSecurity\"\n @update:modelValue=\"handleToggleOperationSecurity\" />\n </div>\n </template>\n\n <!-- Auth Selector -->\n <div\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'cursor-not-allowed'\n \">\n <AuthSelector\n class=\"scalar-collection-auth border-none!\"\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'pointer-events-none opacity-50 mix-blend-luminosity'\n \"\n :createAnySecurityScheme=\"true\"\n :environment\n :eventBus=\"eventBus\"\n isStatic\n :meta=\"authMeta\"\n :proxyUrl=\"proxyUrl\"\n :securityRequirements=\"securityRequirements\"\n :securitySchemes\n :selectedSecurity=\"selectedSecurity\"\n :server\n title=\"Authentication\" />\n </div>\n </Section>\n</template>\n<style scoped>\n.scalar-collection-auth {\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n border-radius: var(--scalar-radius-lg);\n overflow: hidden;\n}\n</style>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"Authentication.vue.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Authentication.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarToggle } from '@scalar/components'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport type { AuthMeta } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getActiveProxyUrl,\n getSelectedSecurity,\n getServers,\n mergeSecurity,\n} from '@scalar/workspace-store/request-example'\nimport { computed, ref, toValue, watchEffect } from 'vue'\n\nimport { AuthSelector } from '@/v2/blocks/scalar-auth-selector-block'\nimport type { OAuth2Options } from '@/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue'\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { getDefaultOperationSecurityToggle } from '@/v2/features/collection/helpers/get-default-operation-security-toggle'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst {\n document,\n eventBus,\n environment,\n workspaceStore,\n documentSlug,\n path,\n method,\n collectionType,\n layout,\n options,\n} = defineProps<CollectionProps>()\n\n/**\n * Compute the authentication metadata based on the current collection type.\n * If we're working with an operation, include its path and method; otherwise, use the document scope.\n */\nconst authMeta = computed<AuthMeta>(() => {\n if (collectionType === 'operation') {\n return {\n type: 'operation',\n path: path ?? '',\n method: method ?? 'get',\n }\n }\n return { type: 'document' }\n})\n\n/**\n * Compute the operation object based on the current collection type.\n */\nconst operation = computed(() => {\n if (collectionType === 'operation') {\n // Operation not found\n if (!path || !isHttpMethod(method)) {\n return null\n }\n // Operation found, return the servers\n return getResolvedRef(document?.paths?.[path]?.[method])\n }\n return null\n})\n\n/**\n * If enabled we use/set the selected security schemes on the operation level\n */\nconst useOperationSecurity = ref(false)\nwatchEffect(() => {\n useOperationSecurity.value = getDefaultOperationSecurityToggle({\n authStore: workspaceStore.auth,\n documentName: documentSlug,\n ...authMeta.value,\n })\n})\n\nconst securitySchemes = computed(() =>\n mergeSecurity(\n document?.components?.securitySchemes ?? {},\n {},\n workspaceStore.auth,\n documentSlug,\n ),\n)\n\n/** Resolved selected security for the current collection (operation or document), with defaults applied */\nconst selectedSecurity = computed(() => {\n if (collectionType === 'operation') {\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'operation',\n documentName: documentSlug,\n path: path ?? '',\n method: method ?? 'get',\n })\n return getSelectedSecurity(\n undefined,\n fromStore,\n operation.value?.security ?? [],\n securitySchemes.value,\n )\n }\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'document',\n documentName: documentSlug,\n })\n return getSelectedSecurity(\n fromStore,\n undefined,\n document?.security ?? [],\n securitySchemes.value,\n )\n})\n\n/** Compute the security requirements for the operation or document based on the current collection type */\nconst securityRequirements = computed(() => {\n if (collectionType === 'operation') {\n return operation.value?.security ?? []\n }\n return document?.security ?? []\n})\n\n/** Compute the proxy URL for the current layout (for the electron we don't want to use the proxy by default) */\nconst proxyUrl = computed(\n () =>\n getActiveProxyUrl(\n workspaceStore.workspace['x-scalar-active-proxy'],\n layout === 'web' ? 'web' : 'other',\n ) ?? '',\n)\n\nconst servers = computed(() => {\n return getServers(operation.value?.servers ?? document?.servers, {\n documentUrl: document?.['x-scalar-original-source-url'],\n })\n})\n\n/** Grab the currently selected server for relative auth URIs */\nconst server = computed(() => {\n const documentServer = document?.['x-scalar-selected-server']\n const operationServer = operation.value?.['x-scalar-selected-server']\n const selectedServerUrl = operationServer ?? documentServer\n return (\n servers.value.find(({ url }) => url === selectedServerUrl) ??\n servers.value[0] ??\n null\n )\n})\n\n/** Auth selector only needs OAuth2-specific option overrides. */\nconst authOptions = computed<OAuth2Options | undefined>(() => {\n const routeOptions = toValue(options)\n if (!routeOptions?.oauth2RedirectUri) {\n return undefined\n }\n\n return {\n oauth2RedirectUri: routeOptions.oauth2RedirectUri,\n }\n})\n\n/**\n * Handles toggling operation-level security authentication. (Only for operation collections)\n * When enabled (`value` is true), overrides document-level authentication for the current operation.\n * When disabled (`value` is false), reverts to using document-level authentication instead.\n */\nconst handleToggleOperationSecurity = (value: boolean) => {\n if (authMeta.value.type !== 'operation') {\n return\n }\n\n useOperationSecurity.value = value\n\n if (value) {\n // Use the same resolved selection as the UI; unpack so the event payload is plain objects\n const { selectedSchemes } = selectedSecurity.value\n return eventBus.emit('auth:update:selected-security-schemes', {\n selectedRequirements: unpackProxyObject(selectedSchemes, { depth: 1 }),\n newSchemes: [],\n meta: authMeta.value,\n })\n }\n\n // Clear the operation security so document level authentication is used\n return eventBus.emit('auth:clear:selected-security-schemes', {\n meta: authMeta.value,\n })\n}\n</script>\n\n<template>\n <Section>\n <template #title>Authentication</template>\n <template #description>\n <template v-if=\"collectionType === 'operation'\">\n <span class=\"block\">\n Override authentication for this operation with the toggle.\n </span>\n <span class=\"mt-1 block\">\n <strong>On</strong> — Authentication below applies only to this\n operation.\n </span>\n <span class=\"mt-1 block\">\n <strong>Off</strong> — This operation uses document-level\n authentication from the OpenAPI spec.\n </span>\n </template>\n <template v-else>\n Configure authentication for this document. Selected authentication\n applies to all operations unless overridden at the operation level.\n </template>\n </template>\n <template\n v-if=\"collectionType === 'operation'\"\n #actions>\n <div class=\"flex h-8 items-center\">\n <ScalarToggle\n class=\"w-4\"\n :modelValue=\"useOperationSecurity\"\n @update:modelValue=\"handleToggleOperationSecurity\" />\n </div>\n </template>\n\n <!-- Auth Selector -->\n <div\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'cursor-not-allowed'\n \">\n <AuthSelector\n class=\"scalar-collection-auth border-none!\"\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'pointer-events-none opacity-50 mix-blend-luminosity'\n \"\n :createAnySecurityScheme=\"true\"\n :environment\n :eventBus=\"eventBus\"\n isStatic\n :meta=\"authMeta\"\n :options=\"authOptions\"\n :proxyUrl=\"proxyUrl\"\n :securityRequirements=\"securityRequirements\"\n :securitySchemes\n :selectedSecurity=\"selectedSecurity\"\n :server\n title=\"Authentication\" />\n </div>\n </Section>\n</template>\n<style scoped>\n.scalar-collection-auth {\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n border-radius: var(--scalar-radius-lg);\n overflow: hidden;\n}\n</style>\n"],"mappings":""}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import AuthSelector_default from "../../../blocks/scalar-auth-selector-block/components/AuthSelector.vue.js";
|
|
2
2
|
import { getDefaultOperationSecurityToggle } from "../helpers/get-default-operation-security-toggle.js";
|
|
3
3
|
import Section_default from "../../settings/components/Section.vue.js";
|
|
4
|
-
import { Fragment, computed, createBlock, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, ref, unref, watchEffect, withCtx } from "vue";
|
|
4
|
+
import { Fragment, computed, createBlock, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, ref, toValue, unref, watchEffect, withCtx } from "vue";
|
|
5
5
|
import { ScalarToggle } from "@scalar/components";
|
|
6
6
|
import { getActiveProxyUrl, getSelectedSecurity, getServers, mergeSecurity } from "@scalar/workspace-store/request-example";
|
|
7
7
|
import { getResolvedRef } from "@scalar/workspace-store/helpers/get-resolved-ref";
|
|
@@ -29,6 +29,7 @@ var Authentication_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
|
|
|
29
29
|
fetchRegistryDocument: { type: Function },
|
|
30
30
|
telemetry: { type: Boolean },
|
|
31
31
|
onUpdateTelemetry: { type: Function },
|
|
32
|
+
options: {},
|
|
32
33
|
collectionType: {}
|
|
33
34
|
},
|
|
34
35
|
setup(__props) {
|
|
@@ -95,6 +96,12 @@ var Authentication_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
|
|
|
95
96
|
const selectedServerUrl = operation.value?.["x-scalar-selected-server"] ?? documentServer;
|
|
96
97
|
return servers.value.find(({ url }) => url === selectedServerUrl) ?? servers.value[0] ?? null;
|
|
97
98
|
});
|
|
99
|
+
/** Auth selector only needs OAuth2-specific option overrides. */
|
|
100
|
+
const authOptions = computed(() => {
|
|
101
|
+
const routeOptions = toValue(__props.options);
|
|
102
|
+
if (!routeOptions?.oauth2RedirectUri) return;
|
|
103
|
+
return { oauth2RedirectUri: routeOptions.oauth2RedirectUri };
|
|
104
|
+
});
|
|
98
105
|
/**
|
|
99
106
|
* Handles toggling operation-level security authentication. (Only for operation collections)
|
|
100
107
|
* When enabled (`value` is true), overrides document-level authentication for the current operation.
|
|
@@ -128,6 +135,7 @@ var Authentication_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
|
|
|
128
135
|
eventBus: __props.eventBus,
|
|
129
136
|
isStatic: "",
|
|
130
137
|
meta: authMeta.value,
|
|
138
|
+
options: authOptions.value,
|
|
131
139
|
proxyUrl: proxyUrl.value,
|
|
132
140
|
securityRequirements: securityRequirements.value,
|
|
133
141
|
securitySchemes: securitySchemes.value,
|
|
@@ -139,6 +147,7 @@ var Authentication_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
|
|
|
139
147
|
"environment",
|
|
140
148
|
"eventBus",
|
|
141
149
|
"meta",
|
|
150
|
+
"options",
|
|
142
151
|
"proxyUrl",
|
|
143
152
|
"securityRequirements",
|
|
144
153
|
"securitySchemes",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Authentication.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Authentication.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarToggle } from '@scalar/components'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport type { AuthMeta } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getActiveProxyUrl,\n getSelectedSecurity,\n getServers,\n mergeSecurity,\n} from '@scalar/workspace-store/request-example'\nimport { computed, ref, watchEffect } from 'vue'\n\nimport { AuthSelector } from '@/v2/blocks/scalar-auth-selector-block'\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { getDefaultOperationSecurityToggle } from '@/v2/features/collection/helpers/get-default-operation-security-toggle'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst {\n document,\n eventBus,\n environment,\n workspaceStore,\n documentSlug,\n path,\n method,\n collectionType,\n layout,\n} = defineProps<CollectionProps>()\n\n/**\n * Compute the authentication metadata based on the current collection type.\n * If we're working with an operation, include its path and method; otherwise, use the document scope.\n */\nconst authMeta = computed<AuthMeta>(() => {\n if (collectionType === 'operation') {\n return {\n type: 'operation',\n path: path ?? '',\n method: method ?? 'get',\n }\n }\n return { type: 'document' }\n})\n\n/**\n * Compute the operation object based on the current collection type.\n */\nconst operation = computed(() => {\n if (collectionType === 'operation') {\n // Operation not found\n if (!path || !isHttpMethod(method)) {\n return null\n }\n // Operation found, return the servers\n return getResolvedRef(document?.paths?.[path]?.[method])\n }\n return null\n})\n\n/**\n * If enabled we use/set the selected security schemes on the operation level\n */\nconst useOperationSecurity = ref(false)\nwatchEffect(() => {\n useOperationSecurity.value = getDefaultOperationSecurityToggle({\n authStore: workspaceStore.auth,\n documentName: documentSlug,\n ...authMeta.value,\n })\n})\n\nconst securitySchemes = computed(() =>\n mergeSecurity(\n document?.components?.securitySchemes ?? {},\n {},\n workspaceStore.auth,\n documentSlug,\n ),\n)\n\n/** Resolved selected security for the current collection (operation or document), with defaults applied */\nconst selectedSecurity = computed(() => {\n if (collectionType === 'operation') {\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'operation',\n documentName: documentSlug,\n path: path ?? '',\n method: method ?? 'get',\n })\n return getSelectedSecurity(\n undefined,\n fromStore,\n operation.value?.security ?? [],\n securitySchemes.value,\n )\n }\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'document',\n documentName: documentSlug,\n })\n return getSelectedSecurity(\n fromStore,\n undefined,\n document?.security ?? [],\n securitySchemes.value,\n )\n})\n\n/** Compute the security requirements for the operation or document based on the current collection type */\nconst securityRequirements = computed(() => {\n if (collectionType === 'operation') {\n return operation.value?.security ?? []\n }\n return document?.security ?? []\n})\n\n/** Compute the proxy URL for the current layout (for the electron we don't want to use the proxy by default) */\nconst proxyUrl = computed(\n () =>\n getActiveProxyUrl(\n workspaceStore.workspace['x-scalar-active-proxy'],\n layout === 'web' ? 'web' : 'other',\n ) ?? '',\n)\n\nconst servers = computed(() => {\n return getServers(operation.value?.servers ?? document?.servers, {\n documentUrl: document?.['x-scalar-original-source-url'],\n })\n})\n\n/** Grab the currently selected server for relative auth URIs */\nconst server = computed(() => {\n const documentServer = document?.['x-scalar-selected-server']\n const operationServer = operation.value?.['x-scalar-selected-server']\n const selectedServerUrl = operationServer ?? documentServer\n return (\n servers.value.find(({ url }) => url === selectedServerUrl) ??\n servers.value[0] ??\n null\n )\n})\n\n/**\n * Handles toggling operation-level security authentication. (Only for operation collections)\n * When enabled (`value` is true), overrides document-level authentication for the current operation.\n * When disabled (`value` is false), reverts to using document-level authentication instead.\n */\nconst handleToggleOperationSecurity = (value: boolean) => {\n if (authMeta.value.type !== 'operation') {\n return\n }\n\n useOperationSecurity.value = value\n\n if (value) {\n // Use the same resolved selection as the UI; unpack so the event payload is plain objects\n const { selectedSchemes } = selectedSecurity.value\n return eventBus.emit('auth:update:selected-security-schemes', {\n selectedRequirements: unpackProxyObject(selectedSchemes, { depth: 1 }),\n newSchemes: [],\n meta: authMeta.value,\n })\n }\n\n // Clear the operation security so document level authentication is used\n return eventBus.emit('auth:clear:selected-security-schemes', {\n meta: authMeta.value,\n })\n}\n</script>\n\n<template>\n <Section>\n <template #title>Authentication</template>\n <template #description>\n <template v-if=\"collectionType === 'operation'\">\n <span class=\"block\">\n Override authentication for this operation with the toggle.\n </span>\n <span class=\"mt-1 block\">\n <strong>On</strong> — Authentication below applies only to this\n operation.\n </span>\n <span class=\"mt-1 block\">\n <strong>Off</strong> — This operation uses document-level\n authentication from the OpenAPI spec.\n </span>\n </template>\n <template v-else>\n Configure authentication for this document. Selected authentication\n applies to all operations unless overridden at the operation level.\n </template>\n </template>\n <template\n v-if=\"collectionType === 'operation'\"\n #actions>\n <div class=\"flex h-8 items-center\">\n <ScalarToggle\n class=\"w-4\"\n :modelValue=\"useOperationSecurity\"\n @update:modelValue=\"handleToggleOperationSecurity\" />\n </div>\n </template>\n\n <!-- Auth Selector -->\n <div\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'cursor-not-allowed'\n \">\n <AuthSelector\n class=\"scalar-collection-auth border-none!\"\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'pointer-events-none opacity-50 mix-blend-luminosity'\n \"\n :createAnySecurityScheme=\"true\"\n :environment\n :eventBus=\"eventBus\"\n isStatic\n :meta=\"authMeta\"\n :proxyUrl=\"proxyUrl\"\n :securityRequirements=\"securityRequirements\"\n :securitySchemes\n :selectedSecurity=\"selectedSecurity\"\n :server\n title=\"Authentication\" />\n </div>\n </Section>\n</template>\n<style scoped>\n.scalar-collection-auth {\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n border-radius: var(--scalar-radius-lg);\n overflow: hidden;\n}\n</style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Authentication.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Authentication.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarToggle } from '@scalar/components'\nimport { isHttpMethod } from '@scalar/helpers/http/is-http-method'\nimport type { AuthMeta } from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { unpackProxyObject } from '@scalar/workspace-store/helpers/unpack-proxy'\nimport {\n getActiveProxyUrl,\n getSelectedSecurity,\n getServers,\n mergeSecurity,\n} from '@scalar/workspace-store/request-example'\nimport { computed, ref, toValue, watchEffect } from 'vue'\n\nimport { AuthSelector } from '@/v2/blocks/scalar-auth-selector-block'\nimport type { OAuth2Options } from '@/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue'\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { getDefaultOperationSecurityToggle } from '@/v2/features/collection/helpers/get-default-operation-security-toggle'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst {\n document,\n eventBus,\n environment,\n workspaceStore,\n documentSlug,\n path,\n method,\n collectionType,\n layout,\n options,\n} = defineProps<CollectionProps>()\n\n/**\n * Compute the authentication metadata based on the current collection type.\n * If we're working with an operation, include its path and method; otherwise, use the document scope.\n */\nconst authMeta = computed<AuthMeta>(() => {\n if (collectionType === 'operation') {\n return {\n type: 'operation',\n path: path ?? '',\n method: method ?? 'get',\n }\n }\n return { type: 'document' }\n})\n\n/**\n * Compute the operation object based on the current collection type.\n */\nconst operation = computed(() => {\n if (collectionType === 'operation') {\n // Operation not found\n if (!path || !isHttpMethod(method)) {\n return null\n }\n // Operation found, return the servers\n return getResolvedRef(document?.paths?.[path]?.[method])\n }\n return null\n})\n\n/**\n * If enabled we use/set the selected security schemes on the operation level\n */\nconst useOperationSecurity = ref(false)\nwatchEffect(() => {\n useOperationSecurity.value = getDefaultOperationSecurityToggle({\n authStore: workspaceStore.auth,\n documentName: documentSlug,\n ...authMeta.value,\n })\n})\n\nconst securitySchemes = computed(() =>\n mergeSecurity(\n document?.components?.securitySchemes ?? {},\n {},\n workspaceStore.auth,\n documentSlug,\n ),\n)\n\n/** Resolved selected security for the current collection (operation or document), with defaults applied */\nconst selectedSecurity = computed(() => {\n if (collectionType === 'operation') {\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'operation',\n documentName: documentSlug,\n path: path ?? '',\n method: method ?? 'get',\n })\n return getSelectedSecurity(\n undefined,\n fromStore,\n operation.value?.security ?? [],\n securitySchemes.value,\n )\n }\n const fromStore = workspaceStore.auth.getAuthSelectedSchemas({\n type: 'document',\n documentName: documentSlug,\n })\n return getSelectedSecurity(\n fromStore,\n undefined,\n document?.security ?? [],\n securitySchemes.value,\n )\n})\n\n/** Compute the security requirements for the operation or document based on the current collection type */\nconst securityRequirements = computed(() => {\n if (collectionType === 'operation') {\n return operation.value?.security ?? []\n }\n return document?.security ?? []\n})\n\n/** Compute the proxy URL for the current layout (for the electron we don't want to use the proxy by default) */\nconst proxyUrl = computed(\n () =>\n getActiveProxyUrl(\n workspaceStore.workspace['x-scalar-active-proxy'],\n layout === 'web' ? 'web' : 'other',\n ) ?? '',\n)\n\nconst servers = computed(() => {\n return getServers(operation.value?.servers ?? document?.servers, {\n documentUrl: document?.['x-scalar-original-source-url'],\n })\n})\n\n/** Grab the currently selected server for relative auth URIs */\nconst server = computed(() => {\n const documentServer = document?.['x-scalar-selected-server']\n const operationServer = operation.value?.['x-scalar-selected-server']\n const selectedServerUrl = operationServer ?? documentServer\n return (\n servers.value.find(({ url }) => url === selectedServerUrl) ??\n servers.value[0] ??\n null\n )\n})\n\n/** Auth selector only needs OAuth2-specific option overrides. */\nconst authOptions = computed<OAuth2Options | undefined>(() => {\n const routeOptions = toValue(options)\n if (!routeOptions?.oauth2RedirectUri) {\n return undefined\n }\n\n return {\n oauth2RedirectUri: routeOptions.oauth2RedirectUri,\n }\n})\n\n/**\n * Handles toggling operation-level security authentication. (Only for operation collections)\n * When enabled (`value` is true), overrides document-level authentication for the current operation.\n * When disabled (`value` is false), reverts to using document-level authentication instead.\n */\nconst handleToggleOperationSecurity = (value: boolean) => {\n if (authMeta.value.type !== 'operation') {\n return\n }\n\n useOperationSecurity.value = value\n\n if (value) {\n // Use the same resolved selection as the UI; unpack so the event payload is plain objects\n const { selectedSchemes } = selectedSecurity.value\n return eventBus.emit('auth:update:selected-security-schemes', {\n selectedRequirements: unpackProxyObject(selectedSchemes, { depth: 1 }),\n newSchemes: [],\n meta: authMeta.value,\n })\n }\n\n // Clear the operation security so document level authentication is used\n return eventBus.emit('auth:clear:selected-security-schemes', {\n meta: authMeta.value,\n })\n}\n</script>\n\n<template>\n <Section>\n <template #title>Authentication</template>\n <template #description>\n <template v-if=\"collectionType === 'operation'\">\n <span class=\"block\">\n Override authentication for this operation with the toggle.\n </span>\n <span class=\"mt-1 block\">\n <strong>On</strong> — Authentication below applies only to this\n operation.\n </span>\n <span class=\"mt-1 block\">\n <strong>Off</strong> — This operation uses document-level\n authentication from the OpenAPI spec.\n </span>\n </template>\n <template v-else>\n Configure authentication for this document. Selected authentication\n applies to all operations unless overridden at the operation level.\n </template>\n </template>\n <template\n v-if=\"collectionType === 'operation'\"\n #actions>\n <div class=\"flex h-8 items-center\">\n <ScalarToggle\n class=\"w-4\"\n :modelValue=\"useOperationSecurity\"\n @update:modelValue=\"handleToggleOperationSecurity\" />\n </div>\n </template>\n\n <!-- Auth Selector -->\n <div\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'cursor-not-allowed'\n \">\n <AuthSelector\n class=\"scalar-collection-auth border-none!\"\n :class=\"\n collectionType === 'operation' &&\n !useOperationSecurity &&\n 'pointer-events-none opacity-50 mix-blend-luminosity'\n \"\n :createAnySecurityScheme=\"true\"\n :environment\n :eventBus=\"eventBus\"\n isStatic\n :meta=\"authMeta\"\n :options=\"authOptions\"\n :proxyUrl=\"proxyUrl\"\n :securityRequirements=\"securityRequirements\"\n :securitySchemes\n :selectedSecurity=\"selectedSecurity\"\n :server\n title=\"Authentication\" />\n </div>\n </Section>\n</template>\n<style scoped>\n.scalar-collection-auth {\n border: var(--scalar-border-width) solid var(--scalar-border-color);\n border-radius: var(--scalar-radius-lg);\n overflow: hidden;\n}\n</style>\n"],"mappings":"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"}
|
|
@@ -21,6 +21,7 @@ var Cookies_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ define
|
|
|
21
21
|
fetchRegistryDocument: { type: Function },
|
|
22
22
|
telemetry: { type: Boolean },
|
|
23
23
|
onUpdateTelemetry: { type: Function },
|
|
24
|
+
options: {},
|
|
24
25
|
collectionType: {}
|
|
25
26
|
},
|
|
26
27
|
setup(__props) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Cookies.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Cookies.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Cookies section for the collection.\n * Renders document or workspace cookies and lets users manage key-value data\n * sent with API requests (e.g. session tokens, auth, preferences).\n */\nexport default {\n name: 'Cookies',\n}\n</script>\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { CookiesTable } from '@/v2/features/global-cookies'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst { collectionType, eventBus, document, workspaceStore } =\n defineProps<CollectionProps>()\n\nconst cookies = computed(() => {\n return (\n (collectionType === 'document'\n ? document['x-scalar-cookies']\n : workspaceStore.workspace['x-scalar-cookies']) ?? []\n )\n})\n</script>\n\n<template>\n <Section v-if=\"collectionType !== 'operation'\">\n <template #title>Cookies</template>\n <template #description>\n Manage your collection's cookies here.<br />Cookies allow you to store and\n send key-value data with your API requests—often used for things like\n session tokens, authentication, and saving user preferences.<br />\n </template>\n <CookiesTable\n :collectionType=\"collectionType\"\n :cookies=\"cookies\"\n :eventBus=\"eventBus\" />\n </Section>\n</template>\n"],"mappings":";;;;CAOE,MAAM
|
|
1
|
+
{"version":3,"file":"Cookies.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Cookies.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Cookies section for the collection.\n * Renders document or workspace cookies and lets users manage key-value data\n * sent with API requests (e.g. session tokens, auth, preferences).\n */\nexport default {\n name: 'Cookies',\n}\n</script>\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { CookiesTable } from '@/v2/features/global-cookies'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst { collectionType, eventBus, document, workspaceStore } =\n defineProps<CollectionProps>()\n\nconst cookies = computed(() => {\n return (\n (collectionType === 'document'\n ? document['x-scalar-cookies']\n : workspaceStore.workspace['x-scalar-cookies']) ?? []\n )\n})\n</script>\n\n<template>\n <Section v-if=\"collectionType !== 'operation'\">\n <template #title>Cookies</template>\n <template #description>\n Manage your collection's cookies here.<br />Cookies allow you to store and\n send key-value data with your API requests—often used for things like\n session tokens, authentication, and saving user preferences.<br />\n </template>\n <CookiesTable\n :collectionType=\"collectionType\"\n :cookies=\"cookies\"\n :eventBus=\"eventBus\" />\n </Section>\n</template>\n"],"mappings":";;;;CAOE,MAAM;;;;;;;;;;;;;;;;;;;;;;;EAaR,MAAM,UAAU,eAAe;AAC7B,WACG,QAAA,mBAAmB,aAChB,QAAA,SAAS,sBACT,QAAA,eAAe,UAAU,wBAAwB,EAAC;IAEzD;;UAIgB,QAAA,mBAAc,eAAA,WAAA,EAA7B,YAWU,iBAAA,EAAA,KAAA,GAAA,EAAA;IAVG,OAAK,cAAQ,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAAP,WAAO,GAAA,CAAA,EAAA,CAAA;IACb,aAAW,cACkB,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA;qBADjB,2CACiB,GAAA;KAAA,mBAAM,MAAA,MAAA,MAAA,GAAA;qBAAA,qKAEgB,GAAA;KAAA,mBAAM,MAAA,MAAA,MAAA,GAAA;;2BAK3C,CAHzB,YAGyB,MAAA,qBAAA,EAAA;KAFtB,gBAAgB,QAAA;KAChB,SAAS,QAAA;KACT,UAAU,QAAA"}
|
|
@@ -55,6 +55,7 @@ var Editor_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineC
|
|
|
55
55
|
fetchRegistryDocument: { type: Function },
|
|
56
56
|
telemetry: { type: Boolean },
|
|
57
57
|
onUpdateTelemetry: { type: Function },
|
|
58
|
+
options: {},
|
|
58
59
|
collectionType: {}
|
|
59
60
|
},
|
|
60
61
|
setup(__props) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Editor.vue.script.js","names":[],"sources":["../../../../../../src/v2/features/collection/components/Editor/Editor.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarHotkey, useLoadingState } from '@scalar/components'\nimport { debounce } from '@scalar/helpers/general/debounce'\nimport { isObject } from '@scalar/helpers/object/is-object'\nimport { ScalarIconArrowsIn, ScalarIconArrowsOut } from '@scalar/icons'\nimport * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n ref,\n shallowRef,\n watch,\n} from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { useEditor, useJsonPointerLinkSupport } from '@/v2/features/editor'\nimport { createJsonModel } from '@/v2/features/editor/helpers/json/create-json-model'\nimport { createYamlModel } from '@/v2/features/editor/helpers/yaml/create-yaml-model'\nimport { useEditorMarkers } from '@/v2/features/editor/hooks/use-editor-markers'\n\nimport EditorDiagnosticsPanel from './components/EditorDiagnosticsPanel.vue'\nimport EditorSavePanel from './components/EditorSavePanel.vue'\nimport { getDiagnosticCounts } from './helpers/get-diagnostic-counts'\nimport { getOperationContext } from './helpers/get-operation-context'\nimport { getVisibleDiagnostics } from './helpers/get-visible-diagnostics'\nimport { parseEditorObject } from './helpers/parse-editor-object'\nimport { stringifyDocument } from './helpers/stringify-document'\nimport { useEditorState } from './hooks/use-editor-state'\n\nconst { collectionType, documentSlug, method, path, workspaceStore } =\n defineProps<CollectionProps>()\n\nconst MAX_VISIBLE_DIAGNOSTICS = 6\nconst EDITOR_PERSIST_DEBOUNCE_KEY = 'editor:replace-document'\n\nconst monacoEditorRef = ref<HTMLElement>()\nconst editorApi = shallowRef<ReturnType<typeof useEditor>>()\n\nconst saveLoader = useLoadingState()\nconst {\n isAutoSaveEnabled,\n isDirty,\n editorLanguage,\n isDiagnosticsPaneExpanded,\n isEditorMaximized,\n isYamlMode,\n editorBottomPadding,\n editorRootClass,\n getLanguageToggleClass,\n toggleEditorMaximized,\n} = useEditorState()\n\nconst jsonModel = createJsonModel()\nconst yamlModel = createYamlModel()\n\nconst selectedLanguage = ref<'json' | 'yaml'>('json')\n\nconst currentModel = computed(() => {\n return selectedLanguage.value === 'json' ? jsonModel : yamlModel\n})\n\nconst monacoEditorInstance = computed(() => editorApi.value?.editor)\nconst { markers: diagnostics } = useEditorMarkers(monacoEditorInstance)\n\nconst syncEditorBottomPadding = () => {\n editorApi.value?.editor.updateOptions({\n padding: {\n top: 0,\n bottom: editorBottomPadding.value,\n },\n })\n}\n\nconst diagnosticCounts = computed(() => getDiagnosticCounts(diagnostics.value))\nconst visibleDiagnostics = computed(() =>\n getVisibleDiagnostics(diagnostics.value, MAX_VISIBLE_DIAGNOSTICS),\n)\n\nconst focusDiagnostic = (marker: monaco.editor.IMarker) => {\n const editor = editorApi.value?.editor\n if (!editor) {\n return\n }\n editor.setSelection({\n startLineNumber: marker.startLineNumber,\n startColumn: marker.startColumn,\n endLineNumber: marker.endLineNumber,\n endColumn: marker.endColumn,\n })\n editor.revealPositionInCenter({\n lineNumber: marker.startLineNumber,\n column: marker.startColumn,\n })\n}\n\nconst getEditorValue = (): string | null => currentModel.value.model.getValue()\n\n/** Value from the editor for a specific language (use when switching to avoid reading the wrong model). */\nconst getEditorValueForLanguage = (language: 'json' | 'yaml'): string | null =>\n (language === 'json' ? jsonModel : yamlModel).model.getValue()\n\nconst getDocumentValue = async (\n language?: 'json' | 'yaml',\n): Promise<string> => {\n const document = await workspaceStore.getEditableDocument(documentSlug)\n return stringifyDocument(document, language ?? selectedLanguage.value)\n}\n\nconst debouncedPersist = debounce({ delay: 1500 })\n\nconst applyProgrammaticEditorValue = (value: string): void => {\n // Cancel pending auto-save work so synthetic model updates do not persist stale data.\n debouncedPersist.cleanup()\n editorApi.value?.setValue(value, true)\n}\n\nconst loadDocumentIntoEditor = async () => {\n applyProgrammaticEditorValue(await getDocumentValue())\n isDirty.value = false\n await focusOperation()\n}\n\nconst formatDocument = async () => {\n await editorApi.value?.formatDocument()\n}\n\nconst focusOperation = async () => {\n const operationContext = getOperationContext(path, method)\n if (!operationContext) {\n return\n }\n\n await editorApi.value?.focusPath([\n 'paths',\n operationContext.path,\n operationContext.method,\n ])\n}\n\nconst persistEditorToWorkspace = async (value: string) => {\n const parsed = parseEditorObject(value, editorLanguage.value)\n if (!parsed) {\n const firstError = diagnostics.value.find(\n (m) => m.severity === monaco.MarkerSeverity.Error,\n )\n if (firstError) {\n focusDiagnostic(firstError)\n }\n await saveLoader.invalidate()\n return\n }\n\n saveLoader.start()\n await workspaceStore.replaceDocument(documentSlug, parsed)\n isDirty.value = false\n await saveLoader.validate({ duration: 900 })\n}\n\nconst saveNow = async () => {\n const value = getEditorValue()\n if (!value) {\n return\n }\n await persistEditorToWorkspace(value)\n}\n\nconst handleEditorChange = (value: string) => {\n isDirty.value = true\n\n if (!isAutoSaveEnabled.value) {\n return\n }\n\n debouncedPersist.execute(EDITOR_PERSIST_DEBOUNCE_KEY, () =>\n persistEditorToWorkspace(value),\n )\n}\n\nconst focusOperationServers = async () => {\n const operationContext = getOperationContext(path, method)\n if (!operationContext) {\n return\n }\n\n const value = getEditorValue()\n if (!value) {\n return\n }\n\n const parsed = parseEditorObject(value, editorLanguage.value)\n\n if (!parsed || !isObject(parsed.paths)) {\n return\n }\n\n const pathsObject = parsed.paths as Record<string, unknown>\n const operationPathItem = pathsObject[operationContext.path]\n if (!isObject(operationPathItem)) {\n return\n }\n\n const operation = operationPathItem[operationContext.method]\n if (!isObject(operation)) {\n return\n }\n\n // Add default servers if not present\n operation.servers ??= []\n\n // Update the editor value\n editorApi.value?.setValue(stringifyDocument(parsed, editorLanguage.value))\n await editorApi.value?.focusPath([\n 'paths',\n operationContext.path,\n operationContext.method,\n 'servers',\n ])\n}\n\nuseJsonPointerLinkSupport(editorApi, currentModel)\n\nonMounted(() => {\n editorApi.value = useEditor({\n element: monacoEditorRef.value ?? document.createElement('div'),\n onChange: handleEditorChange,\n model: currentModel,\n actions: [\n {\n id: 'scalar.editor.focusOperation',\n label: 'Focus Operation',\n keybindings: [monaco.KeyMod.Alt | monaco.KeyCode.KeyO],\n run: async () => {\n await focusOperation()\n },\n },\n {\n id: 'scalar.editor.focusOperationServers',\n label: 'Focus Operation Servers',\n keybindings: [monaco.KeyMod.Alt | monaco.KeyCode.KeyS],\n run: async () => {\n await focusOperationServers()\n },\n },\n {\n id: 'scalar.editor.formatDocument',\n label: 'Format Document',\n keybindings: [\n monaco.KeyMod.Alt | monaco.KeyMod.Shift | monaco.KeyCode.KeyF,\n ],\n run: async () => {\n await formatDocument()\n },\n },\n ],\n })\n\n syncEditorBottomPadding()\n void loadDocumentIntoEditor()\n})\n\nonBeforeUnmount(() => {\n debouncedPersist.cleanup()\n\n // Persist if there is a pending save\n if (isDirty.value && isAutoSaveEnabled.value) {\n void saveNow()\n }\n editorApi.value?.dispose?.()\n // Dispose models created at setup; useEditor only disposes the editor widget, not external models.\n jsonModel.model.dispose()\n yamlModel.model.dispose()\n})\n\nwatch(() => documentSlug, loadDocumentIntoEditor)\n\nwatch(\n () => [path, method] as const,\n async () => {\n await focusOperation()\n },\n)\n\nwatch(isDiagnosticsPaneExpanded, () => {\n syncEditorBottomPadding()\n})\n\nwatch(editorLanguage, async (nextLanguage, previousLanguage) => {\n const wasDirty = isDirty.value\n // Read from the previous model before switching; getEditorValue() would use currentModel\n // which changes with selectedLanguage, so we would read the (empty) new model otherwise.\n const value = getEditorValueForLanguage(previousLanguage ?? 'json')\n if (!value) {\n selectedLanguage.value = nextLanguage\n await nextTick()\n await focusOperation()\n return\n }\n\n const parsed = parseEditorObject(value, previousLanguage ?? 'json')\n selectedLanguage.value = nextLanguage\n await nextTick()\n if (parsed) {\n applyProgrammaticEditorValue(stringifyDocument(parsed, nextLanguage))\n isDirty.value = wasDirty\n }\n await focusOperation()\n})\n\nwatch(\n isAutoSaveEnabled,\n (isEnabled) => {\n if (!isEnabled) {\n debouncedPersist.cleanup()\n return\n }\n\n if (isDirty.value) {\n const value = getEditorValue()\n if (!value) {\n return\n }\n debouncedPersist.execute(EDITOR_PERSIST_DEBOUNCE_KEY, () =>\n persistEditorToWorkspace(value),\n )\n }\n },\n { flush: 'post' },\n)\n</script>\n\n<template>\n <div\n v-if=\"\n collectionType === 'operation' &&\n getOperationContext(path, method) !== null\n \"\n class=\"flex w-full min-w-0 flex-1 flex-col gap-2\"\n :class=\"editorRootClass\">\n <div\n class=\"grid grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3\">\n <div\n class=\"flex min-w-0 items-center gap-1 overflow-x-auto whitespace-nowrap\">\n <span class=\"text-c-2 text-xs font-medium whitespace-nowrap\">\n Shortcuts\n </span>\n\n <ScalarButton\n class=\"whitespace-nowrap\"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"focusOperation\">\n <span>Operation</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarHotkey\n hotkey=\"O\"\n :modifier=\"['Alt']\" />\n </span>\n </ScalarButton>\n\n <ScalarButton\n class=\"whitespace-nowrap\"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"focusOperationServers\">\n <span>Servers</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarHotkey\n hotkey=\"S\"\n :modifier=\"['Alt']\" />\n </span>\n </ScalarButton>\n </div>\n\n <div\n aria-label=\"Editor language\"\n class=\"bg-b-1 shadow-border flex items-center justify-self-center overflow-hidden rounded-lg p-0.5\"\n role=\"tablist\">\n <ScalarButton\n :aria-selected=\"!isYamlMode\"\n :class=\"getLanguageToggleClass(!isYamlMode)\"\n role=\"tab\"\n size=\"xs\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"editorLanguage = 'json'\">\n JSON\n </ScalarButton>\n <ScalarButton\n :aria-selected=\"isYamlMode\"\n :class=\"getLanguageToggleClass(isYamlMode)\"\n role=\"tab\"\n size=\"xs\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"editorLanguage = 'yaml'\">\n YAML\n </ScalarButton>\n </div>\n\n <div class=\"flex min-w-0 shrink-0 items-center gap-2 justify-self-end\">\n <ScalarButton\n size=\"xs\"\n variant=\"ghost\"\n @click=\"formatDocument\">\n <span>Format {{ isYamlMode ? 'YAML' : 'JSON' }}</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarHotkey\n hotkey=\"F\"\n :modifier=\"['Alt', 'Shift']\" />\n </span>\n </ScalarButton>\n <ScalarButton\n :aria-label=\"\n isEditorMaximized ? 'Restore editor size' : 'Maximize editor'\n \"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"toggleEditorMaximized\">\n <span>{{ isEditorMaximized ? 'Restore' : 'Maximize' }}</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarIconArrowsIn\n v-if=\"isEditorMaximized\"\n class=\"size-3.5\" />\n <ScalarIconArrowsOut\n v-else\n class=\"size-3.5\" />\n </span>\n </ScalarButton>\n </div>\n </div>\n\n <div class=\"flex min-h-0 w-full min-w-0 flex-1 rounded-lg border\">\n <div\n class=\"relative w-full min-w-0 flex-1\"\n :class=\"isEditorMaximized ? 'h-full min-h-0' : 'h-125'\">\n <div class=\"pointer-events-none absolute top-2 right-2 z-10\">\n <EditorSavePanel\n :isAutoSaveEnabled=\"isAutoSaveEnabled\"\n :isDirty=\"isDirty\"\n :saveLoader=\"saveLoader\"\n @saveNow=\"saveNow\"\n @update:isAutoSaveEnabled=\"isAutoSaveEnabled = $event\" />\n </div>\n\n <EditorDiagnosticsPanel\n :diagnosticCounts=\"diagnosticCounts\"\n :expanded=\"isDiagnosticsPaneExpanded\"\n :visibleDiagnostics=\"visibleDiagnostics\"\n @focusDiagnostic=\"focusDiagnostic\"\n @toggle=\"isDiagnosticsPaneExpanded = !isDiagnosticsPaneExpanded\" />\n\n <div\n ref=\"monacoEditorRef\"\n class=\"h-full w-full min-w-0 flex-1 [&_.monaco-editor]:rounded-lg [&_.overflow-guard]:rounded-lg\" />\n </div>\n </div>\n </div>\n <div v-else>No operation context found</div>\n</template>\n<style scoped>\n.editor-container {\n width: 100%;\n height: 100%;\n}\n\n:deep(.json-path-highlight) {\n background-color: rgba(255, 200, 0, 0.35);\n border-radius: 4px;\n}\n\n:deep(.json-focus-highlight) {\n background-color: color-mix(\n in srgb,\n var(--scalar-color-accent, #24b47e) 18%,\n transparent\n );\n border-radius: 4px;\n}\n</style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,IAAM,0BAA0B;AAChC,IAAM,8BAA8B;;;;;;;;;;;;;;;;;;;;;;;;EAEpC,MAAM,kBAAkB,KAAiB;EACzC,MAAM,YAAY,YAAyC;EAE3D,MAAM,aAAa,iBAAgB;EACnC,MAAM,EACJ,mBACA,SACA,gBACA,2BACA,mBACA,YACA,qBACA,iBACA,wBACA,0BACE,gBAAe;EAEnB,MAAM,YAAY,iBAAgB;EAClC,MAAM,YAAY,iBAAgB;EAElC,MAAM,mBAAmB,IAAqB,OAAM;EAEpD,MAAM,eAAe,eAAe;AAClC,UAAO,iBAAiB,UAAU,SAAS,YAAY;IACxD;EAGD,MAAM,EAAE,SAAS,gBAAgB,iBADJ,eAAe,UAAU,OAAO,OAAM,CACG;EAEtE,MAAM,gCAAgC;AACpC,aAAU,OAAO,OAAO,cAAc,EACpC,SAAS;IACP,KAAK;IACL,QAAQ,oBAAoB;IAC7B,EACF,CAAA;;EAGH,MAAM,mBAAmB,eAAe,oBAAoB,YAAY,MAAM,CAAA;EAC9E,MAAM,qBAAqB,eACzB,sBAAsB,YAAY,OAAO,wBAAwB,CACnE;EAEA,MAAM,mBAAmB,WAAkC;GACzD,MAAM,SAAS,UAAU,OAAO;AAChC,OAAI,CAAC,OACH;AAEF,UAAO,aAAa;IAClB,iBAAiB,OAAO;IACxB,aAAa,OAAO;IACpB,eAAe,OAAO;IACtB,WAAW,OAAO;IACnB,CAAA;AACD,UAAO,uBAAuB;IAC5B,YAAY,OAAO;IACnB,QAAQ,OAAO;IAChB,CAAA;;EAGH,MAAM,uBAAsC,aAAa,MAAM,MAAM,UAAS;;EAG9E,MAAM,6BAA6B,cAChC,aAAa,SAAS,YAAY,WAAW,MAAM,UAAS;EAE/D,MAAM,mBAAmB,OACvB,aACoB;AAEpB,UAAO,kBADU,MAAM,QAAA,eAAe,oBAAoB,QAAA,aAAY,EACnC,YAAY,iBAAiB,MAAK;;EAGvE,MAAM,mBAAmB,SAAS,EAAE,OAAO,MAAM,CAAA;EAEjD,MAAM,gCAAgC,UAAwB;AAE5D,oBAAiB,SAAQ;AACzB,aAAU,OAAO,SAAS,OAAO,KAAI;;EAGvC,MAAM,yBAAyB,YAAY;AACzC,gCAA6B,MAAM,kBAAkB,CAAA;AACrD,WAAQ,QAAQ;AAChB,SAAM,gBAAe;;EAGvB,MAAM,iBAAiB,YAAY;AACjC,SAAM,UAAU,OAAO,gBAAe;;EAGxC,MAAM,iBAAiB,YAAY;GACjC,MAAM,mBAAmB,oBAAoB,QAAA,MAAM,QAAA,OAAM;AACzD,OAAI,CAAC,iBACH;AAGF,SAAM,UAAU,OAAO,UAAU;IAC/B;IACA,iBAAiB;IACjB,iBAAiB;IAClB,CAAA;;EAGH,MAAM,2BAA2B,OAAO,UAAkB;GACxD,MAAM,SAAS,kBAAkB,OAAO,eAAe,MAAK;AAC5D,OAAI,CAAC,QAAQ;IACX,MAAM,aAAa,YAAY,MAAM,MAClC,MAAM,EAAE,aAAa,OAAO,eAAe,MAC9C;AACA,QAAI,WACF,iBAAgB,WAAU;AAE5B,UAAM,WAAW,YAAW;AAC5B;;AAGF,cAAW,OAAM;AACjB,SAAM,QAAA,eAAe,gBAAgB,QAAA,cAAc,OAAM;AACzD,WAAQ,QAAQ;AAChB,SAAM,WAAW,SAAS,EAAE,UAAU,KAAK,CAAA;;EAG7C,MAAM,UAAU,YAAY;GAC1B,MAAM,QAAQ,gBAAe;AAC7B,OAAI,CAAC,MACH;AAEF,SAAM,yBAAyB,MAAK;;EAGtC,MAAM,sBAAsB,UAAkB;AAC5C,WAAQ,QAAQ;AAEhB,OAAI,CAAC,kBAAkB,MACrB;AAGF,oBAAiB,QAAQ,mCACvB,yBAAyB,MAAM,CACjC;;EAGF,MAAM,wBAAwB,YAAY;GACxC,MAAM,mBAAmB,oBAAoB,QAAA,MAAM,QAAA,OAAM;AACzD,OAAI,CAAC,iBACH;GAGF,MAAM,QAAQ,gBAAe;AAC7B,OAAI,CAAC,MACH;GAGF,MAAM,SAAS,kBAAkB,OAAO,eAAe,MAAK;AAE5D,OAAI,CAAC,UAAU,CAAC,SAAS,OAAO,MAAM,CACpC;GAIF,MAAM,oBADc,OAAO,MACW,iBAAiB;AACvD,OAAI,CAAC,SAAS,kBAAkB,CAC9B;GAGF,MAAM,YAAY,kBAAkB,iBAAiB;AACrD,OAAI,CAAC,SAAS,UAAU,CACtB;AAIF,aAAU,YAAY,EAAC;AAGvB,aAAU,OAAO,SAAS,kBAAkB,QAAQ,eAAe,MAAM,CAAA;AACzE,SAAM,UAAU,OAAO,UAAU;IAC/B;IACA,iBAAiB;IACjB,iBAAiB;IACjB;IACD,CAAA;;AAGH,4BAA0B,WAAW,aAAY;AAEjD,kBAAgB;AACd,aAAU,QAAQ,UAAU;IAC1B,SAAS,gBAAgB,SAAS,SAAS,cAAc,MAAM;IAC/D,UAAU;IACV,OAAO;IACP,SAAS;KACP;MACE,IAAI;MACJ,OAAO;MACP,aAAa,CAAC,OAAO,OAAO,MAAM,OAAO,QAAQ,KAAK;MACtD,KAAK,YAAY;AACf,aAAM,gBAAe;;MAExB;KACD;MACE,IAAI;MACJ,OAAO;MACP,aAAa,CAAC,OAAO,OAAO,MAAM,OAAO,QAAQ,KAAK;MACtD,KAAK,YAAY;AACf,aAAM,uBAAsB;;MAE/B;KACD;MACE,IAAI;MACJ,OAAO;MACP,aAAa,CACX,OAAO,OAAO,MAAM,OAAO,OAAO,QAAQ,OAAO,QAAQ,KAC1D;MACD,KAAK,YAAY;AACf,aAAM,gBAAe;;MAExB;KACF;IACF,CAAA;AAED,4BAAwB;AACnB,2BAAuB;IAC7B;AAED,wBAAsB;AACpB,oBAAiB,SAAQ;AAGzB,OAAI,QAAQ,SAAS,kBAAkB,MAChC,UAAQ;AAEf,aAAU,OAAO,WAAU;AAE3B,aAAU,MAAM,SAAQ;AACxB,aAAU,MAAM,SAAQ;IACzB;AAED,cAAY,QAAA,cAAc,uBAAsB;AAEhD,cACQ,CAAC,QAAA,MAAM,QAAA,OAAO,EACpB,YAAY;AACV,SAAM,gBAAe;IAEzB;AAEA,QAAM,iCAAiC;AACrC,4BAAwB;IACzB;AAED,QAAM,gBAAgB,OAAO,cAAc,qBAAqB;GAC9D,MAAM,WAAW,QAAQ;GAGzB,MAAM,QAAQ,0BAA0B,oBAAoB,OAAM;AAClE,OAAI,CAAC,OAAO;AACV,qBAAiB,QAAQ;AACzB,UAAM,UAAS;AACf,UAAM,gBAAe;AACrB;;GAGF,MAAM,SAAS,kBAAkB,OAAO,oBAAoB,OAAM;AAClE,oBAAiB,QAAQ;AACzB,SAAM,UAAS;AACf,OAAI,QAAQ;AACV,iCAA6B,kBAAkB,QAAQ,aAAa,CAAA;AACpE,YAAQ,QAAQ;;AAElB,SAAM,gBAAe;IACtB;AAED,QACE,oBACC,cAAc;AACb,OAAI,CAAC,WAAW;AACd,qBAAiB,SAAQ;AACzB;;AAGF,OAAI,QAAQ,OAAO;IACjB,MAAM,QAAQ,gBAAe;AAC7B,QAAI,CAAC,MACH;AAEF,qBAAiB,QAAQ,mCACvB,yBAAyB,MAAM,CACjC;;KAGJ,EAAE,OAAO,QAAQ,CACnB;;UAKiB,QAAA,mBAAc,eAA0B,MAAA,oBAAmB,CAAC,QAAA,MAAM,QAAA,OAAM,KAAA,QAAA,WAAA,EADvF,mBA6HM,OAAA;;IAxHJ,OAAK,eAAA,CAAC,6CACE,MAAA,gBAAe,CAAA,CAAA;OACvB,mBA2FM,OA3FN,YA2FM;IAzFJ,mBA+BM,OA/BN,YA+BM;+BA7BJ,mBAEO,QAAA,EAFD,OAAM,kDAAgD,EAAC,eAE7D,GAAA;KAEA,YAWe,MAAA,aAAA,EAAA;MAVb,OAAM;MACN,MAAK;MACL,SAAQ;MACP,SAAO;;6BACc,CAAA,OAAA,OAAA,OAAA,KAAtB,mBAAsB,QAAA,MAAhB,aAAS,GAAA,GACf,mBAIO,QAJP,YAIO,CAHL,YAEwB,MAAA,aAAA,EAAA;OADtB,QAAO;OACN,UAAU,CAAA,MAAO;;;;KAIxB,YAWe,MAAA,aAAA,EAAA;MAVb,OAAM;MACN,MAAK;MACL,SAAQ;MACP,SAAO;;6BACY,CAAA,OAAA,OAAA,OAAA,KAApB,mBAAoB,QAAA,MAAd,WAAO,GAAA,GACb,mBAIO,QAJP,YAIO,CAHL,YAEwB,MAAA,aAAA,EAAA;OADtB,QAAO;OACN,UAAU,CAAA,MAAO;;;;;IAK1B,mBAwBM,OAxBN,YAwBM,CApBJ,YASe,MAAA,aAAA,EAAA;KARZ,iBAAa,CAAG,MAAA,WAAU;KAC1B,OAAK,eAAE,MAAA,uBAAsB,CAAA,CAAE,MAAA,WAAU,CAAA,CAAA;KAC1C,MAAK;KACL,MAAK;KACL,MAAK;KACL,SAAQ;KACP,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,eAAA,QAAc;;4BAExB,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAFmC,UAEnC,GAAA,CAAA,EAAA,CAAA;;uCACA,YASe,MAAA,aAAA,EAAA;KARZ,iBAAe,MAAA,WAAU;KACzB,OAAK,eAAE,MAAA,uBAAsB,CAAC,MAAA,WAAU,CAAA,CAAA;KACzC,MAAK;KACL,MAAK;KACL,MAAK;KACL,SAAQ;KACP,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,eAAA,QAAc;;4BAExB,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAFmC,UAEnC,GAAA,CAAA,EAAA,CAAA;;;IAGF,mBA6BM,OA7BN,YA6BM,CA5BJ,YAUe,MAAA,aAAA,EAAA;KATb,MAAK;KACL,SAAQ;KACP,SAAO;;4BAC8C,CAAtD,mBAAsD,QAAA,MAAhD,YAAO,gBAAG,MAAA,WAAU,GAAA,SAAA,OAAA,EAAA,EAAA,EAC1B,mBAIO,QAJP,YAIO,CAHL,YAEiC,MAAA,aAAA,EAAA;MAD/B,QAAO;MACN,UAAU,CAAA,OAAA,QAAgB;;;QAGjC,YAgBe,MAAA,aAAA,EAAA;KAfZ,cAAyB,MAAA,kBAAiB,GAAA,wBAAA;KAG3C,MAAK;KACL,SAAQ;KACP,SAAO,MAAA,sBAAqB;;4BACgC,CAA7D,mBAA6D,QAAA,MAAA,gBAApD,MAAA,kBAAiB,GAAA,YAAA,WAAA,EAAA,EAAA,EAC1B,mBAOO,QAPP,YAOO,CALG,MAAA,kBAAiB,IAAA,WAAA,EADzB,YAEqB,MAAA,mBAAA,EAAA;;MAAnB,OAAM;yBACR,YAEqB,MAAA,oBAAA,EAAA;;MAAnB,OAAM;;;;OAMhB,mBAwBM,OAxBN,YAwBM,CAvBJ,mBAsBM,OAAA,EArBJ,OAAK,eAAA,CAAC,kCACE,MAAA,kBAAiB,GAAA,mBAAA,QAAA,CAAA,EAAA,EAAA;IACzB,mBAOM,OAPN,aAOM,CANJ,YAK2D,yBAAA;KAJxD,mBAAmB,MAAA,kBAAiB;KACpC,SAAS,MAAA,QAAO;KAChB,YAAY,MAAA,WAAU;KACtB,WAAS;KACT,8BAAwB,OAAA,OAAA,OAAA,MAAA,WAAE,kBAAA,QAAoB;;;;;;IAGnD,YAKqE,gCAAA;KAJlE,kBAAkB,iBAAA;KAClB,UAAU,MAAA,0BAAyB;KACnC,oBAAoB,mBAAA;KACpB,mBAAiB;KACjB,UAAM,OAAA,OAAA,OAAA,MAAA,WAAE,0BAAA,QAAyB,CAAI,MAAA,0BAAyB;;;;;;IAEjE,mBAEsG,OAAA;cADhG;KAAJ,KAAI;KACJ,OAAM;;iCAId,mBAA4C,OAAA,aAAhC,6BAA0B"}
|
|
1
|
+
{"version":3,"file":"Editor.vue.script.js","names":[],"sources":["../../../../../../src/v2/features/collection/components/Editor/Editor.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton, ScalarHotkey, useLoadingState } from '@scalar/components'\nimport { debounce } from '@scalar/helpers/general/debounce'\nimport { isObject } from '@scalar/helpers/object/is-object'\nimport { ScalarIconArrowsIn, ScalarIconArrowsOut } from '@scalar/icons'\nimport * as monaco from 'monaco-editor/esm/vs/editor/editor.api.js'\nimport {\n computed,\n nextTick,\n onBeforeUnmount,\n onMounted,\n ref,\n shallowRef,\n watch,\n} from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { useEditor, useJsonPointerLinkSupport } from '@/v2/features/editor'\nimport { createJsonModel } from '@/v2/features/editor/helpers/json/create-json-model'\nimport { createYamlModel } from '@/v2/features/editor/helpers/yaml/create-yaml-model'\nimport { useEditorMarkers } from '@/v2/features/editor/hooks/use-editor-markers'\n\nimport EditorDiagnosticsPanel from './components/EditorDiagnosticsPanel.vue'\nimport EditorSavePanel from './components/EditorSavePanel.vue'\nimport { getDiagnosticCounts } from './helpers/get-diagnostic-counts'\nimport { getOperationContext } from './helpers/get-operation-context'\nimport { getVisibleDiagnostics } from './helpers/get-visible-diagnostics'\nimport { parseEditorObject } from './helpers/parse-editor-object'\nimport { stringifyDocument } from './helpers/stringify-document'\nimport { useEditorState } from './hooks/use-editor-state'\n\nconst { collectionType, documentSlug, method, path, workspaceStore } =\n defineProps<CollectionProps>()\n\nconst MAX_VISIBLE_DIAGNOSTICS = 6\nconst EDITOR_PERSIST_DEBOUNCE_KEY = 'editor:replace-document'\n\nconst monacoEditorRef = ref<HTMLElement>()\nconst editorApi = shallowRef<ReturnType<typeof useEditor>>()\n\nconst saveLoader = useLoadingState()\nconst {\n isAutoSaveEnabled,\n isDirty,\n editorLanguage,\n isDiagnosticsPaneExpanded,\n isEditorMaximized,\n isYamlMode,\n editorBottomPadding,\n editorRootClass,\n getLanguageToggleClass,\n toggleEditorMaximized,\n} = useEditorState()\n\nconst jsonModel = createJsonModel()\nconst yamlModel = createYamlModel()\n\nconst selectedLanguage = ref<'json' | 'yaml'>('json')\n\nconst currentModel = computed(() => {\n return selectedLanguage.value === 'json' ? jsonModel : yamlModel\n})\n\nconst monacoEditorInstance = computed(() => editorApi.value?.editor)\nconst { markers: diagnostics } = useEditorMarkers(monacoEditorInstance)\n\nconst syncEditorBottomPadding = () => {\n editorApi.value?.editor.updateOptions({\n padding: {\n top: 0,\n bottom: editorBottomPadding.value,\n },\n })\n}\n\nconst diagnosticCounts = computed(() => getDiagnosticCounts(diagnostics.value))\nconst visibleDiagnostics = computed(() =>\n getVisibleDiagnostics(diagnostics.value, MAX_VISIBLE_DIAGNOSTICS),\n)\n\nconst focusDiagnostic = (marker: monaco.editor.IMarker) => {\n const editor = editorApi.value?.editor\n if (!editor) {\n return\n }\n editor.setSelection({\n startLineNumber: marker.startLineNumber,\n startColumn: marker.startColumn,\n endLineNumber: marker.endLineNumber,\n endColumn: marker.endColumn,\n })\n editor.revealPositionInCenter({\n lineNumber: marker.startLineNumber,\n column: marker.startColumn,\n })\n}\n\nconst getEditorValue = (): string | null => currentModel.value.model.getValue()\n\n/** Value from the editor for a specific language (use when switching to avoid reading the wrong model). */\nconst getEditorValueForLanguage = (language: 'json' | 'yaml'): string | null =>\n (language === 'json' ? jsonModel : yamlModel).model.getValue()\n\nconst getDocumentValue = async (\n language?: 'json' | 'yaml',\n): Promise<string> => {\n const document = await workspaceStore.getEditableDocument(documentSlug)\n return stringifyDocument(document, language ?? selectedLanguage.value)\n}\n\nconst debouncedPersist = debounce({ delay: 1500 })\n\nconst applyProgrammaticEditorValue = (value: string): void => {\n // Cancel pending auto-save work so synthetic model updates do not persist stale data.\n debouncedPersist.cleanup()\n editorApi.value?.setValue(value, true)\n}\n\nconst loadDocumentIntoEditor = async () => {\n applyProgrammaticEditorValue(await getDocumentValue())\n isDirty.value = false\n await focusOperation()\n}\n\nconst formatDocument = async () => {\n await editorApi.value?.formatDocument()\n}\n\nconst focusOperation = async () => {\n const operationContext = getOperationContext(path, method)\n if (!operationContext) {\n return\n }\n\n await editorApi.value?.focusPath([\n 'paths',\n operationContext.path,\n operationContext.method,\n ])\n}\n\nconst persistEditorToWorkspace = async (value: string) => {\n const parsed = parseEditorObject(value, editorLanguage.value)\n if (!parsed) {\n const firstError = diagnostics.value.find(\n (m) => m.severity === monaco.MarkerSeverity.Error,\n )\n if (firstError) {\n focusDiagnostic(firstError)\n }\n await saveLoader.invalidate()\n return\n }\n\n saveLoader.start()\n await workspaceStore.replaceDocument(documentSlug, parsed)\n isDirty.value = false\n await saveLoader.validate({ duration: 900 })\n}\n\nconst saveNow = async () => {\n const value = getEditorValue()\n if (!value) {\n return\n }\n await persistEditorToWorkspace(value)\n}\n\nconst handleEditorChange = (value: string) => {\n isDirty.value = true\n\n if (!isAutoSaveEnabled.value) {\n return\n }\n\n debouncedPersist.execute(EDITOR_PERSIST_DEBOUNCE_KEY, () =>\n persistEditorToWorkspace(value),\n )\n}\n\nconst focusOperationServers = async () => {\n const operationContext = getOperationContext(path, method)\n if (!operationContext) {\n return\n }\n\n const value = getEditorValue()\n if (!value) {\n return\n }\n\n const parsed = parseEditorObject(value, editorLanguage.value)\n\n if (!parsed || !isObject(parsed.paths)) {\n return\n }\n\n const pathsObject = parsed.paths as Record<string, unknown>\n const operationPathItem = pathsObject[operationContext.path]\n if (!isObject(operationPathItem)) {\n return\n }\n\n const operation = operationPathItem[operationContext.method]\n if (!isObject(operation)) {\n return\n }\n\n // Add default servers if not present\n operation.servers ??= []\n\n // Update the editor value\n editorApi.value?.setValue(stringifyDocument(parsed, editorLanguage.value))\n await editorApi.value?.focusPath([\n 'paths',\n operationContext.path,\n operationContext.method,\n 'servers',\n ])\n}\n\nuseJsonPointerLinkSupport(editorApi, currentModel)\n\nonMounted(() => {\n editorApi.value = useEditor({\n element: monacoEditorRef.value ?? document.createElement('div'),\n onChange: handleEditorChange,\n model: currentModel,\n actions: [\n {\n id: 'scalar.editor.focusOperation',\n label: 'Focus Operation',\n keybindings: [monaco.KeyMod.Alt | monaco.KeyCode.KeyO],\n run: async () => {\n await focusOperation()\n },\n },\n {\n id: 'scalar.editor.focusOperationServers',\n label: 'Focus Operation Servers',\n keybindings: [monaco.KeyMod.Alt | monaco.KeyCode.KeyS],\n run: async () => {\n await focusOperationServers()\n },\n },\n {\n id: 'scalar.editor.formatDocument',\n label: 'Format Document',\n keybindings: [\n monaco.KeyMod.Alt | monaco.KeyMod.Shift | monaco.KeyCode.KeyF,\n ],\n run: async () => {\n await formatDocument()\n },\n },\n ],\n })\n\n syncEditorBottomPadding()\n void loadDocumentIntoEditor()\n})\n\nonBeforeUnmount(() => {\n debouncedPersist.cleanup()\n\n // Persist if there is a pending save\n if (isDirty.value && isAutoSaveEnabled.value) {\n void saveNow()\n }\n editorApi.value?.dispose?.()\n // Dispose models created at setup; useEditor only disposes the editor widget, not external models.\n jsonModel.model.dispose()\n yamlModel.model.dispose()\n})\n\nwatch(() => documentSlug, loadDocumentIntoEditor)\n\nwatch(\n () => [path, method] as const,\n async () => {\n await focusOperation()\n },\n)\n\nwatch(isDiagnosticsPaneExpanded, () => {\n syncEditorBottomPadding()\n})\n\nwatch(editorLanguage, async (nextLanguage, previousLanguage) => {\n const wasDirty = isDirty.value\n // Read from the previous model before switching; getEditorValue() would use currentModel\n // which changes with selectedLanguage, so we would read the (empty) new model otherwise.\n const value = getEditorValueForLanguage(previousLanguage ?? 'json')\n if (!value) {\n selectedLanguage.value = nextLanguage\n await nextTick()\n await focusOperation()\n return\n }\n\n const parsed = parseEditorObject(value, previousLanguage ?? 'json')\n selectedLanguage.value = nextLanguage\n await nextTick()\n if (parsed) {\n applyProgrammaticEditorValue(stringifyDocument(parsed, nextLanguage))\n isDirty.value = wasDirty\n }\n await focusOperation()\n})\n\nwatch(\n isAutoSaveEnabled,\n (isEnabled) => {\n if (!isEnabled) {\n debouncedPersist.cleanup()\n return\n }\n\n if (isDirty.value) {\n const value = getEditorValue()\n if (!value) {\n return\n }\n debouncedPersist.execute(EDITOR_PERSIST_DEBOUNCE_KEY, () =>\n persistEditorToWorkspace(value),\n )\n }\n },\n { flush: 'post' },\n)\n</script>\n\n<template>\n <div\n v-if=\"\n collectionType === 'operation' &&\n getOperationContext(path, method) !== null\n \"\n class=\"flex w-full min-w-0 flex-1 flex-col gap-2\"\n :class=\"editorRootClass\">\n <div\n class=\"grid grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-3\">\n <div\n class=\"flex min-w-0 items-center gap-1 overflow-x-auto whitespace-nowrap\">\n <span class=\"text-c-2 text-xs font-medium whitespace-nowrap\">\n Shortcuts\n </span>\n\n <ScalarButton\n class=\"whitespace-nowrap\"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"focusOperation\">\n <span>Operation</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarHotkey\n hotkey=\"O\"\n :modifier=\"['Alt']\" />\n </span>\n </ScalarButton>\n\n <ScalarButton\n class=\"whitespace-nowrap\"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"focusOperationServers\">\n <span>Servers</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarHotkey\n hotkey=\"S\"\n :modifier=\"['Alt']\" />\n </span>\n </ScalarButton>\n </div>\n\n <div\n aria-label=\"Editor language\"\n class=\"bg-b-1 shadow-border flex items-center justify-self-center overflow-hidden rounded-lg p-0.5\"\n role=\"tablist\">\n <ScalarButton\n :aria-selected=\"!isYamlMode\"\n :class=\"getLanguageToggleClass(!isYamlMode)\"\n role=\"tab\"\n size=\"xs\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"editorLanguage = 'json'\">\n JSON\n </ScalarButton>\n <ScalarButton\n :aria-selected=\"isYamlMode\"\n :class=\"getLanguageToggleClass(isYamlMode)\"\n role=\"tab\"\n size=\"xs\"\n type=\"button\"\n variant=\"ghost\"\n @click=\"editorLanguage = 'yaml'\">\n YAML\n </ScalarButton>\n </div>\n\n <div class=\"flex min-w-0 shrink-0 items-center gap-2 justify-self-end\">\n <ScalarButton\n size=\"xs\"\n variant=\"ghost\"\n @click=\"formatDocument\">\n <span>Format {{ isYamlMode ? 'YAML' : 'JSON' }}</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarHotkey\n hotkey=\"F\"\n :modifier=\"['Alt', 'Shift']\" />\n </span>\n </ScalarButton>\n <ScalarButton\n :aria-label=\"\n isEditorMaximized ? 'Restore editor size' : 'Maximize editor'\n \"\n size=\"xs\"\n variant=\"ghost\"\n @click=\"toggleEditorMaximized\">\n <span>{{ isEditorMaximized ? 'Restore' : 'Maximize' }}</span>\n <span class=\"text-c-3 ml-2 text-[11px]\">\n <ScalarIconArrowsIn\n v-if=\"isEditorMaximized\"\n class=\"size-3.5\" />\n <ScalarIconArrowsOut\n v-else\n class=\"size-3.5\" />\n </span>\n </ScalarButton>\n </div>\n </div>\n\n <div class=\"flex min-h-0 w-full min-w-0 flex-1 rounded-lg border\">\n <div\n class=\"relative w-full min-w-0 flex-1\"\n :class=\"isEditorMaximized ? 'h-full min-h-0' : 'h-125'\">\n <div class=\"pointer-events-none absolute top-2 right-2 z-10\">\n <EditorSavePanel\n :isAutoSaveEnabled=\"isAutoSaveEnabled\"\n :isDirty=\"isDirty\"\n :saveLoader=\"saveLoader\"\n @saveNow=\"saveNow\"\n @update:isAutoSaveEnabled=\"isAutoSaveEnabled = $event\" />\n </div>\n\n <EditorDiagnosticsPanel\n :diagnosticCounts=\"diagnosticCounts\"\n :expanded=\"isDiagnosticsPaneExpanded\"\n :visibleDiagnostics=\"visibleDiagnostics\"\n @focusDiagnostic=\"focusDiagnostic\"\n @toggle=\"isDiagnosticsPaneExpanded = !isDiagnosticsPaneExpanded\" />\n\n <div\n ref=\"monacoEditorRef\"\n class=\"h-full w-full min-w-0 flex-1 [&_.monaco-editor]:rounded-lg [&_.overflow-guard]:rounded-lg\" />\n </div>\n </div>\n </div>\n <div v-else>No operation context found</div>\n</template>\n<style scoped>\n.editor-container {\n width: 100%;\n height: 100%;\n}\n\n:deep(.json-path-highlight) {\n background-color: rgba(255, 200, 0, 0.35);\n border-radius: 4px;\n}\n\n:deep(.json-focus-highlight) {\n background-color: color-mix(\n in srgb,\n var(--scalar-color-accent, #24b47e) 18%,\n transparent\n );\n border-radius: 4px;\n}\n</style>\n"],"mappings":"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"}
|
|
@@ -21,6 +21,7 @@ var Environment_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ de
|
|
|
21
21
|
fetchRegistryDocument: { type: Function },
|
|
22
22
|
telemetry: { type: Boolean },
|
|
23
23
|
onUpdateTelemetry: { type: Function },
|
|
24
|
+
options: {},
|
|
24
25
|
collectionType: {}
|
|
25
26
|
},
|
|
26
27
|
setup(__props) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Environment.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Environment.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Environment variables section for the collection.\n * Renders document or workspace environments and lets users set variables\n * that can be referenced in request inputs via {{ variable }}.\n */\nexport default {\n name: 'Environment',\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { EnvironmentsList } from '@/v2/features/environments'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst { document, eventBus, collectionType, workspaceStore } =\n defineProps<CollectionProps>()\n\n/** Document or workspace environments */\nconst environments = computed(\n () =>\n (collectionType === 'document'\n ? document['x-scalar-environments']\n : workspaceStore.workspace['x-scalar-environments']) ?? {},\n)\n\nconst activeEnvironment = computed(() => {\n return workspaceStore.workspace['x-scalar-active-environment']\n})\n</script>\n\n<template>\n <Section v-if=\"collectionType !== 'operation'\">\n <template #title>Environment Variables</template>\n <template #description>\n Set environment variables at your collection level. Use\n <code\n v-pre\n class=\"font-code text-c-2\">\n {{ variable }}\n </code>\n to add / search among the selected environment's variables in your request\n inputs.\n </template>\n <EnvironmentsList\n :activeEnvironment\n :collectionType\n :environments\n :eventBus />\n </Section>\n</template>\n"],"mappings":";;;;CAOE,MAAM
|
|
1
|
+
{"version":3,"file":"Environment.vue.script.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Environment.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * Environment variables section for the collection.\n * Renders document or workspace environments and lets users set variables\n * that can be referenced in request inputs via {{ variable }}.\n */\nexport default {\n name: 'Environment',\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue'\n\nimport type { CollectionProps } from '@/v2/features/app/helpers/routes'\nimport { EnvironmentsList } from '@/v2/features/environments'\nimport Section from '@/v2/features/settings/components/Section.vue'\n\nconst { document, eventBus, collectionType, workspaceStore } =\n defineProps<CollectionProps>()\n\n/** Document or workspace environments */\nconst environments = computed(\n () =>\n (collectionType === 'document'\n ? document['x-scalar-environments']\n : workspaceStore.workspace['x-scalar-environments']) ?? {},\n)\n\nconst activeEnvironment = computed(() => {\n return workspaceStore.workspace['x-scalar-active-environment']\n})\n</script>\n\n<template>\n <Section v-if=\"collectionType !== 'operation'\">\n <template #title>Environment Variables</template>\n <template #description>\n Set environment variables at your collection level. Use\n <code\n v-pre\n class=\"font-code text-c-2\">\n {{ variable }}\n </code>\n to add / search among the selected environment's variables in your request\n inputs.\n </template>\n <EnvironmentsList\n :activeEnvironment\n :collectionType\n :environments\n :eventBus />\n </Section>\n</template>\n"],"mappings":";;;;CAOE,MAAM;;;;;;;;;;;;;;;;;;;;;;;;EAeR,MAAM,eAAe,gBAEhB,QAAA,mBAAmB,aAChB,QAAA,SAAS,2BACT,QAAA,eAAe,UAAU,6BAA6B,EAAE,CAChE;EAEA,MAAM,oBAAoB,eAAe;AACvC,UAAO,QAAA,eAAe,UAAU;IACjC;;UAIgB,QAAA,mBAAc,eAAA,WAAA,EAA7B,YAiBU,iBAAA,EAAA,KAAA,GAAA,EAAA;IAhBG,OAAK,cAAsB,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAArB,yBAAqB,GAAA,CAAA,EAAA,CAAA;IAC3B,aAAW,cAEpB,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA;qBAFqB,6DAErB,GAAA;KAAA,mBAIO,QAAA,EAFL,OAAM,sBAAoB,EAAC,oBAE7B,GAAA;qBAAO,wFAGT,GAAA;;2BAKc,CAJd,YAIc,MAAA,yBAAA,EAAA;KAHX,mBAAA,kBAAA;KACA,gBAAA,QAAA;KACA,cAAA,aAAA;KACA,UAAA,QAAA"}
|
|
@@ -10,6 +10,8 @@ type __VLS_Props = {
|
|
|
10
10
|
data: Record<string, any>;
|
|
11
11
|
onUpdate: (key: string, value: string | number) => void;
|
|
12
12
|
environment: XScalarEnvironment;
|
|
13
|
+
/** Whether to show context function suggestions like $guid, $timestamp. Defaults to true */
|
|
14
|
+
withFakeData?: boolean;
|
|
13
15
|
};
|
|
14
16
|
declare var __VLS_9: {};
|
|
15
17
|
type __VLS_Slots = {} & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Form.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/collection/components/Form.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Form.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/collection/components/Form.vue"],"names":[],"mappings":"AA+EA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AAQnH,KAAK,WAAW,GAAG;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,EAAE;QACP,GAAG,EAAE,MAAM,CAAA;QACX,KAAK,EAAE,MAAM,CAAA;QACb,WAAW,EAAE,MAAM,CAAA;QACnB,YAAY,CAAC,EAAE,OAAO,CAAA;KACvB,EAAE,CAAA;IACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IACzB,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,KAAK,IAAI,CAAA;IACvD,WAAW,EAAE,kBAAkB,CAAA;IAC/B,4FAA4F;IAC5F,YAAY,CAAC,EAAE,OAAO,CAAA;CACvB,CAAC;AA2KF,QAAA,IAAI,OAAO,IAAW,CAAE;AACxB,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,OAAO,KAAK,GAAG,CAAA;CAAE,CAAC;AAK7C,QAAA,MAAM,UAAU,kSAEd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Form.vue.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Form.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarIcon } from '@scalar/components'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { useId } from 'vue'\n\nimport ViewLayoutSection from '@/components/ViewLayout/ViewLayoutSection.vue'\nimport DataTable from '@/v2/components/data-table/DataTable.vue'\nimport DataTableInput from '@/v2/components/data-table/DataTableInput.vue'\nimport DataTableRow from '@/v2/components/data-table/DataTableRow.vue'\n\ndefineProps<{\n title?: string\n options: {\n key: string\n label: string\n placeholder: string\n lineWrapping?: boolean\n }[]\n data: Record<string, any>\n onUpdate: (key: string, value: string | number) => void\n environment: XScalarEnvironment\n}>()\n\nconst id = useId()\n</script>\n<template>\n <ViewLayoutSection class=\"last:rounded-b-lg\">\n <template\n v-if=\"title || $slots.title\"\n #title>\n <span v-if=\"title\">{{ title }}</span>\n <slot\n v-else\n name=\"title\" />\n </template>\n <div class=\"flex flex-1 flex-col gap-1.5\">\n <DataTable\n v-if=\"Object.keys(data).length > 0\"\n class=\"rounded-b-lg\"\n :columns=\"['']\">\n <DataTableRow\n v-for=\"(option, index) in options\"\n :key=\"index\">\n <DataTableInput\n :id=\"id\"\n class=\"pr-9\"\n :environment=\"environment\"\n :lineWrapping=\"option.lineWrapping ?? false\"\n :modelValue=\"data[option.key] ?? ''\"\n :placeholder=\"option.placeholder\"\n @update:modelValue=\"onUpdate(option.key, $event)\">\n <template #default>\n <label :for=\"id\">\n {{ option.label }}\n </label>\n </template>\n <template\n v-if=\"option.key === 'description'\"\n #icon>\n <div\n class=\"centered-y bg-b-2 flex-center absolute right-1 z-1 rounded px-1 py-0.5\">\n <ScalarIcon\n icon=\"Markdown\"\n size=\"lg\" />\n </div>\n </template>\n </DataTableInput>\n </DataTableRow>\n </DataTable>\n </div>\n </ViewLayoutSection>\n</template>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"Form.vue.js","names":[],"sources":["../../../../../src/v2/features/collection/components/Form.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarIcon } from '@scalar/components'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { useId } from 'vue'\n\nimport ViewLayoutSection from '@/components/ViewLayout/ViewLayoutSection.vue'\nimport DataTable from '@/v2/components/data-table/DataTable.vue'\nimport DataTableInput from '@/v2/components/data-table/DataTableInput.vue'\nimport DataTableRow from '@/v2/components/data-table/DataTableRow.vue'\n\ndefineProps<{\n title?: string\n options: {\n key: string\n label: string\n placeholder: string\n lineWrapping?: boolean\n }[]\n data: Record<string, any>\n onUpdate: (key: string, value: string | number) => void\n environment: XScalarEnvironment\n /** Whether to show context function suggestions like $guid, $timestamp. Defaults to true */\n withFakeData?: boolean\n}>()\n\nconst id = useId()\n</script>\n<template>\n <ViewLayoutSection class=\"last:rounded-b-lg\">\n <template\n v-if=\"title || $slots.title\"\n #title>\n <span v-if=\"title\">{{ title }}</span>\n <slot\n v-else\n name=\"title\" />\n </template>\n <div class=\"flex flex-1 flex-col gap-1.5\">\n <DataTable\n v-if=\"Object.keys(data).length > 0\"\n class=\"rounded-b-lg\"\n :columns=\"['']\">\n <DataTableRow\n v-for=\"(option, index) in options\"\n :key=\"index\">\n <DataTableInput\n :id=\"id\"\n class=\"pr-9\"\n :environment=\"environment\"\n :lineWrapping=\"option.lineWrapping ?? false\"\n :modelValue=\"data[option.key] ?? ''\"\n :placeholder=\"option.placeholder\"\n :withFakeData=\"withFakeData ?? true\"\n @update:modelValue=\"onUpdate(option.key, $event)\">\n <template #default>\n <label :for=\"id\">\n {{ option.label }}\n </label>\n </template>\n <template\n v-if=\"option.key === 'description'\"\n #icon>\n <div\n class=\"centered-y bg-b-2 flex-center absolute right-1 z-1 rounded px-1 py-0.5\">\n <ScalarIcon\n icon=\"Markdown\"\n size=\"lg\" />\n </div>\n </template>\n </DataTableInput>\n </DataTableRow>\n </DataTable>\n </div>\n </ViewLayoutSection>\n</template>\n"],"mappings":""}
|
|
@@ -16,7 +16,8 @@ var Form_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
|
|
|
16
16
|
options: {},
|
|
17
17
|
data: {},
|
|
18
18
|
onUpdate: { type: Function },
|
|
19
|
-
environment: {}
|
|
19
|
+
environment: {},
|
|
20
|
+
withFakeData: { type: Boolean }
|
|
20
21
|
},
|
|
21
22
|
setup(__props) {
|
|
22
23
|
const id = useId();
|
|
@@ -36,6 +37,7 @@ var Form_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
|
|
|
36
37
|
lineWrapping: option.lineWrapping ?? false,
|
|
37
38
|
modelValue: __props.data[option.key] ?? "",
|
|
38
39
|
placeholder: option.placeholder,
|
|
40
|
+
withFakeData: __props.withFakeData ?? true,
|
|
39
41
|
"onUpdate:modelValue": ($event) => __props.onUpdate(option.key, $event)
|
|
40
42
|
}, createSlots({
|
|
41
43
|
default: withCtx(() => [createElementVNode("label", { for: unref(id) }, toDisplayString(option.label), 9, _hoisted_3)]),
|
|
@@ -53,6 +55,7 @@ var Form_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineCom
|
|
|
53
55
|
"lineWrapping",
|
|
54
56
|
"modelValue",
|
|
55
57
|
"placeholder",
|
|
58
|
+
"withFakeData",
|
|
56
59
|
"onUpdate:modelValue"
|
|
57
60
|
])]),
|
|
58
61
|
_: 2
|