@scalar/api-client 3.19.3 → 3.21.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 +79 -0
- package/dist/components/HttpMethod/HttpMethod.vue.d.ts +2 -2
- package/dist/components/HttpMethod/HttpMethod.vue.d.ts.map +1 -1
- package/dist/components/HttpMethod/HttpMethod.vue.js +1 -1
- package/dist/components/HttpMethod/HttpMethod.vue.js.map +1 -1
- package/dist/components/HttpMethod/HttpMethod.vue.script.js +15 -7
- package/dist/components/HttpMethod/HttpMethod.vue.script.js.map +1 -1
- package/dist/components/SectionFilter.vue.d.ts +2 -0
- package/dist/components/SectionFilter.vue.d.ts.map +1 -1
- package/dist/components/SectionFilter.vue.js +1 -1
- package/dist/components/SectionFilter.vue.js.map +1 -1
- package/dist/components/SectionFilter.vue.script.js +11 -8
- package/dist/components/SectionFilter.vue.script.js.map +1 -1
- package/dist/components/Server/ServerVariablesSelect.vue.d.ts.map +1 -1
- package/dist/components/Server/ServerVariablesSelect.vue.js.map +1 -1
- package/dist/components/Server/ServerVariablesSelect.vue.script.js +5 -3
- package/dist/components/Server/ServerVariablesSelect.vue.script.js.map +1 -1
- package/dist/components/Server/ServerVariablesTextbox.vue.d.ts.map +1 -1
- package/dist/components/Server/ServerVariablesTextbox.vue.js.map +1 -1
- package/dist/components/Server/ServerVariablesTextbox.vue.script.js +6 -3
- package/dist/components/Server/ServerVariablesTextbox.vue.script.js.map +1 -1
- package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.d.ts.map +1 -1
- package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.js.map +1 -1
- package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.script.js +4 -2
- package/dist/components/Sidebar/Actions/DeleteSidebarListElement.vue.script.js.map +1 -1
- package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.d.ts.map +1 -1
- package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.js.map +1 -1
- package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.script.js +3 -1
- package/dist/components/Sidebar/Actions/SidebarListElementForm.vue.script.js.map +1 -1
- package/dist/style.css +164 -141
- package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts +3 -2
- 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 +16 -3
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.d.ts +1 -2
- package/dist/v2/blocks/operation-block/components/Header.vue.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.js +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.js.map +1 -1
- package/dist/v2/blocks/operation-block/components/Header.vue.script.js +10 -6
- package/dist/v2/blocks/operation-block/components/Header.vue.script.js.map +1 -1
- package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.js +1 -1
- package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.js.map +1 -1
- package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.script.js +6 -3
- package/dist/v2/blocks/operation-block/components/OpenApiClientButton.vue.script.js.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/har-to-fetch-response.d.ts +1 -2
- package/dist/v2/blocks/operation-block/helpers/har-to-fetch-response.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/har-to-fetch-response.js.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/send-request.d.ts +1 -2
- package/dist/v2/blocks/operation-block/helpers/send-request.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/helpers/send-request.js +4 -3
- package/dist/v2/blocks/operation-block/helpers/send-request.js.map +1 -1
- package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts +3 -2
- 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 +59 -26
- 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 +28 -8
- package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.script.js +9 -3
- package/dist/v2/blocks/request-block/components/RequestBodyStructured.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBodyViewToggle.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBodyViewToggle.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBodyViewToggle.vue.script.js +6 -4
- package/dist/v2/blocks/request-block/components/RequestBodyViewToggle.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 +13 -4
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestParams.vue.d.ts +2 -0
- package/dist/v2/blocks/request-block/components/RequestParams.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestParams.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestParams.vue.script.js +14 -7
- package/dist/v2/blocks/request-block/components/RequestParams.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts +6 -6
- package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.js +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js +40 -7
- package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts +16 -16
- 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 +24 -20
- package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.script.js +6 -4
- package/dist/v2/blocks/request-block/components/RequestTableTooltip.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/helpers/create-parameter-rows.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/helpers/create-parameter-rows.js +14 -6
- package/dist/v2/blocks/request-block/helpers/create-parameter-rows.js.map +1 -1
- package/dist/v2/blocks/request-block/helpers/get-form-body-rows.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js +5 -4
- package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js.map +1 -1
- package/dist/v2/blocks/response-block/ResponseBlock.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/ResponseBlock.vue.js +1 -1
- package/dist/v2/blocks/response-block/ResponseBlock.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/ResponseBlock.vue.script.js +34 -13
- package/dist/v2/blocks/response-block/ResponseBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/components/Headers.vue.d.ts +3 -3
- package/dist/v2/blocks/response-block/components/Headers.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/components/Headers.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/components/Headers.vue.script.js +5 -3
- package/dist/v2/blocks/response-block/components/Headers.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBody.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBody.vue.js +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBody.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBody.vue.script.js +3 -1
- package/dist/v2/blocks/response-block/components/ResponseBody.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyDownload.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyDownload.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyDownload.vue.script.js +11 -3
- package/dist/v2/blocks/response-block/components/ResponseBodyDownload.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.js +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.script.js +8 -6
- package/dist/v2/blocks/response-block/components/ResponseBodyPreview.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.d.ts +1 -0
- package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.script.js +109 -56
- package/dist/v2/blocks/response-block/components/ResponseBodyStreaming.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyToggle.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyToggle.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyToggle.vue.script.js +5 -3
- package/dist/v2/blocks/response-block/components/ResponseBodyToggle.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyVirtual.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyVirtual.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseBodyVirtual.vue.script.js +6 -3
- package/dist/v2/blocks/response-block/components/ResponseBodyVirtual.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseCookies.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseCookies.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseCookies.vue.script.js +7 -5
- package/dist/v2/blocks/response-block/components/ResponseCookies.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.d.ts +2 -2
- package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.js +1 -1
- package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.script.js +20 -15
- package/dist/v2/blocks/response-block/components/ResponseEmpty.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.js +1 -1
- package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.script.js +4 -2
- package/dist/v2/blocks/response-block/components/ResponseLoadingOverlay.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseMetaInformation.vue.d.ts.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseMetaInformation.vue.js.map +1 -1
- package/dist/v2/blocks/response-block/components/ResponseMetaInformation.vue.script.js +11 -6
- package/dist/v2/blocks/response-block/components/ResponseMetaInformation.vue.script.js.map +1 -1
- package/dist/v2/blocks/response-block/helpers/response-stream-multipart.d.ts +4 -0
- package/dist/v2/blocks/response-block/helpers/response-stream-multipart.d.ts.map +1 -0
- package/dist/v2/blocks/response-block/helpers/response-stream-multipart.js +100 -0
- package/dist/v2/blocks/response-block/helpers/response-stream-multipart.js.map +1 -0
- package/dist/v2/blocks/response-block/helpers/response-stream.d.ts +13 -0
- package/dist/v2/blocks/response-block/helpers/response-stream.d.ts.map +1 -0
- package/dist/v2/blocks/response-block/helpers/response-stream.js +97 -0
- package/dist/v2/blocks/response-block/helpers/response-stream.js.map +1 -0
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBar.vue.d.ts +2 -3
- 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 +41 -29
- 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 +6 -7
- 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 +7 -4
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.script.js +21 -16
- package/dist/v2/blocks/scalar-address-bar-block/components/EnvironmentSelector.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.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 +7 -5
- 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/DeleteRequestAuthModal.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue.script.js +7 -5
- package/dist/v2/blocks/scalar-auth-selector-block/components/DeleteRequestAuthModal.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js +105 -40
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.script.js +10 -8
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesAddModal.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.script.js +20 -14
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.script.js +6 -4
- package/dist/v2/blocks/scalar-auth-selector-block/components/OpenIDConnect.vue.script.js.map +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 +3 -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.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 +40 -40
- 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/auth-options.d.ts +108 -7
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/auth-options.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/auth-options.js +12 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/auth-options.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/extract-security-scheme-secrets.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.js +8 -5
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.d.ts +2 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js +2 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-openid-connect-discovery.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.d.ts +3 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.d.ts.map +1 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.js +8 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.js.map +1 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-client-authorization.d.ts +3 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-client-authorization.d.ts.map +1 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-client-authorization.js +11 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-client-authorization.js.map +1 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.d.ts +19 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.d.ts.map +1 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.js +117 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.js.map +1 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts +2 -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 +15 -11
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.d.ts +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.js +8 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.js +6 -0
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.d.ts +2 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.js +8 -6
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.js.map +1 -1
- package/dist/v2/components/code-input/CodeInput.vue.d.ts +4 -4
- 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 +10 -10
- package/dist/v2/components/code-input/CodeInput.vue.script.js.map +1 -1
- package/dist/v2/components/code-input/CodeInputLite.vue.d.ts +4 -4
- package/dist/v2/components/code-input/CodeInputLite.vue.d.ts.map +1 -1
- package/dist/v2/components/code-input/CodeInputLite.vue.js +1 -1
- package/dist/v2/components/code-input/CodeInputLite.vue.js.map +1 -1
- package/dist/v2/components/code-input/CodeInputLite.vue.script.js +8 -5
- package/dist/v2/components/code-input/CodeInputLite.vue.script.js.map +1 -1
- package/dist/v2/components/code-input/PillTooltipHost.vue.d.ts +4 -0
- package/dist/v2/components/code-input/PillTooltipHost.vue.d.ts.map +1 -1
- package/dist/v2/components/code-input/PillTooltipHost.vue.js.map +1 -1
- package/dist/v2/components/code-input/PillTooltipHost.vue.script.js +7 -3
- package/dist/v2/components/code-input/PillTooltipHost.vue.script.js.map +1 -1
- package/dist/v2/components/code-input/code-variable-widget.d.ts +3 -0
- package/dist/v2/components/code-input/code-variable-widget.d.ts.map +1 -1
- package/dist/v2/components/code-input/code-variable-widget.js +6 -3
- package/dist/v2/components/code-input/code-variable-widget.js.map +1 -1
- package/dist/v2/components/data-table/DataTable.vue.d.ts.map +1 -1
- package/dist/v2/components/data-table/DataTable.vue.js.map +1 -1
- package/dist/v2/components/data-table/DataTable.vue.script.js +2 -1
- package/dist/v2/components/data-table/DataTable.vue.script.js.map +1 -1
- package/dist/v2/components/data-table/DataTableCheckbox.vue.d.ts +0 -1
- package/dist/v2/components/data-table/DataTableCheckbox.vue.d.ts.map +1 -1
- package/dist/v2/components/data-table/DataTableCheckbox.vue.js.map +1 -1
- package/dist/v2/components/data-table/DataTableCheckbox.vue.script.js +4 -2
- package/dist/v2/components/data-table/DataTableCheckbox.vue.script.js.map +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.d.ts.map +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.js +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.js.map +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.script.js +5 -3
- package/dist/v2/components/data-table/DataTableInput.vue.script.js.map +1 -1
- package/dist/v2/components/data-table/DataTableInputSelect.vue.d.ts.map +1 -1
- package/dist/v2/components/data-table/DataTableInputSelect.vue.js.map +1 -1
- package/dist/v2/components/data-table/DataTableInputSelect.vue.script.js +12 -9
- package/dist/v2/components/data-table/DataTableInputSelect.vue.script.js.map +1 -1
- package/dist/v2/components/forms/ConfirmationForm.vue.d.ts.map +1 -1
- package/dist/v2/components/forms/ConfirmationForm.vue.js.map +1 -1
- package/dist/v2/components/forms/ConfirmationForm.vue.script.js +5 -3
- package/dist/v2/components/forms/ConfirmationForm.vue.script.js.map +1 -1
- package/dist/v2/components/layout/CollapsibleSection.vue.d.ts.map +1 -1
- package/dist/v2/components/layout/CollapsibleSection.vue.js.map +1 -1
- package/dist/v2/components/layout/CollapsibleSection.vue.script.js +3 -1
- package/dist/v2/components/layout/CollapsibleSection.vue.script.js.map +1 -1
- package/dist/v2/components/modals/DeleteModal.vue.d.ts.map +1 -1
- package/dist/v2/components/modals/DeleteModal.vue.js.map +1 -1
- package/dist/v2/components/modals/DeleteModal.vue.script.js +3 -1
- package/dist/v2/components/modals/DeleteModal.vue.script.js.map +1 -1
- package/dist/v2/components/modals/ModalClientContainer.vue.d.ts.map +1 -1
- package/dist/v2/components/modals/ModalClientContainer.vue.js +1 -1
- package/dist/v2/components/modals/ModalClientContainer.vue.js.map +1 -1
- package/dist/v2/components/modals/ModalClientContainer.vue.script.js +5 -2
- package/dist/v2/components/modals/ModalClientContainer.vue.script.js.map +1 -1
- package/dist/v2/components/server/ServerDropdown.vue.d.ts.map +1 -1
- package/dist/v2/components/server/ServerDropdown.vue.js.map +1 -1
- package/dist/v2/components/server/ServerDropdown.vue.script.js +9 -5
- package/dist/v2/components/server/ServerDropdown.vue.script.js.map +1 -1
- package/dist/v2/components/sidebar/Sidebar.vue.d.ts.map +1 -1
- package/dist/v2/components/sidebar/Sidebar.vue.js.map +1 -1
- package/dist/v2/components/sidebar/Sidebar.vue.script.js +4 -2
- package/dist/v2/components/sidebar/Sidebar.vue.script.js.map +1 -1
- package/dist/v2/components/sidebar/SidebarMenu.vue.d.ts.map +1 -1
- package/dist/v2/components/sidebar/SidebarMenu.vue.js.map +1 -1
- package/dist/v2/components/sidebar/SidebarMenu.vue.script.js +4 -2
- package/dist/v2/components/sidebar/SidebarMenu.vue.script.js.map +1 -1
- package/dist/v2/components/sidebar/SidebarToggle.vue.d.ts.map +1 -1
- package/dist/v2/components/sidebar/SidebarToggle.vue.js.map +1 -1
- package/dist/v2/components/sidebar/SidebarToggle.vue.script.js +4 -2
- package/dist/v2/components/sidebar/SidebarToggle.vue.script.js.map +1 -1
- package/dist/v2/constants.js +1 -1
- package/dist/v2/features/command-palette/components/CommandActionForm.vue.d.ts.map +1 -1
- package/dist/v2/features/command-palette/components/CommandActionForm.vue.js.map +1 -1
- package/dist/v2/features/command-palette/components/CommandActionForm.vue.script.js +4 -2
- package/dist/v2/features/command-palette/components/CommandActionForm.vue.script.js.map +1 -1
- package/dist/v2/features/command-palette/components/CommandActionInput.vue.d.ts +2 -2
- package/dist/v2/features/environments/EnvironmentsList.vue.d.ts.map +1 -1
- package/dist/v2/features/environments/EnvironmentsList.vue.js.map +1 -1
- package/dist/v2/features/environments/EnvironmentsList.vue.script.js +4 -2
- package/dist/v2/features/environments/EnvironmentsList.vue.script.js.map +1 -1
- package/dist/v2/features/environments/components/Environment.vue.d.ts.map +1 -1
- package/dist/v2/features/environments/components/Environment.vue.js.map +1 -1
- package/dist/v2/features/environments/components/Environment.vue.script.js +12 -10
- package/dist/v2/features/environments/components/Environment.vue.script.js.map +1 -1
- package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.d.ts.map +1 -1
- package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.js.map +1 -1
- package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.script.js +5 -3
- package/dist/v2/features/environments/components/EnvironmentCreateModal.vue.script.js.map +1 -1
- package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.d.ts.map +1 -1
- package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.js.map +1 -1
- package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.script.js +9 -6
- package/dist/v2/features/environments/components/EnvironmentDeleteModal.vue.script.js.map +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 +6 -4
- package/dist/v2/features/environments/components/EnvironmentVariablesDropdown.vue.script.js.map +1 -1
- package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.d.ts.map +1 -1
- package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.js +1 -1
- package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.js.map +1 -1
- package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.script.js +22 -10
- package/dist/v2/features/environments/components/EnvironmentVariablesTable.vue.script.js.map +1 -1
- package/dist/v2/features/localization/index.d.ts +18 -0
- package/dist/v2/features/localization/index.d.ts.map +1 -0
- package/dist/v2/features/localization/index.js +35 -0
- package/dist/v2/features/localization/index.js.map +1 -0
- package/dist/v2/features/localization/locales/ar.d.ts +389 -0
- package/dist/v2/features/localization/locales/ar.d.ts.map +1 -0
- package/dist/v2/features/localization/locales/ar.js +351 -0
- package/dist/v2/features/localization/locales/ar.js.map +1 -0
- package/dist/v2/features/localization/locales/de.d.ts +389 -0
- package/dist/v2/features/localization/locales/de.d.ts.map +1 -0
- package/dist/v2/features/localization/locales/de.js +351 -0
- package/dist/v2/features/localization/locales/de.js.map +1 -0
- package/dist/v2/features/localization/locales/es.d.ts +389 -0
- package/dist/v2/features/localization/locales/es.d.ts.map +1 -0
- package/dist/v2/features/localization/locales/es.js +351 -0
- package/dist/v2/features/localization/locales/es.js.map +1 -0
- package/dist/v2/features/localization/locales/fr.d.ts +389 -0
- package/dist/v2/features/localization/locales/fr.d.ts.map +1 -0
- package/dist/v2/features/localization/locales/fr.js +351 -0
- package/dist/v2/features/localization/locales/fr.js.map +1 -0
- package/dist/v2/features/localization/locales/pt.d.ts +389 -0
- package/dist/v2/features/localization/locales/pt.d.ts.map +1 -0
- package/dist/v2/features/localization/locales/pt.js +351 -0
- package/dist/v2/features/localization/locales/pt.js.map +1 -0
- package/dist/v2/features/localization/locales/ru.d.ts +389 -0
- package/dist/v2/features/localization/locales/ru.d.ts.map +1 -0
- package/dist/v2/features/localization/locales/ru.js +351 -0
- package/dist/v2/features/localization/locales/ru.js.map +1 -0
- package/dist/v2/features/localization/locales/zh-cn.d.ts +389 -0
- package/dist/v2/features/localization/locales/zh-cn.d.ts.map +1 -0
- package/dist/v2/features/localization/locales/zh-cn.js +351 -0
- package/dist/v2/features/localization/locales/zh-cn.js.map +1 -0
- package/dist/v2/features/localization/translations.d.ts +389 -0
- package/dist/v2/features/localization/translations.d.ts.map +1 -0
- package/dist/v2/features/localization/translations.js +351 -0
- package/dist/v2/features/localization/translations.js.map +1 -0
- package/dist/v2/features/modal/Modal.vue.d.ts +1 -2
- 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 +15 -4
- package/dist/v2/features/modal/Modal.vue.script.js.map +1 -1
- package/dist/v2/features/modal/helpers/resolve-route-parameters.d.ts +2 -3
- package/dist/v2/features/modal/helpers/resolve-route-parameters.d.ts.map +1 -1
- package/dist/v2/features/modal/helpers/resolve-route-parameters.js +8 -7
- package/dist/v2/features/modal/helpers/resolve-route-parameters.js.map +1 -1
- package/dist/v2/features/modal/hooks/use-modal-sidebar.d.ts +2 -3
- package/dist/v2/features/modal/hooks/use-modal-sidebar.d.ts.map +1 -1
- package/dist/v2/features/modal/hooks/use-modal-sidebar.js.map +1 -1
- package/dist/v2/features/modal/use-lazy-api-client.d.ts +11 -0
- package/dist/v2/features/modal/use-lazy-api-client.d.ts.map +1 -0
- package/dist/v2/features/modal/use-lazy-api-client.js +48 -0
- package/dist/v2/features/modal/use-lazy-api-client.js.map +1 -0
- package/dist/v2/features/operation/Operation.vue.d.ts +1 -2
- 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 +22 -6
- package/dist/v2/features/operation/Operation.vue.script.js.map +1 -1
- package/dist/v2/features/search/components/DocumentSearchModal.vue.d.ts.map +1 -1
- package/dist/v2/features/search/components/DocumentSearchModal.vue.js +1 -1
- package/dist/v2/features/search/components/DocumentSearchModal.vue.js.map +1 -1
- package/dist/v2/features/search/components/DocumentSearchModal.vue.script.js +12 -8
- package/dist/v2/features/search/components/DocumentSearchModal.vue.script.js.map +1 -1
- package/dist/v2/features/search/components/SearchResult.vue.d.ts.map +1 -1
- package/dist/v2/features/search/components/SearchResult.vue.js.map +1 -1
- package/dist/v2/features/search/components/SearchResult.vue.script.js +14 -10
- package/dist/v2/features/search/components/SearchResult.vue.script.js.map +1 -1
- package/dist/v2/helpers/generate-location-id.d.ts +1 -2
- package/dist/v2/helpers/generate-location-id.d.ts.map +1 -1
- package/dist/v2/helpers/generate-location-id.js.map +1 -1
- package/dist/v2/types/options.d.ts +1 -1
- package/dist/v2/types/options.d.ts.map +1 -1
- package/dist/v2/workspace-events.d.ts +2 -2
- package/dist/v2/workspace-events.d.ts.map +1 -1
- package/dist/v2/workspace-events.js +8 -1
- package/dist/v2/workspace-events.js.map +1 -1
- package/dist/vue-styles.css +128 -129
- package/package.json +22 -11
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { getOAuthCallbackData } from "./oauth-callback.js";
|
|
2
|
+
import { oauthClientAuthorization } from "./oauth-client-authorization.js";
|
|
3
|
+
import { authorizeDevice } from "./oauth-device-authorization.js";
|
|
2
4
|
import { getServerVariables } from "@scalar/workspace-store/request-example";
|
|
3
5
|
import { makeUrlAbsolute } from "@scalar/helpers/url/make-url-absolute";
|
|
4
6
|
import { replaceEnvVariables, replacePathVariables } from "@scalar/helpers/regex/replace-variables";
|
|
5
7
|
import { isRelativePath } from "@scalar/helpers/url/is-relative-path";
|
|
6
8
|
import { shouldUseProxy } from "@scalar/helpers/url/redirect-to-proxy";
|
|
7
|
-
import {
|
|
9
|
+
import { fromUint8Array } from "js-base64";
|
|
8
10
|
//#region src/v2/blocks/scalar-auth-selector-block/helpers/oauth.ts
|
|
9
11
|
/**
|
|
10
12
|
* Resolves the active server URL using OpenAPI server variables first, then
|
|
@@ -51,10 +53,12 @@ var generateCodeChallenge = async (verifier, encoding) => {
|
|
|
51
53
|
*
|
|
52
54
|
* @returns the resolved oauth2 tokens
|
|
53
55
|
*/
|
|
54
|
-
var authorizeOauth2 = async (flows, type, selectedScopes, activeServer, proxyUrl, environmentVariables = {}, customFetch, captureCallback) => {
|
|
56
|
+
var authorizeOauth2 = async (flows, type, selectedScopes, activeServer, proxyUrl, environmentVariables = {}, customFetch, captureCallback, deviceOptions) => {
|
|
55
57
|
const flow = flows[type];
|
|
56
58
|
try {
|
|
57
59
|
if (!flow) return [/* @__PURE__ */ new Error("Flow not found"), null];
|
|
60
|
+
if (type === "deviceAuthorization" && flows.deviceAuthorization) return authorizeDevice(flows.deviceAuthorization, selectedScopes, activeServer, proxyUrl, environmentVariables, customFetch, deviceOptions);
|
|
61
|
+
if (type === "deviceAuthorization") return [/* @__PURE__ */ new Error("Flow not found"), null];
|
|
58
62
|
const scopes = selectedScopes.join(" ");
|
|
59
63
|
if (type === "clientCredentials" || type === "password") return authorizeServers(flows, type, scopes, {
|
|
60
64
|
proxyUrl,
|
|
@@ -92,7 +96,7 @@ var authorizeOauth2 = async (flows, type, selectedScopes, activeServer, proxyUrl
|
|
|
92
96
|
if (!value) return;
|
|
93
97
|
url.searchParams.set(key, value);
|
|
94
98
|
});
|
|
95
|
-
url.searchParams.set("client_id", flow["x-scalar-secret-client-id"].trim());
|
|
99
|
+
url.searchParams.set("client_id", replaceEnvVariables(flow["x-scalar-secret-client-id"], environmentVariables).trim());
|
|
96
100
|
url.searchParams.set("state", state);
|
|
97
101
|
if (scopes) url.searchParams.set("scope", scopes);
|
|
98
102
|
if (captureCallback) {
|
|
@@ -168,8 +172,8 @@ var authorizeServers = async (flows, type, scopes, { code, pkce, proxyUrl, custo
|
|
|
168
172
|
if (!flow) return [/* @__PURE__ */ new Error("OAuth2 flow was not defined"), null];
|
|
169
173
|
const formData = new URLSearchParams();
|
|
170
174
|
if (scopes && (type === "clientCredentials" || type === "password")) formData.set("scope", scopes);
|
|
171
|
-
const clientId = flow["x-scalar-secret-client-id"].trim();
|
|
172
|
-
const clientSecret = flow["x-scalar-secret-client-secret"].trim();
|
|
175
|
+
const clientId = replaceEnvVariables(flow["x-scalar-secret-client-id"], environmentVariables).trim();
|
|
176
|
+
const clientSecret = replaceEnvVariables(flow["x-scalar-secret-client-secret"], environmentVariables).trim();
|
|
173
177
|
/** Where to add the credentials */
|
|
174
178
|
const addCredentialsToBody = flow["x-scalar-credentials-location"] === "body";
|
|
175
179
|
/**
|
|
@@ -177,7 +181,7 @@ var authorizeServers = async (flows, type, scopes, { code, pkce, proxyUrl, custo
|
|
|
177
181
|
* We send the client_secret whenever one is set, regardless of PKCE (see RFC 9700 Section 2.1.1).
|
|
178
182
|
*/
|
|
179
183
|
const hasClientSecret = Boolean(clientSecret);
|
|
180
|
-
if (addCredentialsToBody || type === "authorizationCode" && !hasClientSecret) formData.set("client_id", clientId);
|
|
184
|
+
if (addCredentialsToBody || (type === "authorizationCode" || type === "deviceAuthorization") && !hasClientSecret) formData.set("client_id", clientId);
|
|
181
185
|
if (addCredentialsToBody && hasClientSecret) formData.set("client_secret", clientSecret);
|
|
182
186
|
if (redirectUri) formData.set("redirect_uri", redirectUri);
|
|
183
187
|
else if ("x-scalar-secret-redirect-uri" in flow && flow["x-scalar-secret-redirect-uri"]) formData.set("redirect_uri", flow["x-scalar-secret-redirect-uri"]);
|
|
@@ -196,7 +200,7 @@ var authorizeServers = async (flows, type, scopes, { code, pkce, proxyUrl, custo
|
|
|
196
200
|
});
|
|
197
201
|
try {
|
|
198
202
|
const headers = { "Content-Type": "application/x-www-form-urlencoded" };
|
|
199
|
-
if (!addCredentialsToBody && hasClientSecret) headers.Authorization =
|
|
203
|
+
if (!addCredentialsToBody && hasClientSecret) headers.Authorization = oauthClientAuthorization(clientId, clientSecret);
|
|
200
204
|
const tokenUrl = makeUrlAbsolute(flow["x-scalar-secret-token-url"] ?? flow.tokenUrl, getActiveServerBase(activeServer, environmentVariables));
|
|
201
205
|
const responseData = await (await customFetch(shouldUseProxy(proxyUrl, tokenUrl) ? `${proxyUrl}?${new URLSearchParams([["scalar_url", tokenUrl]]).toString()}` : tokenUrl, {
|
|
202
206
|
method: "POST",
|
|
@@ -228,19 +232,19 @@ var refreshOauth2Token = async (flows, type, proxyUrl, activeServer, environment
|
|
|
228
232
|
const formData = new URLSearchParams();
|
|
229
233
|
formData.set("grant_type", "refresh_token");
|
|
230
234
|
formData.set("refresh_token", refreshToken);
|
|
231
|
-
const clientId = flow["x-scalar-secret-client-id"].trim();
|
|
232
|
-
const clientSecret = flow["x-scalar-secret-client-secret"].trim();
|
|
235
|
+
const clientId = replaceEnvVariables(flow["x-scalar-secret-client-id"], environmentVariables).trim();
|
|
236
|
+
const clientSecret = replaceEnvVariables(flow["x-scalar-secret-client-secret"], environmentVariables).trim();
|
|
233
237
|
const addCredentialsToBody = flow["x-scalar-credentials-location"] === "body";
|
|
234
238
|
/** A confidential client keeps using its secret on refresh, even when PKCE is enabled. */
|
|
235
239
|
const hasClientSecret = Boolean(clientSecret);
|
|
236
|
-
if (addCredentialsToBody || type === "authorizationCode" && !hasClientSecret) formData.set("client_id", clientId);
|
|
240
|
+
if (addCredentialsToBody || (type === "authorizationCode" || type === "deviceAuthorization") && !hasClientSecret) formData.set("client_id", clientId);
|
|
237
241
|
if (addCredentialsToBody && hasClientSecret) formData.set("client_secret", clientSecret);
|
|
238
242
|
if (flow["x-scalar-security-body"]) Object.entries(flow["x-scalar-security-body"]).forEach(([key, value]) => {
|
|
239
243
|
if (value !== void 0 && value !== null) formData.set(key, String(value));
|
|
240
244
|
});
|
|
241
245
|
try {
|
|
242
246
|
const headers = { "Content-Type": "application/x-www-form-urlencoded" };
|
|
243
|
-
if (!addCredentialsToBody && hasClientSecret) headers.Authorization =
|
|
247
|
+
if (!addCredentialsToBody && hasClientSecret) headers.Authorization = oauthClientAuthorization(clientId, clientSecret);
|
|
244
248
|
const absoluteRefreshUrl = makeUrlAbsolute(flow.refreshUrl || flow["x-scalar-secret-token-url"] || flow.tokenUrl, getActiveServerBase(activeServer, environmentVariables));
|
|
245
249
|
const responseData = await (await customFetch(shouldUseProxy(proxyUrl, absoluteRefreshUrl) ? `${proxyUrl}?${new URLSearchParams([["scalar_url", absoluteRefreshUrl]]).toString()}` : absoluteRefreshUrl, {
|
|
246
250
|
method: "POST",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth.ts"],"sourcesContent":["import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error'\nimport { replaceEnvVariables, replacePathVariables } from '@scalar/helpers/regex/replace-variables'\nimport { isRelativePath } from '@scalar/helpers/url/is-relative-path'\nimport { makeUrlAbsolute } from '@scalar/helpers/url/make-url-absolute'\nimport { shouldUseProxy } from '@scalar/helpers/url/redirect-to-proxy'\nimport type { OAuthFlowsObjectSecret } from '@scalar/workspace-store/request-example'\nimport { getServerVariables } from '@scalar/workspace-store/request-example'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { encode, fromUint8Array } from 'js-base64'\n\nimport type { CustomFetch } from '@/v2/blocks/operation-block/helpers/send-request'\n\nimport { getOAuthCallbackData } from './oauth-callback'\n\n/** Oauth2 security schemes which are not implicit */\ntype NonImplicitFlows = Omit<OAuthFlowsObjectSecret, 'implicit'>\n\ntype PKCEState = {\n codeVerifier: string\n codeChallenge: string\n codeChallengeMethod: string\n}\n\ntype ActiveServerBase = { basePath: string } | { baseUrl: string } | Record<string, never>\n\nexport type OAuth2Tokens = {\n accessToken: string\n refreshToken?: string\n}\n\n/**\n * Captures the OAuth2 redirect for environments where the browser-popup polling\n * approach cannot work (notably the Electron desktop app, where the renderer\n * runs on `file://` and providers reject `file://` redirect URIs).\n *\n * The implementation opens the authorization URL in the system browser and\n * resolves once the provider redirects back. Because the redirect target (for\n * example an ephemeral loopback port) is only known to the host environment, the\n * implementation appends the `redirect_uri` itself and reports back the exact\n * value it used so the token exchange can send the matching `redirect_uri`.\n */\nexport type CaptureOAuth2Callback = (params: {\n /** The fully built authorization URL, without a `redirect_uri` parameter. */\n authorizationUrl: string\n}) => Promise<\n ErrorResponse<{\n /** The full callback URL the provider redirected to, including query and/or hash params. */\n callbackUrl: string\n /** The `redirect_uri` the host environment used, so the token exchange can match it. */\n redirectUri: string\n }>\n>\n\n/** Flow types that support token refresh (all except implicit) */\ntype RefreshableFlows = Exclude<keyof OAuthFlowsObjectSecret, 'implicit'>\n\n/**\n * Resolves the active server URL using OpenAPI server variables first, then\n * Scalar environment variables.\n */\nexport const getServerUrl = (\n activeServer: ServerObject | null,\n environmentVariables: Record<string, string> = {},\n): string =>\n replaceEnvVariables(\n replacePathVariables(activeServer?.url ?? '', getServerVariables(activeServer)),\n environmentVariables,\n )\n\n/**\n * Builds the base option used when OAuth URLs are relative to the active server.\n *\n * Relative server URLs become browser-only base paths because they need the\n * current window location to resolve correctly.\n */\nexport const getActiveServerBase = (\n activeServer: ServerObject | null,\n environmentVariables: Record<string, string> = {},\n): ActiveServerBase => {\n const serverUrl = getServerUrl(activeServer, environmentVariables)\n if (!serverUrl) {\n return {}\n }\n\n if (isRelativePath(serverUrl)) {\n return typeof window === 'undefined' ? {} : { basePath: serverUrl }\n }\n\n return { baseUrl: serverUrl }\n}\n\n/**\n * Generates a random string for PKCE code verifier\n *\n * @see https://www.rfc-editor.org/rfc/rfc7636#page-8\n */\nconst generateCodeVerifier = (): string => {\n // Generate 32 random bytes\n const buffer = new Uint8Array(32)\n crypto.getRandomValues(buffer)\n\n // Base64URL encode the bytes\n return fromUint8Array(buffer, true)\n}\n\n/**\n * Creates a code challenge from the code verifier\n */\nconst generateCodeChallenge = async (verifier: string, encoding: 'SHA-256' | 'plain'): Promise<string> => {\n if (encoding === 'plain') {\n return verifier\n }\n\n // If crypto.subtle.digest is not a function, we cannot use SHA-256\n if (typeof crypto?.subtle?.digest !== 'function') {\n console.warn('SHA-256 is only supported when using https, using a plain text code challenge instead.')\n return verifier\n }\n\n // ASCII encoding is just taking the lower 8 bits of each character\n const encoder = new TextEncoder()\n const data = encoder.encode(verifier)\n const digest = await crypto.subtle.digest('SHA-256', data)\n\n // Base64URL encode the bytes\n return fromUint8Array(new Uint8Array(digest), true)\n}\n\n/**\n * Authorize oauth2 flow\n *\n * @returns the resolved oauth2 tokens\n */\nexport const authorizeOauth2 = async (\n flows: OAuthFlowsObjectSecret,\n type: keyof OAuthFlowsObjectSecret,\n selectedScopes: string[],\n /** We use the active server to set a base for relative redirect uris */\n activeServer: ServerObject | null,\n /** If we want to use the proxy */\n proxyUrl: string,\n /** Flattened environment variables used to resolve server URL templates like `{protocol}` */\n environmentVariables: Record<string, string> = {},\n /** Fetch used for the token request; the desktop app passes an IPC-backed fetch (see {@link authorizeServers}). */\n customFetch?: CustomFetch,\n /**\n * Optional redirect capture for interactive flows (authorization code and implicit).\n * When provided, the system browser plus a host-owned redirect target replaces the\n * default popup-polling approach. Required for the Electron desktop app.\n */\n captureCallback?: CaptureOAuth2Callback,\n): Promise<ErrorResponse<OAuth2Tokens>> => {\n const flow = flows[type]\n\n try {\n if (!flow) {\n return [new Error('Flow not found'), null]\n }\n\n const scopes = selectedScopes.join(' ')\n\n // Client Credentials or Password Flow\n if (type === 'clientCredentials' || type === 'password') {\n return authorizeServers(\n flows,\n type,\n scopes,\n {\n proxyUrl,\n customFetch,\n },\n activeServer,\n environmentVariables,\n )\n }\n\n // Generate a random state string with the length of 8 characters\n const state = (Math.random() + 1).toString(36).substring(2, 10)\n\n const authorizationUrl = makeUrlAbsolute(\n flows[type]!['x-scalar-secret-auth-url'] ?? flows[type]!.authorizationUrl,\n getActiveServerBase(activeServer, environmentVariables),\n )\n\n const url = new URL(authorizationUrl)\n\n /** Special PKCE state */\n let pkce: PKCEState | null = null\n\n // Params unique to the flows\n if (type === 'implicit') {\n url.searchParams.set('response_type', 'token')\n } else if (type === 'authorizationCode') {\n const typedFlow = flows[type]! // Safe to assert due to earlier check\n\n url.searchParams.set('response_type', 'code')\n\n // PKCE\n if (typedFlow['x-usePkce'] !== 'no') {\n const codeVerifier = generateCodeVerifier()\n const codeChallenge = await generateCodeChallenge(codeVerifier, typedFlow['x-usePkce'])\n\n // Set state for later verification\n pkce = {\n codeVerifier,\n codeChallenge,\n codeChallengeMethod: typedFlow['x-usePkce'] === 'SHA-256' ? 'S256' : 'plain',\n }\n\n // Set the code challenge and method on the url\n url.searchParams.set('code_challenge', codeChallenge)\n url.searchParams.set('code_challenge_method', pkce.codeChallengeMethod)\n }\n }\n\n const typedFlow = flows[type]! // Safe to assert due to earlier check\n\n // The capture path appends its own `redirect_uri` (it owns the target, for\n // example an ephemeral loopback port), so we only set it here for the popup path.\n if (!captureCallback) {\n // Handle relative redirect uris\n if (typedFlow['x-scalar-secret-redirect-uri'].startsWith('/')) {\n const baseUrl =\n getServerUrl(activeServer, environmentVariables) || window.location.origin + window.location.pathname\n const redirectUri = new URL(typedFlow['x-scalar-secret-redirect-uri'], baseUrl).toString()\n\n url.searchParams.set('redirect_uri', redirectUri)\n } else {\n url.searchParams.set('redirect_uri', typedFlow['x-scalar-secret-redirect-uri'])\n }\n }\n\n if (flow['x-scalar-security-query']) {\n Object.keys(flow['x-scalar-security-query']).forEach((key: string): void => {\n const value = flow['x-scalar-security-query']?.[key]\n if (!value) {\n return\n }\n url.searchParams.set(key, value)\n })\n }\n\n // Common to all flows\n url.searchParams.set('client_id', flow['x-scalar-secret-client-id'].trim())\n url.searchParams.set('state', state)\n if (scopes) {\n url.searchParams.set('scope', scopes)\n }\n\n // Capture path: open the system browser and let the host environment catch\n // the redirect (used by the desktop app, where popup polling cannot work).\n if (captureCallback) {\n const [captureError, capture] = await captureCallback({ authorizationUrl: url.toString() })\n\n if (captureError || !capture) {\n return [captureError ?? new Error('Failed to capture the OAuth2 redirect'), null]\n }\n\n const { accessToken, accessTokenParams, code, codeParams, error, errorDescription, refreshToken } =\n getOAuthCallbackData(() => capture.callbackUrl, flow['x-tokenName'] || 'access_token')\n\n if (error) {\n return [new Error(`OAuth error: ${error}${errorDescription ? ` (${errorDescription})` : ''}`), null]\n }\n\n // Implicit Flow\n if (accessToken) {\n if ((accessTokenParams?.get('state') ?? null) !== state) {\n return [new Error('State mismatch'), null]\n }\n return [null, { accessToken, ...(refreshToken ? { refreshToken } : {}) }]\n }\n\n // Authorization Code Server Flow\n if (code && type === 'authorizationCode') {\n if ((codeParams?.get('state') ?? null) !== state) {\n return [new Error('State mismatch'), null]\n }\n return authorizeServers(\n flows,\n type,\n scopes,\n {\n code,\n pkce,\n proxyUrl,\n customFetch,\n // The token request must echo the exact redirect_uri used in the authorization request.\n redirectUri: capture.redirectUri,\n },\n activeServer,\n environmentVariables,\n )\n }\n\n return [new Error('No authorization code or access token was returned'), null]\n }\n\n const windowFeatures = 'left=100,top=100,width=800,height=600'\n const authWindow = window.open(url, 'openAuth2Window', windowFeatures)\n\n // Open up a window and poll until closed or we have the data we want\n if (authWindow) {\n // We need to return a promise here due to the setInterval\n return new Promise<ErrorResponse<OAuth2Tokens>>((resolve) => {\n const checkWindowClosed = setInterval(() => {\n const { accessToken, accessTokenParams, code, codeParams, error, errorDescription, refreshToken } =\n getOAuthCallbackData(() => authWindow.location.href, flow['x-tokenName'] || 'access_token')\n\n // The window has closed OR we have what we are looking for so we stop polling\n if (authWindow.closed || accessToken || code || error) {\n clearInterval(checkWindowClosed)\n authWindow.close()\n\n if (error) {\n resolve([new Error(`OAuth error: ${error}${errorDescription ? ` (${errorDescription})` : ''}`), null])\n return\n }\n\n // Implicit Flow\n if (accessToken) {\n const _state = accessTokenParams?.get('state') ?? null\n\n if (_state === state) {\n resolve([null, { accessToken, ...(refreshToken ? { refreshToken } : {}) }])\n } else {\n resolve([new Error('State mismatch'), null])\n }\n return\n }\n\n // Authorization Code Server Flow\n if (code && type === 'authorizationCode') {\n const _state = codeParams?.get('state') ?? null\n\n if (_state === state) {\n void authorizeServers(\n flows,\n type,\n scopes,\n {\n code,\n pkce,\n proxyUrl,\n customFetch,\n },\n activeServer,\n environmentVariables,\n )\n .then(resolve)\n .catch((error: unknown) => {\n resolve([\n error instanceof Error ? error : new Error('Failed to get an access token', { cause: error }),\n null,\n ])\n })\n } else {\n resolve([new Error('State mismatch'), null])\n }\n return\n }\n\n // User closed window without authorizing\n resolve([new Error('Window was closed without granting authorization'), null])\n }\n }, 200)\n })\n }\n return [new Error('Failed to open auth window'), null]\n } catch (error) {\n return [error instanceof Error ? error : new Error('Failed to authorize oauth2 flow', { cause: error }), null]\n }\n}\n\n/**\n * Makes the BE authorization call to grab the token server to server\n * Used for clientCredentials and authorizationCode\n */\nconst authorizeServers = async (\n flows: NonImplicitFlows,\n type: keyof NonImplicitFlows,\n scopes: string,\n {\n code,\n pkce,\n proxyUrl,\n customFetch = fetch,\n redirectUri,\n }: {\n code?: string\n pkce?: PKCEState | null\n proxyUrl?: string\n customFetch?: CustomFetch\n /** Overrides the stored redirect_uri (the capture path owns the real target). */\n redirectUri?: string\n } = {},\n activeServer: ServerObject | null,\n environmentVariables: Record<string, string> = {},\n): Promise<ErrorResponse<OAuth2Tokens>> => {\n const flow = flows[type]\n\n if (!flow) {\n return [new Error('OAuth2 flow was not defined'), null]\n }\n\n const formData = new URLSearchParams()\n\n // Only client credentials and password flows support scopes in the token request\n if (scopes && (type === 'clientCredentials' || type === 'password')) {\n formData.set('scope', scopes)\n }\n\n // Ignore surrounding copy/paste whitespace without changing stored credentials or other secrets.\n const clientId = flow['x-scalar-secret-client-id'].trim()\n const clientSecret = flow['x-scalar-secret-client-secret'].trim()\n /** Where to add the credentials */\n const addCredentialsToBody = flow['x-scalar-credentials-location'] === 'body'\n /**\n * PKCE and client authentication are independent: a confidential client may use both.\n * We send the client_secret whenever one is set, regardless of PKCE (see RFC 9700 Section 2.1.1).\n */\n const hasClientSecret = Boolean(clientSecret)\n /**\n * Public authorization-code clients still need client_id in the token body.\n * We only send it implicitly for that case to avoid conflicting with Basic auth.\n */\n const shouldSendClientIdInBody = addCredentialsToBody || (type === 'authorizationCode' && !hasClientSecret)\n\n if (shouldSendClientIdInBody) {\n formData.set('client_id', clientId)\n }\n if (addCredentialsToBody && hasClientSecret) {\n formData.set('client_secret', clientSecret)\n }\n if (redirectUri) {\n formData.set('redirect_uri', redirectUri)\n } else if ('x-scalar-secret-redirect-uri' in flow && flow['x-scalar-secret-redirect-uri']) {\n formData.set('redirect_uri', flow['x-scalar-secret-redirect-uri'])\n }\n\n // Authorization Code\n if (code) {\n formData.set('code', code)\n formData.set('grant_type', 'authorization_code')\n\n // PKCE\n if (pkce) {\n formData.set('code_verifier', pkce.codeVerifier)\n }\n }\n // Password\n else if (type === 'password') {\n const typedFlow = flows[type]! // Safe to assert due to earlier check\n formData.set('grant_type', 'password')\n formData.set('username', typedFlow['x-scalar-secret-username'])\n formData.set('password', typedFlow['x-scalar-secret-password'])\n }\n // Client Credentials\n else {\n formData.set('grant_type', 'client_credentials')\n }\n\n // Additional request body parameters\n if (flow['x-scalar-security-body']) {\n Object.entries(flow['x-scalar-security-body']).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n formData.set(key, String(value))\n }\n })\n }\n\n try {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/x-www-form-urlencoded',\n }\n\n // Add client id + secret to headers for confidential clients.\n if (!addCredentialsToBody && hasClientSecret) {\n headers.Authorization = `Basic ${encode(`${clientId}:${clientSecret}`)}`\n }\n\n // Check if we should use the proxy\n const tokenUrl = makeUrlAbsolute(\n flow['x-scalar-secret-token-url'] ?? flow.tokenUrl,\n getActiveServerBase(activeServer, environmentVariables),\n )\n const url = shouldUseProxy(proxyUrl, tokenUrl)\n ? `${proxyUrl}?${new URLSearchParams([['scalar_url', tokenUrl]]).toString()}`\n : tokenUrl\n\n // Make the call\n const resp = await customFetch(url, {\n method: 'POST',\n headers,\n body: formData,\n })\n const responseData = await resp.json()\n\n // Use custom token name if specified, otherwise default to access_token\n const tokenName = flow['x-tokenName'] || 'access_token'\n const accessToken = responseData[tokenName]\n const refreshToken = responseData.refresh_token\n\n if (!accessToken) {\n return [new Error(responseData.error_description ?? responseData.error ?? 'Failed to get an access token'), null]\n }\n\n return [null, { accessToken, ...(typeof refreshToken === 'string' ? { refreshToken } : {}) }]\n } catch (error) {\n return [\n error instanceof Error\n ? error\n : new Error('Failed to get an access token. Please check your credentials.', { cause: error }),\n null,\n ]\n }\n}\n\n/**\n * Exchange a refresh token for a new access token using the `grant_type=refresh_token` flow.\n *\n * Uses the stored refresh token, client credentials, and the token URL (or refreshUrl when available)\n * to request fresh tokens from the authorization server per RFC 6749 Section 6.\n */\nexport const refreshOauth2Token = async (\n flows: OAuthFlowsObjectSecret,\n type: RefreshableFlows,\n /** If we want to use the proxy */\n proxyUrl: string,\n /** We use the active server to set a base for relative URLs */\n activeServer: ServerObject | null,\n /** Flattened environment variables used to resolve server URL templates */\n environmentVariables: Record<string, string> = {},\n /** Fetch used for the refresh request; the desktop app passes an IPC-backed fetch so it leaves the renderer's network stack. */\n customFetch: CustomFetch = fetch,\n): Promise<ErrorResponse<OAuth2Tokens>> => {\n const flow = flows[type]\n\n if (!flow) {\n return [new Error('OAuth2 flow was not defined'), null]\n }\n\n const refreshToken = flow['x-scalar-secret-refresh-token']\n if (!refreshToken) {\n return [new Error('No refresh token available'), null]\n }\n\n const formData = new URLSearchParams()\n formData.set('grant_type', 'refresh_token')\n formData.set('refresh_token', refreshToken)\n\n // Ignore surrounding copy/paste whitespace without changing stored credentials or other secrets.\n const clientId = flow['x-scalar-secret-client-id'].trim()\n const clientSecret = flow['x-scalar-secret-client-secret'].trim()\n const addCredentialsToBody = flow['x-scalar-credentials-location'] === 'body'\n /** A confidential client keeps using its secret on refresh, even when PKCE is enabled. */\n const hasClientSecret = Boolean(clientSecret)\n /**\n * Public authorization-code clients still need client_id in the refresh body per RFC 6749 Section 6.\n * We only send it implicitly for that case to avoid conflicting with Basic auth.\n */\n const shouldSendClientIdInBody = addCredentialsToBody || (type === 'authorizationCode' && !hasClientSecret)\n\n if (shouldSendClientIdInBody) {\n formData.set('client_id', clientId)\n }\n if (addCredentialsToBody && hasClientSecret) {\n formData.set('client_secret', clientSecret)\n }\n\n if (flow['x-scalar-security-body']) {\n Object.entries(flow['x-scalar-security-body']).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n formData.set(key, String(value))\n }\n })\n }\n\n try {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/x-www-form-urlencoded',\n }\n\n if (!addCredentialsToBody && hasClientSecret) {\n headers.Authorization = `Basic ${encode(`${clientId}:${clientSecret}`)}`\n }\n\n const refreshUrl = flow.refreshUrl || flow['x-scalar-secret-token-url'] || flow.tokenUrl\n const absoluteRefreshUrl = makeUrlAbsolute(refreshUrl, getActiveServerBase(activeServer, environmentVariables))\n const url = shouldUseProxy(proxyUrl, absoluteRefreshUrl)\n ? `${proxyUrl}?${new URLSearchParams([['scalar_url', absoluteRefreshUrl]]).toString()}`\n : absoluteRefreshUrl\n\n const resp = await customFetch(url, {\n method: 'POST',\n headers,\n body: formData,\n })\n const responseData = await resp.json()\n\n const tokenName = flow['x-tokenName'] || 'access_token'\n const accessToken = responseData[tokenName]\n const newRefreshToken = responseData.refresh_token\n\n if (!accessToken) {\n return [new Error(responseData.error_description ?? responseData.error ?? 'Token refresh failed'), null]\n }\n\n return [\n null,\n {\n accessToken,\n ...(typeof newRefreshToken === 'string' ? { refreshToken: newRefreshToken } : { refreshToken }),\n },\n ]\n } catch (error) {\n return [\n error instanceof Error\n ? error\n : new Error('Failed to refresh the access token. Please re-authorize.', { cause: error }),\n null,\n ]\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"oauth.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth.ts"],"sourcesContent":["import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error'\nimport { replaceEnvVariables, replacePathVariables } from '@scalar/helpers/regex/replace-variables'\nimport { isRelativePath } from '@scalar/helpers/url/is-relative-path'\nimport { makeUrlAbsolute } from '@scalar/helpers/url/make-url-absolute'\nimport { shouldUseProxy } from '@scalar/helpers/url/redirect-to-proxy'\nimport type { OAuthFlowsObjectSecret } from '@scalar/workspace-store/request-example'\nimport { getServerVariables } from '@scalar/workspace-store/request-example'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { fromUint8Array } from 'js-base64'\n\nimport type { CustomFetch } from '@/v2/blocks/operation-block/helpers/send-request'\n\nimport { getOAuthCallbackData } from './oauth-callback'\nimport { oauthClientAuthorization } from './oauth-client-authorization'\nimport { type DeviceAuthorizationOptions, authorizeDevice } from './oauth-device-authorization'\n\n/** Oauth2 security schemes which are not implicit */\ntype NonImplicitFlows = Omit<OAuthFlowsObjectSecret, 'implicit'>\n\ntype PKCEState = {\n codeVerifier: string\n codeChallenge: string\n codeChallengeMethod: string\n}\n\ntype ActiveServerBase = { basePath: string } | { baseUrl: string } | Record<string, never>\n\nexport type OAuth2Tokens = {\n accessToken: string\n refreshToken?: string\n}\n\n/**\n * Captures the OAuth2 redirect for environments where the browser-popup polling\n * approach cannot work (notably the Electron desktop app, where the renderer\n * runs on `file://` and providers reject `file://` redirect URIs).\n *\n * The implementation opens the authorization URL in the system browser and\n * resolves once the provider redirects back. Because the redirect target (for\n * example an ephemeral loopback port) is only known to the host environment, the\n * implementation appends the `redirect_uri` itself and reports back the exact\n * value it used so the token exchange can send the matching `redirect_uri`.\n */\nexport type CaptureOAuth2Callback = (params: {\n /** The fully built authorization URL, without a `redirect_uri` parameter. */\n authorizationUrl: string\n}) => Promise<\n ErrorResponse<{\n /** The full callback URL the provider redirected to, including query and/or hash params. */\n callbackUrl: string\n /** The `redirect_uri` the host environment used, so the token exchange can match it. */\n redirectUri: string\n }>\n>\n\n/** Flow types that support token refresh (all except implicit) */\ntype RefreshableFlows = Exclude<keyof OAuthFlowsObjectSecret, 'implicit'>\n\n/**\n * Resolves the active server URL using OpenAPI server variables first, then\n * Scalar environment variables.\n */\nexport const getServerUrl = (\n activeServer: ServerObject | null,\n environmentVariables: Record<string, string> = {},\n): string =>\n replaceEnvVariables(\n replacePathVariables(activeServer?.url ?? '', getServerVariables(activeServer)),\n environmentVariables,\n )\n\n/**\n * Builds the base option used when OAuth URLs are relative to the active server.\n *\n * Relative server URLs become browser-only base paths because they need the\n * current window location to resolve correctly.\n */\nexport const getActiveServerBase = (\n activeServer: ServerObject | null,\n environmentVariables: Record<string, string> = {},\n): ActiveServerBase => {\n const serverUrl = getServerUrl(activeServer, environmentVariables)\n if (!serverUrl) {\n return {}\n }\n\n if (isRelativePath(serverUrl)) {\n return typeof window === 'undefined' ? {} : { basePath: serverUrl }\n }\n\n return { baseUrl: serverUrl }\n}\n\n/**\n * Generates a random string for PKCE code verifier\n *\n * @see https://www.rfc-editor.org/rfc/rfc7636#page-8\n */\nconst generateCodeVerifier = (): string => {\n // Generate 32 random bytes\n const buffer = new Uint8Array(32)\n crypto.getRandomValues(buffer)\n\n // Base64URL encode the bytes\n return fromUint8Array(buffer, true)\n}\n\n/**\n * Creates a code challenge from the code verifier\n */\nconst generateCodeChallenge = async (verifier: string, encoding: 'SHA-256' | 'plain'): Promise<string> => {\n if (encoding === 'plain') {\n return verifier\n }\n\n // If crypto.subtle.digest is not a function, we cannot use SHA-256\n if (typeof crypto?.subtle?.digest !== 'function') {\n console.warn('SHA-256 is only supported when using https, using a plain text code challenge instead.')\n return verifier\n }\n\n // ASCII encoding is just taking the lower 8 bits of each character\n const encoder = new TextEncoder()\n const data = encoder.encode(verifier)\n const digest = await crypto.subtle.digest('SHA-256', data)\n\n // Base64URL encode the bytes\n return fromUint8Array(new Uint8Array(digest), true)\n}\n\n/**\n * Authorize oauth2 flow\n *\n * @returns the resolved oauth2 tokens\n */\nexport const authorizeOauth2 = async (\n flows: OAuthFlowsObjectSecret,\n type: keyof OAuthFlowsObjectSecret,\n selectedScopes: string[],\n /** We use the active server to set a base for relative redirect uris */\n activeServer: ServerObject | null,\n /** If we want to use the proxy */\n proxyUrl: string,\n /** Flattened environment variables used to resolve server URL templates like `{protocol}` */\n environmentVariables: Record<string, string> = {},\n /** Fetch used for the token request; the desktop app passes an IPC-backed fetch (see {@link authorizeServers}). */\n customFetch?: CustomFetch,\n /**\n * Optional redirect capture for interactive flows (authorization code and implicit).\n * When provided, the system browser plus a host-owned redirect target replaces the\n * default popup-polling approach. Required for the Electron desktop app.\n */\n captureCallback?: CaptureOAuth2Callback,\n deviceOptions?: DeviceAuthorizationOptions,\n): Promise<ErrorResponse<OAuth2Tokens>> => {\n const flow = flows[type]\n\n try {\n if (!flow) {\n return [new Error('Flow not found'), null]\n }\n\n if (type === 'deviceAuthorization' && flows.deviceAuthorization) {\n return authorizeDevice(\n flows.deviceAuthorization,\n selectedScopes,\n activeServer,\n proxyUrl,\n environmentVariables,\n customFetch,\n deviceOptions,\n )\n }\n if (type === 'deviceAuthorization') {\n return [new Error('Flow not found'), null]\n }\n const scopes = selectedScopes.join(' ')\n\n // Client Credentials or Password Flow\n if (type === 'clientCredentials' || type === 'password') {\n return authorizeServers(\n flows,\n type,\n scopes,\n {\n proxyUrl,\n customFetch,\n },\n activeServer,\n environmentVariables,\n )\n }\n\n // Generate a random state string with the length of 8 characters\n const state = (Math.random() + 1).toString(36).substring(2, 10)\n\n const authorizationUrl = makeUrlAbsolute(\n flows[type]!['x-scalar-secret-auth-url'] ?? flows[type]!.authorizationUrl,\n getActiveServerBase(activeServer, environmentVariables),\n )\n\n const url = new URL(authorizationUrl)\n\n /** Special PKCE state */\n let pkce: PKCEState | null = null\n\n // Params unique to the flows\n if (type === 'implicit') {\n url.searchParams.set('response_type', 'token')\n } else if (type === 'authorizationCode') {\n const typedFlow = flows[type]! // Safe to assert due to earlier check\n\n url.searchParams.set('response_type', 'code')\n\n // PKCE\n if (typedFlow['x-usePkce'] !== 'no') {\n const codeVerifier = generateCodeVerifier()\n const codeChallenge = await generateCodeChallenge(codeVerifier, typedFlow['x-usePkce'])\n\n // Set state for later verification\n pkce = {\n codeVerifier,\n codeChallenge,\n codeChallengeMethod: typedFlow['x-usePkce'] === 'SHA-256' ? 'S256' : 'plain',\n }\n\n // Set the code challenge and method on the url\n url.searchParams.set('code_challenge', codeChallenge)\n url.searchParams.set('code_challenge_method', pkce.codeChallengeMethod)\n }\n }\n\n const typedFlow = flows[type]! // Safe to assert due to earlier check\n\n // The capture path appends its own `redirect_uri` (it owns the target, for\n // example an ephemeral loopback port), so we only set it here for the popup path.\n if (!captureCallback) {\n // Handle relative redirect uris\n if (typedFlow['x-scalar-secret-redirect-uri'].startsWith('/')) {\n const baseUrl =\n getServerUrl(activeServer, environmentVariables) || window.location.origin + window.location.pathname\n const redirectUri = new URL(typedFlow['x-scalar-secret-redirect-uri'], baseUrl).toString()\n\n url.searchParams.set('redirect_uri', redirectUri)\n } else {\n url.searchParams.set('redirect_uri', typedFlow['x-scalar-secret-redirect-uri'])\n }\n }\n\n if (flow['x-scalar-security-query']) {\n Object.keys(flow['x-scalar-security-query']).forEach((key: string): void => {\n const value = flow['x-scalar-security-query']?.[key]\n if (!value) {\n return\n }\n url.searchParams.set(key, value)\n })\n }\n\n // Common to all flows\n url.searchParams.set(\n 'client_id',\n replaceEnvVariables(flow['x-scalar-secret-client-id'], environmentVariables).trim(),\n )\n url.searchParams.set('state', state)\n if (scopes) {\n url.searchParams.set('scope', scopes)\n }\n\n // Capture path: open the system browser and let the host environment catch\n // the redirect (used by the desktop app, where popup polling cannot work).\n if (captureCallback) {\n const [captureError, capture] = await captureCallback({ authorizationUrl: url.toString() })\n\n if (captureError || !capture) {\n return [captureError ?? new Error('Failed to capture the OAuth2 redirect'), null]\n }\n\n const { accessToken, accessTokenParams, code, codeParams, error, errorDescription, refreshToken } =\n getOAuthCallbackData(() => capture.callbackUrl, flow['x-tokenName'] || 'access_token')\n\n if (error) {\n return [new Error(`OAuth error: ${error}${errorDescription ? ` (${errorDescription})` : ''}`), null]\n }\n\n // Implicit Flow\n if (accessToken) {\n if ((accessTokenParams?.get('state') ?? null) !== state) {\n return [new Error('State mismatch'), null]\n }\n return [null, { accessToken, ...(refreshToken ? { refreshToken } : {}) }]\n }\n\n // Authorization Code Server Flow\n if (code && type === 'authorizationCode') {\n if ((codeParams?.get('state') ?? null) !== state) {\n return [new Error('State mismatch'), null]\n }\n return authorizeServers(\n flows,\n type,\n scopes,\n {\n code,\n pkce,\n proxyUrl,\n customFetch,\n // The token request must echo the exact redirect_uri used in the authorization request.\n redirectUri: capture.redirectUri,\n },\n activeServer,\n environmentVariables,\n )\n }\n\n return [new Error('No authorization code or access token was returned'), null]\n }\n\n const windowFeatures = 'left=100,top=100,width=800,height=600'\n const authWindow = window.open(url, 'openAuth2Window', windowFeatures)\n\n // Open up a window and poll until closed or we have the data we want\n if (authWindow) {\n // We need to return a promise here due to the setInterval\n return new Promise<ErrorResponse<OAuth2Tokens>>((resolve) => {\n const checkWindowClosed = setInterval(() => {\n const { accessToken, accessTokenParams, code, codeParams, error, errorDescription, refreshToken } =\n getOAuthCallbackData(() => authWindow.location.href, flow['x-tokenName'] || 'access_token')\n\n // The window has closed OR we have what we are looking for so we stop polling\n if (authWindow.closed || accessToken || code || error) {\n clearInterval(checkWindowClosed)\n authWindow.close()\n\n if (error) {\n resolve([new Error(`OAuth error: ${error}${errorDescription ? ` (${errorDescription})` : ''}`), null])\n return\n }\n\n // Implicit Flow\n if (accessToken) {\n const _state = accessTokenParams?.get('state') ?? null\n\n if (_state === state) {\n resolve([null, { accessToken, ...(refreshToken ? { refreshToken } : {}) }])\n } else {\n resolve([new Error('State mismatch'), null])\n }\n return\n }\n\n // Authorization Code Server Flow\n if (code && type === 'authorizationCode') {\n const _state = codeParams?.get('state') ?? null\n\n if (_state === state) {\n void authorizeServers(\n flows,\n type,\n scopes,\n {\n code,\n pkce,\n proxyUrl,\n customFetch,\n },\n activeServer,\n environmentVariables,\n )\n .then(resolve)\n .catch((error: unknown) => {\n resolve([\n error instanceof Error ? error : new Error('Failed to get an access token', { cause: error }),\n null,\n ])\n })\n } else {\n resolve([new Error('State mismatch'), null])\n }\n return\n }\n\n // User closed window without authorizing\n resolve([new Error('Window was closed without granting authorization'), null])\n }\n }, 200)\n })\n }\n return [new Error('Failed to open auth window'), null]\n } catch (error) {\n return [error instanceof Error ? error : new Error('Failed to authorize oauth2 flow', { cause: error }), null]\n }\n}\n\n/**\n * Makes the BE authorization call to grab the token server to server\n * Used for clientCredentials and authorizationCode\n */\nconst authorizeServers = async (\n flows: NonImplicitFlows,\n type: keyof NonImplicitFlows,\n scopes: string,\n {\n code,\n pkce,\n proxyUrl,\n customFetch = fetch,\n redirectUri,\n }: {\n code?: string\n pkce?: PKCEState | null\n proxyUrl?: string\n customFetch?: CustomFetch\n /** Overrides the stored redirect_uri (the capture path owns the real target). */\n redirectUri?: string\n } = {},\n activeServer: ServerObject | null,\n environmentVariables: Record<string, string> = {},\n): Promise<ErrorResponse<OAuth2Tokens>> => {\n const flow = flows[type]\n\n if (!flow) {\n return [new Error('OAuth2 flow was not defined'), null]\n }\n\n const formData = new URLSearchParams()\n\n // Only client credentials and password flows support scopes in the token request\n if (scopes && (type === 'clientCredentials' || type === 'password')) {\n formData.set('scope', scopes)\n }\n\n // Ignore surrounding copy/paste whitespace without changing stored credentials or other secrets.\n const clientId = replaceEnvVariables(flow['x-scalar-secret-client-id'], environmentVariables).trim()\n const clientSecret = replaceEnvVariables(flow['x-scalar-secret-client-secret'], environmentVariables).trim()\n /** Where to add the credentials */\n const addCredentialsToBody = flow['x-scalar-credentials-location'] === 'body'\n /**\n * PKCE and client authentication are independent: a confidential client may use both.\n * We send the client_secret whenever one is set, regardless of PKCE (see RFC 9700 Section 2.1.1).\n */\n const hasClientSecret = Boolean(clientSecret)\n /**\n * Public authorization-code clients still need client_id in the token body.\n * We only send it implicitly for that case to avoid conflicting with Basic auth.\n */\n const shouldSendClientIdInBody =\n addCredentialsToBody || ((type === 'authorizationCode' || type === 'deviceAuthorization') && !hasClientSecret)\n\n if (shouldSendClientIdInBody) {\n formData.set('client_id', clientId)\n }\n if (addCredentialsToBody && hasClientSecret) {\n formData.set('client_secret', clientSecret)\n }\n if (redirectUri) {\n formData.set('redirect_uri', redirectUri)\n } else if ('x-scalar-secret-redirect-uri' in flow && flow['x-scalar-secret-redirect-uri']) {\n formData.set('redirect_uri', flow['x-scalar-secret-redirect-uri'])\n }\n\n // Authorization Code\n if (code) {\n formData.set('code', code)\n formData.set('grant_type', 'authorization_code')\n\n // PKCE\n if (pkce) {\n formData.set('code_verifier', pkce.codeVerifier)\n }\n }\n // Password\n else if (type === 'password') {\n const typedFlow = flows[type]! // Safe to assert due to earlier check\n formData.set('grant_type', 'password')\n formData.set('username', typedFlow['x-scalar-secret-username'])\n formData.set('password', typedFlow['x-scalar-secret-password'])\n }\n // Client Credentials\n else {\n formData.set('grant_type', 'client_credentials')\n }\n\n // Additional request body parameters\n if (flow['x-scalar-security-body']) {\n Object.entries(flow['x-scalar-security-body']).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n formData.set(key, String(value))\n }\n })\n }\n\n try {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/x-www-form-urlencoded',\n }\n\n // Add client id + secret to headers for confidential clients.\n if (!addCredentialsToBody && hasClientSecret) {\n headers.Authorization = oauthClientAuthorization(clientId, clientSecret)\n }\n\n // Check if we should use the proxy\n const tokenUrl = makeUrlAbsolute(\n flow['x-scalar-secret-token-url'] ?? flow.tokenUrl,\n getActiveServerBase(activeServer, environmentVariables),\n )\n const url = shouldUseProxy(proxyUrl, tokenUrl)\n ? `${proxyUrl}?${new URLSearchParams([['scalar_url', tokenUrl]]).toString()}`\n : tokenUrl\n\n // Make the call\n const resp = await customFetch(url, {\n method: 'POST',\n headers,\n body: formData,\n })\n const responseData = await resp.json()\n\n // Use custom token name if specified, otherwise default to access_token\n const tokenName = flow['x-tokenName'] || 'access_token'\n const accessToken = responseData[tokenName]\n const refreshToken = responseData.refresh_token\n\n if (!accessToken) {\n return [new Error(responseData.error_description ?? responseData.error ?? 'Failed to get an access token'), null]\n }\n\n return [null, { accessToken, ...(typeof refreshToken === 'string' ? { refreshToken } : {}) }]\n } catch (error) {\n return [\n error instanceof Error\n ? error\n : new Error('Failed to get an access token. Please check your credentials.', { cause: error }),\n null,\n ]\n }\n}\n\n/**\n * Exchange a refresh token for a new access token using the `grant_type=refresh_token` flow.\n *\n * Uses the stored refresh token, client credentials, and the token URL (or refreshUrl when available)\n * to request fresh tokens from the authorization server per RFC 6749 Section 6.\n */\nexport const refreshOauth2Token = async (\n flows: OAuthFlowsObjectSecret,\n type: RefreshableFlows,\n /** If we want to use the proxy */\n proxyUrl: string,\n /** We use the active server to set a base for relative URLs */\n activeServer: ServerObject | null,\n /** Flattened environment variables used to resolve server URL templates */\n environmentVariables: Record<string, string> = {},\n /** Fetch used for the refresh request; the desktop app passes an IPC-backed fetch so it leaves the renderer's network stack. */\n customFetch: CustomFetch = fetch,\n): Promise<ErrorResponse<OAuth2Tokens>> => {\n const flow = flows[type]\n\n if (!flow) {\n return [new Error('OAuth2 flow was not defined'), null]\n }\n\n const refreshToken = flow['x-scalar-secret-refresh-token']\n if (!refreshToken) {\n return [new Error('No refresh token available'), null]\n }\n\n const formData = new URLSearchParams()\n formData.set('grant_type', 'refresh_token')\n formData.set('refresh_token', refreshToken)\n\n // Ignore surrounding copy/paste whitespace without changing stored credentials or other secrets.\n const clientId = replaceEnvVariables(flow['x-scalar-secret-client-id'], environmentVariables).trim()\n const clientSecret = replaceEnvVariables(flow['x-scalar-secret-client-secret'], environmentVariables).trim()\n const addCredentialsToBody = flow['x-scalar-credentials-location'] === 'body'\n /** A confidential client keeps using its secret on refresh, even when PKCE is enabled. */\n const hasClientSecret = Boolean(clientSecret)\n /**\n * Public authorization-code clients still need client_id in the refresh body per RFC 6749 Section 6.\n * We only send it implicitly for that case to avoid conflicting with Basic auth.\n */\n const shouldSendClientIdInBody =\n addCredentialsToBody || ((type === 'authorizationCode' || type === 'deviceAuthorization') && !hasClientSecret)\n\n if (shouldSendClientIdInBody) {\n formData.set('client_id', clientId)\n }\n if (addCredentialsToBody && hasClientSecret) {\n formData.set('client_secret', clientSecret)\n }\n\n if (flow['x-scalar-security-body']) {\n Object.entries(flow['x-scalar-security-body']).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n formData.set(key, String(value))\n }\n })\n }\n\n try {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/x-www-form-urlencoded',\n }\n\n if (!addCredentialsToBody && hasClientSecret) {\n headers.Authorization = oauthClientAuthorization(clientId, clientSecret)\n }\n\n const refreshUrl = flow.refreshUrl || flow['x-scalar-secret-token-url'] || flow.tokenUrl\n const absoluteRefreshUrl = makeUrlAbsolute(refreshUrl, getActiveServerBase(activeServer, environmentVariables))\n const url = shouldUseProxy(proxyUrl, absoluteRefreshUrl)\n ? `${proxyUrl}?${new URLSearchParams([['scalar_url', absoluteRefreshUrl]]).toString()}`\n : absoluteRefreshUrl\n\n const resp = await customFetch(url, {\n method: 'POST',\n headers,\n body: formData,\n })\n const responseData = await resp.json()\n\n const tokenName = flow['x-tokenName'] || 'access_token'\n const accessToken = responseData[tokenName]\n const newRefreshToken = responseData.refresh_token\n\n if (!accessToken) {\n return [new Error(responseData.error_description ?? responseData.error ?? 'Token refresh failed'), null]\n }\n\n return [\n null,\n {\n accessToken,\n ...(typeof newRefreshToken === 'string' ? { refreshToken: newRefreshToken } : { refreshToken }),\n },\n ]\n } catch (error) {\n return [\n error instanceof Error\n ? error\n : new Error('Failed to refresh the access token. Please re-authorize.', { cause: error }),\n null,\n ]\n }\n}\n"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import type { OpenIDConnectDiscovery } from './fetch-openid-connect-discovery.js
|
|
|
3
3
|
type FlowUpdates = {
|
|
4
4
|
[Key in keyof OAuthFlowsObject]?: Partial<NonNullable<OAuthFlowsObject[Key]>>;
|
|
5
5
|
};
|
|
6
|
-
/** Supplements endpoints
|
|
6
|
+
/** Supplements declared endpoints while preserving explicit scopes, including empty scope sets. */
|
|
7
7
|
export declare const oauth2MetadataToFlows: (metadata: OpenIDConnectDiscovery, flows: OAuthFlowsObject) => FlowUpdates;
|
|
8
8
|
export {};
|
|
9
9
|
//# sourceMappingURL=oauth2-metadata-to-flows.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth2-metadata-to-flows.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8DAA8D,CAAA;AAEpG,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AAE9E,KAAK,WAAW,GAAG;KAAG,GAAG,IAAI,MAAM,gBAAgB,CAAC,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;CAAE,CAAA;AAEpG,
|
|
1
|
+
{"version":3,"file":"oauth2-metadata-to-flows.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8DAA8D,CAAA;AAEpG,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AAE9E,KAAK,WAAW,GAAG;KAAG,GAAG,IAAI,MAAM,gBAAgB,CAAC,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC;CAAE,CAAA;AAEpG,mGAAmG;AACnG,eAAO,MAAM,qBAAqB,GAAI,UAAU,sBAAsB,EAAE,OAAO,gBAAgB,KAAG,WAoCjG,CAAA"}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
//#region src/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.ts
|
|
2
|
-
/** Supplements endpoints
|
|
2
|
+
/** Supplements declared endpoints while preserving explicit scopes, including empty scope sets. */
|
|
3
3
|
var oauth2MetadataToFlows = (metadata, flows) => {
|
|
4
4
|
const scopes = Object.fromEntries((metadata.scopes_supported ?? []).map((scope) => [scope, ""]));
|
|
5
5
|
const grants = new Set(metadata.grant_types_supported ?? ["authorization_code", "implicit"]);
|
|
6
6
|
const authorizationUrl = metadata.authorization_endpoint;
|
|
7
7
|
const tokenUrl = metadata.token_endpoint;
|
|
8
|
+
const deviceAuthorizationUrl = metadata.device_authorization_endpoint;
|
|
8
9
|
const discovered = {
|
|
10
|
+
...grants.has("urn:ietf:params:oauth:grant-type:device_code") && deviceAuthorizationUrl && tokenUrl ? { deviceAuthorization: {
|
|
11
|
+
deviceAuthorizationUrl,
|
|
12
|
+
tokenUrl,
|
|
13
|
+
scopes
|
|
14
|
+
} } : {},
|
|
9
15
|
...grants.has("implicit") && authorizationUrl ? { implicit: {
|
|
10
16
|
authorizationUrl,
|
|
11
17
|
scopes
|
|
@@ -27,6 +33,7 @@ var oauth2MetadataToFlows = (metadata, flows) => {
|
|
|
27
33
|
if (!Object.keys(flows).length) return discovered;
|
|
28
34
|
return Object.fromEntries(Object.entries(flows).filter(([, flow]) => flow).map(([key, flow]) => [key, {
|
|
29
35
|
..."authorizationUrl" in flow && !flow.authorizationUrl && authorizationUrl ? { authorizationUrl } : {},
|
|
36
|
+
..."deviceAuthorizationUrl" in flow && !flow.deviceAuthorizationUrl && deviceAuthorizationUrl ? { deviceAuthorizationUrl } : {},
|
|
30
37
|
..."tokenUrl" in flow && !flow.tokenUrl && tokenUrl ? { tokenUrl } : {}
|
|
31
38
|
}]).filter(([, update]) => Object.keys(update).length > 0));
|
|
32
39
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth2-metadata-to-flows.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.ts"],"sourcesContent":["import type { OAuthFlowsObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport type { OpenIDConnectDiscovery } from './fetch-openid-connect-discovery'\n\ntype FlowUpdates = { [Key in keyof OAuthFlowsObject]?: Partial<NonNullable<OAuthFlowsObject[Key]>> }\n\n/** Supplements endpoints
|
|
1
|
+
{"version":3,"file":"oauth2-metadata-to-flows.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth2-metadata-to-flows.ts"],"sourcesContent":["import type { OAuthFlowsObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport type { OpenIDConnectDiscovery } from './fetch-openid-connect-discovery'\n\ntype FlowUpdates = { [Key in keyof OAuthFlowsObject]?: Partial<NonNullable<OAuthFlowsObject[Key]>> }\n\n/** Supplements declared endpoints while preserving explicit scopes, including empty scope sets. */\nexport const oauth2MetadataToFlows = (metadata: OpenIDConnectDiscovery, flows: OAuthFlowsObject): FlowUpdates => {\n const scopes = Object.fromEntries((metadata.scopes_supported ?? []).map((scope) => [scope, '']))\n const grants = new Set(metadata.grant_types_supported ?? ['authorization_code', 'implicit'])\n const authorizationUrl = metadata.authorization_endpoint\n const tokenUrl = metadata.token_endpoint\n const deviceAuthorizationUrl = metadata.device_authorization_endpoint\n const discovered: FlowUpdates = {\n ...(grants.has('urn:ietf:params:oauth:grant-type:device_code') && deviceAuthorizationUrl && tokenUrl\n ? { deviceAuthorization: { deviceAuthorizationUrl, tokenUrl, scopes } }\n : {}),\n ...(grants.has('implicit') && authorizationUrl ? { implicit: { authorizationUrl, scopes } } : {}),\n ...(grants.has('password') && tokenUrl ? { password: { tokenUrl, scopes } } : {}),\n ...(grants.has('client_credentials') && tokenUrl ? { clientCredentials: { tokenUrl, scopes } } : {}),\n ...(grants.has('authorization_code') && authorizationUrl && tokenUrl\n ? { authorizationCode: { authorizationUrl, tokenUrl, scopes } }\n : {}),\n }\n // An empty Flows Object can discover supported grants. Otherwise the API description controls the allowed flows.\n if (!Object.keys(flows).length) {\n return discovered\n }\n return Object.fromEntries(\n Object.entries(flows)\n .filter(([, flow]) => flow)\n .map(([key, flow]): [string, Record<string, string>] => [\n key,\n {\n ...('authorizationUrl' in flow && !flow.authorizationUrl && authorizationUrl ? { authorizationUrl } : {}),\n ...('deviceAuthorizationUrl' in flow && !flow.deviceAuthorizationUrl && deviceAuthorizationUrl\n ? { deviceAuthorizationUrl }\n : {}),\n ...('tokenUrl' in flow && !flow.tokenUrl && tokenUrl ? { tokenUrl } : {}),\n },\n ])\n .filter(([, update]) => Object.keys(update).length > 0),\n )\n}\n"],"mappings":";;AAOA,IAAa,yBAAyB,UAAkC,UAAyC;CAC/G,MAAM,SAAS,OAAO,aAAa,SAAS,oBAAoB,CAAC,EAAA,CAAG,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;CAC/F,MAAM,SAAS,IAAI,IAAI,SAAS,yBAAyB,CAAC,sBAAsB,UAAU,CAAC;CAC3F,MAAM,mBAAmB,SAAS;CAClC,MAAM,WAAW,SAAS;CAC1B,MAAM,yBAAyB,SAAS;CACxC,MAAM,aAA0B;EAC9B,GAAI,OAAO,IAAI,8CAA8C,KAAK,0BAA0B,WACxF,EAAE,qBAAqB;GAAE;GAAwB;GAAU;EAAO,EAAE,IACpE,CAAC;EACL,GAAI,OAAO,IAAI,UAAU,KAAK,mBAAmB,EAAE,UAAU;GAAE;GAAkB;EAAO,EAAE,IAAI,CAAC;EAC/F,GAAI,OAAO,IAAI,UAAU,KAAK,WAAW,EAAE,UAAU;GAAE;GAAU;EAAO,EAAE,IAAI,CAAC;EAC/E,GAAI,OAAO,IAAI,oBAAoB,KAAK,WAAW,EAAE,mBAAmB;GAAE;GAAU;EAAO,EAAE,IAAI,CAAC;EAClG,GAAI,OAAO,IAAI,oBAAoB,KAAK,oBAAoB,WACxD,EAAE,mBAAmB;GAAE;GAAkB;GAAU;EAAO,EAAE,IAC5D,CAAC;CACP;CAEA,IAAI,CAAC,OAAO,KAAK,KAAK,CAAC,CAAC,QACtB,OAAO;CAET,OAAO,OAAO,YACZ,OAAO,QAAQ,KAAK,CAAC,CAClB,QAAQ,GAAG,UAAU,IAAI,CAAC,CAC1B,KAAK,CAAC,KAAK,UAA4C,CACtD,KACA;EACE,GAAI,sBAAsB,QAAQ,CAAC,KAAK,oBAAoB,mBAAmB,EAAE,iBAAiB,IAAI,CAAC;EACvG,GAAI,4BAA4B,QAAQ,CAAC,KAAK,0BAA0B,yBACpE,EAAE,uBAAuB,IACzB,CAAC;EACL,GAAI,cAAc,QAAQ,CAAC,KAAK,YAAY,WAAW,EAAE,SAAS,IAAI,CAAC;CACzE,CACF,CAAC,CAAC,CACD,QAAQ,GAAG,YAAY,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS,CAAC,CAC1D;AACF"}
|
package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openid-discovery-to-flows.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,uCAAuC,CAAA;AAItG,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AAE9E,qHAAqH;AACrH,eAAO,MAAM,sBAAsB,GAAI,WAAW,sBAAsB,KAAG,
|
|
1
|
+
{"version":3,"file":"openid-discovery-to-flows.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,oBAAoB,EAAE,MAAM,uCAAuC,CAAA;AAItG,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AAE9E,qHAAqH;AACrH,eAAO,MAAM,sBAAsB,GAAI,WAAW,sBAAsB,KAAG,oBAiE1E,CAAA"}
|
|
@@ -9,6 +9,12 @@ var openIDDiscoveryToFlows = (discovery) => {
|
|
|
9
9
|
const tokenUrl = discovery.token_endpoint;
|
|
10
10
|
const usePkce = discovery.code_challenge_methods_supported?.includes("S256") ? "SHA-256" : discovery.code_challenge_methods_supported?.includes("plain") ? "plain" : "no";
|
|
11
11
|
const flows = {};
|
|
12
|
+
if (grantTypes.has("urn:ietf:params:oauth:grant-type:device_code") && discovery.device_authorization_endpoint && tokenUrl) flows.deviceAuthorization = {
|
|
13
|
+
deviceAuthorizationUrl: discovery.device_authorization_endpoint,
|
|
14
|
+
tokenUrl,
|
|
15
|
+
refreshUrl: tokenUrl,
|
|
16
|
+
scopes
|
|
17
|
+
};
|
|
12
18
|
if (grantTypes.has("implicit") && authorizationUrl) flows.implicit = {
|
|
13
19
|
authorizationUrl,
|
|
14
20
|
refreshUrl: authorizationUrl,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openid-discovery-to-flows.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.ts"],"sourcesContent":["import { OpenIDConnectSchema, type SecretsOpenIdConnect } from '@scalar/workspace-store/entities/auth'\nimport { coerceValue } from '@scalar/workspace-store/schemas/typebox-coerce'\nimport type { OAuthFlowsObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport type { OpenIDConnectDiscovery } from './fetch-openid-connect-discovery'\n\n/** Takes in an open ID Connect discovery response and converts it into an oauth flow to be used for authorization */\nexport const openIDDiscoveryToFlows = (discovery: OpenIDConnectDiscovery): SecretsOpenIdConnect => {\n const scopes = Object.fromEntries((discovery.scopes_supported ?? []).map((scope) => [scope, '']))\n const grantTypes = new Set(discovery.grant_types_supported ?? ['authorization_code', 'implicit'])\n const authorizationUrl = discovery.authorization_endpoint\n const tokenUrl = discovery.token_endpoint\n\n const usePkce = discovery.code_challenge_methods_supported?.includes('S256')\n ? 'SHA-256'\n : discovery.code_challenge_methods_supported?.includes('plain')\n ? 'plain'\n : 'no'\n\n const flows: OAuthFlowsObject = {}\n\n // Implicit\n if (grantTypes.has('implicit') && authorizationUrl) {\n flows.implicit = {\n authorizationUrl,\n refreshUrl: authorizationUrl,\n scopes,\n }\n }\n\n // Password\n if (grantTypes.has('password') && tokenUrl) {\n flows.password = {\n tokenUrl,\n refreshUrl: tokenUrl,\n scopes,\n }\n }\n\n // Client Credentials\n if (grantTypes.has('client_credentials') && tokenUrl) {\n flows.clientCredentials = {\n tokenUrl,\n refreshUrl: tokenUrl,\n scopes,\n }\n }\n\n // Authorization Code\n if (grantTypes.has('authorization_code') && authorizationUrl && tokenUrl) {\n flows.authorizationCode = {\n authorizationUrl,\n tokenUrl,\n refreshUrl: tokenUrl,\n 'x-usePkce': usePkce,\n scopes,\n }\n }\n\n return coerceValue(OpenIDConnectSchema, flows)\n}\n"],"mappings":";;;;AAOA,IAAa,0BAA0B,cAA4D;CACjG,MAAM,SAAS,OAAO,aAAa,UAAU,oBAAoB,CAAC,EAAA,CAAG,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;CAChG,MAAM,aAAa,IAAI,IAAI,UAAU,yBAAyB,CAAC,sBAAsB,UAAU,CAAC;CAChG,MAAM,mBAAmB,UAAU;CACnC,MAAM,WAAW,UAAU;CAE3B,MAAM,UAAU,UAAU,kCAAkC,SAAS,MAAM,IACvE,YACA,UAAU,kCAAkC,SAAS,OAAO,IAC1D,UACA;CAEN,MAAM,QAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"openid-discovery-to-flows.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.ts"],"sourcesContent":["import { OpenIDConnectSchema, type SecretsOpenIdConnect } from '@scalar/workspace-store/entities/auth'\nimport { coerceValue } from '@scalar/workspace-store/schemas/typebox-coerce'\nimport type { OAuthFlowsObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport type { OpenIDConnectDiscovery } from './fetch-openid-connect-discovery'\n\n/** Takes in an open ID Connect discovery response and converts it into an oauth flow to be used for authorization */\nexport const openIDDiscoveryToFlows = (discovery: OpenIDConnectDiscovery): SecretsOpenIdConnect => {\n const scopes = Object.fromEntries((discovery.scopes_supported ?? []).map((scope) => [scope, '']))\n const grantTypes = new Set(discovery.grant_types_supported ?? ['authorization_code', 'implicit'])\n const authorizationUrl = discovery.authorization_endpoint\n const tokenUrl = discovery.token_endpoint\n\n const usePkce = discovery.code_challenge_methods_supported?.includes('S256')\n ? 'SHA-256'\n : discovery.code_challenge_methods_supported?.includes('plain')\n ? 'plain'\n : 'no'\n\n const flows: OAuthFlowsObject = {}\n if (\n grantTypes.has('urn:ietf:params:oauth:grant-type:device_code') &&\n discovery.device_authorization_endpoint &&\n tokenUrl\n ) {\n flows.deviceAuthorization = {\n deviceAuthorizationUrl: discovery.device_authorization_endpoint,\n tokenUrl,\n refreshUrl: tokenUrl,\n scopes,\n }\n }\n\n // Implicit\n if (grantTypes.has('implicit') && authorizationUrl) {\n flows.implicit = {\n authorizationUrl,\n refreshUrl: authorizationUrl,\n scopes,\n }\n }\n\n // Password\n if (grantTypes.has('password') && tokenUrl) {\n flows.password = {\n tokenUrl,\n refreshUrl: tokenUrl,\n scopes,\n }\n }\n\n // Client Credentials\n if (grantTypes.has('client_credentials') && tokenUrl) {\n flows.clientCredentials = {\n tokenUrl,\n refreshUrl: tokenUrl,\n scopes,\n }\n }\n\n // Authorization Code\n if (grantTypes.has('authorization_code') && authorizationUrl && tokenUrl) {\n flows.authorizationCode = {\n authorizationUrl,\n tokenUrl,\n refreshUrl: tokenUrl,\n 'x-usePkce': usePkce,\n scopes,\n }\n }\n\n return coerceValue(OpenIDConnectSchema, flows)\n}\n"],"mappings":";;;;AAOA,IAAa,0BAA0B,cAA4D;CACjG,MAAM,SAAS,OAAO,aAAa,UAAU,oBAAoB,CAAC,EAAA,CAAG,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;CAChG,MAAM,aAAa,IAAI,IAAI,UAAU,yBAAyB,CAAC,sBAAsB,UAAU,CAAC;CAChG,MAAM,mBAAmB,UAAU;CACnC,MAAM,WAAW,UAAU;CAE3B,MAAM,UAAU,UAAU,kCAAkC,SAAS,MAAM,IACvE,YACA,UAAU,kCAAkC,SAAS,OAAO,IAC1D,UACA;CAEN,MAAM,QAA0B,CAAC;CACjC,IACE,WAAW,IAAI,8CAA8C,KAC7D,UAAU,iCACV,UAEA,MAAM,sBAAsB;EAC1B,wBAAwB,UAAU;EAClC;EACA,YAAY;EACZ;CACF;CAIF,IAAI,WAAW,IAAI,UAAU,KAAK,kBAChC,MAAM,WAAW;EACf;EACA,YAAY;EACZ;CACF;CAIF,IAAI,WAAW,IAAI,UAAU,KAAK,UAChC,MAAM,WAAW;EACf;EACA,YAAY;EACZ;CACF;CAIF,IAAI,WAAW,IAAI,oBAAoB,KAAK,UAC1C,MAAM,oBAAoB;EACxB;EACA,YAAY;EACZ;CACF;CAIF,IAAI,WAAW,IAAI,oBAAoB,KAAK,oBAAoB,UAC9D,MAAM,oBAAoB;EACxB;EACA;EACA,YAAY;EACZ,aAAa;EACb;CACF;CAGF,OAAO,YAAY,qBAAqB,KAAK;AAC/C"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ApiClientTranslations } from '@scalar/types/api-reference';
|
|
1
2
|
import type { MergedSecuritySchemes, OAuthFlowsObjectSecret } from '@scalar/workspace-store/request-example';
|
|
2
3
|
import type { ComponentsObject, OpenApiDocument, SecurityRequirementObject, SecuritySchemeObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document';
|
|
3
4
|
/** A single security scheme option used in the auth dropdown */
|
|
@@ -59,5 +60,5 @@ export declare const getSecuritySchemeOptions: (security: NonNullable<OpenApiDoc
|
|
|
59
60
|
/** We need to add the selected schemes if they do not already exist in the calculated options */
|
|
60
61
|
selectedSchemes: SecurityRequirementObject[],
|
|
61
62
|
/** Allows adding authentication which is not in the document */
|
|
62
|
-
canAddNewAuth?: boolean) => SecuritySchemeOption[] | SecuritySchemeGroup[];
|
|
63
|
+
canAddNewAuth?: boolean, labels?: Pick<ApiClientTranslations, "authSelector" | "authOptions">) => SecuritySchemeOption[] | SecuritySchemeGroup[];
|
|
63
64
|
//# sourceMappingURL=security-scheme.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security-scheme.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"security-scheme.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAA;AAGxE,OAAO,KAAK,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAA;AAC5G,OAAO,KAAK,EACV,gBAAgB,EAChB,eAAe,EACf,yBAAyB,EACzB,oBAAoB,EACrB,MAAM,8DAA8D,CAAA;AAYrE,gEAAgE;AAChE,MAAM,MAAM,oBAAoB,GAAG;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,yBAAyB,CAAA;IAChC,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,OAAO,CAAC,EAAE,oBAAoB,CAAA;CAC/B,CAAA;AAED,mEAAmE;AACnE,MAAM,MAAM,mBAAmB,GAAG;IAChC,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,oBAAoB,EAAE,CAAA;CAChC,CAAA;AAKD;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,iBAAiB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,yBAAyB,CAAA;CAAE;;;;;CAK9F,CAAA;AAEF,uCAAuC;AACvC,eAAO,MAAM,mBAAmB,GAAI,QAAQ,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC;;;;;CAIxF,CAAA;AAuCJ;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,GACrC,iBAAiB,WAAW,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC,GAAG,qBAAqB,KACxF;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,sBAAsB,CAAA;IAC7B,QAAQ,EAAE,mBAAmB,GAAG,UAAU,CAAA;IAC1C,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,GAAG,IAgCH,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,GACnC,UAAU,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,EAClD,iBAAiB,WAAW,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC,GAAG,qBAAqB;AACzF,iGAAiG;AACjG,iBAAiB,yBAAyB,EAAE;AAC5C,gEAAgE;AAChE,uBAAqB,EACrB,SAAQ,IAAI,CAAC,qBAAqB,EAAE,cAAc,GAAG,aAAa,CAAM,KACvE,oBAAoB,EAAE,GAAG,mBAAmB,EAuF9C,CAAA"}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { en } from "../../../features/localization/translations.js";
|
|
1
2
|
import { authOptions } from "./auth-options.js";
|
|
3
|
+
import { objectEntries } from "@scalar/helpers/object/object-entries";
|
|
2
4
|
import { getResolvedRef } from "@scalar/workspace-store/helpers/get-resolved-ref";
|
|
3
5
|
import { generateHash } from "@scalar/helpers/string/generate-hash";
|
|
4
6
|
import { isHidden } from "@scalar/workspace-store/helpers/is-hidden";
|
|
@@ -80,7 +82,7 @@ var getOauth2AcquisitionTarget = (securitySchemes) => {
|
|
|
80
82
|
*
|
|
81
83
|
* Contains either a flat list, or different groups of required, available, and add new
|
|
82
84
|
*/
|
|
83
|
-
var getSecuritySchemeOptions = (security, securitySchemes, selectedSchemes, canAddNewAuth = false) => {
|
|
85
|
+
var getSecuritySchemeOptions = (security, securitySchemes, selectedSchemes, canAddNewAuth = false, labels = en) => {
|
|
84
86
|
const selectedByRequirement = new Map(selectedSchemes.map((selectedScheme) => [requirementSignature(selectedScheme), selectedScheme]));
|
|
85
87
|
/**
|
|
86
88
|
* Build required schemes formatted as options and track scheme names in a single pass.
|
|
@@ -125,18 +127,18 @@ var getSecuritySchemeOptions = (security, securitySchemes, selectedSchemes, canA
|
|
|
125
127
|
}
|
|
126
128
|
}
|
|
127
129
|
const options = [{
|
|
128
|
-
label:
|
|
130
|
+
label: labels.authSelector.requiredGroup,
|
|
129
131
|
options: requiredFormatted
|
|
130
132
|
}, {
|
|
131
|
-
label:
|
|
133
|
+
label: labels.authSelector.availableGroup,
|
|
132
134
|
options: availableFormatted
|
|
133
135
|
}];
|
|
134
136
|
if (!canAddNewAuth) return requiredFormatted.length ? options : availableFormatted;
|
|
135
137
|
options.push({
|
|
136
|
-
label:
|
|
137
|
-
options:
|
|
138
|
+
label: labels.authSelector.addGroup,
|
|
139
|
+
options: objectEntries(authOptions).map(([key, value]) => ({
|
|
138
140
|
id: key,
|
|
139
|
-
label:
|
|
141
|
+
label: labels.authOptions[key],
|
|
140
142
|
value: { [key]: [] },
|
|
141
143
|
payload: value.payload,
|
|
142
144
|
isDeletable: false
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security-scheme.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.ts"],"sourcesContent":["import { generateHash } from '@scalar/helpers/string/generate-hash'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { isHidden } from '@scalar/workspace-store/helpers/is-hidden'\nimport type { MergedSecuritySchemes, OAuthFlowsObjectSecret } from '@scalar/workspace-store/request-example'\nimport type {\n ComponentsObject,\n OpenApiDocument,\n SecurityRequirementObject,\n SecuritySchemeObject,\n} from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport { authOptions } from '@/v2/blocks/scalar-auth-selector-block/helpers/auth-options'\n\n/**\n * Minimal shape read by `isHidden`. Some scheme union members (AsyncAPI broker schemes) do not\n * structurally carry the ignore extensions, so we cast to this before the check to satisfy the\n * weak-type check without widening `isHidden` itself.\n */\ntype Hideable = { 'x-internal'?: boolean; 'x-scalar-ignore'?: boolean }\n\n/** A single security scheme option used in the auth dropdown */\nexport type SecuritySchemeOption = {\n id: string\n label: string\n value: SecurityRequirementObject\n isDeletable?: boolean\n payload?: SecuritySchemeObject\n}\n\n/** A group of security scheme options used in the auth dropdown */\nexport type SecuritySchemeGroup = {\n label: string\n options: SecuritySchemeOption[]\n}\n\nconst requirementSignature = (requirement: SecurityRequirementObject): string =>\n JSON.stringify(Object.keys(requirement))\n\n/**\n * Format a scheme object into a display object\n *\n * We also add a hash to the id to ensure it is unique across\n * multiple requirements of the same scheme with different scopes\n */\nexport const formatScheme = ({ name, value }: { name: string; value: SecurityRequirementObject }) => ({\n id: generateHash(JSON.stringify(value)),\n label: name,\n value,\n isDeletable: true,\n})\n\n/** Formats complex security schemes */\nexport const formatComplexScheme = (scheme: NonNullable<OpenApiDocument['security']>[number]) =>\n formatScheme({\n name: Object.keys(scheme).join(' & '),\n value: scheme,\n })\n\n/**\n * Formats a security requirement into a SecuritySchemeOption.\n * Handles both simple (single key) and complex (multiple keys) auth schemes.\n */\nconst formatSecurityRequirement = (\n requirement: SecurityRequirementObject,\n securitySchemes: NonNullable<ComponentsObject['securitySchemes']> | MergedSecuritySchemes,\n): SecuritySchemeOption | undefined => {\n const keys = Object.keys(requirement)\n\n // Complex auth (multiple keys)\n if (keys.length > 1) {\n // Drop the whole AND combination if any of its schemes is hidden via x-scalar-ignore — a\n // partly hidden requirement cannot be configured, so it should not appear as an option.\n const anyHidden = keys.some((key) => {\n const scheme = getResolvedRef(securitySchemes[key])\n return scheme ? isHidden(scheme as Hideable) : false\n })\n if (anyHidden) {\n return undefined\n }\n return formatComplexScheme(requirement)\n }\n\n // Simple auth (single key)\n if (keys[0]) {\n const scheme = getResolvedRef(securitySchemes[keys[0]])\n // Drop schemes that do not exist or are hidden from the auth UI via x-scalar-ignore.\n if (!scheme || isHidden(scheme as Hideable)) {\n return undefined\n }\n return formatScheme({ name: keys[0], value: requirement })\n }\n\n return undefined\n}\n\n/**\n * Finds the oauth2 scheme best suited to power a bearer scheme's \"Authorize via OAuth2\" shortcut:\n * the first scheme with an interactive grant (authorization code / implicit), the kind that sends\n * a user to an IdP login. Prefers the authorization-code grant (which can refresh) over one\n * offering only implicit, so the more capable flow wins even when it is declared later.\n *\n * This only surfaces a convenience shortcut on the bearer form — it never hides the oauth2 scheme,\n * which stays independently selectable in the auth dropdown.\n */\nexport const getOauth2AcquisitionTarget = (\n securitySchemes: NonNullable<ComponentsObject['securitySchemes']> | MergedSecuritySchemes,\n): {\n name: string\n flows: OAuthFlowsObjectSecret\n flowType: 'authorizationCode' | 'implicit'\n scopes: string[]\n} | null => {\n let implicitFallback: {\n name: string\n flows: OAuthFlowsObjectSecret\n flowType: 'implicit'\n scopes: string[]\n } | null = null\n\n for (const [name, schemeRef] of Object.entries(securitySchemes)) {\n const scheme = getResolvedRef(schemeRef)\n // Skip schemes hidden from the auth UI via x-scalar-ignore, so the shortcut never\n // targets a flow the user cannot see or configure.\n if (scheme?.type !== 'oauth2' || isHidden(scheme)) {\n continue\n }\n const flows = scheme.flows as OAuthFlowsObjectSecret | undefined\n if (!flows) {\n continue\n }\n const scopes = (scheme as { 'x-default-scopes'?: string[] })['x-default-scopes'] ?? []\n\n // Authorization code can refresh, so it wins outright the moment we find one.\n if (flows.authorizationCode && !isHidden(flows.authorizationCode)) {\n return { name, flows, flowType: 'authorizationCode', scopes }\n }\n // Otherwise remember the first implicit-only scheme in case no auth-code flow turns up.\n if (flows.implicit && !isHidden(flows.implicit) && !implicitFallback) {\n implicitFallback = { name, flows, flowType: 'implicit', scopes }\n }\n }\n\n return implicitFallback\n}\n\n/**\n * Generates the options for the security scheme combobox\n *\n * Contains either a flat list, or different groups of required, available, and add new\n */\nexport const getSecuritySchemeOptions = (\n security: NonNullable<OpenApiDocument['security']>,\n securitySchemes: NonNullable<ComponentsObject['securitySchemes']> | MergedSecuritySchemes,\n /** We need to add the selected schemes if they do not already exist in the calculated options */\n selectedSchemes: SecurityRequirementObject[],\n /** Allows adding authentication which is not in the document */\n canAddNewAuth = false,\n): SecuritySchemeOption[] | SecuritySchemeGroup[] => {\n const selectedByRequirement = new Map(\n selectedSchemes.map((selectedScheme) => [requirementSignature(selectedScheme), selectedScheme]),\n )\n\n /**\n * Build required schemes formatted as options and track scheme names in a single pass.\n * We use names (not full IDs) because we want to exclude any scheme that is already\n * required, regardless of its specific scopes or hash.\n */\n const { requiredFormatted, requiredSchemeNames, existingIds } = security.reduce<{\n requiredFormatted: SecuritySchemeOption[]\n requiredSchemeNames: Set<string>\n existingIds: Set<string>\n }>(\n (acc, requirement) => {\n // If a required requirement is selected with scopes, use that selected value to\n // keep a single option entry and avoid a phantom duplicate.\n const requirementValue = selectedByRequirement.get(requirementSignature(requirement)) ?? requirement\n const formatted = formatSecurityRequirement(requirementValue, securitySchemes)\n if (formatted) {\n acc.requiredFormatted.push(formatted)\n acc.existingIds.add(formatted.id)\n }\n for (const name of Object.keys(requirement)) {\n acc.requiredSchemeNames.add(name)\n }\n return acc\n },\n {\n requiredFormatted: [],\n requiredSchemeNames: new Set<string>(),\n existingIds: new Set<string>(),\n },\n )\n\n // Build available schemes (excluding schemes that are in the required list)\n const availableFormatted: SecuritySchemeOption[] = []\n for (const [name, schemeRef] of Object.entries(securitySchemes)) {\n if (requiredSchemeNames.has(name)) {\n continue\n }\n\n const scheme = getResolvedRef(schemeRef)\n // Skip schemes hidden from the auth UI via x-scalar-ignore.\n if (scheme && !isHidden(scheme as Hideable)) {\n const formatted = formatScheme({ name, value: { [name]: [] } })\n availableFormatted.push(formatted)\n existingIds.add(formatted.id)\n }\n }\n\n /**\n * Add selected schemes to available if they do not already exist\n * This ensures that selected schemes with specific scopes are always available as options\n */\n for (const selectedScheme of selectedSchemes) {\n const formatted = formatSecurityRequirement(selectedScheme, securitySchemes)\n if (formatted && !existingIds.has(formatted.id)) {\n availableFormatted.push(formatted)\n existingIds.add(formatted.id)\n }\n }\n\n const options = [\n { label: 'Required authentication', options: requiredFormatted },\n { label: 'Available authentication', options: availableFormatted },\n ]\n\n // We don't return the groups if we don't have any required schemes\n if (!canAddNewAuth) {\n return requiredFormatted.length ? options : availableFormatted\n }\n\n // Add new authentication options (unless explicitly hidden)\n options.push({\n label: 'Add new authentication',\n options: Object.entries(authOptions).map(([key, value]) => ({\n id: key,\n label: value.label,\n value: { [key]: [] },\n payload: value.payload,\n isDeletable: false,\n })),\n })\n\n return options\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"security-scheme.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/security-scheme.ts"],"sourcesContent":["import { objectEntries } from '@scalar/helpers/object/object-entries'\nimport { generateHash } from '@scalar/helpers/string/generate-hash'\nimport type { ApiClientTranslations } from '@scalar/types/api-reference'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport { isHidden } from '@scalar/workspace-store/helpers/is-hidden'\nimport type { MergedSecuritySchemes, OAuthFlowsObjectSecret } from '@scalar/workspace-store/request-example'\nimport type {\n ComponentsObject,\n OpenApiDocument,\n SecurityRequirementObject,\n SecuritySchemeObject,\n} from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport { authOptions } from '@/v2/blocks/scalar-auth-selector-block/helpers/auth-options'\nimport { en } from '@/v2/features/localization/translations'\n\n/**\n * Minimal shape read by `isHidden`. Some scheme union members (AsyncAPI broker schemes) do not\n * structurally carry the ignore extensions, so we cast to this before the check to satisfy the\n * weak-type check without widening `isHidden` itself.\n */\ntype Hideable = { 'x-internal'?: boolean; 'x-scalar-ignore'?: boolean }\n\n/** A single security scheme option used in the auth dropdown */\nexport type SecuritySchemeOption = {\n id: string\n label: string\n value: SecurityRequirementObject\n isDeletable?: boolean\n payload?: SecuritySchemeObject\n}\n\n/** A group of security scheme options used in the auth dropdown */\nexport type SecuritySchemeGroup = {\n label: string\n options: SecuritySchemeOption[]\n}\n\nconst requirementSignature = (requirement: SecurityRequirementObject): string =>\n JSON.stringify(Object.keys(requirement))\n\n/**\n * Format a scheme object into a display object\n *\n * We also add a hash to the id to ensure it is unique across\n * multiple requirements of the same scheme with different scopes\n */\nexport const formatScheme = ({ name, value }: { name: string; value: SecurityRequirementObject }) => ({\n id: generateHash(JSON.stringify(value)),\n label: name,\n value,\n isDeletable: true,\n})\n\n/** Formats complex security schemes */\nexport const formatComplexScheme = (scheme: NonNullable<OpenApiDocument['security']>[number]) =>\n formatScheme({\n name: Object.keys(scheme).join(' & '),\n value: scheme,\n })\n\n/**\n * Formats a security requirement into a SecuritySchemeOption.\n * Handles both simple (single key) and complex (multiple keys) auth schemes.\n */\nconst formatSecurityRequirement = (\n requirement: SecurityRequirementObject,\n securitySchemes: NonNullable<ComponentsObject['securitySchemes']> | MergedSecuritySchemes,\n): SecuritySchemeOption | undefined => {\n const keys = Object.keys(requirement)\n\n // Complex auth (multiple keys)\n if (keys.length > 1) {\n // Drop the whole AND combination if any of its schemes is hidden via x-scalar-ignore — a\n // partly hidden requirement cannot be configured, so it should not appear as an option.\n const anyHidden = keys.some((key) => {\n const scheme = getResolvedRef(securitySchemes[key])\n return scheme ? isHidden(scheme as Hideable) : false\n })\n if (anyHidden) {\n return undefined\n }\n return formatComplexScheme(requirement)\n }\n\n // Simple auth (single key)\n if (keys[0]) {\n const scheme = getResolvedRef(securitySchemes[keys[0]])\n // Drop schemes that do not exist or are hidden from the auth UI via x-scalar-ignore.\n if (!scheme || isHidden(scheme as Hideable)) {\n return undefined\n }\n return formatScheme({ name: keys[0], value: requirement })\n }\n\n return undefined\n}\n\n/**\n * Finds the oauth2 scheme best suited to power a bearer scheme's \"Authorize via OAuth2\" shortcut:\n * the first scheme with an interactive grant (authorization code / implicit), the kind that sends\n * a user to an IdP login. Prefers the authorization-code grant (which can refresh) over one\n * offering only implicit, so the more capable flow wins even when it is declared later.\n *\n * This only surfaces a convenience shortcut on the bearer form — it never hides the oauth2 scheme,\n * which stays independently selectable in the auth dropdown.\n */\nexport const getOauth2AcquisitionTarget = (\n securitySchemes: NonNullable<ComponentsObject['securitySchemes']> | MergedSecuritySchemes,\n): {\n name: string\n flows: OAuthFlowsObjectSecret\n flowType: 'authorizationCode' | 'implicit'\n scopes: string[]\n} | null => {\n let implicitFallback: {\n name: string\n flows: OAuthFlowsObjectSecret\n flowType: 'implicit'\n scopes: string[]\n } | null = null\n\n for (const [name, schemeRef] of Object.entries(securitySchemes)) {\n const scheme = getResolvedRef(schemeRef)\n // Skip schemes hidden from the auth UI via x-scalar-ignore, so the shortcut never\n // targets a flow the user cannot see or configure.\n if (scheme?.type !== 'oauth2' || isHidden(scheme)) {\n continue\n }\n const flows = scheme.flows as OAuthFlowsObjectSecret | undefined\n if (!flows) {\n continue\n }\n const scopes = (scheme as { 'x-default-scopes'?: string[] })['x-default-scopes'] ?? []\n\n // Authorization code can refresh, so it wins outright the moment we find one.\n if (flows.authorizationCode && !isHidden(flows.authorizationCode)) {\n return { name, flows, flowType: 'authorizationCode', scopes }\n }\n // Otherwise remember the first implicit-only scheme in case no auth-code flow turns up.\n if (flows.implicit && !isHidden(flows.implicit) && !implicitFallback) {\n implicitFallback = { name, flows, flowType: 'implicit', scopes }\n }\n }\n\n return implicitFallback\n}\n\n/**\n * Generates the options for the security scheme combobox\n *\n * Contains either a flat list, or different groups of required, available, and add new\n */\nexport const getSecuritySchemeOptions = (\n security: NonNullable<OpenApiDocument['security']>,\n securitySchemes: NonNullable<ComponentsObject['securitySchemes']> | MergedSecuritySchemes,\n /** We need to add the selected schemes if they do not already exist in the calculated options */\n selectedSchemes: SecurityRequirementObject[],\n /** Allows adding authentication which is not in the document */\n canAddNewAuth = false,\n labels: Pick<ApiClientTranslations, 'authSelector' | 'authOptions'> = en,\n): SecuritySchemeOption[] | SecuritySchemeGroup[] => {\n const selectedByRequirement = new Map(\n selectedSchemes.map((selectedScheme) => [requirementSignature(selectedScheme), selectedScheme]),\n )\n\n /**\n * Build required schemes formatted as options and track scheme names in a single pass.\n * We use names (not full IDs) because we want to exclude any scheme that is already\n * required, regardless of its specific scopes or hash.\n */\n const { requiredFormatted, requiredSchemeNames, existingIds } = security.reduce<{\n requiredFormatted: SecuritySchemeOption[]\n requiredSchemeNames: Set<string>\n existingIds: Set<string>\n }>(\n (acc, requirement) => {\n // If a required requirement is selected with scopes, use that selected value to\n // keep a single option entry and avoid a phantom duplicate.\n const requirementValue = selectedByRequirement.get(requirementSignature(requirement)) ?? requirement\n const formatted = formatSecurityRequirement(requirementValue, securitySchemes)\n if (formatted) {\n acc.requiredFormatted.push(formatted)\n acc.existingIds.add(formatted.id)\n }\n for (const name of Object.keys(requirement)) {\n acc.requiredSchemeNames.add(name)\n }\n return acc\n },\n {\n requiredFormatted: [],\n requiredSchemeNames: new Set<string>(),\n existingIds: new Set<string>(),\n },\n )\n\n // Build available schemes (excluding schemes that are in the required list)\n const availableFormatted: SecuritySchemeOption[] = []\n for (const [name, schemeRef] of Object.entries(securitySchemes)) {\n if (requiredSchemeNames.has(name)) {\n continue\n }\n\n const scheme = getResolvedRef(schemeRef)\n // Skip schemes hidden from the auth UI via x-scalar-ignore.\n if (scheme && !isHidden(scheme as Hideable)) {\n const formatted = formatScheme({ name, value: { [name]: [] } })\n availableFormatted.push(formatted)\n existingIds.add(formatted.id)\n }\n }\n\n /**\n * Add selected schemes to available if they do not already exist\n * This ensures that selected schemes with specific scopes are always available as options\n */\n for (const selectedScheme of selectedSchemes) {\n const formatted = formatSecurityRequirement(selectedScheme, securitySchemes)\n if (formatted && !existingIds.has(formatted.id)) {\n availableFormatted.push(formatted)\n existingIds.add(formatted.id)\n }\n }\n\n const options = [\n { label: labels.authSelector.requiredGroup, options: requiredFormatted },\n { label: labels.authSelector.availableGroup, options: availableFormatted },\n ]\n\n // We don't return the groups if we don't have any required schemes\n if (!canAddNewAuth) {\n return requiredFormatted.length ? options : availableFormatted\n }\n\n // Add new authentication options (unless explicitly hidden)\n options.push({\n label: labels.authSelector.addGroup,\n options: objectEntries(authOptions).map(([key, value]) => ({\n id: key,\n label: labels.authOptions[key],\n value: { [key]: [] },\n payload: value.payload,\n isDeletable: false,\n })),\n })\n\n return options\n}\n"],"mappings":"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"}
|
|
@@ -106,12 +106,12 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
|
106
106
|
serializeValue: (value: CodeInputModelValue) => string;
|
|
107
107
|
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
108
108
|
submit: (value: string, event: KeyboardEvent | FocusEvent) => any;
|
|
109
|
-
"update:modelValue": (value: string) => any;
|
|
110
|
-
blur: (value: string, event: FocusEvent) => any;
|
|
111
109
|
navigate: (route: {
|
|
112
110
|
page: "document";
|
|
113
111
|
path: "environment";
|
|
114
112
|
}) => any;
|
|
113
|
+
"update:modelValue": (value: string) => any;
|
|
114
|
+
blur: (value: string, event: FocusEvent) => any;
|
|
115
115
|
}, string, import("vue").PublicProps, Readonly<{
|
|
116
116
|
modelValue: CodeInputModelValue;
|
|
117
117
|
/** Environment for variable substitution. Pass undefined to disable environment variables */
|
|
@@ -170,12 +170,12 @@ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<{
|
|
|
170
170
|
linethrough?: boolean;
|
|
171
171
|
}> & Readonly<{
|
|
172
172
|
onSubmit?: ((value: string, event: KeyboardEvent | FocusEvent) => any) | undefined;
|
|
173
|
-
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
174
|
-
onBlur?: ((value: string, event: FocusEvent) => any) | undefined;
|
|
175
173
|
onNavigate?: ((route: {
|
|
176
174
|
page: "document";
|
|
177
175
|
path: "environment";
|
|
178
176
|
}) => any) | undefined;
|
|
177
|
+
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
178
|
+
onBlur?: ((value: string, event: FocusEvent) => any) | undefined;
|
|
179
179
|
}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, {
|
|
180
180
|
warning?: (props: {}) => any;
|
|
181
181
|
} & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CodeInput.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/components/code-input/CodeInput.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"CodeInput.vue.d.ts","sourceRoot":"","sources":["../../../../src/v2/components/code-input/CodeInput.vue"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import CodeInput_vue_vue_type_script_setup_true_lang_default from "./CodeInput.v
|
|
|
3
3
|
/* empty css */
|
|
4
4
|
/* empty css */
|
|
5
5
|
//#region src/v2/components/code-input/CodeInput.vue
|
|
6
|
-
var CodeInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(CodeInput_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-
|
|
6
|
+
var CodeInput_default = /*#__PURE__*/ _plugin_vue_export_helper_default(CodeInput_vue_vue_type_script_setup_true_lang_default, [["__scopeId", "data-v-2334e03b"]]);
|
|
7
7
|
//#endregion
|
|
8
8
|
export { CodeInput_default as default };
|
|
9
9
|
|