@scalar/api-client 2.39.4 → 2.41.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 +32 -0
- package/dist/components/AddressBar/AddressBarHistory.vue.d.ts.map +1 -1
- package/dist/components/AddressBar/AddressBarHistory.vue.js +1 -1
- package/dist/components/AddressBar/AddressBarHistory.vue.js.map +1 -1
- package/dist/components/AddressBar/AddressBarHistory.vue.script.js +2 -2
- package/dist/components/AddressBar/AddressBarHistory.vue.script.js.map +1 -1
- package/dist/hooks/useClientConfig.d.ts +12 -0
- package/dist/hooks/useClientConfig.d.ts.map +1 -1
- package/dist/hooks/useClientConfig.js +14 -1
- package/dist/hooks/useClientConfig.js.map +1 -1
- package/dist/libs/index.d.ts +0 -1
- package/dist/libs/index.d.ts.map +1 -1
- package/dist/libs/index.js +1 -2
- package/dist/style.css +207 -248
- package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts +14 -10
- 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 +57 -35
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/send-request.d.ts +1 -5
- package/dist/v2/blocks/operation-block/helpers/send-request.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/send-request.js +18 -33
- package/dist/v2/blocks/operation-block/helpers/send-request.js.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/validate-path-parameters.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/validate-path-parameters.js +1 -1
- package/dist/v2/blocks/operation-block/helpers/validate-path-parameters.js.map +1 -1
- package/dist/v2/blocks/operation-block/index.d.ts +0 -3
- package/dist/v2/blocks/operation-block/index.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/index.js +1 -4
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.d.ts +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 +3 -1
- package/dist/v2/blocks/operation-code-sample/components/OperationCodeSample.vue.script.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.d.ts +4 -2
- package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.d.ts.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.js +3 -2
- package/dist/v2/blocks/operation-code-sample/helpers/generate-code-snippet.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-resolved-ref-deep.js +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-secrets.d.ts +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-secrets.d.ts.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-secrets.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har.d.ts +7 -2
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har.d.ts.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har.js +4 -3
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/operation-to-har.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.d.ts.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.js +2 -3
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-body.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-parameters.d.ts +3 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-parameters.d.ts.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-parameters.js +5 -8
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-parameters.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-security-schemes.d.ts +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-security-schemes.d.ts.map +1 -1
- package/dist/v2/blocks/operation-code-sample/helpers/operation-to-har/process-security-schemes.js.map +1 -1
- package/dist/v2/blocks/operation-code-sample/index.d.ts +0 -1
- package/dist/v2/blocks/operation-code-sample/index.d.ts.map +1 -1
- package/dist/v2/blocks/operation-code-sample/index.js +2 -3
- package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts +7 -9
- package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.js +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.script.js +49 -42
- package/dist/v2/blocks/request-block/RequestBlock.vue.script.js.map +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 +2 -3
- package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js +1 -0
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.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 -1
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js +1 -1
- package/dist/v2/blocks/request-block/helpers/is-param-disabled.d.ts +1 -1
- package/dist/v2/blocks/request-block/helpers/is-param-disabled.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/helpers/is-param-disabled.js +2 -1
- package/dist/v2/blocks/request-block/helpers/is-param-disabled.js.map +1 -1
- package/dist/v2/blocks/response-block/helpers/get-content-length.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/helpers/get-content-length.js +2 -2
- package/dist/v2/blocks/response-block/helpers/get-content-length.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js +76 -25
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.js +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.script.js +2 -2
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.d.ts +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js +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 +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 +8 -4
- 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/RequestAuthDataTable.vue.d.ts +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTable.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.d.ts +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/extract-security-scheme-secrets.d.ts +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/fetch-openid-connect-discovery.js +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts +1 -1
- 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 +6 -2
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/index.d.ts +0 -3
- package/dist/v2/blocks/scalar-auth-selector-block/index.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/index.js +1 -3
- package/dist/v2/components/code-input/CodeInput.vue.d.ts +8 -6
- 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 +11 -9
- package/dist/v2/components/code-input/CodeInput.vue.script.js.map +1 -1
- 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 +1 -5
- package/dist/v2/features/app/App.vue.script.js.map +1 -1
- package/dist/v2/features/app/app-events.d.ts.map +1 -1
- package/dist/v2/features/app/app-events.js +1 -1
- package/dist/v2/features/app/app-events.js.map +1 -1
- package/dist/v2/features/app/app-state.d.ts.map +1 -1
- package/dist/v2/features/app/app-state.js +2 -2
- package/dist/v2/features/app/app-state.js.map +1 -1
- package/dist/v2/features/app/components/AppSidebar.vue.d.ts.map +1 -1
- package/dist/v2/features/app/components/AppSidebar.vue.js +1 -1
- package/dist/v2/features/app/components/AppSidebar.vue.js.map +1 -1
- package/dist/v2/features/app/components/AppSidebar.vue.script.js +1 -1
- package/dist/v2/features/app/components/AppSidebar.vue.script.js.map +1 -1
- package/dist/v2/features/app/helpers/routes.d.ts +0 -3
- package/dist/v2/features/app/helpers/routes.d.ts.map +1 -1
- package/dist/v2/features/app/helpers/routes.js +1 -1
- package/dist/v2/features/app/helpers/routes.js.map +1 -1
- package/dist/v2/features/collection/DocumentCollection.vue.d.ts.map +1 -1
- package/dist/v2/features/collection/DocumentCollection.vue.js.map +1 -1
- package/dist/v2/features/collection/DocumentCollection.vue.script.js +30 -52
- package/dist/v2/features/collection/DocumentCollection.vue.script.js.map +1 -1
- package/dist/v2/features/collection/OperationCollection.vue.script.js +0 -1
- package/dist/v2/features/collection/OperationCollection.vue.script.js.map +1 -1
- package/dist/v2/features/collection/WorkspaceCollection.vue.script.js +0 -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 +6 -8
- package/dist/v2/features/collection/components/Authentication.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Cookies.vue.script.js +0 -1
- package/dist/v2/features/collection/components/Cookies.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Editor/Editor.vue.script.js +0 -1
- package/dist/v2/features/collection/components/Editor/Editor.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Environment.vue.script.js +0 -1
- package/dist/v2/features/collection/components/Environment.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Overview.vue.script.js +0 -1
- package/dist/v2/features/collection/components/Overview.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Servers.vue.script.js +0 -1
- package/dist/v2/features/collection/components/Servers.vue.script.js.map +1 -1
- package/dist/v2/features/collection/components/Settings.vue.js.map +1 -1
- package/dist/v2/features/collection/components/Settings.vue.script.js +2 -3
- package/dist/v2/features/collection/components/Settings.vue.script.js.map +1 -1
- package/dist/v2/features/editor/hooks/use-three-way-merge-editor.js +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 +1 -1
- package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.script.js.map +1 -1
- 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 +4 -9
- package/dist/v2/features/modal/Modal.vue.script.js.map +1 -1
- 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 +1 -17
- package/dist/v2/features/modal/helpers/create-api-client-modal.js.map +1 -1
- package/dist/v2/features/modal/helpers/map-hidden-clients-config.js +1 -1
- 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 +51 -84
- package/dist/v2/features/operation/Operation.vue.script.js.map +1 -1
- package/dist/v2/features/operation/index.d.ts +0 -4
- package/dist/v2/features/operation/index.d.ts.map +1 -1
- package/dist/v2/features/operation/index.js +1 -5
- package/dist/views/Request/RequestSection/RequestAuth/OAuth2.vue.d.ts.map +1 -1
- package/dist/views/Request/RequestSection/RequestAuth/OAuth2.vue.js.map +1 -1
- package/dist/views/Request/RequestSection/RequestAuth/OAuth2.vue.script.js +11 -1
- package/dist/views/Request/RequestSection/RequestAuth/OAuth2.vue.script.js.map +1 -1
- package/dist/views/Request/RequestSection/RequestTable.vue.d.ts.map +1 -1
- package/dist/views/Request/RequestSection/RequestTable.vue.js +1 -1
- package/dist/views/Request/RequestSection/RequestTable.vue.js.map +1 -1
- package/dist/views/Request/RequestSection/RequestTable.vue.script.js +1 -1
- package/dist/views/Request/RequestSection/RequestTable.vue.script.js.map +1 -1
- package/dist/views/Request/ResponseSection/ResponseEmpty.vue.script.js +1 -1
- package/dist/views/Request/ResponseSection/ResponseMetaInformation.vue.d.ts.map +1 -1
- package/dist/views/Request/ResponseSection/ResponseMetaInformation.vue.js.map +1 -1
- package/dist/views/Request/ResponseSection/ResponseMetaInformation.vue.script.js +2 -2
- package/dist/views/Request/ResponseSection/ResponseMetaInformation.vue.script.js.map +1 -1
- package/dist/views/Request/libs/oauth2.js +1 -1
- package/dist/views/Request/libs/oauth2.js.map +1 -1
- package/package.json +24 -30
- package/dist/libs/formatters.d.ts +0 -12
- package/dist/libs/formatters.d.ts.map +0 -1
- package/dist/libs/formatters.js +0 -36
- package/dist/libs/formatters.js.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/apply-allow-reserved-to-url.d.ts +0 -6
- package/dist/v2/blocks/operation-block/helpers/apply-allow-reserved-to-url.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/apply-allow-reserved-to-url.js +0 -58
- package/dist/v2/blocks/operation-block/helpers/apply-allow-reserved-to-url.js.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/build-request-body.d.ts +0 -12
- package/dist/v2/blocks/operation-block/helpers/build-request-body.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/build-request-body.js +0 -65
- package/dist/v2/blocks/operation-block/helpers/build-request-body.js.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/build-request-cookie-header.d.ts +0 -31
- package/dist/v2/blocks/operation-block/helpers/build-request-cookie-header.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/build-request-cookie-header.js +0 -55
- package/dist/v2/blocks/operation-block/helpers/build-request-cookie-header.js.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/build-request-parameters.d.ts +0 -27
- package/dist/v2/blocks/operation-block/helpers/build-request-parameters.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/build-request-parameters.js +0 -159
- package/dist/v2/blocks/operation-block/helpers/build-request-parameters.js.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/build-request-security.d.ts +0 -25
- package/dist/v2/blocks/operation-block/helpers/build-request-security.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/build-request-security.js +0 -53
- package/dist/v2/blocks/operation-block/helpers/build-request-security.js.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/build-request.d.ts +0 -46
- package/dist/v2/blocks/operation-block/helpers/build-request.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/build-request.js +0 -102
- package/dist/v2/blocks/operation-block/helpers/build-request.js.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/de-serialize-parameter.d.ts +0 -4
- package/dist/v2/blocks/operation-block/helpers/de-serialize-parameter.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/de-serialize-parameter.js +0 -41
- package/dist/v2/blocks/operation-block/helpers/de-serialize-parameter.js.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/filter-global-cookies.d.ts +0 -14
- package/dist/v2/blocks/operation-block/helpers/filter-global-cookies.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/filter-global-cookies.js +0 -20
- package/dist/v2/blocks/operation-block/helpers/filter-global-cookies.js.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/get-delimiter.d.ts +0 -8
- package/dist/v2/blocks/operation-block/helpers/get-delimiter.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/get-environment-variables.d.ts +0 -9
- package/dist/v2/blocks/operation-block/helpers/get-environment-variables.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/get-environment-variables.js +0 -17
- package/dist/v2/blocks/operation-block/helpers/get-environment-variables.js.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/get-example.d.ts +0 -10
- package/dist/v2/blocks/operation-block/helpers/get-example.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/get-example.js +0 -41
- package/dist/v2/blocks/operation-block/helpers/get-example.js.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/get-resolved-url.d.ts +0 -26
- package/dist/v2/blocks/operation-block/helpers/get-resolved-url.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/get-resolved-url.js +0 -32
- package/dist/v2/blocks/operation-block/helpers/get-resolved-url.js.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/get-selected-body-content-type.d.ts +0 -10
- package/dist/v2/blocks/operation-block/helpers/get-selected-body-content-type.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/get-selected-body-content-type.js +0 -15
- package/dist/v2/blocks/operation-block/helpers/get-selected-body-content-type.js.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/get-server-url.d.ts +0 -3
- package/dist/v2/blocks/operation-block/helpers/get-server-url.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/get-server-url.js +0 -18
- package/dist/v2/blocks/operation-block/helpers/get-server-url.js.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/serialize-parameter.d.ts +0 -96
- package/dist/v2/blocks/operation-block/helpers/serialize-parameter.d.ts.map +0 -1
- package/dist/v2/blocks/operation-block/helpers/serialize-parameter.js +0 -160
- package/dist/v2/blocks/operation-block/helpers/serialize-parameter.js.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-example-from-schema.d.ts +0 -40
- package/dist/v2/blocks/operation-code-sample/helpers/get-example-from-schema.d.ts.map +0 -1
- package/dist/v2/blocks/operation-code-sample/helpers/get-example-from-schema.js +0 -437
- package/dist/v2/blocks/operation-code-sample/helpers/get-example-from-schema.js.map +0 -1
- package/dist/v2/blocks/request-block/helpers/get-request-body-example.d.ts +0 -6
- package/dist/v2/blocks/request-block/helpers/get-request-body-example.d.ts.map +0 -1
- package/dist/v2/blocks/request-block/helpers/get-request-body-example.js +0 -25
- package/dist/v2/blocks/request-block/helpers/get-request-body-example.js.map +0 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/extract-security-scheme-secrets.js +0 -141
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/extract-security-scheme-secrets.js.map +0 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-auth-optional.d.ts +0 -4
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-auth-optional.d.ts.map +0 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-auth-optional.js +0 -10
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-auth-optional.js.map +0 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/merge-security.d.ts +0 -9
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/merge-security.d.ts.map +0 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/merge-security.js +0 -27
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/merge-security.js.map +0 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/secret-types.d.ts +0 -25
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/secret-types.d.ts.map +0 -1
- package/dist/v2/components/callout/Callout.vue.js +0 -9
- package/dist/v2/components/callout/Callout.vue.js.map +0 -1
- package/dist/v2/components/callout/Callout.vue.script.js +0 -35
- package/dist/v2/components/callout/Callout.vue.script.js.map +0 -1
- package/dist/v2/features/modal/helpers/restore-workspace-state.d.ts +0 -18
- package/dist/v2/features/modal/helpers/restore-workspace-state.d.ts.map +0 -1
- package/dist/v2/features/modal/helpers/restore-workspace-state.js +0 -51
- package/dist/v2/features/modal/helpers/restore-workspace-state.js.map +0 -1
- package/dist/v2/features/operation/helpers/combine-params.d.ts +0 -4
- package/dist/v2/features/operation/helpers/combine-params.d.ts.map +0 -1
- package/dist/v2/features/operation/helpers/combine-params.js +0 -20
- package/dist/v2/features/operation/helpers/combine-params.js.map +0 -1
- package/dist/v2/features/operation/helpers/get-operation-header.d.ts +0 -17
- package/dist/v2/features/operation/helpers/get-operation-header.d.ts.map +0 -1
- package/dist/v2/features/operation/helpers/get-security-requirements.d.ts +0 -12
- package/dist/v2/features/operation/helpers/get-security-requirements.d.ts.map +0 -1
- package/dist/v2/features/operation/helpers/get-security-requirements.js +0 -17
- package/dist/v2/features/operation/helpers/get-security-requirements.js.map +0 -1
- package/dist/v2/features/operation/helpers/get-selected-security.d.ts +0 -15
- package/dist/v2/features/operation/helpers/get-selected-security.d.ts.map +0 -1
- package/dist/v2/features/operation/helpers/get-selected-security.js +0 -41
- package/dist/v2/features/operation/helpers/get-selected-security.js.map +0 -1
- package/dist/v2/features/operation/helpers/get-selected-server.d.ts +0 -13
- package/dist/v2/features/operation/helpers/get-selected-server.d.ts.map +0 -1
- package/dist/v2/features/operation/helpers/get-selected-server.js +0 -21
- package/dist/v2/features/operation/helpers/get-selected-server.js.map +0 -1
- package/dist/v2/helpers/get-active-environment.d.ts +0 -5
- package/dist/v2/helpers/get-active-environment.d.ts.map +0 -1
- package/dist/v2/helpers/get-active-environment.js +0 -19
- package/dist/v2/helpers/get-active-environment.js.map +0 -1
- package/dist/v2/helpers/get-active-proxy-url.d.ts +0 -18
- package/dist/v2/helpers/get-active-proxy-url.d.ts.map +0 -1
- package/dist/v2/helpers/get-active-proxy-url.js +0 -26
- package/dist/v2/helpers/get-active-proxy-url.js.map +0 -1
- package/dist/v2/helpers/get-servers.d.ts +0 -23
- package/dist/v2/helpers/get-servers.d.ts.map +0 -1
- package/dist/v2/helpers/get-servers.js +0 -106
- package/dist/v2/helpers/get-servers.js.map +0 -1
- package/dist/v2/helpers/index.d.ts +0 -3
- package/dist/v2/helpers/index.d.ts.map +0 -1
- package/dist/v2/helpers/index.js +0 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DocumentCollection.vue.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 { ScalarButton, ScalarModal, useModal } 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 Callout from '@/v2/components/callout/Callout.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 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 = () => {\n props.workspaceStore.saveDocument(props.documentSlug)\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=\"w-full px-3 md:mx-auto md:max-w-180\">\n <!-- Header -->\n <div\n :aria-label=\"`title: ${title}`\"\n class=\"mx-auto flex h-fit w-full flex-col gap-2 pt-14 pb-3 md:max-w-180 md:pt-6\">\n <Callout\n v-if=\"document?.['x-scalar-is-dirty']\"\n class=\"mb-5\"\n type=\"warning\">\n <p>\n You have unsaved changes. Save your work to keep your changes, or\n undo to revert them.\n </p>\n <template #actions>\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex items-center gap-2\"\n size=\"xs\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"undoChanges\">\n <span>Undo</span>\n </ScalarButton>\n <ScalarButton\n class=\"text-c-btn flex items-center gap-2\"\n size=\"xs\"\n type=\"button\"\n variant=\"solid\"\n @click=\"saveChanges\">\n <ScalarIconFloppyDisk\n size=\"sm\"\n thickness=\"1.5\" />\n <span>Save</span>\n </ScalarButton>\n </template>\n </Callout>\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 py-8\">\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=\"size-5 text-[var(--scalar-color-yellow)]\" />\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\n class=\"flex flex-wrap items-center justify-end gap-2 border-t border-[var(--scalar-border-color)] 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":""}
|
|
1
|
+
{"version":3,"file":"DocumentCollection.vue.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":""}
|
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
import IconSelector_default from "../../../components/IconSelector.vue.js";
|
|
2
|
-
import Callout_default from "../../components/callout/Callout.vue.js";
|
|
3
2
|
import { downloadAsFile } from "../../helpers/download-document.js";
|
|
4
3
|
import LabelInput_default from "./components/LabelInput.vue.js";
|
|
5
4
|
import SyncConflictResolutionEditor_default from "./components/SyncConflictResolutionEditor.vue.js";
|
|
6
5
|
import Tabs_default from "./components/Tabs.vue.js";
|
|
7
6
|
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeProps, openBlock, ref, resolveDynamicComponent, unref, withCtx } from "vue";
|
|
8
|
-
import { ScalarButton, ScalarModal, useModal } from "@scalar/components";
|
|
7
|
+
import { ScalarButton, ScalarModal, ScalarSavePrompt, useLoadingState, useModal } from "@scalar/components";
|
|
9
8
|
import { useToasts } from "@scalar/use-toasts";
|
|
10
9
|
import { RouterView } from "vue-router";
|
|
11
10
|
import { LibraryIcon } from "@scalar/icons/library";
|
|
12
11
|
import { ScalarIconCloudArrowDown, ScalarIconDownload, ScalarIconFloppyDisk, ScalarIconSpinner, ScalarIconWarning } from "@scalar/icons";
|
|
13
|
-
import { deepClone } from "@scalar/workspace-store/helpers/deep-clone";
|
|
14
12
|
import { apply } from "@scalar/json-magic/diff";
|
|
13
|
+
import { deepClone } from "@scalar/workspace-store/helpers/deep-clone";
|
|
15
14
|
//#region src/v2/features/collection/DocumentCollection.vue?vue&type=script&setup=true&lang.ts
|
|
16
15
|
var _hoisted_1 = { class: "custom-scroll h-full" };
|
|
17
16
|
var _hoisted_2 = {
|
|
18
17
|
key: 0,
|
|
19
|
-
class: "w-full px-3 md:mx-auto
|
|
18
|
+
class: "md:max-w-content w-full px-3 md:mx-auto"
|
|
20
19
|
};
|
|
21
20
|
var _hoisted_3 = ["aria-label"];
|
|
22
21
|
var _hoisted_4 = { class: "flex flex-row items-center justify-between gap-2" };
|
|
23
22
|
var _hoisted_5 = { class: "flex min-w-0 items-center gap-2" };
|
|
24
23
|
var _hoisted_6 = { class: "group relative ml-1.25 min-w-0" };
|
|
25
|
-
var _hoisted_7 = { class: "px-1.5
|
|
24
|
+
var _hoisted_7 = { class: "px-1.5 pt-8 pb-20" };
|
|
26
25
|
var _hoisted_8 = {
|
|
27
26
|
key: 1,
|
|
28
27
|
class: "flex w-full flex-1 items-center justify-center"
|
|
@@ -33,7 +32,7 @@ var _hoisted_11 = {
|
|
|
33
32
|
"aria-hidden": "true",
|
|
34
33
|
class: "bg-b-3 text-c-2 flex size-10 shrink-0 items-center justify-center rounded-lg"
|
|
35
34
|
};
|
|
36
|
-
var _hoisted_12 = { class: "flex flex-wrap items-center justify-end gap-2 border-t
|
|
35
|
+
var _hoisted_12 = { class: "flex flex-wrap items-center justify-end gap-2 border-t pt-4" };
|
|
37
36
|
var _hoisted_13 = { class: "flex h-full w-full flex-col gap-4 overflow-hidden" };
|
|
38
37
|
var DocumentCollection_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
|
|
39
38
|
name: "DocumentCollection",
|
|
@@ -46,7 +45,6 @@ var DocumentCollection_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
|
|
|
46
45
|
method: {},
|
|
47
46
|
exampleName: {},
|
|
48
47
|
environment: {},
|
|
49
|
-
securitySchemes: {},
|
|
50
48
|
workspaceStore: {},
|
|
51
49
|
activeWorkspace: {},
|
|
52
50
|
plugins: {},
|
|
@@ -66,6 +64,7 @@ var DocumentCollection_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
|
|
|
66
64
|
const syncModal = useModal();
|
|
67
65
|
const dirtyBeforeSyncModal = useModal();
|
|
68
66
|
const isDocumentDirty = computed(() => props.document?.["x-scalar-is-dirty"] === true);
|
|
67
|
+
const saveLoader = useLoadingState();
|
|
69
68
|
const documentSourceUrl = computed(() => props.document?.["x-scalar-original-source-url"]);
|
|
70
69
|
const documentRegistryMeta = computed(() => props.document?.["x-scalar-registry-meta"]);
|
|
71
70
|
/** Show Sync when the document has a source URL or registry meta (registry can be used if fetchRegistryDocument is set). */
|
|
@@ -74,8 +73,9 @@ var DocumentCollection_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
|
|
|
74
73
|
const undoChanges = () => {
|
|
75
74
|
props.workspaceStore.revertDocumentChanges(props.documentSlug);
|
|
76
75
|
};
|
|
77
|
-
const saveChanges = () => {
|
|
78
|
-
|
|
76
|
+
const saveChanges = async () => {
|
|
77
|
+
saveLoader.start();
|
|
78
|
+
await (await props.workspaceStore.saveDocument(props.documentSlug) ? saveLoader.validate() : saveLoader.invalidate({ persist: true }));
|
|
79
79
|
};
|
|
80
80
|
/** Downloads the document as a JSON file using the last saved state. */
|
|
81
81
|
const downloadDocument = () => {
|
|
@@ -193,41 +193,19 @@ var DocumentCollection_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
|
|
|
193
193
|
createElementVNode("div", _hoisted_1, [__props.document ? (openBlock(), createElementBlock("div", _hoisted_2, [
|
|
194
194
|
createElementVNode("div", {
|
|
195
195
|
"aria-label": `title: ${title.value}`,
|
|
196
|
-
class: "mx-auto flex h-fit w-full flex-col gap-2 pt-14 pb-3 md:
|
|
197
|
-
}, [
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
type: "button",
|
|
206
|
-
variant: "outlined",
|
|
207
|
-
onClick: undoChanges
|
|
208
|
-
}, {
|
|
209
|
-
default: withCtx(() => [..._cache[5] || (_cache[5] = [createElementVNode("span", null, "Undo", -1)])]),
|
|
210
|
-
_: 1
|
|
211
|
-
}), createVNode(unref(ScalarButton), {
|
|
212
|
-
class: "text-c-btn flex items-center gap-2",
|
|
213
|
-
size: "xs",
|
|
214
|
-
type: "button",
|
|
215
|
-
variant: "solid",
|
|
216
|
-
onClick: saveChanges
|
|
217
|
-
}, {
|
|
218
|
-
default: withCtx(() => [createVNode(unref(ScalarIconFloppyDisk), {
|
|
219
|
-
size: "sm",
|
|
220
|
-
thickness: "1.5"
|
|
221
|
-
}), _cache[6] || (_cache[6] = createElementVNode("span", null, "Save", -1))]),
|
|
222
|
-
_: 1
|
|
223
|
-
})]),
|
|
224
|
-
default: withCtx(() => [_cache[7] || (_cache[7] = createElementVNode("p", null, " You have unsaved changes. Save your work to keep your changes, or undo to revert them. ", -1))]),
|
|
225
|
-
_: 1
|
|
226
|
-
})) : createCommentVNode("", true), createElementVNode("div", _hoisted_4, [
|
|
196
|
+
class: "md:max-w-content mx-auto flex h-fit w-full flex-col gap-2 pt-14 pb-3 md:pt-6"
|
|
197
|
+
}, [createVNode(unref(ScalarSavePrompt), {
|
|
198
|
+
modelValue: isDocumentDirty.value,
|
|
199
|
+
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => isDocumentDirty.value = $event),
|
|
200
|
+
class: "w-content-padded-4 max-w-full-padded-4 absolute",
|
|
201
|
+
loader: unref(saveLoader),
|
|
202
|
+
onDiscard: undoChanges,
|
|
203
|
+
onSave: saveChanges
|
|
204
|
+
}, null, 8, ["modelValue", "loader"]), createElementVNode("div", _hoisted_4, [
|
|
227
205
|
createElementVNode("div", _hoisted_5, [createVNode(IconSelector_default, {
|
|
228
206
|
modelValue: icon.value,
|
|
229
207
|
placement: "bottom-start",
|
|
230
|
-
"onUpdate:modelValue": _cache[
|
|
208
|
+
"onUpdate:modelValue": _cache[1] || (_cache[1] = (icon) => __props.eventBus.emit("document:update:icon", icon))
|
|
231
209
|
}, {
|
|
232
210
|
default: withCtx(() => [createVNode(unref(ScalarButton), {
|
|
233
211
|
class: "hover:bg-b-2 aspect-square h-7 w-7 cursor-pointer rounded border border-transparent p-0 hover:border-inherit",
|
|
@@ -245,7 +223,7 @@ var DocumentCollection_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
|
|
|
245
223
|
class: "text-xl font-bold",
|
|
246
224
|
inputId: "documentName",
|
|
247
225
|
modelValue: title.value,
|
|
248
|
-
"onUpdate:modelValue": _cache[
|
|
226
|
+
"onUpdate:modelValue": _cache[2] || (_cache[2] = (title) => __props.eventBus.emit("document:update:info", { title }))
|
|
249
227
|
}, null, 8, ["modelValue"])])]),
|
|
250
228
|
createVNode(unref(ScalarButton), {
|
|
251
229
|
class: "text-c-2 hover:text-c-1 flex shrink-0 items-center gap-2",
|
|
@@ -257,7 +235,7 @@ var DocumentCollection_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
|
|
|
257
235
|
default: withCtx(() => [createVNode(unref(ScalarIconDownload), {
|
|
258
236
|
size: "sm",
|
|
259
237
|
thickness: "1.5"
|
|
260
|
-
}), _cache[
|
|
238
|
+
}), _cache[6] || (_cache[6] = createElementVNode("span", null, "Download document", -1))]),
|
|
261
239
|
_: 1
|
|
262
240
|
}),
|
|
263
241
|
canShowSyncButton.value ? (openBlock(), createBlock(unref(ScalarButton), {
|
|
@@ -280,7 +258,7 @@ var DocumentCollection_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
|
|
|
280
258
|
class: "size-3.5",
|
|
281
259
|
size: "sm",
|
|
282
260
|
thickness: "1.5"
|
|
283
|
-
})), _cache[
|
|
261
|
+
})), _cache[7] || (_cache[7] = createElementVNode("span", null, "Sync from source", -1))]),
|
|
284
262
|
_: 1
|
|
285
263
|
}, 8, ["disabled"])) : createCommentVNode("", true)
|
|
286
264
|
])], 8, _hoisted_3),
|
|
@@ -289,22 +267,22 @@ var DocumentCollection_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
|
|
|
289
267
|
default: withCtx(({ Component }) => [(openBlock(), createBlock(resolveDynamicComponent(Component), mergeProps(props, { collectionType: "document" }), null, 16))]),
|
|
290
268
|
_: 1
|
|
291
269
|
})])
|
|
292
|
-
])) : (openBlock(), createElementBlock("div", _hoisted_8, [..._cache[
|
|
270
|
+
])) : (openBlock(), createElementBlock("div", _hoisted_8, [..._cache[8] || (_cache[8] = [createElementVNode("div", { class: "flex h-full flex-col items-center justify-center" }, [createElementVNode("h1", { class: "text-2xl font-bold" }, "Document not found"), createElementVNode("p", { class: "text-gray-500" }, " The document you are looking for does not exist. ")], -1)])]))]),
|
|
293
271
|
createVNode(unref(ScalarModal), {
|
|
294
272
|
bodyClass: "border-t-0 rounded-t-lg flex flex-col gap-5",
|
|
295
273
|
size: "xs",
|
|
296
274
|
state: unref(dirtyBeforeSyncModal),
|
|
297
275
|
title: "Sync requires saved document",
|
|
298
|
-
onClose: _cache[
|
|
276
|
+
onClose: _cache[4] || (_cache[4] = ($event) => unref(dirtyBeforeSyncModal).hide())
|
|
299
277
|
}, {
|
|
300
|
-
default: withCtx(() => [createElementVNode("div", _hoisted_9, [createElementVNode("div", _hoisted_10, [createElementVNode("div", _hoisted_11, [createVNode(unref(ScalarIconWarning), { class: "size-5
|
|
278
|
+
default: withCtx(() => [createElementVNode("div", _hoisted_9, [createElementVNode("div", _hoisted_10, [createElementVNode("div", _hoisted_11, [createVNode(unref(ScalarIconWarning), { class: "text-yellow size-5" })]), _cache[9] || (_cache[9] = createElementVNode("div", { class: "min-w-0 flex-1 space-y-1" }, [createElementVNode("p", { class: "text-c-1 text-sm leading-snug font-medium" }, " You have unsaved changes "), createElementVNode("p", { class: "text-c-2 text-sm leading-relaxed" }, " Save your work to keep changes, or discard to revert to the last saved version. Then you can sync with the source. ")], -1))]), createElementVNode("div", _hoisted_12, [
|
|
301
279
|
createVNode(unref(ScalarButton), {
|
|
302
280
|
size: "sm",
|
|
303
281
|
type: "button",
|
|
304
282
|
variant: "ghost",
|
|
305
|
-
onClick: _cache[
|
|
283
|
+
onClick: _cache[3] || (_cache[3] = ($event) => unref(dirtyBeforeSyncModal).hide())
|
|
306
284
|
}, {
|
|
307
|
-
default: withCtx(() => [..._cache[
|
|
285
|
+
default: withCtx(() => [..._cache[10] || (_cache[10] = [createTextVNode(" Cancel ", -1)])]),
|
|
308
286
|
_: 1
|
|
309
287
|
}),
|
|
310
288
|
createVNode(unref(ScalarButton), {
|
|
@@ -313,7 +291,7 @@ var DocumentCollection_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
|
|
|
313
291
|
variant: "outlined",
|
|
314
292
|
onClick: handleDiscardThenCloseDirtyModal
|
|
315
293
|
}, {
|
|
316
|
-
default: withCtx(() => [..._cache[
|
|
294
|
+
default: withCtx(() => [..._cache[11] || (_cache[11] = [createTextVNode(" Discard changes ", -1)])]),
|
|
317
295
|
_: 1
|
|
318
296
|
}),
|
|
319
297
|
createVNode(unref(ScalarButton), {
|
|
@@ -326,7 +304,7 @@ var DocumentCollection_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
|
|
|
326
304
|
default: withCtx(() => [createVNode(unref(ScalarIconFloppyDisk), {
|
|
327
305
|
size: "sm",
|
|
328
306
|
thickness: "1.5"
|
|
329
|
-
}), _cache[
|
|
307
|
+
}), _cache[12] || (_cache[12] = createTextVNode(" Save and continue ", -1))]),
|
|
330
308
|
_: 1
|
|
331
309
|
})
|
|
332
310
|
])])]),
|
|
@@ -344,7 +322,7 @@ var DocumentCollection_vue_vue_type_script_setup_true_lang_default = /* @__PURE_
|
|
|
344
322
|
baseDocument: rebaseResult.value.originalDocument,
|
|
345
323
|
conflicts: rebaseResult.value.conflicts,
|
|
346
324
|
resolvedDocument: rebaseResult.value.resolvedDocument,
|
|
347
|
-
onApplyChanges: _cache[
|
|
325
|
+
onApplyChanges: _cache[5] || (_cache[5] = (payload) => handleApplyChanges(payload))
|
|
348
326
|
}, null, 8, [
|
|
349
327
|
"baseDocument",
|
|
350
328
|
"conflicts",
|
|
@@ -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 { ScalarButton, ScalarModal, useModal } 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 Callout from '@/v2/components/callout/Callout.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 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 = () => {\n props.workspaceStore.saveDocument(props.documentSlug)\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=\"w-full px-3 md:mx-auto md:max-w-180\">\n <!-- Header -->\n <div\n :aria-label=\"`title: ${title}`\"\n class=\"mx-auto flex h-fit w-full flex-col gap-2 pt-14 pb-3 md:max-w-180 md:pt-6\">\n <Callout\n v-if=\"document?.['x-scalar-is-dirty']\"\n class=\"mb-5\"\n type=\"warning\">\n <p>\n You have unsaved changes. Save your work to keep your changes, or\n undo to revert them.\n </p>\n <template #actions>\n <ScalarButton\n class=\"text-c-2 hover:text-c-1 flex items-center gap-2\"\n size=\"xs\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"undoChanges\">\n <span>Undo</span>\n </ScalarButton>\n <ScalarButton\n class=\"text-c-btn flex items-center gap-2\"\n size=\"xs\"\n type=\"button\"\n variant=\"solid\"\n @click=\"saveChanges\">\n <ScalarIconFloppyDisk\n size=\"sm\"\n thickness=\"1.5\" />\n <span>Save</span>\n </ScalarButton>\n </template>\n </Callout>\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 py-8\">\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=\"size-5 text-[var(--scalar-color-yellow)]\" />\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\n class=\"flex flex-wrap items-center justify-end gap-2 border-t border-[var(--scalar-border-color)] 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAUE,MAAM;;;;;;;;;;;;;;;;;;;;;;EA6BR,MAAM,QAAQ;;EAGd,MAAM,QAAQ,eAAe,MAAM,UAAU,MAAM,SAAS,GAAE;;EAG9D,MAAM,OAAO,eACL,MAAM,WAAW,oBAAoB,2BAC7C;EAEA,MAAM,YAAY,UAAS;EAC3B,MAAM,uBAAuB,UAAS;EAEtC,MAAM,kBAAkB,eAChB,MAAM,WAAW,yBAAyB,KAClD;EAEA,MAAM,oBAAoB,eAClB,MAAM,WAAW,gCACzB;EAEA,MAAM,uBAAuB,eAEzB,MAAM,WAAW,0BAGrB;;EAGA,MAAM,oBAAoB,eAEtB,kBAAkB,UAAU,KAAA,KAC5B,qBAAqB,UAAU,KAAA,EACnC;EAEA,MAAM,EAAE,UAAU,WAAU;EAE5B,MAAM,oBAAoB;AACxB,SAAM,eAAe,sBAAsB,MAAM,aAAY;;EAG/D,MAAM,oBAAoB;AACxB,SAAM,eAAe,aAAa,MAAM,aAAY;;;EAItD,MAAM,yBAAyB;GAC7B,MAAM,UAAU,MAAM,eAAe,eACnC,MAAM,cACN,QACA,MACF;AACA,OAAI,CAAC,QAAS;AAEd,kBAAe,SAAS,GADP,MAAM,MAAM,QAAQ,aAAa,GAAG,CAAC,MAAM,IAAI,WAC5B,OAAM;;EAG5C,MAAM,gCAAgC,YAAY;AAChD,SAAM,MAAM,eAAe,aAAa,MAAM,aAAY;AAC1D,wBAAqB,MAAK;AAC1B,SAAM,gBAAe;;EAGvB,MAAM,mCAAmC,YAAY;AACnD,SAAM,MAAM,eAAe,sBAAsB,MAAM,aAAY;AACnE,wBAAqB,MAAK;AAC1B,SAAM,gBAAe;;EAGvB,MAAM,mBAAmB,IAAI,MAAK;EAElC,MAAM,eAAe,IAaX,KAAI;;;;;EAMd,MAAM,mBAAmB,YAEpB;GACH,MAAM,eAAe,qBAAqB;AAC1C,OAAI,gBAAgB,MAAM,sBACxB,KAAI;IACF,MAAM,SAAS,MAAM,MAAM,sBAAsB,aAAY;AAC7D,QAAI,CAAC,OAAO,IAAI;AACd,WAAM,OAAO,OAAO,QAAO;AAC3B,YAAO;;AAET,WAAO,EAAE,UAAU,OAAO,MAAK;YACxB,KAAK;AACZ,UAAM,4CAA4C,QAAO;AACzD,WAAO;;GAGX,MAAM,MAAM,kBAAkB;AAC9B,OAAI,IACF,QAAO,EAAE,KAAI;AAEf,UAAO;;;;;;;EAQT,MAAM,uBAAuB;AAC3B,aAAU,MAAK;AACf,oBAAiB,QAAQ;AAEzB,SACE,2EACA,OACF;AAEA,SAAM,SAAS,KAAK,qCAAqC,EACvD,MAAM,EACJ,cAAc,MAAM,cACrB,EACF,CAAA;;;;;;;EAQH,MAAM,eAAe,UAAyB;AAC5C,OAAI,UAAU,KACZ,OAAM,OAAO,QAAO;AAEtB,oBAAiB,QAAQ;;;;;;;;EAS3B,MAAM,iBAAiB,YAAY;AACjC,OAAI,gBAAgB,OAAO;AACzB,yBAAqB,MAAK;AAC1B;;AAGF,OAAI,iBAAiB,MACnB;AAGF,oBAAiB,QAAQ;GAEzB,MAAM,QAAQ,MAAM,kBAAiB;AACrC,OAAI,CAAC,OAAO;AACV,gBAAY,KAAI;AAChB;;GAGF,MAAM,SAAS,MAAM,MAAM,eAAe,eAAe;IACvD,MAAM,MAAM;IACZ,GAAG;IACJ,CAAA;AAED,OAAI,QAAQ,IAAI;IACd,MAAM,mBACJ,MAAM,eAAe,oBAAoB,MAAM,aAAa,IAAI,EAAC;AACnE,iBAAa,QAAQ;KACnB,WAAW,OAAO;KAClB,cAAc,OAAO;KACrB,kBAAkB,MAAM,UAAU,iBAAiB,EAAE,OAAO,QAAQ;KACpE;KACF;AAEA,QAAI,aAAa,MAAM,UAAU,SAAS,EACxC,WAAU,MAAK;SACV;AAEL,WAAM,aAAa,OAAO,aAAa,EACrC,kBAAkB,aAAa,MAAM,kBACtC,CAAA;AACD,qBAAe;;cAER,QAAQ,OAAO,SAAS,OAAO,SAAS,sBAEjD,iBAAe;OAEf,aAAY,0BAAyB;;EAQzC,MAAM,qBAAqB,OAAO,EAChC,uBAGI;AACJ,SAAM,aAAa,OAAO,aAAa,EAAE,kBAAkB,CAAA;AAC3D,SAAM,SAAS,KAAK,qCAAqC,EACvD,MAAM,EACJ,cAAc,MAAM,cACrB,EACF,CAAA;AACD,aAAU,MAAK;;;;;;;EAQjB,MAAM,yBAAyB;AAC7B,oBAAiB,QAAQ;AACzB,gBAAa,QAAQ;;;;IAKrB,mBAgIM,OAhIN,YAgIM,CA9HI,QAAA,YAAA,WAAA,EADR,mBAkHM,OAlHN,YAkHM;KA9GJ,mBAgGM,OAAA;MA/FH,cAAU,UAAY,MAAA;MACvB,OAAM;SAEE,QAAA,WAAQ,wBAAA,WAAA,EADhB,YA6BU,iBAAA;;MA3BR,OAAM;MACN,MAAK;;MAKM,SAAO,cAQD,CAPf,YAOe,MAAA,aAAA,EAAA;OANb,OAAM;OACN,MAAK;OACL,MAAK;OACL,SAAQ;OACP,SAAO;;8BACS,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAjB,mBAAiB,QAAA,MAAX,QAAI,GAAA,CAAA,EAAA,CAAA;;UAEZ,YAUe,MAAA,aAAA,EAAA;OATb,OAAM;OACN,MAAK;OACL,MAAK;OACL,SAAQ;OACP,SAAO;;8BAGY,CAFpB,YAEoB,MAAA,qBAAA,EAAA;QADlB,MAAK;QACL,WAAU;qCACZ,mBAAiB,QAAA,MAAX,QAAI,GAAA,EAAA,CAAA;;;6BAnBV,CAAA,OAAA,OAAA,OAAA,KAHJ,mBAGI,KAAA,MAHD,4FAGH,GAAA,EAAA,CAAA;;yCAuBF,mBA8DM,OA9DN,YA8DM;MA7DJ,mBA0BM,OA1BN,YA0BM,CAzBJ,YAce,sBAAA;OAbZ,YAAY,KAAA;OACb,WAAU;OACT,uBAAiB,OAAA,OAAA,OAAA,MAAoB,SAAS,QAAA,SAAS,KAAI,wBAAyB,KAAI;;8BAU1E,CAPf,YAOe,MAAA,aAAA,EAAA;QANb,OAAM;QACN,SAAQ;;+BAIa,CAHrB,YAGqB,MAAA,YAAA,EAAA;SAFnB,OAAM;SACL,KAAK,KAAA;SACN,gBAAa;;;;;6BAInB,mBAQM,OARN,YAQM,CAPJ,YAMM,oBAAA;OALJ,OAAM;OACN,SAAQ;OACP,YAAY,MAAA;OACZ,uBAAiB,OAAA,OAAA,OAAA,MAAsB,UAAU,QAAA,SAAS,KAAI,wBAAA,EAA2B,OAAK,CAAA;;MAMrG,YAUe,MAAA,aAAA,EAAA;OATb,OAAM;OACN,MAAK;OACL,MAAK;OACL,SAAQ;OACP,SAAO;;8BAGY,CAFpB,YAEoB,MAAA,mBAAA,EAAA;QADlB,MAAK;QACL,WAAU;qCACZ,mBAA8B,QAAA,MAAxB,qBAAiB,GAAA,EAAA,CAAA;;;MAIjB,kBAAA,SAAA,WAAA,EADR,YAoBe,MAAA,aAAA,EAAA;;OAlBb,OAAM;OACN,eAAY;OACX,UAAU,iBAAA;OACX,MAAK;OACJ,OAAO;OACR,MAAK;OACL,SAAQ;OACP,SAAO;;8BAIM,CAFN,iBAAA,SAAA,WAAA,EADR,YAGc,MAAA,kBAAA,EAAA;;QADZ,OAAM;QACN,MAAK;2BACP,YAIoB,MAAA,yBAAA,EAAA;;QAFlB,OAAM;QACN,MAAK;QACL,WAAU;sCACZ,mBAA6B,QAAA,MAAvB,oBAAgB,GAAA,EAAA,CAAA;;;;KAM5B,YAAwB,cAAA,EAAlB,MAAK,YAAU,CAAA;KAGrB,mBAOM,OAPN,YAOM,CANJ,YAKa,MAAA,WAAA,EAAA,MAAA;wBADmB,EAJV,gBAAS,EAAA,WAAA,EAC7B,YAG8B,wBAFvB,UAAS,EADhB,WAEU,OAAK,EACb,gBAAe,YAAU,CAAA,EAAA,MAAA,GAAA,EAAA,CAAA;;;wBAMjC,mBASM,OATN,YASM,CAAA,GAAA,OAAA,QAAA,OAAA,MAAA,CANJ,mBAKM,OAAA,EALD,OAAM,oDAAkD,EAAA,CAC3D,mBAAsD,MAAA,EAAlD,OAAM,sBAAoB,EAAC,qBAAkB,EACjD,mBAEI,KAAA,EAFD,OAAM,iBAAe,EAAC,qDAEzB,CAAA,EAAA,GAAA,CAAA,EAAA,CAAA,EAAA,CAAA;IAIN,YAoDc,MAAA,YAAA,EAAA;KAnDZ,WAAU;KACV,MAAK;KACJ,OAAO,MAAA,qBAAoB;KAC5B,OAAM;KACL,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,qBAAoB,CAAC,MAAI;;4BA8C3B,CA7CN,mBA6CM,OA7CN,YA6CM,CA5CJ,mBAeM,OAfN,aAeM,CAdJ,mBAIM,OAJN,aAIM,CADJ,YAAsE,MAAA,kBAAA,EAAA,EAAnD,OAAM,4CAA0C,CAAA,CAAA,CAAA,EAAA,OAAA,QAAA,OAAA,MAErE,mBAQM,OAAA,EARD,OAAM,4BAA0B,EAAA,CACnC,mBAEI,KAAA,EAFD,OAAM,6CAA2C,EAAC,6BAErD,EACA,mBAGI,KAAA,EAHD,OAAM,oCAAkC,EAAC,uHAG5C,CAAA,EAAA,GAAA,EAAA,CAAA,EAGJ,mBA2BM,OA3BN,aA2BM;MAzBJ,YAMe,MAAA,aAAA,EAAA;OALb,MAAK;OACL,MAAK;OACL,SAAQ;OACP,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,qBAAoB,CAAC,MAAI;;8BAEnC,CAAA,GAAA,OAAA,QAAA,OAAA,MAAA,CAAA,gBAFuC,YAEvC,GAAA,CAAA,EAAA,CAAA;;;MACA,YAMe,MAAA,aAAA,EAAA;OALb,MAAK;OACL,MAAK;OACL,SAAQ;OACP,SAAO;;8BAEV,CAAA,GAAA,OAAA,QAAA,OAAA,MAAA,CAAA,gBAF4C,qBAE5C,GAAA,CAAA,EAAA,CAAA;;;MACA,YAUe,MAAA,aAAA,EAAA;OATb,OAAM;OACN,MAAK;OACL,MAAK;OACL,SAAQ;OACP,SAAO;;8BAGY,CAFpB,YAEoB,MAAA,qBAAA,EAAA;QADlB,MAAK;QACL,WAAU;uDAAQ,uBAEtB,GAAA,EAAA,CAAA;;;;;;IAKE,aAAA,SAAA,WAAA,EADR,YAcc,MAAA,YAAA,EAAA;;KAZZ,WAAU;KACV,UAAS;KACT,MAAK;KACJ,OAAO,MAAA,UAAS;KAChB,SAAO;;4BAOF,CANN,mBAMM,OANN,aAMM,CALJ,YAI6D,sCAAA;MAH1D,cAAc,aAAA,MAAa;MAC3B,WAAW,aAAA,MAAa;MACxB,kBAAkB,aAAA,MAAa;MAC/B,gBAAY,OAAA,OAAA,OAAA,MAAG,YAAY,mBAAmB,QAAO"}
|
|
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 +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"}
|
|
@@ -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":"
|
|
1
|
+
{"version":3,"file":"Authentication.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/features/collection/components/Authentication.vue"],"names":[],"mappings":"AA+jBA,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-6bba6b78"]]);
|
|
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 { 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
|
|
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,11 +1,9 @@
|
|
|
1
1
|
import AuthSelector_default from "../../../blocks/scalar-auth-selector-block/components/AuthSelector.vue.js";
|
|
2
|
-
import { getSelectedSecurity } from "../../operation/helpers/get-selected-security.js";
|
|
3
|
-
import { getActiveProxyUrl } from "../../../helpers/get-active-proxy-url.js";
|
|
4
|
-
import { getServers } from "../../../helpers/get-servers.js";
|
|
5
2
|
import { getDefaultOperationSecurityToggle } from "../helpers/get-default-operation-security-toggle.js";
|
|
6
3
|
import Section_default from "../../settings/components/Section.vue.js";
|
|
7
4
|
import { Fragment, computed, createBlock, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, ref, unref, watchEffect, withCtx } from "vue";
|
|
8
5
|
import { ScalarToggle } from "@scalar/components";
|
|
6
|
+
import { getActiveProxyUrl, getSelectedSecurity, getServers, mergeSecurity } from "@scalar/workspace-store/request-example";
|
|
9
7
|
import { getResolvedRef } from "@scalar/workspace-store/helpers/get-resolved-ref";
|
|
10
8
|
import { unpackProxyObject } from "@scalar/workspace-store/helpers/unpack-proxy";
|
|
11
9
|
import { isHttpMethod } from "@scalar/helpers/http/is-http-method";
|
|
@@ -22,7 +20,6 @@ var Authentication_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
|
|
|
22
20
|
method: {},
|
|
23
21
|
exampleName: {},
|
|
24
22
|
environment: {},
|
|
25
|
-
securitySchemes: {},
|
|
26
23
|
workspaceStore: {},
|
|
27
24
|
activeWorkspace: {},
|
|
28
25
|
plugins: {},
|
|
@@ -68,6 +65,7 @@ var Authentication_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
|
|
|
68
65
|
...authMeta.value
|
|
69
66
|
});
|
|
70
67
|
});
|
|
68
|
+
const securitySchemes = computed(() => mergeSecurity(__props.document?.components?.securitySchemes ?? {}, {}, __props.workspaceStore.auth, __props.documentSlug));
|
|
71
69
|
/** Resolved selected security for the current collection (operation or document), with defaults applied */
|
|
72
70
|
const selectedSecurity = computed(() => {
|
|
73
71
|
if (__props.collectionType === "operation") return getSelectedSecurity(void 0, __props.workspaceStore.auth.getAuthSelectedSchemas({
|
|
@@ -75,11 +73,11 @@ var Authentication_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
|
|
|
75
73
|
documentName: __props.documentSlug,
|
|
76
74
|
path: __props.path ?? "",
|
|
77
75
|
method: __props.method ?? "get"
|
|
78
|
-
}), operation.value?.security ?? [],
|
|
76
|
+
}), operation.value?.security ?? [], securitySchemes.value);
|
|
79
77
|
return getSelectedSecurity(__props.workspaceStore.auth.getAuthSelectedSchemas({
|
|
80
78
|
type: "document",
|
|
81
79
|
documentName: __props.documentSlug
|
|
82
|
-
}), void 0, __props.document?.security ?? [],
|
|
80
|
+
}), void 0, __props.document?.security ?? [], securitySchemes.value);
|
|
83
81
|
});
|
|
84
82
|
/** Compute the security requirements for the operation or document based on the current collection type */
|
|
85
83
|
const securityRequirements = computed(() => {
|
|
@@ -87,7 +85,7 @@ var Authentication_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
|
|
|
87
85
|
return __props.document?.security ?? [];
|
|
88
86
|
});
|
|
89
87
|
/** Compute the proxy URL for the current layout (for the electron we don't want to use the proxy by default) */
|
|
90
|
-
const proxyUrl = computed(() => getActiveProxyUrl(__props.workspaceStore.workspace["x-scalar-active-proxy"], __props.layout) ?? "");
|
|
88
|
+
const proxyUrl = computed(() => getActiveProxyUrl(__props.workspaceStore.workspace["x-scalar-active-proxy"], __props.layout === "web" ? "web" : "other") ?? "");
|
|
91
89
|
const servers = computed(() => {
|
|
92
90
|
return getServers(operation.value?.servers ?? __props.document?.servers, { documentUrl: __props.document?.["x-scalar-original-source-url"] });
|
|
93
91
|
});
|
|
@@ -132,7 +130,7 @@ var Authentication_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
|
|
|
132
130
|
meta: authMeta.value,
|
|
133
131
|
proxyUrl: proxyUrl.value,
|
|
134
132
|
securityRequirements: securityRequirements.value,
|
|
135
|
-
securitySchemes:
|
|
133
|
+
securitySchemes: securitySchemes.value,
|
|
136
134
|
selectedSecurity: selectedSecurity.value,
|
|
137
135
|
server: server.value,
|
|
138
136
|
title: "Authentication"
|