@scalar/api-client 3.22.0 → 3.23.1

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.
Files changed (171) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/components/ScalarAsciiArt/ScalarAsciiArt.vue.js +1 -1
  3. package/dist/components/ScalarAsciiArt/ScalarAsciiArt.vue.js.map +1 -1
  4. package/dist/components/ScalarAsciiArt/ScalarAsciiArt.vue.script.js +2 -2
  5. package/dist/components/ScalarAsciiArt/ScalarAsciiArt.vue.script.js.map +1 -1
  6. package/dist/hooks/use-file-dialog.js +1 -1
  7. package/dist/hooks/use-file-dialog.js.map +1 -1
  8. package/dist/style.css +190 -144
  9. package/dist/v2/blocks/operation-block/OperationBlock.vue.js.map +1 -1
  10. package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
  11. package/dist/v2/blocks/operation-block/components/Header.vue.d.ts.map +1 -1
  12. package/dist/v2/blocks/operation-block/components/Header.vue.js +1 -1
  13. package/dist/v2/blocks/operation-block/components/Header.vue.js.map +1 -1
  14. package/dist/v2/blocks/operation-block/components/Header.vue.script.js.map +1 -1
  15. package/dist/v2/blocks/operation-block/helpers/persist-response-cookies.d.ts +3 -3
  16. package/dist/v2/blocks/operation-block/helpers/persist-response-cookies.d.ts.map +1 -1
  17. package/dist/v2/blocks/operation-block/helpers/persist-response-cookies.js +4 -4
  18. package/dist/v2/blocks/operation-block/helpers/persist-response-cookies.js.map +1 -1
  19. package/dist/v2/blocks/operation-block/helpers/validate-path-parameters.js +1 -1
  20. package/dist/v2/blocks/operation-block/helpers/validate-path-parameters.js.map +1 -1
  21. package/dist/v2/blocks/request-block/RequestBlock.vue.d.ts.map +1 -1
  22. package/dist/v2/blocks/request-block/RequestBlock.vue.js +1 -1
  23. package/dist/v2/blocks/request-block/RequestBlock.vue.js.map +1 -1
  24. package/dist/v2/blocks/request-block/RequestBlock.vue.script.js +13 -8
  25. package/dist/v2/blocks/request-block/RequestBlock.vue.script.js.map +1 -1
  26. package/dist/v2/blocks/request-block/components/RequestBody.vue.d.ts.map +1 -1
  27. package/dist/v2/blocks/request-block/components/RequestBody.vue.js +1 -1
  28. package/dist/v2/blocks/request-block/components/RequestBody.vue.js.map +1 -1
  29. package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js +3 -1
  30. package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js.map +1 -1
  31. package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.js.map +1 -1
  32. package/dist/v2/blocks/request-block/components/RequestBodyForm.vue.script.js.map +1 -1
  33. package/dist/v2/blocks/request-block/components/RequestParams.vue.d.ts +12 -0
  34. package/dist/v2/blocks/request-block/components/RequestParams.vue.d.ts.map +1 -1
  35. package/dist/v2/blocks/request-block/components/RequestParams.vue.js.map +1 -1
  36. package/dist/v2/blocks/request-block/components/RequestParams.vue.script.js +132 -32
  37. package/dist/v2/blocks/request-block/components/RequestParams.vue.script.js.map +1 -1
  38. package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts +3 -1
  39. package/dist/v2/blocks/request-block/components/RequestTable.vue.d.ts.map +1 -1
  40. package/dist/v2/blocks/request-block/components/RequestTable.vue.js +1 -1
  41. package/dist/v2/blocks/request-block/components/RequestTable.vue.js.map +1 -1
  42. package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js +13 -2
  43. package/dist/v2/blocks/request-block/components/RequestTable.vue.script.js.map +1 -1
  44. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts +3 -1
  45. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.d.ts.map +1 -1
  46. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.js.map +1 -1
  47. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js +6 -2
  48. package/dist/v2/blocks/request-block/components/RequestTableRow.vue.script.js.map +1 -1
  49. package/dist/v2/blocks/request-block/helpers/create-parameter-handlers.d.ts.map +1 -1
  50. package/dist/v2/blocks/request-block/helpers/create-parameter-handlers.js +10 -3
  51. package/dist/v2/blocks/request-block/helpers/create-parameter-handlers.js.map +1 -1
  52. package/dist/v2/blocks/request-block/helpers/create-parameter-rows.d.ts.map +1 -1
  53. package/dist/v2/blocks/request-block/helpers/create-parameter-rows.js +10 -1
  54. package/dist/v2/blocks/request-block/helpers/create-parameter-rows.js.map +1 -1
  55. package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js +1 -1
  56. package/dist/v2/blocks/request-block/helpers/get-form-body-rows.js.map +1 -1
  57. package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.js +1 -1
  58. package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.js.map +1 -1
  59. package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.script.js +4 -4
  60. package/dist/v2/blocks/response-block/components/ResponseBodyRaw.vue.script.js.map +1 -1
  61. package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js.map +1 -1
  62. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.d.ts.map +1 -1
  63. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.js.map +1 -1
  64. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js +55 -16
  65. package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js.map +1 -1
  66. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.d.ts +3 -3
  67. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.d.ts.map +1 -1
  68. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.js.map +1 -1
  69. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.script.js +20 -7
  70. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.script.js.map +1 -1
  71. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.d.ts.map +1 -1
  72. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.js.map +1 -1
  73. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js +33 -27
  74. package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js.map +1 -1
  75. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.d.ts.map +1 -1
  76. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.js +1 -1
  77. package/dist/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.js.map +1 -1
  78. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.d.ts.map +1 -1
  79. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.js +1 -1
  80. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.js.map +1 -1
  81. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts.map +1 -1
  82. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js +2 -0
  83. package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js.map +1 -1
  84. package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.d.ts.map +1 -1
  85. package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.js +2 -1
  86. package/dist/v2/blocks/scalar-auth-selector-block/helpers/openid-discovery-to-flows.js.map +1 -1
  87. package/dist/v2/components/code-input/CodeInput.vue.js +1 -1
  88. package/dist/v2/components/code-input/CodeInput.vue.js.map +1 -1
  89. package/dist/v2/components/code-input/CodeInput.vue.script.js +4 -4
  90. package/dist/v2/components/code-input/CodeInput.vue.script.js.map +1 -1
  91. package/dist/v2/components/code-input/CodeInputLite.vue.d.ts.map +1 -1
  92. package/dist/v2/components/code-input/CodeInputLite.vue.js +1 -1
  93. package/dist/v2/components/code-input/CodeInputLite.vue.js.map +1 -1
  94. package/dist/v2/components/code-input/CodeInputLite.vue.script.js.map +1 -1
  95. package/dist/v2/components/code-input/PillTooltipHost.vue.d.ts.map +1 -1
  96. package/dist/v2/components/code-input/PillTooltipHost.vue.js.map +1 -1
  97. package/dist/v2/components/code-input/PillTooltipHost.vue.script.js +4 -1
  98. package/dist/v2/components/code-input/PillTooltipHost.vue.script.js.map +1 -1
  99. package/dist/v2/components/code-input/code-variable-widget.js +1 -1
  100. package/dist/v2/components/code-input/code-variable-widget.js.map +1 -1
  101. package/dist/v2/components/data-table/DataTableInput.vue.d.ts +3 -1
  102. package/dist/v2/components/data-table/DataTableInput.vue.d.ts.map +1 -1
  103. package/dist/v2/components/data-table/DataTableInput.vue.js +1 -1
  104. package/dist/v2/components/data-table/DataTableInput.vue.js.map +1 -1
  105. package/dist/v2/components/data-table/DataTableInput.vue.script.js +46 -15
  106. package/dist/v2/components/data-table/DataTableInput.vue.script.js.map +1 -1
  107. package/dist/v2/constants.js +1 -1
  108. package/dist/v2/features/localization/index.d.ts.map +1 -1
  109. package/dist/v2/features/localization/index.js +2 -0
  110. package/dist/v2/features/localization/index.js.map +1 -1
  111. package/dist/v2/features/localization/locales/ar.d.ts +3 -0
  112. package/dist/v2/features/localization/locales/ar.d.ts.map +1 -1
  113. package/dist/v2/features/localization/locales/ar.js +3 -0
  114. package/dist/v2/features/localization/locales/ar.js.map +1 -1
  115. package/dist/v2/features/localization/locales/de.d.ts +3 -0
  116. package/dist/v2/features/localization/locales/de.d.ts.map +1 -1
  117. package/dist/v2/features/localization/locales/de.js +3 -0
  118. package/dist/v2/features/localization/locales/de.js.map +1 -1
  119. package/dist/v2/features/localization/locales/es.d.ts +3 -0
  120. package/dist/v2/features/localization/locales/es.d.ts.map +1 -1
  121. package/dist/v2/features/localization/locales/es.js +3 -0
  122. package/dist/v2/features/localization/locales/es.js.map +1 -1
  123. package/dist/v2/features/localization/locales/fr.d.ts +3 -0
  124. package/dist/v2/features/localization/locales/fr.d.ts.map +1 -1
  125. package/dist/v2/features/localization/locales/fr.js +3 -0
  126. package/dist/v2/features/localization/locales/fr.js.map +1 -1
  127. package/dist/v2/features/localization/locales/pt.d.ts +3 -0
  128. package/dist/v2/features/localization/locales/pt.d.ts.map +1 -1
  129. package/dist/v2/features/localization/locales/pt.js +3 -0
  130. package/dist/v2/features/localization/locales/pt.js.map +1 -1
  131. package/dist/v2/features/localization/locales/ru.d.ts +3 -0
  132. package/dist/v2/features/localization/locales/ru.d.ts.map +1 -1
  133. package/dist/v2/features/localization/locales/ru.js +3 -0
  134. package/dist/v2/features/localization/locales/ru.js.map +1 -1
  135. package/dist/v2/features/localization/locales/zh-cn.d.ts +3 -0
  136. package/dist/v2/features/localization/locales/zh-cn.d.ts.map +1 -1
  137. package/dist/v2/features/localization/locales/zh-cn.js +3 -0
  138. package/dist/v2/features/localization/locales/zh-cn.js.map +1 -1
  139. package/dist/v2/features/localization/locales/zh-tw.d.ts +398 -0
  140. package/dist/v2/features/localization/locales/zh-tw.d.ts.map +1 -0
  141. package/dist/v2/features/localization/locales/zh-tw.js +360 -0
  142. package/dist/v2/features/localization/locales/zh-tw.js.map +1 -0
  143. package/dist/v2/features/localization/translations.d.ts +3 -0
  144. package/dist/v2/features/localization/translations.d.ts.map +1 -1
  145. package/dist/v2/features/localization/translations.js +3 -0
  146. package/dist/v2/features/localization/translations.js.map +1 -1
  147. package/dist/v2/features/modal/Modal.vue.d.ts.map +1 -1
  148. package/dist/v2/features/modal/Modal.vue.js.map +1 -1
  149. package/dist/v2/features/modal/Modal.vue.script.js +1 -0
  150. package/dist/v2/features/modal/Modal.vue.script.js.map +1 -1
  151. package/dist/v2/features/modal/index.d.ts +1 -1
  152. package/dist/v2/features/modal/index.d.ts.map +1 -1
  153. package/dist/v2/features/modal/modal-events.d.ts +3 -1
  154. package/dist/v2/features/modal/modal-events.d.ts.map +1 -1
  155. package/dist/v2/features/modal/modal-events.js +2 -1
  156. package/dist/v2/features/modal/modal-events.js.map +1 -1
  157. package/dist/v2/helpers/handle-hotkeys.d.ts.map +1 -1
  158. package/dist/v2/helpers/handle-hotkeys.js +4 -1
  159. package/dist/v2/helpers/handle-hotkeys.js.map +1 -1
  160. package/dist/v2/workspace-events.d.ts +4 -1
  161. package/dist/v2/workspace-events.d.ts.map +1 -1
  162. package/dist/v2/workspace-events.js +2 -2
  163. package/dist/v2/workspace-events.js.map +1 -1
  164. package/dist/vue-styles.css +51 -51
  165. package/package.json +14 -14
  166. package/dist/v2/blocks/scalar-auth-selector-block/helpers/extract-security-scheme-secrets.d.ts +0 -10
  167. package/dist/v2/blocks/scalar-auth-selector-block/helpers/extract-security-scheme-secrets.d.ts.map +0 -1
  168. package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.d.ts +0 -3
  169. package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.d.ts.map +0 -1
  170. package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.js +0 -8
  171. package/dist/v2/blocks/scalar-auth-selector-block/helpers/is-allowed-oauth-url.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"RequestAuthTab.vue.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarIconButton } from '@scalar/components/icon-button'\nimport { useLoadingState } from '@scalar/components/loading'\nimport { ScalarMarkdownSummary } from '@scalar/components/markdown'\nimport { ScalarModal, useModal } from '@scalar/components/modal'\nimport { ScalarIconGear } from '@scalar/icons'\nimport { useToasts } from '@scalar/use-toasts'\nimport type {\n SecretsApiKey,\n SecretsHttp,\n} from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport {\n getEnvironmentVariables,\n type MergedSecuritySchemes,\n type OAuthFlowsObjectSecret,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { getDocumentTypeLabel } from '@scalar/workspace-store/schemas/type-guards'\nimport type {\n ApiKeyObject,\n SecurityRequirementObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { capitalize, computed, ref } from 'vue'\n\nimport { refreshOauth2Token } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth'\nimport { getVisibleOrderedFlowKeys } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth-flows'\nimport {\n runOAuth2Authorize,\n storeOAuth2Tokens,\n} from '@/v2/blocks/scalar-auth-selector-block/helpers/run-oauth2-authorize'\nimport { getOauth2AcquisitionTarget } from '@/v2/blocks/scalar-auth-selector-block/helpers/security-scheme'\nimport {\n DataTable,\n DataTableCell,\n DataTableRow,\n} from '@/v2/components/data-table'\nimport { useLocalization } from '@/v2/features/localization'\n\nimport OAuth2, { type OAuth2Options } from './OAuth2.vue'\nimport OAuth2Metadata from './OAuth2Metadata.vue'\nimport OpenIDConnect from './OpenIDConnect.vue'\nimport RequestAuthDataTableInput from './RequestAuthDataTableInput.vue'\n\nconst {\n environment,\n isStatic,\n proxyUrl,\n selectedSecuritySchemas,\n securitySchemes,\n server,\n eventBus,\n options,\n documentType = 'openapi',\n} = defineProps<{\n /** Current environment configuration */\n environment: XScalarEnvironment\n /** Controls the display of certain borders which are used when we are non-collapsible */\n isStatic: boolean\n /** Proxy URL */\n proxyUrl: string\n /** Selected security schemes*/\n selectedSecuritySchemas: SecurityRequirementObject\n /** Merged security schemes from the document and the config together with the auth store secrets */\n securitySchemes: MergedSecuritySchemes\n /** Current server configuration */\n server: ServerObject | null\n /** Event bus for authentication updates */\n eventBus: WorkspaceEventBus\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n /** Type of the document the schemes belong to, used to label the missing-type warning */\n documentType?: 'openapi' | 'asyncapi'\n}>()\n\nconst emits = defineEmits<{\n (\n e: 'update:selectedScopes',\n payload: Omit<ApiReferenceEvents['auth:update:selected-scopes'], 'meta'>,\n ): void\n (e: 'upsert:scope', payload: ApiReferenceEvents['auth:upsert:scopes']): void\n (e: 'delete:scope', payload: ApiReferenceEvents['auth:delete:scopes']): void\n}>()\n\nconst { translate } = useLocalization()\n\ntype SecurityItem = {\n scheme: SecuritySchemeObjectSecret | undefined\n name: string\n scopes: string[]\n /** Ordered, non-hidden oauth2/openIdConnect flow keys for this scheme (empty for other types). */\n visibleFlowKeys: (keyof OAuthFlowsObjectSecret)[]\n}\n\n/**\n * Human-readable name of the document type.\n * Used in the missing-type warning so it points at the correct document\n * (e.g. \"AsyncAPI\") instead of always naming OpenAPI.\n */\nconst documentTypeLabel = computed<string>(() =>\n getDocumentTypeLabel(documentType),\n)\n\n/**\n * Resolves security schemes from the OpenAPI document and combines them with their selected scopes.\n * Each item includes the scheme definition, name, and associated scopes.\n */\nconst security = computed<SecurityItem[]>(() =>\n Object.entries(selectedSecuritySchemas).map(([name, scopes = []]) => {\n const scheme = getResolvedRef(securitySchemes[name])\n return {\n scheme,\n name,\n scopes,\n // Compute the visible, ordered flow keys once per scheme so the tabs, the label, and the\n // active-flow tracking all agree on the same set (and we do not filter + sort on every access).\n visibleFlowKeys:\n scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\n ? getVisibleOrderedFlowKeys(scheme.flows)\n : [],\n }\n }),\n)\n\n/** Tracks which OAuth2 flow is currently active when multiple flows are available. */\nconst activeFlow = ref<string>('')\n\n/**\n * Keeps the selected flow in sync with the currently visible flow keys. Validating against the\n * visible set (not every declared flow) means a selection that becomes hidden — e.g. the document\n * is updated to mark the active flow with `x-scalar-ignore` — resets, so the default (first visible)\n * flow activates instead of leaving no tab selected.\n */\nconst selectedFlow = computed<string>(() => {\n const visibleFlowKeys = security.value.flatMap((item) => item.visibleFlowKeys)\n\n return visibleFlowKeys.some((key) => key === activeFlow.value)\n ? activeFlow.value\n : ''\n})\n\nconst setActiveFlow = (flow: string): void => {\n activeFlow.value = flow\n}\n\n/** Determines if multiple auth schemes are configured, which affects the UI layout. */\nconst hasMultipleSchemes = computed<boolean>(() => security.value.length > 1)\n\n/**\n * Generates a human-readable label for the security scheme.\n * Intentionally omits the description here — it is rendered separately as\n * rich text via ScalarMarkdownSummary so markdown formatting is preserved.\n */\nconst generateLabel = (\n name: string,\n scheme: SecuritySchemeObjectSecret,\n): string => {\n const capitalizedName = capitalize(name)\n\n switch (scheme.type) {\n case 'apiKey':\n return `${capitalizedName}: ${scheme.in}`\n\n case 'openIdConnect':\n case 'oauth2': {\n const firstFlow = getVisibleOrderedFlowKeys(scheme.flows)[0]\n const currentFlow = selectedFlow.value || firstFlow\n if (!currentFlow) {\n return capitalizedName\n }\n return `${capitalizedName}: ${currentFlow}`\n }\n\n case 'http':\n return `${capitalizedName}: ${scheme.scheme}`\n\n default:\n return capitalizedName\n }\n}\n\n/**\n * Whether an API key scheme exposes an editable parameter name.\n *\n * OpenAPI `apiKey` and AsyncAPI `httpApiKey` (normalized to `apiKey`) name a query/header/cookie\n * parameter, so the Name input is shown. AsyncAPI `apiKey` places the key in the broker `user` or\n * `password` slot and has no parameter name, so the Name input is hidden and only the value is asked for.\n */\nconst apiKeyHasName = (scheme: { in?: string }): boolean =>\n scheme.in !== 'user' && scheme.in !== 'password'\n\n/**\n * The scheme's type when it is one we do not render inputs for (a type outside both the OpenAPI\n * and AsyncAPI security scheme unions). Read through a helper so the fallback template branch,\n * where the scheme type is narrowed to `never` after the supported cases, can still surface the type.\n */\nconst getUnsupportedSchemeType = (\n scheme: SecurityItem['scheme'],\n): string | undefined => scheme?.type\n\n/**\n * Determines if an OAuth2 flow tab should be active.\n * The first flow is active by default if no flow is explicitly selected.\n */\nconst isFlowActive = (flowKey: string, index: number): boolean =>\n selectedFlow.value === flowKey || (index === 0 && !selectedFlow.value)\n\n/** Computes the container class for static display mode. */\nconst getStaticBorderClass = (): string | false => isStatic && 'border-t'\n\nconst handleHttpSecretsUpdate = (\n payload: Omit<Partial<SecretsHttp>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'http', ...payload },\n name,\n })\n\nconst handleApiKeySecretsUpdate = (\n payload: Omit<Partial<SecretsApiKey>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\nconst handleApiKeySecuritySchemeUpdate = (\n payload: Omit<Partial<ApiKeyObject>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\n/** Handles scope selection updates for OAuth2 */\nconst handleScopesUpdate = (\n name: string,\n event: { scopes?: string[]; scope?: string; selected?: boolean },\n): void => {\n emits('update:selectedScopes', {\n id: Object.keys(selectedSecuritySchemas),\n name,\n ...event,\n })\n}\n\n/** Handles scope-definition upserts (add / rename / description change) */\nconst handleScopeUpsert = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:upsert:scopes'], 'name'>,\n): void => {\n emits('upsert:scope', { ...event, name })\n}\n\n/** Handles scope-definition deletes */\nconst handleScopeDelete = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:delete:scopes'], 'name'>,\n): void => {\n emits('delete:scope', { ...event, name })\n}\n\n/**\n * Computes dynamic classes for OAuth2 flow tabs based on active state.\n */\nconst getFlowTabClasses = (flowKey: string, index: number): string => {\n const baseClasses =\n 'floating-bg text-c-3 relative cursor-pointer border-b border-transparent py-1 text-base font-medium'\n const activeClasses = '!text-c-1 !rounded-none border-b !border-current'\n\n return isFlowActive(flowKey, index)\n ? `${baseClasses} ${activeClasses} ${isStatic ? 'opacity-100' : ''}`\n : baseClasses\n}\n\n/**\n * OAuth2 token-acquisition target (an oauth2 scheme with an interactive grant) sourced from\n * the merged schemes. When the active scheme is HTTP bearer, this powers the inline\n * \"Authorize via OAuth2\" shortcut: the flow's bearer token is written onto the bearer scheme,\n * so the panel never switches to oauth2.\n *\n * The shortcut is purely a convenience, so it is offered for any interactive oauth2 scheme —\n * including one that is also independently selectable in the dropdown (e.g. Scalar Galaxy's\n * `oAuth2`). Whether that oauth2 scheme is *hidden* from the dropdown is a separate decision made\n * in the selector; here we only surface the shortcut.\n */\nconst oauth2Target = computed(() => getOauth2AcquisitionTarget(securitySchemes))\n\n/** Resolved oauth2 scheme object, for embedding its config form behind the gear. */\nconst oauth2Scheme = computed(() =>\n oauth2Target.value\n ? getResolvedRef(securitySchemes[oauth2Target.value.name])\n : undefined,\n)\n\nconst acquisitionLoader = useLoadingState()\nconst { toast } = useToasts()\nconst configModal = useModal()\n/** Bearer scheme that opened the config modal, so its Authorize callback targets it. */\nconst configBearerName = ref<string | undefined>()\n\n/** Runs the OAuth2 flow and writes the resulting bearer token onto the bearer scheme. */\nconst handleAcquisitionAuthorize = async (\n bearerName: string,\n): Promise<void> => {\n const target = oauth2Target.value\n if (!target || acquisitionLoader.isLoading) {\n return\n }\n acquisitionLoader.start()\n const [error] = await runOAuth2Authorize({\n eventBus,\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flows: target.flows,\n flowType: target.flowType,\n scopes: target.scopes,\n server,\n proxyUrl,\n environment,\n options,\n })\n await acquisitionLoader.clear()\n if (error) {\n toast(\n error?.message ?? translate('apiClient.requestAuthTab.failedToauthorize'),\n 'error',\n )\n }\n}\n\n/** Refreshes the OAuth2 token and rewrites it onto the bearer scheme. */\nconst handleAcquisitionRefresh = async (bearerName: string): Promise<void> => {\n const target = oauth2Target.value\n // Only the authorization-code flow carries a refresh token; implicit can't be refreshed.\n if (\n !target ||\n target.flowType !== 'authorizationCode' ||\n acquisitionLoader.isLoading\n ) {\n return\n }\n acquisitionLoader.start()\n const [error, tokens] = await refreshOauth2Token(\n target.flows,\n target.flowType,\n proxyUrl,\n server,\n getEnvironmentVariables(environment),\n options?.customFetch,\n )\n await acquisitionLoader.clear()\n if (tokens?.accessToken) {\n storeOAuth2Tokens(eventBus, {\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flowType: target.flowType,\n tokens,\n })\n } else if (error) {\n toast(\n error?.message ?? translate('apiClient.requestAuthTab.failedToRefresh'),\n 'error',\n )\n }\n}\n\nconst openAcquisitionConfig = (bearerName: string): void => {\n configBearerName.value = bearerName\n configModal.show()\n}\n\n/** Closes the config modal and runs Authorize against the bearer scheme that opened it. */\nconst handleConfigAuthorize = (): void => {\n const bearerName = configBearerName.value\n configModal.hide()\n if (bearerName) {\n void handleAcquisitionAuthorize(bearerName)\n }\n}\n</script>\n<template>\n <template\n v-for=\"{ scheme, name, scopes, visibleFlowKeys } in security\"\n :key=\"name\">\n <!--\n Header row for AND'ed schemes: label (bold) and description (rich text) are\n combined.\n -->\n <DataTableRow v-if=\"hasMultipleSchemes && scheme\">\n <DataTableCell\n :aria-label=\"generateLabel(name, scheme)\"\n class=\"max-h-[auto]\">\n <div class=\"bg-b-1 min-w-0 flex-1 px-3 py-1.25\">\n <p class=\"text-c-1 leading-5.5 font-medium\">\n {{ generateLabel(name, scheme) }}\n </p>\n <ScalarMarkdownSummary\n v-if=\"scheme.description\"\n class=\"auth-description text-c-2 w-full\"\n :value=\"scheme.description\" />\n </div>\n </DataTableCell>\n </DataTableRow>\n\n <!-- Description: shown for single auth schemes with descriptions -->\n <DataTableRow v-if=\"scheme?.description && !hasMultipleSchemes\">\n <DataTableCell\n :aria-label=\"scheme.description\"\n class=\"max-h-[auto]\">\n <ScalarMarkdownSummary\n class=\"auth-description bg-b-1 text-c-2 min-w-0 flex-1 px-3 py-1.25\"\n :value=\"scheme.description\" />\n </DataTableCell>\n </DataTableRow>\n\n <!-- HTTP Authentication -->\n <template v-if=\"scheme?.type === 'http'\">\n <!-- Bearer Token -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer'\">\n <RequestAuthDataTableInput\n canReset\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n :placeholder=\"translate('apiClient.requestAuthTab.token')\"\n type=\"password\"\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-token',\n })\n \"\n @update:modelValue=\"\n (v) => handleHttpSecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.bearerToken') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- OAuth2 token-acquisition shortcut (shown when an interactive oauth2 flow exists) -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer' && oauth2Target\">\n <div class=\"flex h-8 items-center gap-2 border-t pl-3 text-base\">\n <span class=\"text-c-1 mr-auto\">{{\n translate('apiClient.requestAuthTab.getAToken')\n }}</span>\n <ScalarButton\n class=\"text-c-1 px-3 py-1\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n type=\"button\"\n variant=\"gradient\"\n @click=\"handleAcquisitionAuthorize(name)\">\n {{\n translate('apiClient.requestAuthTab.authorizeVia', {\n name: oauth2Target.name,\n })\n }}\n </ScalarButton>\n <ScalarButton\n v-if=\"\n scheme['x-scalar-secret-token'] &&\n oauth2Target.flowType === 'authorizationCode'\n \"\n class=\"px-3 py-1\"\n :disabled=\"acquisitionLoader.isLoading\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleAcquisitionRefresh(name)\">\n {{ translate('apiClient.requestAuthTab.refresh') }}\n </ScalarButton>\n <!-- Sized and inset like the password toggle in the row above so the two icons line up -->\n <ScalarIconButton\n class=\"mr-1.25 h-6 w-6 p-1.25\"\n :icon=\"ScalarIconGear\"\n :label=\"\n translate('apiClient.requestAuthTab.configure', {\n name: oauth2Target.name,\n })\n \"\n @click=\"openAcquisitionConfig(name)\" />\n </div>\n </DataTableRow>\n\n <!-- HTTP Basic Authentication -->\n <template v-else-if=\"scheme?.scheme === 'basic'\">\n <DataTableRow>\n <RequestAuthDataTableInput\n canReset\n class=\"text-c-2\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n required\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-username',\n })\n \"\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-username': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.username') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n canReset\n :environment\n :modelValue=\"scheme['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-password',\n })\n \"\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-password': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.password') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n </template>\n\n <!-- API Key Authentication -->\n <template v-else-if=\"scheme?.type === 'apiKey'\">\n <DataTableRow v-if=\"apiKeyHasName(scheme)\">\n <RequestAuthDataTableInput\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme.name ?? ''\"\n placeholder=\"api-key\"\n @update:modelValue=\"\n (v) => handleApiKeySecuritySchemeUpdate({ name: v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.name') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n canReset\n :containerClass=\"\n apiKeyHasName(scheme) ? undefined : getStaticBorderClass()\n \"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-token',\n })\n \"\n @update:modelValue=\"\n (v) =>\n handleApiKeySecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.value') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n\n <!-- OAuth 2.0 / OpenID Connect Authentication -->\n <template\n v-else-if=\"scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\">\n <OAuth2Metadata\n v-if=\"\n scheme.type === 'oauth2' && (!isStatic || scheme.oauth2MetadataUrl)\n \"\n :customFetch=\"options?.customFetch\"\n :environment\n :eventBus\n :name\n :proxyUrl\n :scheme />\n\n <!-- OpenID Connect -->\n <OpenIDConnect\n v-if=\"scheme?.type === 'openIdConnect' && !visibleFlowKeys.length\"\n :customFetch=\"options?.customFetch\"\n :environment\n :eventBus\n :getStaticBorderClass\n :name\n :proxyUrl\n :scheme />\n\n <!-- Flow selector tabs: shown when multiple visible flows are available -->\n <DataTableRow v-if=\"visibleFlowKeys.length > 1\">\n <div class=\"flex min-h-8 border-t text-base\">\n <div class=\"flex h-8 max-w-full gap-2.5 overflow-x-auto px-3\">\n <button\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\"\n :class=\"getFlowTabClasses(key, ind)\"\n type=\"button\"\n @click=\"setActiveFlow(key)\">\n <span class=\"relative z-10\">{{ key }}</span>\n </button>\n </div>\n </div>\n </DataTableRow>\n\n <!-- OAuth2 flow configuration -->\n <template\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\">\n <OAuth2\n v-if=\"scheme.flows && isFlowActive(key, ind)\"\n :environment\n :eventBus\n :flows=\"scheme.flows\"\n :name\n :options\n :proxyUrl\n :scheme\n :selectedScopes=\"scopes\"\n :server\n :type=\"key\"\n @delete:scope=\"(event) => handleScopeDelete(name, event)\"\n @update:selectedScopes=\"(event) => handleScopesUpdate(name, event)\"\n @upsert:scope=\"(event) => handleScopeUpsert(name, event)\" />\n </template>\n </template>\n\n <!-- Browser WebSocket connections cannot apply these broker credentials. -->\n <div\n v-else-if=\"\n scheme?.type === 'userPassword' ||\n scheme?.type === 'plain' ||\n scheme?.type === 'scramSha256' ||\n scheme?.type === 'scramSha512' ||\n scheme?.type === 'X509' ||\n scheme?.type === 'symmetricEncryption' ||\n scheme?.type === 'asymmetricEncryption' ||\n scheme?.type === 'gssapi'\n \"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{ translate('apiClient.requestAuthTab.unsupportedCredentials') }}\n </div>\n\n <!-- Mutual TLS credentials are chosen during the browser-managed TLS handshake. -->\n <div\n v-else-if=\"scheme?.type === 'mutualTLS'\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{ translate('apiClient.requestAuthTab.mutualTlsHint') }}\n </div>\n\n <!-- Scheme has a type we do not render inputs for -->\n <div\n v-else-if=\"getUnsupportedSchemeType(scheme)\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{\n translate('apiClient.requestAuthTab.unsupportedType', {\n type: getUnsupportedSchemeType(scheme) ?? '',\n })\n }}\n </div>\n\n <!-- Scheme is missing type -->\n <div\n v-else\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{\n translate('apiClient.requestAuthTab.missingType', {\n type: documentTypeLabel,\n })\n }}\n </div>\n </template>\n\n <!-- OAuth2 configuration modal (opened from the bearer scheme's gear) -->\n <ScalarModal\n v-if=\"oauth2Target && oauth2Scheme\"\n size=\"sm\"\n :state=\"configModal\"\n :title=\"\n translate('apiClient.requestAuthTab.configure', {\n name: oauth2Target.name,\n })\n \">\n <DataTable\n :columns=\"['']\"\n presentational>\n <OAuth2\n :environment\n :eventBus\n :flows=\"oauth2Target.flows\"\n hideActions\n :name=\"oauth2Target.name\"\n :options\n :proxyUrl\n :scheme=\"oauth2Scheme\"\n :selectedScopes=\"oauth2Target.scopes\"\n :server\n :type=\"oauth2Target.flowType\"\n @delete:scope=\"(event) => handleScopeDelete(oauth2Target!.name, event)\"\n @update:selectedScopes=\"\n (event) => handleScopesUpdate(oauth2Target!.name, event)\n \"\n @upsert:scope=\"\n (event) => handleScopeUpsert(oauth2Target!.name, event)\n \" />\n </DataTable>\n <div class=\"flex h-8 items-center justify-end gap-2 border-t\">\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"configModal.hide()\">\n {{ translate('apiClient.requestAuthTab.cancel') }}\n </ScalarButton>\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n @click=\"handleConfigAuthorize\">\n {{ translate('apiClient.requestAuthTab.authorize') }}\n </ScalarButton>\n </div>\n </ScalarModal>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"RequestAuthTab.vue.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarIconButton } from '@scalar/components/icon-button'\nimport { useLoadingState } from '@scalar/components/loading'\nimport { ScalarMarkdownSummary } from '@scalar/components/markdown'\nimport { ScalarModal, useModal } from '@scalar/components/modal'\nimport { ScalarIconGear } from '@scalar/icons'\nimport { useToasts } from '@scalar/use-toasts'\nimport type {\n SecretsApiKey,\n SecretsHttp,\n} from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { canResetSecretField } from '@scalar/workspace-store/helpers/auth-secret-fields'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport {\n getEnvironmentVariables,\n type MergedSecuritySchemes,\n type OAuthFlowsObjectSecret,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { getDocumentTypeLabel } from '@scalar/workspace-store/schemas/type-guards'\nimport type {\n ApiKeyObject,\n SecurityRequirementObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { capitalize, computed, ref } from 'vue'\n\nimport { refreshOauth2Token } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth'\nimport { getVisibleOrderedFlowKeys } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth-flows'\nimport {\n runOAuth2Authorize,\n storeOAuth2Tokens,\n} from '@/v2/blocks/scalar-auth-selector-block/helpers/run-oauth2-authorize'\nimport { getOauth2AcquisitionTarget } from '@/v2/blocks/scalar-auth-selector-block/helpers/security-scheme'\nimport {\n DataTable,\n DataTableCell,\n DataTableRow,\n} from '@/v2/components/data-table'\nimport { useLocalization } from '@/v2/features/localization'\n\nimport OAuth2, { type OAuth2Options } from './OAuth2.vue'\nimport OAuth2Metadata from './OAuth2Metadata.vue'\nimport OpenIDConnect from './OpenIDConnect.vue'\nimport RequestAuthDataTableInput from './RequestAuthDataTableInput.vue'\n\nconst {\n environment,\n isStatic,\n proxyUrl,\n selectedSecuritySchemas,\n securitySchemes,\n server,\n eventBus,\n options,\n documentType = 'openapi',\n} = defineProps<{\n /** Current environment configuration */\n environment: XScalarEnvironment\n /** Controls the display of certain borders which are used when we are non-collapsible */\n isStatic: boolean\n /** Proxy URL */\n proxyUrl: string\n /** Selected security schemes*/\n selectedSecuritySchemas: SecurityRequirementObject\n /** Merged security schemes from the document and the config together with the auth store secrets */\n securitySchemes: MergedSecuritySchemes\n /** Current server configuration */\n server: ServerObject | null\n /** Event bus for authentication updates */\n eventBus: WorkspaceEventBus\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n /** Type of the document the schemes belong to, used to label the missing-type warning */\n documentType?: 'openapi' | 'asyncapi'\n}>()\n\nconst emits = defineEmits<{\n (\n e: 'update:selectedScopes',\n payload: Omit<ApiReferenceEvents['auth:update:selected-scopes'], 'meta'>,\n ): void\n (e: 'upsert:scope', payload: ApiReferenceEvents['auth:upsert:scopes']): void\n (e: 'delete:scope', payload: ApiReferenceEvents['auth:delete:scopes']): void\n}>()\n\nconst { translate } = useLocalization()\n\ntype SecurityItem = {\n scheme: SecuritySchemeObjectSecret | undefined\n name: string\n scopes: string[]\n /** Ordered, non-hidden oauth2/openIdConnect flow keys for this scheme (empty for other types). */\n visibleFlowKeys: (keyof OAuthFlowsObjectSecret)[]\n}\n\n/**\n * Human-readable name of the document type.\n * Used in the missing-type warning so it points at the correct document\n * (e.g. \"AsyncAPI\") instead of always naming OpenAPI.\n */\nconst documentTypeLabel = computed<string>(() =>\n getDocumentTypeLabel(documentType),\n)\n\n/**\n * Resolves security schemes from the OpenAPI document and combines them with their selected scopes.\n * Each item includes the scheme definition, name, and associated scopes.\n */\nconst security = computed<SecurityItem[]>(() =>\n Object.entries(selectedSecuritySchemas).map(([name, scopes = []]) => {\n const scheme = getResolvedRef(securitySchemes[name])\n return {\n scheme,\n name,\n scopes,\n // Compute the visible, ordered flow keys once per scheme so the tabs, the label, and the\n // active-flow tracking all agree on the same set (and we do not filter + sort on every access).\n visibleFlowKeys:\n scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\n ? getVisibleOrderedFlowKeys(scheme.flows)\n : [],\n }\n }),\n)\n\n/** Tracks which OAuth2 flow is currently active when multiple flows are available. */\nconst activeFlow = ref<string>('')\n\n/**\n * Keeps the selected flow in sync with the currently visible flow keys. Validating against the\n * visible set (not every declared flow) means a selection that becomes hidden — e.g. the document\n * is updated to mark the active flow with `x-scalar-ignore` — resets, so the default (first visible)\n * flow activates instead of leaving no tab selected.\n */\nconst selectedFlow = computed<string>(() => {\n const visibleFlowKeys = security.value.flatMap((item) => item.visibleFlowKeys)\n\n return visibleFlowKeys.some((key) => key === activeFlow.value)\n ? activeFlow.value\n : ''\n})\n\nconst setActiveFlow = (flow: string): void => {\n activeFlow.value = flow\n}\n\n/** Determines if multiple auth schemes are configured, which affects the UI layout. */\nconst hasMultipleSchemes = computed<boolean>(() => security.value.length > 1)\n\n/**\n * Generates a human-readable label for the security scheme.\n * Intentionally omits the description here — it is rendered separately as\n * rich text via ScalarMarkdownSummary so markdown formatting is preserved.\n */\nconst generateLabel = (\n name: string,\n scheme: SecuritySchemeObjectSecret,\n): string => {\n const capitalizedName = capitalize(name)\n\n switch (scheme.type) {\n case 'apiKey':\n return `${capitalizedName}: ${scheme.in}`\n\n case 'openIdConnect':\n case 'oauth2': {\n const firstFlow = getVisibleOrderedFlowKeys(scheme.flows)[0]\n const currentFlow = selectedFlow.value || firstFlow\n if (!currentFlow) {\n return capitalizedName\n }\n return `${capitalizedName}: ${currentFlow}`\n }\n\n case 'http':\n return `${capitalizedName}: ${scheme.scheme}`\n\n default:\n return capitalizedName\n }\n}\n\n/**\n * Whether an API key scheme exposes an editable parameter name.\n *\n * OpenAPI `apiKey` and AsyncAPI `httpApiKey` (normalized to `apiKey`) name a query/header/cookie\n * parameter, so the Name input is shown. AsyncAPI `apiKey` places the key in the broker `user` or\n * `password` slot and has no parameter name, so the Name input is hidden and only the value is asked for.\n */\nconst apiKeyHasName = (scheme: { in?: string }): boolean =>\n scheme.in !== 'user' && scheme.in !== 'password'\n\n/**\n * The scheme's type when it is one we do not render inputs for (a type outside both the OpenAPI\n * and AsyncAPI security scheme unions). Read through a helper so the fallback template branch,\n * where the scheme type is narrowed to `never` after the supported cases, can still surface the type.\n */\nconst getUnsupportedSchemeType = (\n scheme: SecurityItem['scheme'],\n): string | undefined => scheme?.type\n\n/**\n * Determines if an OAuth2 flow tab should be active.\n * The first flow is active by default if no flow is explicitly selected.\n */\nconst isFlowActive = (flowKey: string, index: number): boolean =>\n selectedFlow.value === flowKey || (index === 0 && !selectedFlow.value)\n\n/** Computes the container class for static display mode. */\nconst getStaticBorderClass = (): string | false => isStatic && 'border-t'\n\nconst handleHttpSecretsUpdate = (\n payload: Omit<Partial<SecretsHttp>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'http', ...payload },\n name,\n })\n\nconst handleApiKeySecretsUpdate = (\n payload: Omit<Partial<SecretsApiKey>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\n/** Name edits may update the document or a configured override; tokens remain secrets. */\nconst handleApiKeySecuritySchemeUpdate = (\n payload: Omit<Partial<ApiKeyObject>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\n/** Handles scope selection updates for OAuth2 */\nconst handleScopesUpdate = (\n name: string,\n event: { scopes?: string[]; scope?: string; selected?: boolean },\n): void => {\n emits('update:selectedScopes', {\n id: Object.keys(selectedSecuritySchemas),\n name,\n ...event,\n })\n}\n\n/** Handles scope-definition upserts (add / rename / description change) */\nconst handleScopeUpsert = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:upsert:scopes'], 'name'>,\n): void => {\n emits('upsert:scope', { ...event, name })\n}\n\n/** Handles scope-definition deletes */\nconst handleScopeDelete = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:delete:scopes'], 'name'>,\n): void => {\n emits('delete:scope', { ...event, name })\n}\n\n/**\n * Computes dynamic classes for OAuth2 flow tabs based on active state.\n */\nconst getFlowTabClasses = (flowKey: string, index: number): string => {\n const baseClasses =\n 'floating-bg text-c-3 relative cursor-pointer border-b border-transparent py-1 text-base font-medium'\n const activeClasses = '!text-c-1 !rounded-none border-b !border-current'\n\n return isFlowActive(flowKey, index)\n ? `${baseClasses} ${activeClasses} ${isStatic ? 'opacity-100' : ''}`\n : baseClasses\n}\n\n/**\n * OAuth2 token-acquisition target (an oauth2 scheme with an interactive grant) sourced from\n * the merged schemes. When the active scheme is HTTP bearer, this powers the inline\n * \"Authorize via OAuth2\" shortcut: the flow's bearer token is written onto the bearer scheme,\n * so the panel never switches to oauth2.\n *\n * The shortcut is purely a convenience, so it is offered for any interactive oauth2 scheme —\n * including one that is also independently selectable in the dropdown (e.g. Scalar Galaxy's\n * `oAuth2`). Whether that oauth2 scheme is *hidden* from the dropdown is a separate decision made\n * in the selector; here we only surface the shortcut.\n */\nconst oauth2Target = computed(() => getOauth2AcquisitionTarget(securitySchemes))\n\n/** Resolved oauth2 scheme object, for embedding its config form behind the gear. */\nconst oauth2Scheme = computed(() =>\n oauth2Target.value\n ? getResolvedRef(securitySchemes[oauth2Target.value.name])\n : undefined,\n)\n\nconst acquisitionLoader = useLoadingState()\nconst { toast } = useToasts()\nconst configModal = useModal()\n/** Bearer scheme that opened the config modal, so its Authorize callback targets it. */\nconst configBearerName = ref<string | undefined>()\n\n/** Runs the OAuth2 flow and writes the resulting bearer token onto the bearer scheme. */\nconst handleAcquisitionAuthorize = async (\n bearerName: string,\n): Promise<void> => {\n const target = oauth2Target.value\n if (!target || acquisitionLoader.isLoading) {\n return\n }\n acquisitionLoader.start()\n const [error] = await runOAuth2Authorize({\n eventBus,\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flows: target.flows,\n flowType: target.flowType,\n scopes: target.scopes,\n server,\n proxyUrl,\n environment,\n options,\n })\n await acquisitionLoader.clear()\n if (error) {\n toast(\n error?.message ?? translate('apiClient.requestAuthTab.failedToauthorize'),\n 'error',\n )\n }\n}\n\n/** Refreshes the OAuth2 token and rewrites it onto the bearer scheme. */\nconst handleAcquisitionRefresh = async (bearerName: string): Promise<void> => {\n const target = oauth2Target.value\n // Only the authorization-code flow carries a refresh token; implicit can't be refreshed.\n if (target?.flowType !== 'authorizationCode' || acquisitionLoader.isLoading) {\n return\n }\n acquisitionLoader.start()\n const [error, tokens] = await refreshOauth2Token(\n target.flows,\n target.flowType,\n proxyUrl,\n server,\n getEnvironmentVariables(environment),\n options?.customFetch,\n )\n await acquisitionLoader.clear()\n if (tokens?.accessToken) {\n storeOAuth2Tokens(eventBus, {\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flowType: target.flowType,\n tokens,\n })\n } else if (error) {\n toast(\n error?.message ?? translate('apiClient.requestAuthTab.failedToRefresh'),\n 'error',\n )\n }\n}\n\nconst openAcquisitionConfig = (bearerName: string): void => {\n configBearerName.value = bearerName\n configModal.show()\n}\n\n/** Closes the config modal and runs Authorize against the bearer scheme that opened it. */\nconst handleConfigAuthorize = (): void => {\n const bearerName = configBearerName.value\n configModal.hide()\n if (bearerName) {\n void handleAcquisitionAuthorize(bearerName)\n }\n}\n</script>\n<template>\n <template\n v-for=\"{ scheme, name, scopes, visibleFlowKeys } in security\"\n :key=\"name\">\n <!--\n Header row for AND'ed schemes: label (bold) and description (rich text) are\n combined.\n -->\n <DataTableRow v-if=\"hasMultipleSchemes && scheme\">\n <DataTableCell\n :aria-label=\"generateLabel(name, scheme)\"\n class=\"max-h-[auto]\">\n <div class=\"bg-b-1 min-w-0 flex-1 px-3 py-1.25\">\n <p class=\"text-c-1 leading-5.5 font-medium\">\n {{ generateLabel(name, scheme) }}\n </p>\n <ScalarMarkdownSummary\n v-if=\"scheme.description\"\n class=\"auth-description text-c-2 w-full\"\n :value=\"scheme.description\" />\n </div>\n </DataTableCell>\n </DataTableRow>\n\n <!-- Description: shown for single auth schemes with descriptions -->\n <DataTableRow v-if=\"scheme?.description && !hasMultipleSchemes\">\n <DataTableCell\n :aria-label=\"scheme.description\"\n class=\"max-h-[auto]\">\n <ScalarMarkdownSummary\n class=\"auth-description bg-b-1 text-c-2 min-w-0 flex-1 px-3 py-1.25\"\n :value=\"scheme.description\" />\n </DataTableCell>\n </DataTableRow>\n\n <!-- HTTP Authentication -->\n <template v-if=\"scheme?.type === 'http'\">\n <!-- Bearer Token -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer'\">\n <RequestAuthDataTableInput\n :canReset=\"\n canResetSecretField(\n scheme,\n 'x-scalar-secret-token',\n scheme['x-scalar-secret-token'],\n )\n \"\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n :placeholder=\"translate('apiClient.requestAuthTab.token')\"\n type=\"password\"\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-token',\n })\n \"\n @update:modelValue=\"\n (v) => handleHttpSecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.bearerToken') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- OAuth2 token-acquisition shortcut (shown when an interactive oauth2 flow exists) -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer' && oauth2Target\">\n <!--\n Authorize stays rightmost so it never moves: Refresh only appears once there is a token,\n and it slots in between the gear and Authorize instead of pushing Authorize aside.\n -->\n <div class=\"flex h-8 items-center gap-2 border-t pr-1 pl-3 text-base\">\n <span class=\"text-c-1 mr-auto\">{{\n translate('apiClient.requestAuthTab.getAToken')\n }}</span>\n <ScalarIconButton\n class=\"h-6 w-6 p-1.25\"\n :icon=\"ScalarIconGear\"\n :label=\"\n translate('apiClient.requestAuthTab.configure', {\n name: oauth2Target.name,\n })\n \"\n @click=\"openAcquisitionConfig(name)\" />\n <ScalarButton\n v-if=\"\n scheme['x-scalar-secret-token'] &&\n oauth2Target.flowType === 'authorizationCode'\n \"\n class=\"px-3 py-1\"\n :disabled=\"acquisitionLoader.isLoading\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleAcquisitionRefresh(name)\">\n {{ translate('apiClient.requestAuthTab.refresh') }}\n </ScalarButton>\n <ScalarButton\n class=\"text-c-1 px-3 py-1\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n type=\"button\"\n variant=\"gradient\"\n @click=\"handleAcquisitionAuthorize(name)\">\n {{\n translate('apiClient.requestAuthTab.authorizeVia', {\n name: oauth2Target.name,\n })\n }}\n </ScalarButton>\n </div>\n </DataTableRow>\n\n <!-- HTTP Basic Authentication -->\n <template v-else-if=\"scheme?.scheme === 'basic'\">\n <DataTableRow>\n <RequestAuthDataTableInput\n :canReset=\"\n canResetSecretField(\n scheme,\n 'x-scalar-secret-username',\n scheme['x-scalar-secret-username'],\n )\n \"\n class=\"text-c-2\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n required\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-username',\n })\n \"\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-username': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.username') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n :canReset=\"\n canResetSecretField(\n scheme,\n 'x-scalar-secret-password',\n scheme['x-scalar-secret-password'],\n )\n \"\n :environment\n :modelValue=\"scheme['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-password',\n })\n \"\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-password': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.password') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n </template>\n\n <!-- API Key Authentication -->\n <template v-else-if=\"scheme?.type === 'apiKey'\">\n <DataTableRow v-if=\"apiKeyHasName(scheme)\">\n <RequestAuthDataTableInput\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme.name ?? ''\"\n placeholder=\"api-key\"\n @update:modelValue=\"\n (v) => handleApiKeySecuritySchemeUpdate({ name: v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.name') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n :canReset=\"\n canResetSecretField(\n scheme,\n 'x-scalar-secret-token',\n scheme['x-scalar-secret-token'],\n )\n \"\n :containerClass=\"\n apiKeyHasName(scheme) ? undefined : getStaticBorderClass()\n \"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-token',\n })\n \"\n @update:modelValue=\"\n (v) =>\n handleApiKeySecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.value') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n\n <!-- OAuth 2.0 / OpenID Connect Authentication -->\n <template\n v-else-if=\"scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\">\n <OAuth2Metadata\n v-if=\"\n scheme.type === 'oauth2' && (!isStatic || scheme.oauth2MetadataUrl)\n \"\n :customFetch=\"options?.customFetch\"\n :environment\n :eventBus\n :name\n :proxyUrl\n :scheme />\n\n <!-- OpenID Connect -->\n <OpenIDConnect\n v-if=\"scheme?.type === 'openIdConnect' && !visibleFlowKeys.length\"\n :customFetch=\"options?.customFetch\"\n :environment\n :eventBus\n :getStaticBorderClass\n :name\n :proxyUrl\n :scheme />\n\n <!-- Flow selector tabs: shown when multiple visible flows are available -->\n <DataTableRow v-if=\"visibleFlowKeys.length > 1\">\n <div class=\"flex min-h-8 border-t text-base\">\n <div class=\"flex h-8 max-w-full gap-2.5 overflow-x-auto px-3\">\n <button\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\"\n :class=\"getFlowTabClasses(key, ind)\"\n type=\"button\"\n @click=\"setActiveFlow(key)\">\n <span class=\"relative z-10\">{{ key }}</span>\n </button>\n </div>\n </div>\n </DataTableRow>\n\n <!-- OAuth2 flow configuration -->\n <template\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\">\n <OAuth2\n v-if=\"scheme.flows && isFlowActive(key, ind)\"\n :environment\n :eventBus\n :flows=\"scheme.flows\"\n :name\n :options\n :proxyUrl\n :scheme\n :selectedScopes=\"scopes\"\n :server\n :type=\"key\"\n @delete:scope=\"(event) => handleScopeDelete(name, event)\"\n @update:selectedScopes=\"(event) => handleScopesUpdate(name, event)\"\n @upsert:scope=\"(event) => handleScopeUpsert(name, event)\" />\n </template>\n </template>\n\n <!-- Browser WebSocket connections cannot apply these broker credentials. -->\n <div\n v-else-if=\"\n scheme?.type === 'userPassword' ||\n scheme?.type === 'plain' ||\n scheme?.type === 'scramSha256' ||\n scheme?.type === 'scramSha512' ||\n scheme?.type === 'X509' ||\n scheme?.type === 'symmetricEncryption' ||\n scheme?.type === 'asymmetricEncryption' ||\n scheme?.type === 'gssapi'\n \"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{ translate('apiClient.requestAuthTab.unsupportedCredentials') }}\n </div>\n\n <!-- Mutual TLS credentials are chosen during the browser-managed TLS handshake. -->\n <div\n v-else-if=\"scheme?.type === 'mutualTLS'\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{ translate('apiClient.requestAuthTab.mutualTlsHint') }}\n </div>\n\n <!-- Scheme has a type we do not render inputs for -->\n <div\n v-else-if=\"getUnsupportedSchemeType(scheme)\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{\n translate('apiClient.requestAuthTab.unsupportedType', {\n type: getUnsupportedSchemeType(scheme) ?? '',\n })\n }}\n </div>\n\n <!-- Scheme is missing type -->\n <div\n v-else\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{\n translate('apiClient.requestAuthTab.missingType', {\n type: documentTypeLabel,\n })\n }}\n </div>\n </template>\n\n <!-- OAuth2 configuration modal (opened from the bearer scheme's gear) -->\n <ScalarModal\n v-if=\"oauth2Target && oauth2Scheme\"\n size=\"sm\"\n :state=\"configModal\"\n :title=\"\n translate('apiClient.requestAuthTab.configure', {\n name: oauth2Target.name,\n })\n \">\n <DataTable\n :columns=\"['']\"\n presentational>\n <OAuth2\n :environment\n :eventBus\n :flows=\"oauth2Target.flows\"\n hideActions\n :name=\"oauth2Target.name\"\n :options\n :proxyUrl\n :scheme=\"oauth2Scheme\"\n :selectedScopes=\"oauth2Target.scopes\"\n :server\n :type=\"oauth2Target.flowType\"\n @delete:scope=\"(event) => handleScopeDelete(oauth2Target!.name, event)\"\n @update:selectedScopes=\"\n (event) => handleScopesUpdate(oauth2Target!.name, event)\n \"\n @upsert:scope=\"\n (event) => handleScopeUpsert(oauth2Target!.name, event)\n \" />\n </DataTable>\n <div class=\"flex h-8 items-center justify-end gap-2 border-t\">\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"configModal.hide()\">\n {{ translate('apiClient.requestAuthTab.cancel') }}\n </ScalarButton>\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n @click=\"handleConfigAuthorize\">\n {{ translate('apiClient.requestAuthTab.authorize') }}\n </ScalarButton>\n </div>\n </ScalarModal>\n</template>\n"],"mappings":""}
@@ -20,11 +20,12 @@ import { useToasts } from "@scalar/use-toasts";
20
20
  import { getResolvedRef } from "@scalar/workspace-store/helpers/get-resolved-ref";
21
21
  import { ScalarMarkdownSummary } from "@scalar/components/markdown";
22
22
  import { useLoadingState } from "@scalar/components/loading";
23
+ import { canResetSecretField } from "@scalar/workspace-store/helpers/auth-secret-fields";
23
24
  import { getDocumentTypeLabel } from "@scalar/workspace-store/schemas/type-guards";
24
25
  //#region src/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue?vue&type=script&setup=true&lang.ts
25
26
  var _hoisted_1 = { class: "bg-b-1 min-w-0 flex-1 px-3 py-1.25" };
26
27
  var _hoisted_2 = { class: "text-c-1 leading-5.5 font-medium" };
27
- var _hoisted_3 = { class: "flex h-8 items-center gap-2 border-t pl-3 text-base" };
28
+ var _hoisted_3 = { class: "flex h-8 items-center gap-2 border-t pr-1 pl-3 text-base" };
28
29
  var _hoisted_4 = { class: "text-c-1 mr-auto" };
29
30
  var _hoisted_5 = { class: "flex min-h-8 border-t text-base" };
30
31
  var _hoisted_6 = { class: "flex h-8 max-w-full gap-2.5 overflow-x-auto px-3" };
@@ -158,6 +159,7 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
158
159
  },
159
160
  name
160
161
  });
162
+ /** Name edits may update the document or a configured override; tokens remain secrets. */
161
163
  const handleApiKeySecuritySchemeUpdate = (payload, name) => __props.eventBus.emit("auth:update:security-scheme", {
162
164
  payload: {
163
165
  type: "apiKey",
@@ -236,7 +238,7 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
236
238
  /** Refreshes the OAuth2 token and rewrites it onto the bearer scheme. */
237
239
  const handleAcquisitionRefresh = async (bearerName) => {
238
240
  const target = oauth2Target.value;
239
- if (!target || target.flowType !== "authorizationCode" || acquisitionLoader.isLoading) return;
241
+ if (target?.flowType !== "authorizationCode" || acquisitionLoader.isLoading) return;
240
242
  acquisitionLoader.start();
241
243
  const [error, tokens] = await refreshOauth2Token(target.flows, target.flowType, __props.proxyUrl, __props.server, getEnvironmentVariables(__props.environment), __props.options?.customFetch);
242
244
  await acquisitionLoader.clear();
@@ -290,7 +292,7 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
290
292
  }, 1024)) : createCommentVNode("", true),
291
293
  scheme?.type === "http" ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [scheme.scheme === "bearer" ? (openBlock(), createBlock(unref(DataTableRow_default), { key: 0 }, {
292
294
  default: withCtx(() => [createVNode(RequestAuthDataTableInput_default, {
293
- canReset: "",
295
+ canReset: unref(canResetSecretField)(scheme, "x-scalar-secret-token", scheme["x-scalar-secret-token"]),
294
296
  containerClass: getStaticBorderClass(),
295
297
  environment: __props.environment,
296
298
  modelValue: scheme["x-scalar-secret-token"],
@@ -305,6 +307,7 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
305
307
  default: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.requestAuthTab.bearerToken")), 1)]),
306
308
  _: 1
307
309
  }, 8, [
310
+ "canReset",
308
311
  "containerClass",
309
312
  "environment",
310
313
  "modelValue",
@@ -316,17 +319,16 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
316
319
  }, 1024)) : createCommentVNode("", true), scheme.scheme === "bearer" && oauth2Target.value ? (openBlock(), createBlock(unref(DataTableRow_default), { key: 1 }, {
317
320
  default: withCtx(() => [createElementVNode("div", _hoisted_3, [
318
321
  createElementVNode("span", _hoisted_4, toDisplayString(unref(translate)("apiClient.requestAuthTab.getAToken")), 1),
319
- createVNode(unref(ScalarButton), {
320
- class: "text-c-1 px-3 py-1",
321
- loader: unref(acquisitionLoader),
322
- size: "sm",
323
- type: "button",
324
- variant: "gradient",
325
- onClick: ($event) => handleAcquisitionAuthorize(name)
326
- }, {
327
- default: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.requestAuthTab.authorizeVia", { name: oauth2Target.value.name })), 1)]),
328
- _: 2
329
- }, 1032, ["loader", "onClick"]),
322
+ createVNode(unref(ScalarIconButton), {
323
+ class: "h-6 w-6 p-1.25",
324
+ icon: unref(ScalarIconGear),
325
+ label: unref(translate)("apiClient.requestAuthTab.configure", { name: oauth2Target.value.name }),
326
+ onClick: ($event) => openAcquisitionConfig(name)
327
+ }, null, 8, [
328
+ "icon",
329
+ "label",
330
+ "onClick"
331
+ ]),
330
332
  scheme["x-scalar-secret-token"] && oauth2Target.value.flowType === "authorizationCode" ? (openBlock(), createBlock(unref(ScalarButton), {
331
333
  key: 0,
332
334
  class: "px-3 py-1",
@@ -339,21 +341,22 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
339
341
  default: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.requestAuthTab.refresh")), 1)]),
340
342
  _: 1
341
343
  }, 8, ["disabled", "onClick"])) : createCommentVNode("", true),
342
- createVNode(unref(ScalarIconButton), {
343
- class: "mr-1.25 h-6 w-6 p-1.25",
344
- icon: unref(ScalarIconGear),
345
- label: unref(translate)("apiClient.requestAuthTab.configure", { name: oauth2Target.value.name }),
346
- onClick: ($event) => openAcquisitionConfig(name)
347
- }, null, 8, [
348
- "icon",
349
- "label",
350
- "onClick"
351
- ])
344
+ createVNode(unref(ScalarButton), {
345
+ class: "text-c-1 px-3 py-1",
346
+ loader: unref(acquisitionLoader),
347
+ size: "sm",
348
+ type: "button",
349
+ variant: "gradient",
350
+ onClick: ($event) => handleAcquisitionAuthorize(name)
351
+ }, {
352
+ default: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.requestAuthTab.authorizeVia", { name: oauth2Target.value.name })), 1)]),
353
+ _: 2
354
+ }, 1032, ["loader", "onClick"])
352
355
  ])]),
353
356
  _: 2
354
357
  }, 1024)) : scheme?.scheme === "basic" ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createVNode(unref(DataTableRow_default), null, {
355
358
  default: withCtx(() => [createVNode(RequestAuthDataTableInput_default, {
356
- canReset: "",
359
+ canReset: unref(canResetSecretField)(scheme, "x-scalar-secret-username", scheme["x-scalar-secret-username"]),
357
360
  class: "text-c-2",
358
361
  environment: __props.environment,
359
362
  modelValue: scheme["x-scalar-secret-username"],
@@ -368,6 +371,7 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
368
371
  default: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.requestAuthTab.username")), 1)]),
369
372
  _: 1
370
373
  }, 8, [
374
+ "canReset",
371
375
  "environment",
372
376
  "modelValue",
373
377
  "onReset",
@@ -376,7 +380,7 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
376
380
  _: 2
377
381
  }, 1024), createVNode(unref(DataTableRow_default), null, {
378
382
  default: withCtx(() => [createVNode(RequestAuthDataTableInput_default, {
379
- canReset: "",
383
+ canReset: unref(canResetSecretField)(scheme, "x-scalar-secret-password", scheme["x-scalar-secret-password"]),
380
384
  environment: __props.environment,
381
385
  modelValue: scheme["x-scalar-secret-password"],
382
386
  placeholder: "********",
@@ -390,6 +394,7 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
390
394
  default: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.requestAuthTab.password")), 1)]),
391
395
  _: 1
392
396
  }, 8, [
397
+ "canReset",
393
398
  "environment",
394
399
  "modelValue",
395
400
  "onReset",
@@ -415,7 +420,7 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
415
420
  _: 2
416
421
  }, 1024)) : createCommentVNode("", true), createVNode(unref(DataTableRow_default), null, {
417
422
  default: withCtx(() => [createVNode(RequestAuthDataTableInput_default, {
418
- canReset: "",
423
+ canReset: unref(canResetSecretField)(scheme, "x-scalar-secret-token", scheme["x-scalar-secret-token"]),
419
424
  containerClass: apiKeyHasName(scheme) ? void 0 : getStaticBorderClass(),
420
425
  environment: __props.environment,
421
426
  modelValue: scheme["x-scalar-secret-token"],
@@ -430,6 +435,7 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
430
435
  default: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.requestAuthTab.value")), 1)]),
431
436
  _: 1
432
437
  }, 8, [
438
+ "canReset",
433
439
  "containerClass",
434
440
  "environment",
435
441
  "modelValue",
@@ -1 +1 @@
1
- {"version":3,"file":"RequestAuthTab.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarIconButton } from '@scalar/components/icon-button'\nimport { useLoadingState } from '@scalar/components/loading'\nimport { ScalarMarkdownSummary } from '@scalar/components/markdown'\nimport { ScalarModal, useModal } from '@scalar/components/modal'\nimport { ScalarIconGear } from '@scalar/icons'\nimport { useToasts } from '@scalar/use-toasts'\nimport type {\n SecretsApiKey,\n SecretsHttp,\n} from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport {\n getEnvironmentVariables,\n type MergedSecuritySchemes,\n type OAuthFlowsObjectSecret,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { getDocumentTypeLabel } from '@scalar/workspace-store/schemas/type-guards'\nimport type {\n ApiKeyObject,\n SecurityRequirementObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { capitalize, computed, ref } from 'vue'\n\nimport { refreshOauth2Token } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth'\nimport { getVisibleOrderedFlowKeys } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth-flows'\nimport {\n runOAuth2Authorize,\n storeOAuth2Tokens,\n} from '@/v2/blocks/scalar-auth-selector-block/helpers/run-oauth2-authorize'\nimport { getOauth2AcquisitionTarget } from '@/v2/blocks/scalar-auth-selector-block/helpers/security-scheme'\nimport {\n DataTable,\n DataTableCell,\n DataTableRow,\n} from '@/v2/components/data-table'\nimport { useLocalization } from '@/v2/features/localization'\n\nimport OAuth2, { type OAuth2Options } from './OAuth2.vue'\nimport OAuth2Metadata from './OAuth2Metadata.vue'\nimport OpenIDConnect from './OpenIDConnect.vue'\nimport RequestAuthDataTableInput from './RequestAuthDataTableInput.vue'\n\nconst {\n environment,\n isStatic,\n proxyUrl,\n selectedSecuritySchemas,\n securitySchemes,\n server,\n eventBus,\n options,\n documentType = 'openapi',\n} = defineProps<{\n /** Current environment configuration */\n environment: XScalarEnvironment\n /** Controls the display of certain borders which are used when we are non-collapsible */\n isStatic: boolean\n /** Proxy URL */\n proxyUrl: string\n /** Selected security schemes*/\n selectedSecuritySchemas: SecurityRequirementObject\n /** Merged security schemes from the document and the config together with the auth store secrets */\n securitySchemes: MergedSecuritySchemes\n /** Current server configuration */\n server: ServerObject | null\n /** Event bus for authentication updates */\n eventBus: WorkspaceEventBus\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n /** Type of the document the schemes belong to, used to label the missing-type warning */\n documentType?: 'openapi' | 'asyncapi'\n}>()\n\nconst emits = defineEmits<{\n (\n e: 'update:selectedScopes',\n payload: Omit<ApiReferenceEvents['auth:update:selected-scopes'], 'meta'>,\n ): void\n (e: 'upsert:scope', payload: ApiReferenceEvents['auth:upsert:scopes']): void\n (e: 'delete:scope', payload: ApiReferenceEvents['auth:delete:scopes']): void\n}>()\n\nconst { translate } = useLocalization()\n\ntype SecurityItem = {\n scheme: SecuritySchemeObjectSecret | undefined\n name: string\n scopes: string[]\n /** Ordered, non-hidden oauth2/openIdConnect flow keys for this scheme (empty for other types). */\n visibleFlowKeys: (keyof OAuthFlowsObjectSecret)[]\n}\n\n/**\n * Human-readable name of the document type.\n * Used in the missing-type warning so it points at the correct document\n * (e.g. \"AsyncAPI\") instead of always naming OpenAPI.\n */\nconst documentTypeLabel = computed<string>(() =>\n getDocumentTypeLabel(documentType),\n)\n\n/**\n * Resolves security schemes from the OpenAPI document and combines them with their selected scopes.\n * Each item includes the scheme definition, name, and associated scopes.\n */\nconst security = computed<SecurityItem[]>(() =>\n Object.entries(selectedSecuritySchemas).map(([name, scopes = []]) => {\n const scheme = getResolvedRef(securitySchemes[name])\n return {\n scheme,\n name,\n scopes,\n // Compute the visible, ordered flow keys once per scheme so the tabs, the label, and the\n // active-flow tracking all agree on the same set (and we do not filter + sort on every access).\n visibleFlowKeys:\n scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\n ? getVisibleOrderedFlowKeys(scheme.flows)\n : [],\n }\n }),\n)\n\n/** Tracks which OAuth2 flow is currently active when multiple flows are available. */\nconst activeFlow = ref<string>('')\n\n/**\n * Keeps the selected flow in sync with the currently visible flow keys. Validating against the\n * visible set (not every declared flow) means a selection that becomes hidden — e.g. the document\n * is updated to mark the active flow with `x-scalar-ignore` — resets, so the default (first visible)\n * flow activates instead of leaving no tab selected.\n */\nconst selectedFlow = computed<string>(() => {\n const visibleFlowKeys = security.value.flatMap((item) => item.visibleFlowKeys)\n\n return visibleFlowKeys.some((key) => key === activeFlow.value)\n ? activeFlow.value\n : ''\n})\n\nconst setActiveFlow = (flow: string): void => {\n activeFlow.value = flow\n}\n\n/** Determines if multiple auth schemes are configured, which affects the UI layout. */\nconst hasMultipleSchemes = computed<boolean>(() => security.value.length > 1)\n\n/**\n * Generates a human-readable label for the security scheme.\n * Intentionally omits the description here — it is rendered separately as\n * rich text via ScalarMarkdownSummary so markdown formatting is preserved.\n */\nconst generateLabel = (\n name: string,\n scheme: SecuritySchemeObjectSecret,\n): string => {\n const capitalizedName = capitalize(name)\n\n switch (scheme.type) {\n case 'apiKey':\n return `${capitalizedName}: ${scheme.in}`\n\n case 'openIdConnect':\n case 'oauth2': {\n const firstFlow = getVisibleOrderedFlowKeys(scheme.flows)[0]\n const currentFlow = selectedFlow.value || firstFlow\n if (!currentFlow) {\n return capitalizedName\n }\n return `${capitalizedName}: ${currentFlow}`\n }\n\n case 'http':\n return `${capitalizedName}: ${scheme.scheme}`\n\n default:\n return capitalizedName\n }\n}\n\n/**\n * Whether an API key scheme exposes an editable parameter name.\n *\n * OpenAPI `apiKey` and AsyncAPI `httpApiKey` (normalized to `apiKey`) name a query/header/cookie\n * parameter, so the Name input is shown. AsyncAPI `apiKey` places the key in the broker `user` or\n * `password` slot and has no parameter name, so the Name input is hidden and only the value is asked for.\n */\nconst apiKeyHasName = (scheme: { in?: string }): boolean =>\n scheme.in !== 'user' && scheme.in !== 'password'\n\n/**\n * The scheme's type when it is one we do not render inputs for (a type outside both the OpenAPI\n * and AsyncAPI security scheme unions). Read through a helper so the fallback template branch,\n * where the scheme type is narrowed to `never` after the supported cases, can still surface the type.\n */\nconst getUnsupportedSchemeType = (\n scheme: SecurityItem['scheme'],\n): string | undefined => scheme?.type\n\n/**\n * Determines if an OAuth2 flow tab should be active.\n * The first flow is active by default if no flow is explicitly selected.\n */\nconst isFlowActive = (flowKey: string, index: number): boolean =>\n selectedFlow.value === flowKey || (index === 0 && !selectedFlow.value)\n\n/** Computes the container class for static display mode. */\nconst getStaticBorderClass = (): string | false => isStatic && 'border-t'\n\nconst handleHttpSecretsUpdate = (\n payload: Omit<Partial<SecretsHttp>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'http', ...payload },\n name,\n })\n\nconst handleApiKeySecretsUpdate = (\n payload: Omit<Partial<SecretsApiKey>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\nconst handleApiKeySecuritySchemeUpdate = (\n payload: Omit<Partial<ApiKeyObject>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\n/** Handles scope selection updates for OAuth2 */\nconst handleScopesUpdate = (\n name: string,\n event: { scopes?: string[]; scope?: string; selected?: boolean },\n): void => {\n emits('update:selectedScopes', {\n id: Object.keys(selectedSecuritySchemas),\n name,\n ...event,\n })\n}\n\n/** Handles scope-definition upserts (add / rename / description change) */\nconst handleScopeUpsert = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:upsert:scopes'], 'name'>,\n): void => {\n emits('upsert:scope', { ...event, name })\n}\n\n/** Handles scope-definition deletes */\nconst handleScopeDelete = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:delete:scopes'], 'name'>,\n): void => {\n emits('delete:scope', { ...event, name })\n}\n\n/**\n * Computes dynamic classes for OAuth2 flow tabs based on active state.\n */\nconst getFlowTabClasses = (flowKey: string, index: number): string => {\n const baseClasses =\n 'floating-bg text-c-3 relative cursor-pointer border-b border-transparent py-1 text-base font-medium'\n const activeClasses = '!text-c-1 !rounded-none border-b !border-current'\n\n return isFlowActive(flowKey, index)\n ? `${baseClasses} ${activeClasses} ${isStatic ? 'opacity-100' : ''}`\n : baseClasses\n}\n\n/**\n * OAuth2 token-acquisition target (an oauth2 scheme with an interactive grant) sourced from\n * the merged schemes. When the active scheme is HTTP bearer, this powers the inline\n * \"Authorize via OAuth2\" shortcut: the flow's bearer token is written onto the bearer scheme,\n * so the panel never switches to oauth2.\n *\n * The shortcut is purely a convenience, so it is offered for any interactive oauth2 scheme —\n * including one that is also independently selectable in the dropdown (e.g. Scalar Galaxy's\n * `oAuth2`). Whether that oauth2 scheme is *hidden* from the dropdown is a separate decision made\n * in the selector; here we only surface the shortcut.\n */\nconst oauth2Target = computed(() => getOauth2AcquisitionTarget(securitySchemes))\n\n/** Resolved oauth2 scheme object, for embedding its config form behind the gear. */\nconst oauth2Scheme = computed(() =>\n oauth2Target.value\n ? getResolvedRef(securitySchemes[oauth2Target.value.name])\n : undefined,\n)\n\nconst acquisitionLoader = useLoadingState()\nconst { toast } = useToasts()\nconst configModal = useModal()\n/** Bearer scheme that opened the config modal, so its Authorize callback targets it. */\nconst configBearerName = ref<string | undefined>()\n\n/** Runs the OAuth2 flow and writes the resulting bearer token onto the bearer scheme. */\nconst handleAcquisitionAuthorize = async (\n bearerName: string,\n): Promise<void> => {\n const target = oauth2Target.value\n if (!target || acquisitionLoader.isLoading) {\n return\n }\n acquisitionLoader.start()\n const [error] = await runOAuth2Authorize({\n eventBus,\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flows: target.flows,\n flowType: target.flowType,\n scopes: target.scopes,\n server,\n proxyUrl,\n environment,\n options,\n })\n await acquisitionLoader.clear()\n if (error) {\n toast(\n error?.message ?? translate('apiClient.requestAuthTab.failedToauthorize'),\n 'error',\n )\n }\n}\n\n/** Refreshes the OAuth2 token and rewrites it onto the bearer scheme. */\nconst handleAcquisitionRefresh = async (bearerName: string): Promise<void> => {\n const target = oauth2Target.value\n // Only the authorization-code flow carries a refresh token; implicit can't be refreshed.\n if (\n !target ||\n target.flowType !== 'authorizationCode' ||\n acquisitionLoader.isLoading\n ) {\n return\n }\n acquisitionLoader.start()\n const [error, tokens] = await refreshOauth2Token(\n target.flows,\n target.flowType,\n proxyUrl,\n server,\n getEnvironmentVariables(environment),\n options?.customFetch,\n )\n await acquisitionLoader.clear()\n if (tokens?.accessToken) {\n storeOAuth2Tokens(eventBus, {\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flowType: target.flowType,\n tokens,\n })\n } else if (error) {\n toast(\n error?.message ?? translate('apiClient.requestAuthTab.failedToRefresh'),\n 'error',\n )\n }\n}\n\nconst openAcquisitionConfig = (bearerName: string): void => {\n configBearerName.value = bearerName\n configModal.show()\n}\n\n/** Closes the config modal and runs Authorize against the bearer scheme that opened it. */\nconst handleConfigAuthorize = (): void => {\n const bearerName = configBearerName.value\n configModal.hide()\n if (bearerName) {\n void handleAcquisitionAuthorize(bearerName)\n }\n}\n</script>\n<template>\n <template\n v-for=\"{ scheme, name, scopes, visibleFlowKeys } in security\"\n :key=\"name\">\n <!--\n Header row for AND'ed schemes: label (bold) and description (rich text) are\n combined.\n -->\n <DataTableRow v-if=\"hasMultipleSchemes && scheme\">\n <DataTableCell\n :aria-label=\"generateLabel(name, scheme)\"\n class=\"max-h-[auto]\">\n <div class=\"bg-b-1 min-w-0 flex-1 px-3 py-1.25\">\n <p class=\"text-c-1 leading-5.5 font-medium\">\n {{ generateLabel(name, scheme) }}\n </p>\n <ScalarMarkdownSummary\n v-if=\"scheme.description\"\n class=\"auth-description text-c-2 w-full\"\n :value=\"scheme.description\" />\n </div>\n </DataTableCell>\n </DataTableRow>\n\n <!-- Description: shown for single auth schemes with descriptions -->\n <DataTableRow v-if=\"scheme?.description && !hasMultipleSchemes\">\n <DataTableCell\n :aria-label=\"scheme.description\"\n class=\"max-h-[auto]\">\n <ScalarMarkdownSummary\n class=\"auth-description bg-b-1 text-c-2 min-w-0 flex-1 px-3 py-1.25\"\n :value=\"scheme.description\" />\n </DataTableCell>\n </DataTableRow>\n\n <!-- HTTP Authentication -->\n <template v-if=\"scheme?.type === 'http'\">\n <!-- Bearer Token -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer'\">\n <RequestAuthDataTableInput\n canReset\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n :placeholder=\"translate('apiClient.requestAuthTab.token')\"\n type=\"password\"\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-token',\n })\n \"\n @update:modelValue=\"\n (v) => handleHttpSecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.bearerToken') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- OAuth2 token-acquisition shortcut (shown when an interactive oauth2 flow exists) -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer' && oauth2Target\">\n <div class=\"flex h-8 items-center gap-2 border-t pl-3 text-base\">\n <span class=\"text-c-1 mr-auto\">{{\n translate('apiClient.requestAuthTab.getAToken')\n }}</span>\n <ScalarButton\n class=\"text-c-1 px-3 py-1\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n type=\"button\"\n variant=\"gradient\"\n @click=\"handleAcquisitionAuthorize(name)\">\n {{\n translate('apiClient.requestAuthTab.authorizeVia', {\n name: oauth2Target.name,\n })\n }}\n </ScalarButton>\n <ScalarButton\n v-if=\"\n scheme['x-scalar-secret-token'] &&\n oauth2Target.flowType === 'authorizationCode'\n \"\n class=\"px-3 py-1\"\n :disabled=\"acquisitionLoader.isLoading\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleAcquisitionRefresh(name)\">\n {{ translate('apiClient.requestAuthTab.refresh') }}\n </ScalarButton>\n <!-- Sized and inset like the password toggle in the row above so the two icons line up -->\n <ScalarIconButton\n class=\"mr-1.25 h-6 w-6 p-1.25\"\n :icon=\"ScalarIconGear\"\n :label=\"\n translate('apiClient.requestAuthTab.configure', {\n name: oauth2Target.name,\n })\n \"\n @click=\"openAcquisitionConfig(name)\" />\n </div>\n </DataTableRow>\n\n <!-- HTTP Basic Authentication -->\n <template v-else-if=\"scheme?.scheme === 'basic'\">\n <DataTableRow>\n <RequestAuthDataTableInput\n canReset\n class=\"text-c-2\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n required\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-username',\n })\n \"\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-username': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.username') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n canReset\n :environment\n :modelValue=\"scheme['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-password',\n })\n \"\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-password': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.password') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n </template>\n\n <!-- API Key Authentication -->\n <template v-else-if=\"scheme?.type === 'apiKey'\">\n <DataTableRow v-if=\"apiKeyHasName(scheme)\">\n <RequestAuthDataTableInput\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme.name ?? ''\"\n placeholder=\"api-key\"\n @update:modelValue=\"\n (v) => handleApiKeySecuritySchemeUpdate({ name: v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.name') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n canReset\n :containerClass=\"\n apiKeyHasName(scheme) ? undefined : getStaticBorderClass()\n \"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-token',\n })\n \"\n @update:modelValue=\"\n (v) =>\n handleApiKeySecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.value') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n\n <!-- OAuth 2.0 / OpenID Connect Authentication -->\n <template\n v-else-if=\"scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\">\n <OAuth2Metadata\n v-if=\"\n scheme.type === 'oauth2' && (!isStatic || scheme.oauth2MetadataUrl)\n \"\n :customFetch=\"options?.customFetch\"\n :environment\n :eventBus\n :name\n :proxyUrl\n :scheme />\n\n <!-- OpenID Connect -->\n <OpenIDConnect\n v-if=\"scheme?.type === 'openIdConnect' && !visibleFlowKeys.length\"\n :customFetch=\"options?.customFetch\"\n :environment\n :eventBus\n :getStaticBorderClass\n :name\n :proxyUrl\n :scheme />\n\n <!-- Flow selector tabs: shown when multiple visible flows are available -->\n <DataTableRow v-if=\"visibleFlowKeys.length > 1\">\n <div class=\"flex min-h-8 border-t text-base\">\n <div class=\"flex h-8 max-w-full gap-2.5 overflow-x-auto px-3\">\n <button\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\"\n :class=\"getFlowTabClasses(key, ind)\"\n type=\"button\"\n @click=\"setActiveFlow(key)\">\n <span class=\"relative z-10\">{{ key }}</span>\n </button>\n </div>\n </div>\n </DataTableRow>\n\n <!-- OAuth2 flow configuration -->\n <template\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\">\n <OAuth2\n v-if=\"scheme.flows && isFlowActive(key, ind)\"\n :environment\n :eventBus\n :flows=\"scheme.flows\"\n :name\n :options\n :proxyUrl\n :scheme\n :selectedScopes=\"scopes\"\n :server\n :type=\"key\"\n @delete:scope=\"(event) => handleScopeDelete(name, event)\"\n @update:selectedScopes=\"(event) => handleScopesUpdate(name, event)\"\n @upsert:scope=\"(event) => handleScopeUpsert(name, event)\" />\n </template>\n </template>\n\n <!-- Browser WebSocket connections cannot apply these broker credentials. -->\n <div\n v-else-if=\"\n scheme?.type === 'userPassword' ||\n scheme?.type === 'plain' ||\n scheme?.type === 'scramSha256' ||\n scheme?.type === 'scramSha512' ||\n scheme?.type === 'X509' ||\n scheme?.type === 'symmetricEncryption' ||\n scheme?.type === 'asymmetricEncryption' ||\n scheme?.type === 'gssapi'\n \"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{ translate('apiClient.requestAuthTab.unsupportedCredentials') }}\n </div>\n\n <!-- Mutual TLS credentials are chosen during the browser-managed TLS handshake. -->\n <div\n v-else-if=\"scheme?.type === 'mutualTLS'\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{ translate('apiClient.requestAuthTab.mutualTlsHint') }}\n </div>\n\n <!-- Scheme has a type we do not render inputs for -->\n <div\n v-else-if=\"getUnsupportedSchemeType(scheme)\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{\n translate('apiClient.requestAuthTab.unsupportedType', {\n type: getUnsupportedSchemeType(scheme) ?? '',\n })\n }}\n </div>\n\n <!-- Scheme is missing type -->\n <div\n v-else\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{\n translate('apiClient.requestAuthTab.missingType', {\n type: documentTypeLabel,\n })\n }}\n </div>\n </template>\n\n <!-- OAuth2 configuration modal (opened from the bearer scheme's gear) -->\n <ScalarModal\n v-if=\"oauth2Target && oauth2Scheme\"\n size=\"sm\"\n :state=\"configModal\"\n :title=\"\n translate('apiClient.requestAuthTab.configure', {\n name: oauth2Target.name,\n })\n \">\n <DataTable\n :columns=\"['']\"\n presentational>\n <OAuth2\n :environment\n :eventBus\n :flows=\"oauth2Target.flows\"\n hideActions\n :name=\"oauth2Target.name\"\n :options\n :proxyUrl\n :scheme=\"oauth2Scheme\"\n :selectedScopes=\"oauth2Target.scopes\"\n :server\n :type=\"oauth2Target.flowType\"\n @delete:scope=\"(event) => handleScopeDelete(oauth2Target!.name, event)\"\n @update:selectedScopes=\"\n (event) => handleScopesUpdate(oauth2Target!.name, event)\n \"\n @upsert:scope=\"\n (event) => handleScopeUpsert(oauth2Target!.name, event)\n \" />\n </DataTable>\n <div class=\"flex h-8 items-center justify-end gap-2 border-t\">\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"configModal.hide()\">\n {{ translate('apiClient.requestAuthTab.cancel') }}\n </ScalarButton>\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n @click=\"handleConfigAuthorize\">\n {{ translate('apiClient.requestAuthTab.authorize') }}\n </ScalarButton>\n </div>\n </ScalarModal>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"RequestAuthTab.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport { ScalarIconButton } from '@scalar/components/icon-button'\nimport { useLoadingState } from '@scalar/components/loading'\nimport { ScalarMarkdownSummary } from '@scalar/components/markdown'\nimport { ScalarModal, useModal } from '@scalar/components/modal'\nimport { ScalarIconGear } from '@scalar/icons'\nimport { useToasts } from '@scalar/use-toasts'\nimport type {\n SecretsApiKey,\n SecretsHttp,\n} from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport { canResetSecretField } from '@scalar/workspace-store/helpers/auth-secret-fields'\nimport { getResolvedRef } from '@scalar/workspace-store/helpers/get-resolved-ref'\nimport {\n getEnvironmentVariables,\n type MergedSecuritySchemes,\n type OAuthFlowsObjectSecret,\n type SecuritySchemeObjectSecret,\n} from '@scalar/workspace-store/request-example'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { getDocumentTypeLabel } from '@scalar/workspace-store/schemas/type-guards'\nimport type {\n ApiKeyObject,\n SecurityRequirementObject,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { capitalize, computed, ref } from 'vue'\n\nimport { refreshOauth2Token } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth'\nimport { getVisibleOrderedFlowKeys } from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth-flows'\nimport {\n runOAuth2Authorize,\n storeOAuth2Tokens,\n} from '@/v2/blocks/scalar-auth-selector-block/helpers/run-oauth2-authorize'\nimport { getOauth2AcquisitionTarget } from '@/v2/blocks/scalar-auth-selector-block/helpers/security-scheme'\nimport {\n DataTable,\n DataTableCell,\n DataTableRow,\n} from '@/v2/components/data-table'\nimport { useLocalization } from '@/v2/features/localization'\n\nimport OAuth2, { type OAuth2Options } from './OAuth2.vue'\nimport OAuth2Metadata from './OAuth2Metadata.vue'\nimport OpenIDConnect from './OpenIDConnect.vue'\nimport RequestAuthDataTableInput from './RequestAuthDataTableInput.vue'\n\nconst {\n environment,\n isStatic,\n proxyUrl,\n selectedSecuritySchemas,\n securitySchemes,\n server,\n eventBus,\n options,\n documentType = 'openapi',\n} = defineProps<{\n /** Current environment configuration */\n environment: XScalarEnvironment\n /** Controls the display of certain borders which are used when we are non-collapsible */\n isStatic: boolean\n /** Proxy URL */\n proxyUrl: string\n /** Selected security schemes*/\n selectedSecuritySchemas: SecurityRequirementObject\n /** Merged security schemes from the document and the config together with the auth store secrets */\n securitySchemes: MergedSecuritySchemes\n /** Current server configuration */\n server: ServerObject | null\n /** Event bus for authentication updates */\n eventBus: WorkspaceEventBus\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n /** Type of the document the schemes belong to, used to label the missing-type warning */\n documentType?: 'openapi' | 'asyncapi'\n}>()\n\nconst emits = defineEmits<{\n (\n e: 'update:selectedScopes',\n payload: Omit<ApiReferenceEvents['auth:update:selected-scopes'], 'meta'>,\n ): void\n (e: 'upsert:scope', payload: ApiReferenceEvents['auth:upsert:scopes']): void\n (e: 'delete:scope', payload: ApiReferenceEvents['auth:delete:scopes']): void\n}>()\n\nconst { translate } = useLocalization()\n\ntype SecurityItem = {\n scheme: SecuritySchemeObjectSecret | undefined\n name: string\n scopes: string[]\n /** Ordered, non-hidden oauth2/openIdConnect flow keys for this scheme (empty for other types). */\n visibleFlowKeys: (keyof OAuthFlowsObjectSecret)[]\n}\n\n/**\n * Human-readable name of the document type.\n * Used in the missing-type warning so it points at the correct document\n * (e.g. \"AsyncAPI\") instead of always naming OpenAPI.\n */\nconst documentTypeLabel = computed<string>(() =>\n getDocumentTypeLabel(documentType),\n)\n\n/**\n * Resolves security schemes from the OpenAPI document and combines them with their selected scopes.\n * Each item includes the scheme definition, name, and associated scopes.\n */\nconst security = computed<SecurityItem[]>(() =>\n Object.entries(selectedSecuritySchemas).map(([name, scopes = []]) => {\n const scheme = getResolvedRef(securitySchemes[name])\n return {\n scheme,\n name,\n scopes,\n // Compute the visible, ordered flow keys once per scheme so the tabs, the label, and the\n // active-flow tracking all agree on the same set (and we do not filter + sort on every access).\n visibleFlowKeys:\n scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\n ? getVisibleOrderedFlowKeys(scheme.flows)\n : [],\n }\n }),\n)\n\n/** Tracks which OAuth2 flow is currently active when multiple flows are available. */\nconst activeFlow = ref<string>('')\n\n/**\n * Keeps the selected flow in sync with the currently visible flow keys. Validating against the\n * visible set (not every declared flow) means a selection that becomes hidden — e.g. the document\n * is updated to mark the active flow with `x-scalar-ignore` — resets, so the default (first visible)\n * flow activates instead of leaving no tab selected.\n */\nconst selectedFlow = computed<string>(() => {\n const visibleFlowKeys = security.value.flatMap((item) => item.visibleFlowKeys)\n\n return visibleFlowKeys.some((key) => key === activeFlow.value)\n ? activeFlow.value\n : ''\n})\n\nconst setActiveFlow = (flow: string): void => {\n activeFlow.value = flow\n}\n\n/** Determines if multiple auth schemes are configured, which affects the UI layout. */\nconst hasMultipleSchemes = computed<boolean>(() => security.value.length > 1)\n\n/**\n * Generates a human-readable label for the security scheme.\n * Intentionally omits the description here — it is rendered separately as\n * rich text via ScalarMarkdownSummary so markdown formatting is preserved.\n */\nconst generateLabel = (\n name: string,\n scheme: SecuritySchemeObjectSecret,\n): string => {\n const capitalizedName = capitalize(name)\n\n switch (scheme.type) {\n case 'apiKey':\n return `${capitalizedName}: ${scheme.in}`\n\n case 'openIdConnect':\n case 'oauth2': {\n const firstFlow = getVisibleOrderedFlowKeys(scheme.flows)[0]\n const currentFlow = selectedFlow.value || firstFlow\n if (!currentFlow) {\n return capitalizedName\n }\n return `${capitalizedName}: ${currentFlow}`\n }\n\n case 'http':\n return `${capitalizedName}: ${scheme.scheme}`\n\n default:\n return capitalizedName\n }\n}\n\n/**\n * Whether an API key scheme exposes an editable parameter name.\n *\n * OpenAPI `apiKey` and AsyncAPI `httpApiKey` (normalized to `apiKey`) name a query/header/cookie\n * parameter, so the Name input is shown. AsyncAPI `apiKey` places the key in the broker `user` or\n * `password` slot and has no parameter name, so the Name input is hidden and only the value is asked for.\n */\nconst apiKeyHasName = (scheme: { in?: string }): boolean =>\n scheme.in !== 'user' && scheme.in !== 'password'\n\n/**\n * The scheme's type when it is one we do not render inputs for (a type outside both the OpenAPI\n * and AsyncAPI security scheme unions). Read through a helper so the fallback template branch,\n * where the scheme type is narrowed to `never` after the supported cases, can still surface the type.\n */\nconst getUnsupportedSchemeType = (\n scheme: SecurityItem['scheme'],\n): string | undefined => scheme?.type\n\n/**\n * Determines if an OAuth2 flow tab should be active.\n * The first flow is active by default if no flow is explicitly selected.\n */\nconst isFlowActive = (flowKey: string, index: number): boolean =>\n selectedFlow.value === flowKey || (index === 0 && !selectedFlow.value)\n\n/** Computes the container class for static display mode. */\nconst getStaticBorderClass = (): string | false => isStatic && 'border-t'\n\nconst handleHttpSecretsUpdate = (\n payload: Omit<Partial<SecretsHttp>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'http', ...payload },\n name,\n })\n\nconst handleApiKeySecretsUpdate = (\n payload: Omit<Partial<SecretsApiKey>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\n/** Name edits may update the document or a configured override; tokens remain secrets. */\nconst handleApiKeySecuritySchemeUpdate = (\n payload: Omit<Partial<ApiKeyObject>, 'type'>,\n name: string,\n): void =>\n eventBus.emit('auth:update:security-scheme', {\n payload: { type: 'apiKey', ...payload },\n name,\n })\n\n/** Handles scope selection updates for OAuth2 */\nconst handleScopesUpdate = (\n name: string,\n event: { scopes?: string[]; scope?: string; selected?: boolean },\n): void => {\n emits('update:selectedScopes', {\n id: Object.keys(selectedSecuritySchemas),\n name,\n ...event,\n })\n}\n\n/** Handles scope-definition upserts (add / rename / description change) */\nconst handleScopeUpsert = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:upsert:scopes'], 'name'>,\n): void => {\n emits('upsert:scope', { ...event, name })\n}\n\n/** Handles scope-definition deletes */\nconst handleScopeDelete = (\n name: string,\n event: Omit<ApiReferenceEvents['auth:delete:scopes'], 'name'>,\n): void => {\n emits('delete:scope', { ...event, name })\n}\n\n/**\n * Computes dynamic classes for OAuth2 flow tabs based on active state.\n */\nconst getFlowTabClasses = (flowKey: string, index: number): string => {\n const baseClasses =\n 'floating-bg text-c-3 relative cursor-pointer border-b border-transparent py-1 text-base font-medium'\n const activeClasses = '!text-c-1 !rounded-none border-b !border-current'\n\n return isFlowActive(flowKey, index)\n ? `${baseClasses} ${activeClasses} ${isStatic ? 'opacity-100' : ''}`\n : baseClasses\n}\n\n/**\n * OAuth2 token-acquisition target (an oauth2 scheme with an interactive grant) sourced from\n * the merged schemes. When the active scheme is HTTP bearer, this powers the inline\n * \"Authorize via OAuth2\" shortcut: the flow's bearer token is written onto the bearer scheme,\n * so the panel never switches to oauth2.\n *\n * The shortcut is purely a convenience, so it is offered for any interactive oauth2 scheme —\n * including one that is also independently selectable in the dropdown (e.g. Scalar Galaxy's\n * `oAuth2`). Whether that oauth2 scheme is *hidden* from the dropdown is a separate decision made\n * in the selector; here we only surface the shortcut.\n */\nconst oauth2Target = computed(() => getOauth2AcquisitionTarget(securitySchemes))\n\n/** Resolved oauth2 scheme object, for embedding its config form behind the gear. */\nconst oauth2Scheme = computed(() =>\n oauth2Target.value\n ? getResolvedRef(securitySchemes[oauth2Target.value.name])\n : undefined,\n)\n\nconst acquisitionLoader = useLoadingState()\nconst { toast } = useToasts()\nconst configModal = useModal()\n/** Bearer scheme that opened the config modal, so its Authorize callback targets it. */\nconst configBearerName = ref<string | undefined>()\n\n/** Runs the OAuth2 flow and writes the resulting bearer token onto the bearer scheme. */\nconst handleAcquisitionAuthorize = async (\n bearerName: string,\n): Promise<void> => {\n const target = oauth2Target.value\n if (!target || acquisitionLoader.isLoading) {\n return\n }\n acquisitionLoader.start()\n const [error] = await runOAuth2Authorize({\n eventBus,\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flows: target.flows,\n flowType: target.flowType,\n scopes: target.scopes,\n server,\n proxyUrl,\n environment,\n options,\n })\n await acquisitionLoader.clear()\n if (error) {\n toast(\n error?.message ?? translate('apiClient.requestAuthTab.failedToauthorize'),\n 'error',\n )\n }\n}\n\n/** Refreshes the OAuth2 token and rewrites it onto the bearer scheme. */\nconst handleAcquisitionRefresh = async (bearerName: string): Promise<void> => {\n const target = oauth2Target.value\n // Only the authorization-code flow carries a refresh token; implicit can't be refreshed.\n if (target?.flowType !== 'authorizationCode' || acquisitionLoader.isLoading) {\n return\n }\n acquisitionLoader.start()\n const [error, tokens] = await refreshOauth2Token(\n target.flows,\n target.flowType,\n proxyUrl,\n server,\n getEnvironmentVariables(environment),\n options?.customFetch,\n )\n await acquisitionLoader.clear()\n if (tokens?.accessToken) {\n storeOAuth2Tokens(eventBus, {\n bearerSchemeName: bearerName,\n oauth2Name: target.name,\n flowType: target.flowType,\n tokens,\n })\n } else if (error) {\n toast(\n error?.message ?? translate('apiClient.requestAuthTab.failedToRefresh'),\n 'error',\n )\n }\n}\n\nconst openAcquisitionConfig = (bearerName: string): void => {\n configBearerName.value = bearerName\n configModal.show()\n}\n\n/** Closes the config modal and runs Authorize against the bearer scheme that opened it. */\nconst handleConfigAuthorize = (): void => {\n const bearerName = configBearerName.value\n configModal.hide()\n if (bearerName) {\n void handleAcquisitionAuthorize(bearerName)\n }\n}\n</script>\n<template>\n <template\n v-for=\"{ scheme, name, scopes, visibleFlowKeys } in security\"\n :key=\"name\">\n <!--\n Header row for AND'ed schemes: label (bold) and description (rich text) are\n combined.\n -->\n <DataTableRow v-if=\"hasMultipleSchemes && scheme\">\n <DataTableCell\n :aria-label=\"generateLabel(name, scheme)\"\n class=\"max-h-[auto]\">\n <div class=\"bg-b-1 min-w-0 flex-1 px-3 py-1.25\">\n <p class=\"text-c-1 leading-5.5 font-medium\">\n {{ generateLabel(name, scheme) }}\n </p>\n <ScalarMarkdownSummary\n v-if=\"scheme.description\"\n class=\"auth-description text-c-2 w-full\"\n :value=\"scheme.description\" />\n </div>\n </DataTableCell>\n </DataTableRow>\n\n <!-- Description: shown for single auth schemes with descriptions -->\n <DataTableRow v-if=\"scheme?.description && !hasMultipleSchemes\">\n <DataTableCell\n :aria-label=\"scheme.description\"\n class=\"max-h-[auto]\">\n <ScalarMarkdownSummary\n class=\"auth-description bg-b-1 text-c-2 min-w-0 flex-1 px-3 py-1.25\"\n :value=\"scheme.description\" />\n </DataTableCell>\n </DataTableRow>\n\n <!-- HTTP Authentication -->\n <template v-if=\"scheme?.type === 'http'\">\n <!-- Bearer Token -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer'\">\n <RequestAuthDataTableInput\n :canReset=\"\n canResetSecretField(\n scheme,\n 'x-scalar-secret-token',\n scheme['x-scalar-secret-token'],\n )\n \"\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n :placeholder=\"translate('apiClient.requestAuthTab.token')\"\n type=\"password\"\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-token',\n })\n \"\n @update:modelValue=\"\n (v) => handleHttpSecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.bearerToken') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- OAuth2 token-acquisition shortcut (shown when an interactive oauth2 flow exists) -->\n <DataTableRow v-if=\"scheme.scheme === 'bearer' && oauth2Target\">\n <!--\n Authorize stays rightmost so it never moves: Refresh only appears once there is a token,\n and it slots in between the gear and Authorize instead of pushing Authorize aside.\n -->\n <div class=\"flex h-8 items-center gap-2 border-t pr-1 pl-3 text-base\">\n <span class=\"text-c-1 mr-auto\">{{\n translate('apiClient.requestAuthTab.getAToken')\n }}</span>\n <ScalarIconButton\n class=\"h-6 w-6 p-1.25\"\n :icon=\"ScalarIconGear\"\n :label=\"\n translate('apiClient.requestAuthTab.configure', {\n name: oauth2Target.name,\n })\n \"\n @click=\"openAcquisitionConfig(name)\" />\n <ScalarButton\n v-if=\"\n scheme['x-scalar-secret-token'] &&\n oauth2Target.flowType === 'authorizationCode'\n \"\n class=\"px-3 py-1\"\n :disabled=\"acquisitionLoader.isLoading\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\n @click=\"handleAcquisitionRefresh(name)\">\n {{ translate('apiClient.requestAuthTab.refresh') }}\n </ScalarButton>\n <ScalarButton\n class=\"text-c-1 px-3 py-1\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n type=\"button\"\n variant=\"gradient\"\n @click=\"handleAcquisitionAuthorize(name)\">\n {{\n translate('apiClient.requestAuthTab.authorizeVia', {\n name: oauth2Target.name,\n })\n }}\n </ScalarButton>\n </div>\n </DataTableRow>\n\n <!-- HTTP Basic Authentication -->\n <template v-else-if=\"scheme?.scheme === 'basic'\">\n <DataTableRow>\n <RequestAuthDataTableInput\n :canReset=\"\n canResetSecretField(\n scheme,\n 'x-scalar-secret-username',\n scheme['x-scalar-secret-username'],\n )\n \"\n class=\"text-c-2\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n required\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-username',\n })\n \"\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-username': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.username') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n :canReset=\"\n canResetSecretField(\n scheme,\n 'x-scalar-secret-password',\n scheme['x-scalar-secret-password'],\n )\n \"\n :environment\n :modelValue=\"scheme['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-password',\n })\n \"\n @update:modelValue=\"\n (v) =>\n handleHttpSecretsUpdate({ 'x-scalar-secret-password': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.password') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n </template>\n\n <!-- API Key Authentication -->\n <template v-else-if=\"scheme?.type === 'apiKey'\">\n <DataTableRow v-if=\"apiKeyHasName(scheme)\">\n <RequestAuthDataTableInput\n :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme.name ?? ''\"\n placeholder=\"api-key\"\n @update:modelValue=\"\n (v) => handleApiKeySecuritySchemeUpdate({ name: v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.name') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n :canReset=\"\n canResetSecretField(\n scheme,\n 'x-scalar-secret-token',\n scheme['x-scalar-secret-token'],\n )\n \"\n :containerClass=\"\n apiKeyHasName(scheme) ? undefined : getStaticBorderClass()\n \"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\n @reset=\"\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n field: 'x-scalar-secret-token',\n })\n \"\n @update:modelValue=\"\n (v) =>\n handleApiKeySecretsUpdate({ 'x-scalar-secret-token': v }, name)\n \">\n {{ translate('apiClient.requestAuthTab.value') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n\n <!-- OAuth 2.0 / OpenID Connect Authentication -->\n <template\n v-else-if=\"scheme?.type === 'oauth2' || scheme?.type === 'openIdConnect'\">\n <OAuth2Metadata\n v-if=\"\n scheme.type === 'oauth2' && (!isStatic || scheme.oauth2MetadataUrl)\n \"\n :customFetch=\"options?.customFetch\"\n :environment\n :eventBus\n :name\n :proxyUrl\n :scheme />\n\n <!-- OpenID Connect -->\n <OpenIDConnect\n v-if=\"scheme?.type === 'openIdConnect' && !visibleFlowKeys.length\"\n :customFetch=\"options?.customFetch\"\n :environment\n :eventBus\n :getStaticBorderClass\n :name\n :proxyUrl\n :scheme />\n\n <!-- Flow selector tabs: shown when multiple visible flows are available -->\n <DataTableRow v-if=\"visibleFlowKeys.length > 1\">\n <div class=\"flex min-h-8 border-t text-base\">\n <div class=\"flex h-8 max-w-full gap-2.5 overflow-x-auto px-3\">\n <button\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\"\n :class=\"getFlowTabClasses(key, ind)\"\n type=\"button\"\n @click=\"setActiveFlow(key)\">\n <span class=\"relative z-10\">{{ key }}</span>\n </button>\n </div>\n </div>\n </DataTableRow>\n\n <!-- OAuth2 flow configuration -->\n <template\n v-for=\"(key, ind) in visibleFlowKeys\"\n :key=\"key\">\n <OAuth2\n v-if=\"scheme.flows && isFlowActive(key, ind)\"\n :environment\n :eventBus\n :flows=\"scheme.flows\"\n :name\n :options\n :proxyUrl\n :scheme\n :selectedScopes=\"scopes\"\n :server\n :type=\"key\"\n @delete:scope=\"(event) => handleScopeDelete(name, event)\"\n @update:selectedScopes=\"(event) => handleScopesUpdate(name, event)\"\n @upsert:scope=\"(event) => handleScopeUpsert(name, event)\" />\n </template>\n </template>\n\n <!-- Browser WebSocket connections cannot apply these broker credentials. -->\n <div\n v-else-if=\"\n scheme?.type === 'userPassword' ||\n scheme?.type === 'plain' ||\n scheme?.type === 'scramSha256' ||\n scheme?.type === 'scramSha512' ||\n scheme?.type === 'X509' ||\n scheme?.type === 'symmetricEncryption' ||\n scheme?.type === 'asymmetricEncryption' ||\n scheme?.type === 'gssapi'\n \"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{ translate('apiClient.requestAuthTab.unsupportedCredentials') }}\n </div>\n\n <!-- Mutual TLS credentials are chosen during the browser-managed TLS handshake. -->\n <div\n v-else-if=\"scheme?.type === 'mutualTLS'\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{ translate('apiClient.requestAuthTab.mutualTlsHint') }}\n </div>\n\n <!-- Scheme has a type we do not render inputs for -->\n <div\n v-else-if=\"getUnsupportedSchemeType(scheme)\"\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{\n translate('apiClient.requestAuthTab.unsupportedType', {\n type: getUnsupportedSchemeType(scheme) ?? '',\n })\n }}\n </div>\n\n <!-- Scheme is missing type -->\n <div\n v-else\n class=\"text-c-3 flex items-center justify-center border-t p-4 px-4 text-center text-xs text-balance\">\n {{\n translate('apiClient.requestAuthTab.missingType', {\n type: documentTypeLabel,\n })\n }}\n </div>\n </template>\n\n <!-- OAuth2 configuration modal (opened from the bearer scheme's gear) -->\n <ScalarModal\n v-if=\"oauth2Target && oauth2Scheme\"\n size=\"sm\"\n :state=\"configModal\"\n :title=\"\n translate('apiClient.requestAuthTab.configure', {\n name: oauth2Target.name,\n })\n \">\n <DataTable\n :columns=\"['']\"\n presentational>\n <OAuth2\n :environment\n :eventBus\n :flows=\"oauth2Target.flows\"\n hideActions\n :name=\"oauth2Target.name\"\n :options\n :proxyUrl\n :scheme=\"oauth2Scheme\"\n :selectedScopes=\"oauth2Target.scopes\"\n :server\n :type=\"oauth2Target.flowType\"\n @delete:scope=\"(event) => handleScopeDelete(oauth2Target!.name, event)\"\n @update:selectedScopes=\"\n (event) => handleScopesUpdate(oauth2Target!.name, event)\n \"\n @upsert:scope=\"\n (event) => handleScopeUpsert(oauth2Target!.name, event)\n \" />\n </DataTable>\n <div class=\"flex h-8 items-center justify-end gap-2 border-t\">\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"configModal.hide()\">\n {{ translate('apiClient.requestAuthTab.cancel') }}\n </ScalarButton>\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n @click=\"handleConfigAuthorize\">\n {{ translate('apiClient.requestAuthTab.authorize') }}\n </ScalarButton>\n </div>\n </ScalarModal>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-oauth2-metadata.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAI3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAGnF,OAAO,EACL,KAAK,sBAAsB,IAAI,2BAA2B,EAE3D,MAAM,kCAAkC,CAAA;AAGzC,4FAA4F;AAC5F,eAAO,MAAM,mBAAmB,GAC9B,KAAK,MAAM,EACX,UAAU,MAAM,EAChB,cAAa,WAAmB,KAC/B,OAAO,CAAC,aAAa,CAAC,2BAA2B,CAAC,CAuBpD,CAAA"}
1
+ {"version":3,"file":"fetch-oauth2-metadata.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAK3E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAGnF,OAAO,EACL,KAAK,sBAAsB,IAAI,2BAA2B,EAE3D,MAAM,kCAAkC,CAAA;AAEzC,4FAA4F;AAC5F,eAAO,MAAM,mBAAmB,GAC9B,KAAK,MAAM,EACX,UAAU,MAAM,EAChB,cAAa,WAAmB,KAC/B,OAAO,CAAC,aAAa,CAAC,2BAA2B,CAAC,CAuBpD,CAAA"}
@@ -1,5 +1,5 @@
1
- import { isAllowedOAuthUrl } from "./is-allowed-oauth-url.js";
2
1
  import { OpenIDConnectDiscoverySchema } from "./fetch-openid-connect-discovery.js";
2
+ import { isAllowedOAuthUrl } from "@scalar/helpers/url/is-allowed-oauth-url";
3
3
  import { redirectToProxy } from "@scalar/helpers/url/redirect-to-proxy";
4
4
  import { coerceValue } from "@scalar/workspace-store/schemas/typebox-coerce";
5
5
  //#region src/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.ts
@@ -1 +1 @@
1
- {"version":3,"file":"fetch-oauth2-metadata.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.ts"],"sourcesContent":["import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error'\nimport { redirectToProxy } from '@scalar/helpers/url/redirect-to-proxy'\nimport { coerceValue } from '@scalar/workspace-store/schemas/typebox-coerce'\n\nimport type { CustomFetch } from '@/v2/blocks/operation-block/helpers/send-request'\n\n// RFC 8414 and OIDC share these consumed fields; this alias does not imply OIDC issuer semantics.\nimport {\n type OpenIDConnectDiscovery as AuthorizationServerMetadata,\n OpenIDConnectDiscoverySchema as AuthorizationServerMetadataSchema,\n} from './fetch-openid-connect-discovery'\nimport { isAllowedOAuthUrl } from './is-allowed-oauth-url'\n\n/** Fetches the exact RFC8414 metadata URL, without applying OIDC issuer URL conventions. */\nexport const fetchOAuth2Metadata = async (\n url: string,\n proxyUrl: string,\n customFetch: CustomFetch = fetch,\n): Promise<ErrorResponse<AuthorizationServerMetadata>> => {\n try {\n const metadataUrl = new URL(url.trim())\n if (!isAllowedOAuthUrl(metadataUrl)) {\n return [new Error('OAuth2 metadata URL must use HTTPS or HTTP for local development URLs'), null]\n }\n const response = await customFetch(redirectToProxy(proxyUrl, metadataUrl.href))\n if (!response.ok) {\n return [new Error(`Failed to fetch OAuth2 metadata: ${response.status} ${response.statusText}`), null]\n }\n const data = coerceValue(AuthorizationServerMetadataSchema, await response.json())\n if (!data.authorization_endpoint && !data.token_endpoint && !data.device_authorization_endpoint) {\n return [new Error('Invalid OAuth2 metadata: missing or invalid endpoints'), null]\n }\n for (const endpoint of [data.authorization_endpoint, data.token_endpoint, data.device_authorization_endpoint]) {\n if (endpoint && !isAllowedOAuthUrl(new URL(endpoint))) {\n return [new Error('OAuth2 metadata endpoints must use HTTPS or HTTP for local development URLs'), null]\n }\n }\n return [null, data]\n } catch (error) {\n return [error instanceof Error ? error : new Error('Failed to fetch OAuth2 metadata'), null]\n }\n}\n"],"mappings":";;;;;;AAcA,IAAa,sBAAsB,OACjC,KACA,UACA,cAA2B,UAC6B;CACxD,IAAI;EACF,MAAM,cAAc,IAAI,IAAI,IAAI,KAAK,CAAC;EACtC,IAAI,CAAC,kBAAkB,WAAW,GAChC,OAAO,iBAAC,IAAI,MAAM,uEAAuE,GAAG,IAAI;EAElG,MAAM,WAAW,MAAM,YAAY,gBAAgB,UAAU,YAAY,IAAI,CAAC;EAC9E,IAAI,CAAC,SAAS,IACZ,OAAO,iBAAC,IAAI,MAAM,oCAAoC,SAAS,OAAO,GAAG,SAAS,YAAY,GAAG,IAAI;EAEvG,MAAM,OAAO,YAAY,8BAAmC,MAAM,SAAS,KAAK,CAAC;EACjF,IAAI,CAAC,KAAK,0BAA0B,CAAC,KAAK,kBAAkB,CAAC,KAAK,+BAChE,OAAO,iBAAC,IAAI,MAAM,uDAAuD,GAAG,IAAI;EAElF,KAAK,MAAM,YAAY;GAAC,KAAK;GAAwB,KAAK;GAAgB,KAAK;EAA6B,GAC1G,IAAI,YAAY,CAAC,kBAAkB,IAAI,IAAI,QAAQ,CAAC,GAClD,OAAO,iBAAC,IAAI,MAAM,6EAA6E,GAAG,IAAI;EAG1G,OAAO,CAAC,MAAM,IAAI;CACpB,SAAS,OAAO;EACd,OAAO,CAAC,iBAAiB,QAAQ,wBAAQ,IAAI,MAAM,iCAAiC,GAAG,IAAI;CAC7F;AACF"}
1
+ {"version":3,"file":"fetch-oauth2-metadata.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/fetch-oauth2-metadata.ts"],"sourcesContent":["import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error'\nimport { isAllowedOAuthUrl } from '@scalar/helpers/url/is-allowed-oauth-url'\nimport { redirectToProxy } from '@scalar/helpers/url/redirect-to-proxy'\nimport { coerceValue } from '@scalar/workspace-store/schemas/typebox-coerce'\n\nimport type { CustomFetch } from '@/v2/blocks/operation-block/helpers/send-request'\n\n// RFC 8414 and OIDC share these consumed fields; this alias does not imply OIDC issuer semantics.\nimport {\n type OpenIDConnectDiscovery as AuthorizationServerMetadata,\n OpenIDConnectDiscoverySchema as AuthorizationServerMetadataSchema,\n} from './fetch-openid-connect-discovery'\n\n/** Fetches the exact RFC8414 metadata URL, without applying OIDC issuer URL conventions. */\nexport const fetchOAuth2Metadata = async (\n url: string,\n proxyUrl: string,\n customFetch: CustomFetch = fetch,\n): Promise<ErrorResponse<AuthorizationServerMetadata>> => {\n try {\n const metadataUrl = new URL(url.trim())\n if (!isAllowedOAuthUrl(metadataUrl)) {\n return [new Error('OAuth2 metadata URL must use HTTPS or HTTP for local development URLs'), null]\n }\n const response = await customFetch(redirectToProxy(proxyUrl, metadataUrl.href))\n if (!response.ok) {\n return [new Error(`Failed to fetch OAuth2 metadata: ${response.status} ${response.statusText}`), null]\n }\n const data = coerceValue(AuthorizationServerMetadataSchema, await response.json())\n if (!data.authorization_endpoint && !data.token_endpoint && !data.device_authorization_endpoint) {\n return [new Error('Invalid OAuth2 metadata: missing or invalid endpoints'), null]\n }\n for (const endpoint of [data.authorization_endpoint, data.token_endpoint, data.device_authorization_endpoint]) {\n if (endpoint && !isAllowedOAuthUrl(new URL(endpoint))) {\n return [new Error('OAuth2 metadata endpoints must use HTTPS or HTTP for local development URLs'), null]\n }\n }\n return [null, data]\n } catch (error) {\n return [error instanceof Error ? error : new Error('Failed to fetch OAuth2 metadata'), null]\n }\n}\n"],"mappings":";;;;;;AAcA,IAAa,sBAAsB,OACjC,KACA,UACA,cAA2B,UAC6B;CACxD,IAAI;EACF,MAAM,cAAc,IAAI,IAAI,IAAI,KAAK,CAAC;EACtC,IAAI,CAAC,kBAAkB,WAAW,GAChC,OAAO,iBAAC,IAAI,MAAM,uEAAuE,GAAG,IAAI;EAElG,MAAM,WAAW,MAAM,YAAY,gBAAgB,UAAU,YAAY,IAAI,CAAC;EAC9E,IAAI,CAAC,SAAS,IACZ,OAAO,iBAAC,IAAI,MAAM,oCAAoC,SAAS,OAAO,GAAG,SAAS,YAAY,GAAG,IAAI;EAEvG,MAAM,OAAO,YAAY,8BAAmC,MAAM,SAAS,KAAK,CAAC;EACjF,IAAI,CAAC,KAAK,0BAA0B,CAAC,KAAK,kBAAkB,CAAC,KAAK,+BAChE,OAAO,iBAAC,IAAI,MAAM,uDAAuD,GAAG,IAAI;EAElF,KAAK,MAAM,YAAY;GAAC,KAAK;GAAwB,KAAK;GAAgB,KAAK;EAA6B,GAC1G,IAAI,YAAY,CAAC,kBAAkB,IAAI,IAAI,QAAQ,CAAC,GAClD,OAAO,iBAAC,IAAI,MAAM,6EAA6E,GAAG,IAAI;EAG1G,OAAO,CAAC,MAAM,IAAI;CACpB,SAAS,OAAO;EACd,OAAO,CAAC,iBAAiB,QAAQ,wBAAQ,IAAI,MAAM,iCAAiC,GAAG,IAAI;CAC7F;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-device-authorization.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAK3E,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,yCAAyC,CAAA;AACjG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAA;AAEhG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAGnF,OAAO,EAAE,KAAK,YAAY,EAAuB,MAAM,SAAS,CAAA;AAOhE,uFAAuF;AACvF,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAA;CACjC,CAAA;AAED,6CAA6C;AAC7C,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,CAAC,MAAM,EAAE,yBAAyB,KAAK,IAAI,CAAA;IACrD,MAAM,EAAE,WAAW,CAAA;CACpB,CAAA;AA4BD,oGAAoG;AACpG,eAAO,MAAM,eAAe,GAC1B,MAAM,kCAAkC,EACxC,QAAQ,MAAM,EAAE,EAChB,QAAQ,YAAY,GAAG,IAAI,EAC3B,UAAU,MAAM,EAChB,aAAa,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,cAAa,WAAmB,EAChC,UAAU,0BAA0B,KACnC,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAgIrC,CAAA"}
1
+ {"version":3,"file":"oauth-device-authorization.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAA;AAM3E,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,yCAAyC,CAAA;AACjG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8DAA8D,CAAA;AAEhG,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAA;AAEnF,OAAO,EAAE,KAAK,YAAY,EAAuB,MAAM,SAAS,CAAA;AAOhE,uFAAuF;AACvF,MAAM,MAAM,yBAAyB,GAAG;IACtC,QAAQ,EAAE,MAAM,CAAA;IAChB,eAAe,EAAE,MAAM,CAAA;IACvB,uBAAuB,CAAC,EAAE,MAAM,CAAA;CACjC,CAAA;AAED,6CAA6C;AAC7C,MAAM,MAAM,0BAA0B,GAAG;IACvC,QAAQ,EAAE,CAAC,MAAM,EAAE,yBAAyB,KAAK,IAAI,CAAA;IACrD,MAAM,EAAE,WAAW,CAAA;CACpB,CAAA;AA4BD,oGAAoG;AACpG,eAAO,MAAM,eAAe,GAC1B,MAAM,kCAAkC,EACxC,QAAQ,MAAM,EAAE,EAChB,QAAQ,YAAY,GAAG,IAAI,EAC3B,UAAU,MAAM,EAChB,aAAa,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,cAAa,WAAmB,EAChC,UAAU,0BAA0B,KACnC,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAgIrC,CAAA"}
@@ -1,9 +1,9 @@
1
1
  import { oauthClientAuthorization } from "./oauth-client-authorization.js";
2
- import { isAllowedOAuthUrl } from "./is-allowed-oauth-url.js";
3
2
  import { getActiveServerBase } from "./oauth.js";
4
3
  import { makeUrlAbsolute } from "@scalar/helpers/url/make-url-absolute";
5
4
  import { replaceEnvVariables } from "@scalar/helpers/regex/replace-variables";
6
5
  import { isObject } from "@scalar/helpers/object/is-object";
6
+ import { isAllowedOAuthUrl } from "@scalar/helpers/url/is-allowed-oauth-url";
7
7
  import { redirectToProxy } from "@scalar/helpers/url/redirect-to-proxy";
8
8
  //#region src/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.ts
9
9
  var REQUEST_TIMEOUT_MS = 3e4;
@@ -1 +1 @@
1
- {"version":3,"file":"oauth-device-authorization.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.ts"],"sourcesContent":["import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error'\nimport { isObject } from '@scalar/helpers/object/is-object'\nimport { replaceEnvVariables } from '@scalar/helpers/regex/replace-variables'\nimport { makeUrlAbsolute } from '@scalar/helpers/url/make-url-absolute'\nimport { redirectToProxy } from '@scalar/helpers/url/redirect-to-proxy'\nimport type { OAuthFlowDeviceAuthorizationSecret } from '@scalar/workspace-store/request-example'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport type { CustomFetch } from '@/v2/blocks/operation-block/helpers/send-request'\n\nimport { isAllowedOAuthUrl } from './is-allowed-oauth-url'\nimport { type OAuth2Tokens, getActiveServerBase } from './oauth'\nimport { oauthClientAuthorization } from './oauth-client-authorization'\n\nconst REQUEST_TIMEOUT_MS = 30_000\n// Maximum delay supported by the browser timer API.\nconst MAX_TIMEOUT_MS = 2_147_483_647\n\n/** Information the user needs to approve a device without exposing the device code. */\nexport type DeviceAuthorizationPrompt = {\n userCode: string\n verificationUri: string\n verificationUriComplete?: string\n}\n\n/** Device flow UI and cancellation hooks. */\nexport type DeviceAuthorizationOptions = {\n onPrompt: (prompt: DeviceAuthorizationPrompt) => void\n signal: AbortSignal\n}\n\n/** Waits between polls, releasing the timer immediately when cancelled or expired. */\nconst waitForPoll = (milliseconds: number, signal: AbortSignal): Promise<void> =>\n new Promise((resolve, reject) => {\n signal.throwIfAborted()\n const abort = (): void => {\n clearTimeout(timer)\n reject(signal.reason)\n }\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', abort)\n resolve()\n }, milliseconds)\n signal.addEventListener('abort', abort, { once: true })\n })\n\nconst verificationUrl = (value: unknown): string => {\n if (typeof value !== 'string') {\n throw new Error('Missing device verification URL')\n }\n const url = new URL(value)\n if (!isAllowedOAuthUrl(url)) {\n throw new Error('Device verification URL must use HTTPS or HTTP for local development URLs')\n }\n return url.href\n}\n\n/** Performs the RFC8628 device grant, respecting expiry, pending responses, and polling backoff. */\nexport const authorizeDevice = async (\n flow: OAuthFlowDeviceAuthorizationSecret,\n scopes: string[],\n server: ServerObject | null,\n proxyUrl: string,\n environment: Record<string, string>,\n customFetch: CustomFetch = fetch,\n options?: DeviceAuthorizationOptions,\n): Promise<ErrorResponse<OAuth2Tokens>> => {\n try {\n if (!options) {\n throw new Error('Device authorization requires a verification prompt')\n }\n const resolveValue = (value: string): string => replaceEnvVariables(value, environment)\n const endpoint = (value: string): string =>\n redirectToProxy(proxyUrl, makeUrlAbsolute(resolveValue(value), getActiveServerBase(server, environment)))\n const tokenUrl = flow['x-scalar-secret-token-url'] ?? flow.tokenUrl\n if (!tokenUrl.trim()) {\n throw new Error('Token URL is required')\n }\n const clientId = resolveValue(flow['x-scalar-secret-client-id'])\n const clientSecret = resolveValue(flow['x-scalar-secret-client-secret'])\n const headers: Record<string, string> = { 'Content-Type': 'application/x-www-form-urlencoded' }\n const credentials = new URLSearchParams()\n if (clientSecret && flow['x-scalar-credentials-location'] !== 'body') {\n headers.Authorization = oauthClientAuthorization(clientId, clientSecret)\n } else {\n credentials.set('client_id', clientId)\n if (clientSecret) {\n credentials.set('client_secret', clientSecret)\n }\n }\n const deviceBody = new URLSearchParams(credentials)\n if (scopes.length) {\n deviceBody.set('scope', scopes.join(' '))\n }\n const response = await customFetch(endpoint(flow.deviceAuthorizationUrl), {\n method: 'POST',\n headers,\n body: deviceBody,\n signal: AbortSignal.any([options.signal, AbortSignal.timeout(REQUEST_TIMEOUT_MS)]),\n })\n const data: unknown = await response.json()\n options.signal.throwIfAborted()\n if (!isObject(data)) {\n throw new Error('Invalid device authorization response')\n }\n if (!response.ok) {\n throw new Error(String(data.error_description ?? data.error ?? 'Device authorization failed'))\n }\n if (\n typeof data.device_code !== 'string' ||\n !data.device_code ||\n typeof data.user_code !== 'string' ||\n !data.user_code ||\n typeof data.expires_in !== 'number' ||\n !Number.isFinite(data.expires_in) ||\n data.expires_in <= 0 ||\n (data.interval !== undefined &&\n (typeof data.interval !== 'number' || !Number.isFinite(data.interval) || data.interval < 0))\n ) {\n throw new Error('Invalid device authorization response')\n }\n const lifetime = Math.min(data.expires_in * 1000, MAX_TIMEOUT_MS)\n const expiresAt = Date.now() + lifetime\n const expiry = AbortSignal.timeout(lifetime)\n const signal = AbortSignal.any([options.signal, expiry])\n options.onPrompt({\n userCode: data.user_code,\n verificationUri: verificationUrl(data.verification_uri),\n ...(data.verification_uri_complete\n ? { verificationUriComplete: verificationUrl(data.verification_uri_complete) }\n : {}),\n })\n const body = new URLSearchParams(credentials)\n for (const [key, value] of Object.entries(flow['x-scalar-security-body'] ?? {})) {\n body.set(key, resolveValue(value))\n }\n body.set('grant_type', 'urn:ietf:params:oauth:grant-type:device_code')\n body.set('device_code', data.device_code)\n let interval = typeof data.interval === 'number' ? Math.max(1000, data.interval * 1000) : 5000\n try {\n while (Date.now() < expiresAt) {\n await waitForPoll(Math.min(interval, expiresAt - Date.now()), signal)\n signal.throwIfAborted()\n if (Date.now() >= expiresAt) {\n throw new Error('Device authorization expired')\n }\n // Connection timeouts require a lower polling frequency (RFC8628 section 3.5).\n const tokenResponse = await customFetch(endpoint(tokenUrl), {\n method: 'POST',\n headers,\n body,\n signal: AbortSignal.any([signal, AbortSignal.timeout(REQUEST_TIMEOUT_MS)]),\n }).catch((error: unknown) => {\n signal.throwIfAborted()\n if (error instanceof Error && error.name === 'TimeoutError') {\n return null\n }\n throw error\n })\n if (!tokenResponse) {\n // Saturating at expiry never schedules an earlier poll: the loop expires instead.\n interval = Math.min(interval * 2, expiresAt - Date.now())\n continue\n }\n const token: unknown = await tokenResponse.json()\n if (!isObject(token)) {\n throw new Error('Invalid device token response')\n }\n if (token.error === 'authorization_pending') {\n continue\n }\n if (token.error === 'slow_down') {\n interval = Math.min(interval + 5000, expiresAt - Date.now())\n continue\n }\n const accessToken = token[flow['x-tokenName'] || 'access_token']\n if (tokenResponse.ok && typeof accessToken === 'string' && accessToken) {\n return [\n null,\n { accessToken, ...(typeof token.refresh_token === 'string' ? { refreshToken: token.refresh_token } : {}) },\n ]\n }\n throw new Error(String(token.error_description ?? token.error ?? 'Failed to get an access token'))\n }\n throw new Error('Device authorization expired')\n } catch (error) {\n if (expiry.aborted && !options.signal.aborted) {\n throw new Error('Device authorization expired')\n }\n throw error\n }\n } catch (error) {\n return [error instanceof Error ? error : new Error('Device authorization failed', { cause: error }), null]\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"oauth-device-authorization.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.ts"],"sourcesContent":["import type { ErrorResponse } from '@scalar/helpers/errors/normalize-error'\nimport { isObject } from '@scalar/helpers/object/is-object'\nimport { replaceEnvVariables } from '@scalar/helpers/regex/replace-variables'\nimport { isAllowedOAuthUrl } from '@scalar/helpers/url/is-allowed-oauth-url'\nimport { makeUrlAbsolute } from '@scalar/helpers/url/make-url-absolute'\nimport { redirectToProxy } from '@scalar/helpers/url/redirect-to-proxy'\nimport type { OAuthFlowDeviceAuthorizationSecret } from '@scalar/workspace-store/request-example'\nimport type { ServerObject } from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\n\nimport type { CustomFetch } from '@/v2/blocks/operation-block/helpers/send-request'\n\nimport { type OAuth2Tokens, getActiveServerBase } from './oauth'\nimport { oauthClientAuthorization } from './oauth-client-authorization'\n\nconst REQUEST_TIMEOUT_MS = 30_000\n// Maximum delay supported by the browser timer API.\nconst MAX_TIMEOUT_MS = 2_147_483_647\n\n/** Information the user needs to approve a device without exposing the device code. */\nexport type DeviceAuthorizationPrompt = {\n userCode: string\n verificationUri: string\n verificationUriComplete?: string\n}\n\n/** Device flow UI and cancellation hooks. */\nexport type DeviceAuthorizationOptions = {\n onPrompt: (prompt: DeviceAuthorizationPrompt) => void\n signal: AbortSignal\n}\n\n/** Waits between polls, releasing the timer immediately when cancelled or expired. */\nconst waitForPoll = (milliseconds: number, signal: AbortSignal): Promise<void> =>\n new Promise((resolve, reject) => {\n signal.throwIfAborted()\n const abort = (): void => {\n clearTimeout(timer)\n reject(signal.reason)\n }\n const timer = setTimeout(() => {\n signal.removeEventListener('abort', abort)\n resolve()\n }, milliseconds)\n signal.addEventListener('abort', abort, { once: true })\n })\n\nconst verificationUrl = (value: unknown): string => {\n if (typeof value !== 'string') {\n throw new Error('Missing device verification URL')\n }\n const url = new URL(value)\n if (!isAllowedOAuthUrl(url)) {\n throw new Error('Device verification URL must use HTTPS or HTTP for local development URLs')\n }\n return url.href\n}\n\n/** Performs the RFC8628 device grant, respecting expiry, pending responses, and polling backoff. */\nexport const authorizeDevice = async (\n flow: OAuthFlowDeviceAuthorizationSecret,\n scopes: string[],\n server: ServerObject | null,\n proxyUrl: string,\n environment: Record<string, string>,\n customFetch: CustomFetch = fetch,\n options?: DeviceAuthorizationOptions,\n): Promise<ErrorResponse<OAuth2Tokens>> => {\n try {\n if (!options) {\n throw new Error('Device authorization requires a verification prompt')\n }\n const resolveValue = (value: string): string => replaceEnvVariables(value, environment)\n const endpoint = (value: string): string =>\n redirectToProxy(proxyUrl, makeUrlAbsolute(resolveValue(value), getActiveServerBase(server, environment)))\n const tokenUrl = flow['x-scalar-secret-token-url'] ?? flow.tokenUrl\n if (!tokenUrl.trim()) {\n throw new Error('Token URL is required')\n }\n const clientId = resolveValue(flow['x-scalar-secret-client-id'])\n const clientSecret = resolveValue(flow['x-scalar-secret-client-secret'])\n const headers: Record<string, string> = { 'Content-Type': 'application/x-www-form-urlencoded' }\n const credentials = new URLSearchParams()\n if (clientSecret && flow['x-scalar-credentials-location'] !== 'body') {\n headers.Authorization = oauthClientAuthorization(clientId, clientSecret)\n } else {\n credentials.set('client_id', clientId)\n if (clientSecret) {\n credentials.set('client_secret', clientSecret)\n }\n }\n const deviceBody = new URLSearchParams(credentials)\n if (scopes.length) {\n deviceBody.set('scope', scopes.join(' '))\n }\n const response = await customFetch(endpoint(flow.deviceAuthorizationUrl), {\n method: 'POST',\n headers,\n body: deviceBody,\n signal: AbortSignal.any([options.signal, AbortSignal.timeout(REQUEST_TIMEOUT_MS)]),\n })\n const data: unknown = await response.json()\n options.signal.throwIfAborted()\n if (!isObject(data)) {\n throw new Error('Invalid device authorization response')\n }\n if (!response.ok) {\n throw new Error(String(data.error_description ?? data.error ?? 'Device authorization failed'))\n }\n if (\n typeof data.device_code !== 'string' ||\n !data.device_code ||\n typeof data.user_code !== 'string' ||\n !data.user_code ||\n typeof data.expires_in !== 'number' ||\n !Number.isFinite(data.expires_in) ||\n data.expires_in <= 0 ||\n (data.interval !== undefined &&\n (typeof data.interval !== 'number' || !Number.isFinite(data.interval) || data.interval < 0))\n ) {\n throw new Error('Invalid device authorization response')\n }\n const lifetime = Math.min(data.expires_in * 1000, MAX_TIMEOUT_MS)\n const expiresAt = Date.now() + lifetime\n const expiry = AbortSignal.timeout(lifetime)\n const signal = AbortSignal.any([options.signal, expiry])\n options.onPrompt({\n userCode: data.user_code,\n verificationUri: verificationUrl(data.verification_uri),\n ...(data.verification_uri_complete\n ? { verificationUriComplete: verificationUrl(data.verification_uri_complete) }\n : {}),\n })\n const body = new URLSearchParams(credentials)\n for (const [key, value] of Object.entries(flow['x-scalar-security-body'] ?? {})) {\n body.set(key, resolveValue(value))\n }\n body.set('grant_type', 'urn:ietf:params:oauth:grant-type:device_code')\n body.set('device_code', data.device_code)\n let interval = typeof data.interval === 'number' ? Math.max(1000, data.interval * 1000) : 5000\n try {\n while (Date.now() < expiresAt) {\n await waitForPoll(Math.min(interval, expiresAt - Date.now()), signal)\n signal.throwIfAborted()\n if (Date.now() >= expiresAt) {\n throw new Error('Device authorization expired')\n }\n // Connection timeouts require a lower polling frequency (RFC8628 section 3.5).\n const tokenResponse = await customFetch(endpoint(tokenUrl), {\n method: 'POST',\n headers,\n body,\n signal: AbortSignal.any([signal, AbortSignal.timeout(REQUEST_TIMEOUT_MS)]),\n }).catch((error: unknown) => {\n signal.throwIfAborted()\n if (error instanceof Error && error.name === 'TimeoutError') {\n return null\n }\n throw error\n })\n if (!tokenResponse) {\n // Saturating at expiry never schedules an earlier poll: the loop expires instead.\n interval = Math.min(interval * 2, expiresAt - Date.now())\n continue\n }\n const token: unknown = await tokenResponse.json()\n if (!isObject(token)) {\n throw new Error('Invalid device token response')\n }\n if (token.error === 'authorization_pending') {\n continue\n }\n if (token.error === 'slow_down') {\n interval = Math.min(interval + 5000, expiresAt - Date.now())\n continue\n }\n const accessToken = token[flow['x-tokenName'] || 'access_token']\n if (tokenResponse.ok && typeof accessToken === 'string' && accessToken) {\n return [\n null,\n { accessToken, ...(typeof token.refresh_token === 'string' ? { refreshToken: token.refresh_token } : {}) },\n ]\n }\n throw new Error(String(token.error_description ?? token.error ?? 'Failed to get an access token'))\n }\n throw new Error('Device authorization expired')\n } catch (error) {\n if (expiry.aborted && !options.signal.aborted) {\n throw new Error('Device authorization expired')\n }\n throw error\n }\n } catch (error) {\n return [error instanceof Error ? error : new Error('Device authorization failed', { cause: error }), null]\n }\n}\n"],"mappings":"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"}