@scalar/api-client 3.21.3 → 3.21.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +20 -0
- package/dist/plugins/posthog/sanitize-event-payload.d.ts.map +1 -1
- package/dist/plugins/posthog/sanitize-event-payload.js +1 -0
- package/dist/plugins/posthog/sanitize-event-payload.js.map +1 -1
- package/dist/style.css +59 -49
- package/dist/v2/blocks/operation-block/OperationBlock.vue.d.ts.map +1 -1
- package/dist/v2/blocks/operation-block/OperationBlock.vue.js.map +1 -1
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js +1 -1
- package/dist/v2/blocks/operation-block/OperationBlock.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.js +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js +1 -1
- package/dist/v2/blocks/request-block/components/RequestBody.vue.script.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.d.ts.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.js.map +1 -1
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js +3 -0
- package/dist/v2/blocks/request-block/components/RequestCodeSnippet.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.js +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.script.js +1 -1
- package/dist/v2/blocks/scalar-address-bar-block/components/AddressBarHistory.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/AuthSelector.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js +53 -22
- package/dist/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.d.ts +4 -0
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.script.js +23 -12
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js +30 -6
- package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue.script.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.js +3 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth-device-authorization.js.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.d.ts.map +1 -1
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js +9 -3
- package/dist/v2/blocks/scalar-auth-selector-block/helpers/oauth.js.map +1 -1
- package/dist/v2/components/code-input/CodeInput.vue.d.ts.map +1 -1
- package/dist/v2/components/code-input/CodeInput.vue.js +1 -1
- package/dist/v2/components/code-input/CodeInput.vue.js.map +1 -1
- package/dist/v2/components/code-input/CodeInput.vue.script.js.map +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.d.ts.map +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.js +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.js.map +1 -1
- package/dist/v2/components/data-table/DataTableInput.vue.script.js +15 -11
- package/dist/v2/components/data-table/DataTableInput.vue.script.js.map +1 -1
- package/dist/v2/components/server/ServerDropdown.vue.d.ts.map +1 -1
- package/dist/v2/components/server/ServerDropdown.vue.js.map +1 -1
- package/dist/v2/components/server/ServerDropdown.vue.script.js +1 -1
- package/dist/v2/components/server/ServerDropdown.vue.script.js.map +1 -1
- package/dist/v2/constants.js +1 -1
- package/dist/v2/features/localization/locales/ar.d.ts +3 -0
- package/dist/v2/features/localization/locales/ar.d.ts.map +1 -1
- package/dist/v2/features/localization/locales/ar.js +4 -1
- package/dist/v2/features/localization/locales/ar.js.map +1 -1
- package/dist/v2/features/localization/locales/de.d.ts +3 -0
- package/dist/v2/features/localization/locales/de.d.ts.map +1 -1
- package/dist/v2/features/localization/locales/de.js +4 -1
- package/dist/v2/features/localization/locales/de.js.map +1 -1
- package/dist/v2/features/localization/locales/es.d.ts +3 -0
- package/dist/v2/features/localization/locales/es.d.ts.map +1 -1
- package/dist/v2/features/localization/locales/es.js +4 -1
- package/dist/v2/features/localization/locales/es.js.map +1 -1
- package/dist/v2/features/localization/locales/fr.d.ts +3 -0
- package/dist/v2/features/localization/locales/fr.d.ts.map +1 -1
- package/dist/v2/features/localization/locales/fr.js +4 -1
- package/dist/v2/features/localization/locales/fr.js.map +1 -1
- package/dist/v2/features/localization/locales/pt.d.ts +3 -0
- package/dist/v2/features/localization/locales/pt.d.ts.map +1 -1
- package/dist/v2/features/localization/locales/pt.js +4 -1
- package/dist/v2/features/localization/locales/pt.js.map +1 -1
- package/dist/v2/features/localization/locales/ru.d.ts +3 -0
- package/dist/v2/features/localization/locales/ru.d.ts.map +1 -1
- package/dist/v2/features/localization/locales/ru.js +4 -1
- package/dist/v2/features/localization/locales/ru.js.map +1 -1
- package/dist/v2/features/localization/locales/zh-cn.d.ts +3 -0
- package/dist/v2/features/localization/locales/zh-cn.d.ts.map +1 -1
- package/dist/v2/features/localization/locales/zh-cn.js +4 -1
- package/dist/v2/features/localization/locales/zh-cn.js.map +1 -1
- package/dist/v2/features/localization/translations.d.ts +3 -0
- package/dist/v2/features/localization/translations.d.ts.map +1 -1
- package/dist/v2/features/localization/translations.js +4 -1
- package/dist/v2/features/localization/translations.js.map +1 -1
- package/dist/v2/workspace-events.d.ts.map +1 -1
- package/dist/v2/workspace-events.js +1 -0
- package/dist/v2/workspace-events.js.map +1 -1
- package/dist/vue-styles.css +29 -31
- package/package.json +11 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OAuth2.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Any config options required for the OAuth2 flow */\nexport type OAuth2Options = Pick<\n ApiClientConfiguration,\n 'oauth2RedirectUri'\n> & {\n /** Optional fetch override (IPC-backed on desktop) used for token exchange, refresh, and OIDC discovery */\n customFetch?: typeof fetch\n /** Optional redirect capture (loopback-backed on desktop) for interactive OAuth2 flows */\n captureOAuth2Callback?: CaptureOAuth2Callback\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport { useLoadingState } from '@scalar/components/loading'\nimport type { ApiClientConfiguration } from '@scalar/types/api-reference'\nimport { pkceOptions } from '@scalar/types/entities'\nimport { useToasts } from '@scalar/use-toasts'\nimport type { SecretsOAuthFlows } from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport {\n getEnvironmentVariables,\n type OAuthFlowAuthorizationCodeSecret,\n type OAuthFlowClientCredentialsSecret,\n type OAuthFlowPasswordSecret,\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 type { XScalarCredentialsLocation } from '@scalar/workspace-store/schemas/extensions/security/x-scalar-credentials-location'\nimport { type XusePkce } from '@scalar/workspace-store/schemas/extensions/security/x-use-pkce'\nimport type {\n OAuthFlow,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { computed, onBeforeUnmount, ref, watch } from 'vue'\n\nimport OAuthScopesInput from '@/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue'\nimport {\n authorizeOauth2,\n refreshOauth2Token,\n type CaptureOAuth2Callback,\n} from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth'\nimport { resolveDefaultOAuth2RedirectUri } from '@/v2/blocks/scalar-auth-selector-block/helpers/resolve-default-oauth2-redirect-url'\nimport { DataTableRow } from '@/v2/components/data-table'\nimport { useLocalization } from '@/v2/features/localization'\n\nimport type { DeviceAuthorizationPrompt } from '../helpers/oauth-device-authorization'\nimport RequestAuthDataTableInput from './RequestAuthDataTableInput.vue'\n\nconst {\n environment,\n flows,\n type,\n scheme,\n selectedScopes: selectedScopesProp,\n server,\n proxyUrl,\n eventBus,\n name,\n options = {},\n} = defineProps<{\n /** Current environment configuration */\n environment: XScalarEnvironment\n /** OAuth flows */\n flows: OAuthFlowsObjectSecret\n /** Type of the OAuth flow */\n type: keyof OAuthFlowsObjectSecret\n /** Selected scopes */\n selectedScopes: string[]\n /** Security scheme */\n scheme: SecuritySchemeObjectSecret\n /** Current server configuration */\n server: ServerObject | null\n /** Proxy URL */\n proxyUrl: string\n /** Name of the security scheme */\n name: string\n /** Event bus for authentication updates */\n eventBus: WorkspaceEventBus\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n /**\n * Hides the Authorize / Refresh / Clear actions. Used when the form is embedded as a\n * configuration-only view (e.g. behind a gear icon), so the host component owns the\n * authorize action and the tokens are routed to the scheme it chooses.\n */\n hideActions?: boolean\n}>()\n\nconst emits = defineEmits<{\n (\n e: 'update:selectedScopes',\n payload: { scopes?: string[]; scope?: string; selected?: boolean },\n ): void\n (\n e: 'upsert:scope',\n payload: Omit<ApiReferenceEvents['auth:upsert:scopes'], 'name'>,\n ): void\n (\n e: 'delete:scope',\n payload: Omit<ApiReferenceEvents['auth:delete:scopes'], 'name'>,\n ): void\n}>()\n\nconst devicePrompt = ref<DeviceAuthorizationPrompt | null>(null)\nlet deviceController: AbortController | undefined\nconst cancelDeviceAuthorization = (): void => {\n deviceController?.abort()\n devicePrompt.value = null\n}\nonBeforeUnmount(cancelDeviceAuthorization)\nwatch(() => [type, name, flows], cancelDeviceAuthorization)\n\nconst { translate } = useLocalization()\n\nconst loader = useLoadingState()\nconst { toast } = useToasts()\n\n/** The current OAuth flow based on the selected type */\nconst flow = computed(() => flows[type]!)\ntype NonImplicitFlow =\n | OAuthFlowPasswordSecret\n | OAuthFlowClientCredentialsSecret\n | OAuthFlowAuthorizationCodeSecret\n\n/** We filter selected scopes to only include scopes that are defined on this flow (own keys only). */\nconst selectedScopes = computed(() => {\n const definedScopes = flow.value.scopes\n if (!definedScopes) {\n return []\n }\n return selectedScopesProp.filter((scope) =>\n Object.hasOwn(definedScopes, scope),\n )\n})\n\n/**\n * Show the client secret whenever the flow supports one. PKCE and a client\n * secret are independent, so confidential clients can use both together\n * (see RFC 9700 Section 2.1.1).\n */\nconst showClientSecret = computed(\n () => 'x-scalar-secret-client-secret' in flow.value,\n)\n\nconst clientSecretValue = computed((): string => {\n const f = flow.value as { 'x-scalar-secret-client-secret'?: string }\n return f['x-scalar-secret-client-secret'] ?? ''\n})\n\n/** Updates the security scheme base */\nconst handleOauth2Update = (\n payload: Partial<OAuthFlow & XScalarCredentialsLocation> & {\n deviceAuthorizationUrl?: string\n },\n): void => {\n // OpenIdConnect uses the secrets update for all\n if (scheme.type === 'openIdConnect') {\n return handleOauth2SecretsUpdate(payload)\n }\n\n // Only OAuth2 schemes carry flows on the document; this component is never\n // rendered for the other scheme types.\n if (scheme.type !== 'oauth2') {\n return\n }\n\n eventBus.emit('auth:update:security-scheme', {\n payload: {\n type: scheme.type,\n flows: {\n [type]: payload,\n },\n },\n name,\n })\n}\n\n/** Updates the flow secrets */\nconst handleOauth2SecretsUpdate = (\n payload: Omit<Partial<SecretsOAuthFlows[keyof SecretsOAuthFlows]>, 'type'>,\n): void => {\n // This component only renders for oauth2/openIdConnect. Other scheme types (e.g. mutualTLS)\n // carry no flow secrets, so there is nothing to persist and no matching secrets payload type.\n if (scheme.type !== 'oauth2' && scheme.type !== 'openIdConnect') {\n return\n }\n\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: {\n type: scheme.type,\n [type]: payload,\n },\n name,\n })\n}\n\n/** Clears the flow secrets */\nconst clearOauth2Secrets = (): void => {\n if (loader.isLoading) {\n return\n }\n eventBus.emit('auth:clear:security-scheme-secrets', {\n name,\n })\n}\n\n/** Clears stored access and refresh tokens (authorized state) */\nconst handleClearAccessTokens = (): void => {\n if (loader.isLoading) {\n return\n }\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': '',\n 'x-scalar-secret-refresh-token': '',\n })\n}\n\n/** Track redirect URI prefill per flow instance to support document switching */\nconst prefilledFlowIdentity = ref<string | null>(null)\nconst hasHandledRedirectPrefill = ref(false)\n\nconst resolveFlowIdentity = (\n currentFlow: OAuthFlowsObjectSecret[keyof OAuthFlowsObjectSecret] | undefined,\n): string =>\n JSON.stringify({\n type,\n authorizationUrl:\n currentFlow && 'authorizationUrl' in currentFlow\n ? currentFlow.authorizationUrl\n : '',\n tokenUrl:\n currentFlow && 'tokenUrl' in currentFlow ? currentFlow.tokenUrl : '',\n refreshUrl: currentFlow?.refreshUrl ?? '',\n scopes: Object.keys(currentFlow?.scopes ?? {}),\n })\n\n/** Default the redirect-uri to the current origin if we have access to window */\nwatch(\n () => flow.value,\n (currentFlow) => {\n if (!currentFlow || !('x-scalar-secret-redirect-uri' in currentFlow)) {\n return\n }\n\n const flowIdentity = resolveFlowIdentity(currentFlow)\n if (prefilledFlowIdentity.value !== flowIdentity) {\n prefilledFlowIdentity.value = flowIdentity\n hasHandledRedirectPrefill.value = false\n }\n\n if (hasHandledRedirectPrefill.value) {\n return\n }\n\n const newRedirectUri = (currentFlow as OAuthFlowAuthorizationCodeSecret)[\n 'x-scalar-secret-redirect-uri'\n ]\n const defaultRedirectUri = resolveDefaultOAuth2RedirectUri(options)\n\n hasHandledRedirectPrefill.value = true\n\n // The desktop loopback path computes the redirect URI at authorize time (an\n // ephemeral 127.0.0.1 port), so persisting a default into the document would\n // only bake in a stale, unused value. Leave it empty and show a hint instead.\n if (\n newRedirectUri ||\n !defaultRedirectUri ||\n options.captureOAuth2Callback\n ) {\n return\n }\n\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-redirect-uri': defaultRedirectUri,\n })\n },\n { immediate: true },\n)\n\n/**\n * Authorizes the user using the specified OAuth flow.\n * Opens the appropriate OAuth dialog and/or performs the token exchange.\n */\nconst handleAuthorize = async (): Promise<void> => {\n if (loader.isLoading) {\n return\n }\n\n loader.start()\n const controller = new AbortController()\n deviceController = controller\n\n const [error, tokens] = await authorizeOauth2(\n flows,\n type,\n selectedScopes.value,\n server,\n proxyUrl,\n getEnvironmentVariables(environment),\n options.customFetch,\n options.captureOAuth2Callback,\n {\n signal: controller.signal,\n onPrompt: (prompt) => {\n devicePrompt.value = prompt\n },\n },\n )\n devicePrompt.value = null\n\n await loader.clear()\n if (controller.signal.aborted) {\n return\n }\n\n if (tokens?.accessToken) {\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': tokens.accessToken,\n ...(tokens.refreshToken\n ? { 'x-scalar-secret-refresh-token': tokens.refreshToken }\n : {}),\n })\n } else {\n console.error(error)\n toast(\n error?.message ?? translate('apiClient.oauth2.failedToauthorize'),\n 'error',\n )\n }\n}\n\n/** Refreshing requires a token issued by the provider, not just a compatible flow. */\nconst canRefreshToken = computed<boolean>(\n (): boolean =>\n type !== 'implicit' && Boolean(flow.value['x-scalar-secret-refresh-token']),\n)\n\n/**\n * Refresh URL placeholder, shows tokenUrl as hint if refreshUrl is not specified.\n * This helps users understand that tokenUrl will be used as fallback.\n */\nconst refreshUrlPlaceholder = computed(() => {\n if ('tokenUrl' in flow.value && flow.value.tokenUrl) {\n return flow.value.tokenUrl\n }\n return 'https://galaxy.scalar.com/oauth/refresh'\n})\n\n/**\n * Uses the stored refresh token to obtain a new access token\n * via grant_type=refresh_token.\n */\nconst handleRefresh = async (): Promise<void> => {\n // The explicit flow check narrows the type for refreshOauth2Token; the computed boolean cannot.\n if (loader.isLoading || type === 'implicit' || !canRefreshToken.value) {\n return\n }\n\n loader.start()\n\n const [error, tokens] = await refreshOauth2Token(\n flows,\n type,\n proxyUrl,\n server,\n getEnvironmentVariables(environment),\n options.customFetch,\n )\n\n await loader.clear()\n\n if (tokens?.accessToken) {\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': tokens.accessToken,\n ...(tokens.refreshToken\n ? { 'x-scalar-secret-refresh-token': tokens.refreshToken }\n : {}),\n })\n } else {\n console.error(error)\n toast(\n error?.message ?? translate('apiClient.oauth2.failedToRefreshToken'),\n 'error',\n )\n }\n}\n\n/** Updates the secret location */\nconst handleSecretLocationUpdate = (value: string): void => {\n const credentialsLocation = value === 'body' ? 'body' : 'header'\n\n if (scheme.type !== 'openIdConnect') {\n handleOauth2Update({\n 'x-scalar-credentials-location': credentialsLocation,\n })\n }\n\n handleOauth2SecretsUpdate({\n 'x-scalar-credentials-location': credentialsLocation,\n })\n}\n</script>\n\n<template>\n <!-- Access Token Display: Shows when user is already authorized -->\n <template v-if=\"Boolean(flow['x-scalar-secret-token'])\">\n <DataTableRow>\n <RequestAuthDataTableInput\n class=\"border-r-transparent\"\n :environment\n :modelValue=\"flow['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-token': v })\n \">\n {{ translate('apiClient.oauth2.accessToken') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"canRefreshToken\">\n <RequestAuthDataTableInput\n class=\"border-r-transparent\"\n :environment\n :modelValue=\"flow.refreshUrl ?? ''\"\n :placeholder=\"refreshUrlPlaceholder\"\n @update:modelValue=\"(v) => handleOauth2Update({ refreshUrl: v })\">\n {{ translate('apiClient.oauth2.refreshUrl') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow\n v-if=\"!hideActions\"\n class=\"min-w-full\">\n <div class=\"flex h-8 items-center justify-end gap-2 border-t\">\n <ScalarButton\n v-if=\"canRefreshToken\"\n class=\"p-0 px-2 py-0.5\"\n :loader\n size=\"sm\"\n variant=\"outlined\"\n @click=\"handleRefresh\">\n {{ translate('apiClient.oauth2.refresh') }}\n </ScalarButton>\n <ScalarButton\n class=\"mr-1 p-0 px-2 py-0.5\"\n :disabled=\"loader.isLoading\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"handleClearAccessTokens\">\n {{ translate('apiClient.oauth2.clear') }}\n </ScalarButton>\n </div>\n </DataTableRow>\n </template>\n\n <!-- Authorization Form: Shows when user needs to authorize -->\n <template v-else>\n <DataTableRow v-if=\"'deviceAuthorizationUrl' in flow\">\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow.deviceAuthorizationUrl\"\n @update:modelValue=\"\n (v) => handleOauth2Update({ deviceAuthorizationUrl: v })\n \">\n {{ translate('apiClient.oauth2.deviceAuthorizationUrl') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow v-if=\"devicePrompt\">\n <div class=\"w-full p-2\">\n <div\n class=\"bg-b-2 flex flex-col gap-3 rounded-lg border p-3 text-sm\"\n role=\"status\">\n <p class=\"text-c-2 text-xs leading-normal\">\n {{ translate('apiClient.oauth2.deviceVerificationPrompt') }}\n </p>\n <strong\n class=\"bg-b-1 font-code w-fit max-w-full rounded border px-3 py-2 text-base font-medium tracking-widest break-all select-all\">\n {{ devicePrompt.userCode }}\n </strong>\n <a\n class=\"text-c-accent w-fit max-w-full text-xs break-all underline underline-offset-2\"\n :href=\"\n devicePrompt.verificationUriComplete ||\n devicePrompt.verificationUri\n \"\n rel=\"noopener noreferrer\"\n target=\"_blank\">\n {{ devicePrompt.verificationUri }}\n </a>\n <div class=\"flex items-center justify-between gap-3\">\n <p class=\"text-c-2 text-xs\">\n {{ translate('apiClient.oauth2.waitingForAuthorization') }}\n </p>\n <ScalarButton\n size=\"xs\"\n variant=\"outlined\"\n @click=\"cancelDeviceAuthorization\">\n {{ translate('apiClient.oauth2.cancelDeviceAuthorization') }}\n </ScalarButton>\n </div>\n </div>\n </div>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n v-if=\"'authorizationUrl' in flow\"\n containerClass=\"border-r-0\"\n :environment\n :modelValue=\"flow['x-scalar-secret-auth-url'] ?? ''\"\n placeholder=\"https://galaxy.scalar.com/authorize\"\n @update:modelValue=\"\n (v) => {\n handleOauth2SecretsUpdate({ 'x-scalar-secret-auth-url': v })\n handleOauth2Update({ authorizationUrl: v })\n }\n \">\n {{ translate('apiClient.oauth2.authUrl') }}\n </RequestAuthDataTableInput>\n\n <RequestAuthDataTableInput\n v-if=\"'tokenUrl' in flow\"\n :environment\n :modelValue=\"flow['x-scalar-secret-token-url'] ?? ''\"\n placeholder=\"https://galaxy.scalar.com/token\"\n @update:modelValue=\"\n (v) => {\n handleOauth2SecretsUpdate({ 'x-scalar-secret-token-url': v })\n handleOauth2Update({ tokenUrl: v })\n }\n \">\n {{ translate('apiClient.oauth2.tokenUrl') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-scalar-secret-redirect-uri' in flow\">\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-redirect-uri']\"\n :placeholder=\"\n options.captureOAuth2Callback\n ? `${resolveDefaultOAuth2RedirectUri(options) || 'http://127.0.0.1'} (handled automatically)`\n : translate('apiClient.oauth2.optionalRedirectUrl')\n \"\n @update:modelValue=\"\n (v) => {\n hasHandledRedirectPrefill = true\n handleOauth2SecretsUpdate({ 'x-scalar-secret-redirect-uri': v })\n }\n \">\n {{ translate('apiClient.oauth2.redirectUrl') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <template\n v-if=\"\n 'x-scalar-secret-username' in flow && 'x-scalar-secret-password' in flow\n \">\n <DataTableRow>\n <RequestAuthDataTableInput\n class=\"text-c-2\"\n :environment\n :modelValue=\"flow['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-username': v })\n \">\n {{ translate('apiClient.oauth2.username') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow>\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-password': v })\n \">\n {{ translate('apiClient.oauth2.password') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n\n <DataTableRow>\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow['x-scalar-secret-client-id']\"\n placeholder=\"12345\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-client-id': v })\n \">\n {{ translate('apiClient.oauth2.clientID') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"showClientSecret\">\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"clientSecretValue\"\n placeholder=\"XYZ123\"\n type=\"password\"\n @update:modelValue=\"\n (v) =>\n handleOauth2SecretsUpdate({ 'x-scalar-secret-client-secret': v })\n \">\n {{ translate('apiClient.oauth2.clientSecret') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-usePkce' in flow\">\n <RequestAuthDataTableInput\n :enum=\"pkceOptions\"\n :environment\n :modelValue=\"flow['x-usePkce']\"\n readOnly\n @update:modelValue=\"\n (v) =>\n handleOauth2Update({\n 'x-usePkce': v as XusePkce['x-usePkce'],\n })\n \">\n {{ translate('apiClient.oauth2.usePKCE') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- Credentials Location -->\n <DataTableRow v-if=\"type !== 'implicit'\">\n <RequestAuthDataTableInput\n :enum=\"['header', 'body']\"\n :environment\n :modelValue=\"\n (flow as NonImplicitFlow)['x-scalar-credentials-location'] || 'header'\n \"\n placeholder=\"header\"\n readOnly\n @update:modelValue=\"(v) => handleSecretLocationUpdate(v)\">\n {{ translate('apiClient.oauth2.credentialsLocation') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- Scopes -->\n <DataTableRow>\n <OAuthScopesInput\n :flow\n :flowType=\"type\"\n :selectedScopes\n @delete:scope=\"(v) => emits('delete:scope', v)\"\n @update:selectedScopes=\"(v) => emits('update:selectedScopes', v)\"\n @upsert:scope=\"(v) => emits('upsert:scope', v)\" />\n </DataTableRow>\n\n <DataTableRow\n v-if=\"!hideActions\"\n class=\"min-w-full\">\n <div class=\"flex h-8 w-full items-center justify-end border-t\">\n <!-- Allow clearing the oauth section and going back to discovery -->\n <ScalarButton\n v-if=\"scheme.type === 'openIdConnect'\"\n class=\"mr-1 p-0 px-2 py-0.5\"\n :disabled=\"loader.isLoading\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"clearOauth2Secrets\">\n {{ translate('apiClient.oauth2.clear') }}\n </ScalarButton>\n\n <ScalarButton\n class=\"mr-0.75 p-0 px-2 py-0.5\"\n :loader\n size=\"sm\"\n variant=\"outlined\"\n @click=\"handleAuthorize\">\n {{ translate('apiClient.oauth2.authorize') }}\n </ScalarButton>\n </div>\n </DataTableRow>\n </template>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"OAuth2.vue.script.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/OAuth2.vue"],"sourcesContent":["<script lang=\"ts\">\n/** Any config options required for the OAuth2 flow */\nexport type OAuth2Options = Pick<\n ApiClientConfiguration,\n 'oauth2RedirectUri'\n> & {\n /** Optional fetch override (IPC-backed on desktop) used for token exchange, refresh, and OIDC discovery */\n customFetch?: typeof fetch\n /** Optional redirect capture (loopback-backed on desktop) for interactive OAuth2 flows */\n captureOAuth2Callback?: CaptureOAuth2Callback\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ScalarButton } from '@scalar/components/button'\nimport { useLoadingState } from '@scalar/components/loading'\nimport type { ApiClientConfiguration } from '@scalar/types/api-reference'\nimport { pkceOptions } from '@scalar/types/entities'\nimport { useToasts } from '@scalar/use-toasts'\nimport type { SecretsOAuthFlows } from '@scalar/workspace-store/entities/auth'\nimport type {\n ApiReferenceEvents,\n WorkspaceEventBus,\n} from '@scalar/workspace-store/events'\nimport {\n isSecretFieldCleared,\n type AuthSecretField,\n} from '@scalar/workspace-store/helpers/auth-secret-fields'\nimport {\n getEnvironmentVariables,\n type OAuthFlowAuthorizationCodeSecret,\n type OAuthFlowClientCredentialsSecret,\n type OAuthFlowPasswordSecret,\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 type { XScalarCredentialsLocation } from '@scalar/workspace-store/schemas/extensions/security/x-scalar-credentials-location'\nimport type {\n OAuthFlow,\n ServerObject,\n} from '@scalar/workspace-store/schemas/v3.2/strict/openapi-document'\nimport { computed, onBeforeUnmount, ref, watch } from 'vue'\n\nimport OAuthScopesInput from '@/v2/blocks/scalar-auth-selector-block/components/OAuthScopesInput.vue'\nimport {\n authorizeOauth2,\n refreshOauth2Token,\n type CaptureOAuth2Callback,\n} from '@/v2/blocks/scalar-auth-selector-block/helpers/oauth'\nimport { resolveDefaultOAuth2RedirectUri } from '@/v2/blocks/scalar-auth-selector-block/helpers/resolve-default-oauth2-redirect-url'\nimport { DataTableRow } from '@/v2/components/data-table'\nimport { useLocalization } from '@/v2/features/localization'\n\nimport type { DeviceAuthorizationPrompt } from '../helpers/oauth-device-authorization'\nimport RequestAuthDataTableInput from './RequestAuthDataTableInput.vue'\n\nconst {\n environment,\n flows,\n type,\n scheme,\n selectedScopes: selectedScopesProp,\n server,\n proxyUrl,\n eventBus,\n name,\n options = {},\n} = defineProps<{\n /** Current environment configuration */\n environment: XScalarEnvironment\n /** OAuth flows */\n flows: OAuthFlowsObjectSecret\n /** Type of the OAuth flow */\n type: keyof OAuthFlowsObjectSecret\n /** Selected scopes */\n selectedScopes: string[]\n /** Security scheme */\n scheme: SecuritySchemeObjectSecret\n /** Current server configuration */\n server: ServerObject | null\n /** Proxy URL */\n proxyUrl: string\n /** Name of the security scheme */\n name: string\n /** Event bus for authentication updates */\n eventBus: WorkspaceEventBus\n /** Any config options required for the OAuth2 flow */\n options?: OAuth2Options\n /**\n * Hides the Authorize / Refresh / Clear actions. Used when the form is embedded as a\n * configuration-only view (e.g. behind a gear icon), so the host component owns the\n * authorize action and the tokens are routed to the scheme it chooses.\n */\n hideActions?: boolean\n}>()\n\nconst emits = defineEmits<{\n (\n e: 'update:selectedScopes',\n payload: { scopes?: string[]; scope?: string; selected?: boolean },\n ): void\n (\n e: 'upsert:scope',\n payload: Omit<ApiReferenceEvents['auth:upsert:scopes'], 'name'>,\n ): void\n (\n e: 'delete:scope',\n payload: Omit<ApiReferenceEvents['auth:delete:scopes'], 'name'>,\n ): void\n}>()\n\nconst devicePrompt = ref<DeviceAuthorizationPrompt | null>(null)\nlet deviceController: AbortController | undefined\nconst cancelDeviceAuthorization = (): void => {\n deviceController?.abort()\n devicePrompt.value = null\n}\nonBeforeUnmount(cancelDeviceAuthorization)\nwatch(() => [type, name, flows], cancelDeviceAuthorization)\n\nconst { translate } = useLocalization()\n\nconst loader = useLoadingState()\nconst { toast } = useToasts()\n\n/** The current OAuth flow based on the selected type */\nconst flow = computed(() => flows[type]!)\ntype NonImplicitFlow =\n | OAuthFlowPasswordSecret\n | OAuthFlowClientCredentialsSecret\n | OAuthFlowAuthorizationCodeSecret\n\n/** We filter selected scopes to only include scopes that are defined on this flow (own keys only). */\nconst selectedScopes = computed(() => {\n const definedScopes = flow.value.scopes\n if (!definedScopes) {\n return []\n }\n return selectedScopesProp.filter((scope) =>\n Object.hasOwn(definedScopes, scope),\n )\n})\n\n/**\n * Show the client secret whenever the flow supports one. PKCE and a client\n * secret are independent, so confidential clients can use both together\n * (see RFC 9700 Section 2.1.1).\n */\nconst showClientSecret = computed(\n () => 'x-scalar-secret-client-secret' in flow.value,\n)\n\nconst clientSecretValue = computed((): string => {\n const f = flow.value as { 'x-scalar-secret-client-secret'?: string }\n return f['x-scalar-secret-client-secret'] ?? ''\n})\n\n/** Updates the security scheme base */\nconst handleOauth2Update = (\n payload: Partial<OAuthFlow & XScalarCredentialsLocation> & {\n deviceAuthorizationUrl?: string\n },\n): void => {\n // OpenIdConnect uses the secrets update for all\n if (scheme.type === 'openIdConnect') {\n return handleOauth2SecretsUpdate(payload)\n }\n\n // Only OAuth2 schemes carry flows on the document; this component is never\n // rendered for the other scheme types.\n if (scheme.type !== 'oauth2') {\n return\n }\n\n eventBus.emit('auth:update:security-scheme', {\n payload: {\n type: scheme.type,\n flows: {\n [type]: payload,\n },\n },\n name,\n })\n}\n\n/** Updates the flow secrets */\nconst handleOauth2SecretsUpdate = (\n payload: Omit<Partial<SecretsOAuthFlows[keyof SecretsOAuthFlows]>, 'type'>,\n): void => {\n // This component only renders for oauth2/openIdConnect. Other scheme types (e.g. mutualTLS)\n // carry no flow secrets, so there is nothing to persist and no matching secrets payload type.\n if (scheme.type !== 'oauth2' && scheme.type !== 'openIdConnect') {\n return\n }\n\n eventBus.emit('auth:update:security-scheme-secrets', {\n payload: {\n type: scheme.type,\n [type]: payload,\n },\n name,\n })\n}\n\n/** Reset only this field; redirect URI may need its browser default prefilled again. */\nconst handleResetSecret = (field: AuthSecretField): void => {\n if (field === 'x-scalar-secret-redirect-uri') {\n hasHandledRedirectPrefill.value = false\n }\n eventBus.emit('auth:reset:security-scheme-secret', {\n name,\n flow: type,\n field,\n })\n}\n\n/** Fixed-choice fields must never write an empty string into the document. */\nconst handlePkceUpdate = (value: string): void => {\n if (value === 'SHA-256' || value === 'plain' || value === 'no') {\n handleOauth2Update({ 'x-usePkce': value })\n }\n}\n\n/** Clears the flow secrets */\nconst clearOauth2Secrets = (): void => {\n if (loader.isLoading) {\n return\n }\n eventBus.emit('auth:clear:security-scheme-secrets', {\n name,\n })\n}\n\n/** Clears stored access and refresh tokens (authorized state) */\nconst handleClearAccessTokens = (): void => {\n if (loader.isLoading) {\n return\n }\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': '',\n 'x-scalar-secret-refresh-token': '',\n })\n}\n\n/** Track redirect URI prefill per flow instance to support document switching */\nconst prefilledFlowIdentity = ref<string | null>(null)\nconst hasHandledRedirectPrefill = ref(false)\n\nconst resolveFlowIdentity = (\n currentFlow: OAuthFlowsObjectSecret[keyof OAuthFlowsObjectSecret] | undefined,\n): string =>\n JSON.stringify({\n type,\n authorizationUrl:\n currentFlow && 'authorizationUrl' in currentFlow\n ? currentFlow.authorizationUrl\n : '',\n tokenUrl:\n currentFlow && 'tokenUrl' in currentFlow ? currentFlow.tokenUrl : '',\n refreshUrl: currentFlow?.refreshUrl ?? '',\n scopes: Object.keys(currentFlow?.scopes ?? {}),\n })\n\n/** Default the redirect-uri to the current origin if we have access to window */\nwatch(\n () => flow.value,\n (currentFlow) => {\n if (!currentFlow || !('x-scalar-secret-redirect-uri' in currentFlow)) {\n return\n }\n\n const flowIdentity = resolveFlowIdentity(currentFlow)\n if (prefilledFlowIdentity.value !== flowIdentity) {\n prefilledFlowIdentity.value = flowIdentity\n hasHandledRedirectPrefill.value = false\n }\n\n if (hasHandledRedirectPrefill.value) {\n return\n }\n\n const newRedirectUri = (currentFlow as OAuthFlowAuthorizationCodeSecret)[\n 'x-scalar-secret-redirect-uri'\n ]\n const defaultRedirectUri = resolveDefaultOAuth2RedirectUri(options)\n\n hasHandledRedirectPrefill.value = true\n\n // The desktop loopback path computes the redirect URI at authorize time (an\n // ephemeral 127.0.0.1 port), so persisting a default into the document would\n // only bake in a stale, unused value. Leave it empty and show a hint instead.\n if (\n isSecretFieldCleared(currentFlow, 'x-scalar-secret-redirect-uri') ||\n newRedirectUri ||\n !defaultRedirectUri ||\n options.captureOAuth2Callback\n ) {\n return\n }\n\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-redirect-uri': defaultRedirectUri,\n })\n },\n { immediate: true },\n)\n\n/**\n * Authorizes the user using the specified OAuth flow.\n * Opens the appropriate OAuth dialog and/or performs the token exchange.\n */\nconst handleAuthorize = async (): Promise<void> => {\n if (loader.isLoading) {\n return\n }\n\n loader.start()\n const controller = new AbortController()\n deviceController = controller\n\n const [error, tokens] = await authorizeOauth2(\n flows,\n type,\n selectedScopes.value,\n server,\n proxyUrl,\n getEnvironmentVariables(environment),\n options.customFetch,\n options.captureOAuth2Callback,\n {\n signal: controller.signal,\n onPrompt: (prompt) => {\n devicePrompt.value = prompt\n },\n },\n )\n devicePrompt.value = null\n\n await loader.clear()\n if (controller.signal.aborted) {\n return\n }\n\n if (tokens?.accessToken) {\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': tokens.accessToken,\n ...(tokens.refreshToken\n ? { 'x-scalar-secret-refresh-token': tokens.refreshToken }\n : {}),\n })\n } else {\n console.error(error)\n toast(\n error?.message ?? translate('apiClient.oauth2.failedToauthorize'),\n 'error',\n )\n }\n}\n\n/** Refreshing requires a token issued by the provider, not just a compatible flow. */\nconst canRefreshToken = computed<boolean>(\n (): boolean =>\n type !== 'implicit' && Boolean(flow.value['x-scalar-secret-refresh-token']),\n)\n\n/**\n * Refresh URL placeholder, shows tokenUrl as hint if refreshUrl is not specified.\n * This helps users understand that tokenUrl will be used as fallback.\n */\nconst refreshUrlPlaceholder = computed(() => {\n if ('tokenUrl' in flow.value && flow.value.tokenUrl) {\n return flow.value.tokenUrl\n }\n return 'https://galaxy.scalar.com/oauth/refresh'\n})\n\n/**\n * Uses the stored refresh token to obtain a new access token\n * via grant_type=refresh_token.\n */\nconst handleRefresh = async (): Promise<void> => {\n // The explicit flow check narrows the type for refreshOauth2Token; the computed boolean cannot.\n if (loader.isLoading || type === 'implicit' || !canRefreshToken.value) {\n return\n }\n\n loader.start()\n\n const [error, tokens] = await refreshOauth2Token(\n flows,\n type,\n proxyUrl,\n server,\n getEnvironmentVariables(environment),\n options.customFetch,\n )\n\n await loader.clear()\n\n if (tokens?.accessToken) {\n handleOauth2SecretsUpdate({\n 'x-scalar-secret-token': tokens.accessToken,\n ...(tokens.refreshToken\n ? { 'x-scalar-secret-refresh-token': tokens.refreshToken }\n : {}),\n })\n } else {\n console.error(error)\n toast(\n error?.message ?? translate('apiClient.oauth2.failedToRefreshToken'),\n 'error',\n )\n }\n}\n\n/** Updates the secret location */\nconst handleSecretLocationUpdate = (value: string): void => {\n if (value !== 'body' && value !== 'header') return\n const credentialsLocation = value\n\n if (scheme.type !== 'openIdConnect') {\n handleOauth2Update({\n 'x-scalar-credentials-location': credentialsLocation,\n })\n }\n\n handleOauth2SecretsUpdate({\n 'x-scalar-credentials-location': credentialsLocation,\n })\n}\n</script>\n\n<template>\n <!-- Access Token Display: Shows when user is already authorized -->\n <template\n v-if=\"\n Boolean(flow['x-scalar-secret-token']) ||\n isSecretFieldCleared(flow, 'x-scalar-secret-token')\n \">\n <DataTableRow>\n <RequestAuthDataTableInput\n canReset\n class=\"border-r-transparent\"\n :environment\n :modelValue=\"flow['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\n @reset=\"handleResetSecret('x-scalar-secret-token')\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-token': v })\n \">\n {{ translate('apiClient.oauth2.accessToken') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"canRefreshToken\">\n <RequestAuthDataTableInput\n class=\"border-r-transparent\"\n :environment\n :modelValue=\"flow.refreshUrl ?? ''\"\n :placeholder=\"refreshUrlPlaceholder\"\n @update:modelValue=\"(v) => handleOauth2Update({ refreshUrl: v })\">\n {{ translate('apiClient.oauth2.refreshUrl') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow\n v-if=\"!hideActions\"\n class=\"min-w-full\">\n <div class=\"flex h-8 items-center justify-end gap-2 border-t\">\n <ScalarButton\n v-if=\"canRefreshToken\"\n class=\"p-0 px-2 py-0.5\"\n :loader\n size=\"sm\"\n variant=\"outlined\"\n @click=\"handleRefresh\">\n {{ translate('apiClient.oauth2.refresh') }}\n </ScalarButton>\n <ScalarButton\n class=\"mr-1 p-0 px-2 py-0.5\"\n :disabled=\"loader.isLoading\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"handleClearAccessTokens\">\n {{ translate('apiClient.oauth2.clearTokens') }}\n </ScalarButton>\n </div>\n </DataTableRow>\n </template>\n\n <!-- Authorization Form: Shows when user needs to authorize -->\n <template v-else>\n <DataTableRow v-if=\"'deviceAuthorizationUrl' in flow\">\n <RequestAuthDataTableInput\n :environment\n :modelValue=\"flow.deviceAuthorizationUrl\"\n @update:modelValue=\"\n (v) => handleOauth2Update({ deviceAuthorizationUrl: v })\n \">\n {{ translate('apiClient.oauth2.deviceAuthorizationUrl') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n <DataTableRow v-if=\"devicePrompt\">\n <div class=\"w-full p-2\">\n <div\n class=\"bg-b-2 flex flex-col gap-3 rounded-lg border p-3 text-sm\"\n role=\"status\">\n <p class=\"text-c-2 text-xs leading-normal\">\n {{ translate('apiClient.oauth2.deviceVerificationPrompt') }}\n </p>\n <strong\n class=\"bg-b-1 font-code w-fit max-w-full rounded border px-3 py-2 text-base font-medium tracking-widest break-all select-all\">\n {{ devicePrompt.userCode }}\n </strong>\n <a\n class=\"text-c-accent w-fit max-w-full text-xs break-all underline underline-offset-2\"\n :href=\"\n devicePrompt.verificationUriComplete ||\n devicePrompt.verificationUri\n \"\n rel=\"noopener noreferrer\"\n target=\"_blank\">\n {{ devicePrompt.verificationUri }}\n </a>\n <div class=\"flex items-center justify-between gap-3\">\n <p class=\"text-c-2 text-xs\">\n {{ translate('apiClient.oauth2.waitingForAuthorization') }}\n </p>\n <ScalarButton\n size=\"xs\"\n variant=\"outlined\"\n @click=\"cancelDeviceAuthorization\">\n {{ translate('apiClient.oauth2.cancelDeviceAuthorization') }}\n </ScalarButton>\n </div>\n </div>\n </div>\n </DataTableRow>\n <DataTableRow>\n <RequestAuthDataTableInput\n v-if=\"'authorizationUrl' in flow\"\n canReset\n containerClass=\"border-r-0\"\n :environment\n :modelValue=\"flow['x-scalar-secret-auth-url'] ?? ''\"\n placeholder=\"https://galaxy.scalar.com/authorize\"\n @reset=\"handleResetSecret('x-scalar-secret-auth-url')\"\n @update:modelValue=\"\n (v) => {\n handleOauth2SecretsUpdate({ 'x-scalar-secret-auth-url': v })\n if (v) handleOauth2Update({ authorizationUrl: v })\n }\n \">\n {{ translate('apiClient.oauth2.authUrl') }}\n </RequestAuthDataTableInput>\n\n <RequestAuthDataTableInput\n v-if=\"'tokenUrl' in flow\"\n canReset\n :environment\n :modelValue=\"flow['x-scalar-secret-token-url'] ?? ''\"\n placeholder=\"https://galaxy.scalar.com/token\"\n @reset=\"handleResetSecret('x-scalar-secret-token-url')\"\n @update:modelValue=\"\n (v) => {\n handleOauth2SecretsUpdate({ 'x-scalar-secret-token-url': v })\n if (v) handleOauth2Update({ tokenUrl: v })\n }\n \">\n {{ translate('apiClient.oauth2.tokenUrl') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-scalar-secret-redirect-uri' in flow\">\n <RequestAuthDataTableInput\n canReset\n :environment\n :modelValue=\"flow['x-scalar-secret-redirect-uri']\"\n :placeholder=\"\n options.captureOAuth2Callback\n ? `${resolveDefaultOAuth2RedirectUri(options) || 'http://127.0.0.1'} (handled automatically)`\n : translate('apiClient.oauth2.optionalRedirectUrl')\n \"\n @reset=\"handleResetSecret('x-scalar-secret-redirect-uri')\"\n @update:modelValue=\"\n (v) => {\n hasHandledRedirectPrefill = true\n handleOauth2SecretsUpdate({ 'x-scalar-secret-redirect-uri': v })\n }\n \">\n {{ translate('apiClient.oauth2.redirectUrl') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <template\n v-if=\"\n 'x-scalar-secret-username' in flow && 'x-scalar-secret-password' in flow\n \">\n <DataTableRow>\n <RequestAuthDataTableInput\n canReset\n class=\"text-c-2\"\n :environment\n :modelValue=\"flow['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n @reset=\"handleResetSecret('x-scalar-secret-username')\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-username': v })\n \">\n {{ translate('apiClient.oauth2.username') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow>\n <RequestAuthDataTableInput\n canReset\n :environment\n :modelValue=\"flow['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\n @reset=\"handleResetSecret('x-scalar-secret-password')\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-password': v })\n \">\n {{ translate('apiClient.oauth2.password') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n </template>\n\n <DataTableRow>\n <RequestAuthDataTableInput\n canReset\n :environment\n :modelValue=\"flow['x-scalar-secret-client-id']\"\n placeholder=\"12345\"\n @reset=\"handleResetSecret('x-scalar-secret-client-id')\"\n @update:modelValue=\"\n (v) => handleOauth2SecretsUpdate({ 'x-scalar-secret-client-id': v })\n \">\n {{ translate('apiClient.oauth2.clientID') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"showClientSecret\">\n <RequestAuthDataTableInput\n canReset\n :environment\n :modelValue=\"clientSecretValue\"\n placeholder=\"XYZ123\"\n type=\"password\"\n @reset=\"handleResetSecret('x-scalar-secret-client-secret')\"\n @update:modelValue=\"\n (v) =>\n handleOauth2SecretsUpdate({ 'x-scalar-secret-client-secret': v })\n \">\n {{ translate('apiClient.oauth2.clientSecret') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <DataTableRow v-if=\"'x-usePkce' in flow\">\n <RequestAuthDataTableInput\n :enum=\"pkceOptions\"\n :environment\n :modelValue=\"flow['x-usePkce']\"\n readOnly\n @update:modelValue=\"handlePkceUpdate\">\n {{ translate('apiClient.oauth2.usePKCE') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- Credentials Location -->\n <DataTableRow v-if=\"type !== 'implicit'\">\n <RequestAuthDataTableInput\n :enum=\"['header', 'body']\"\n :environment\n :modelValue=\"\n (flow as NonImplicitFlow)['x-scalar-credentials-location'] || 'header'\n \"\n placeholder=\"header\"\n readOnly\n @update:modelValue=\"(v) => handleSecretLocationUpdate(v)\">\n {{ translate('apiClient.oauth2.credentialsLocation') }}\n </RequestAuthDataTableInput>\n </DataTableRow>\n\n <!-- Scopes -->\n <DataTableRow>\n <OAuthScopesInput\n :flow\n :flowType=\"type\"\n :selectedScopes\n @delete:scope=\"(v) => emits('delete:scope', v)\"\n @update:selectedScopes=\"(v) => emits('update:selectedScopes', v)\"\n @upsert:scope=\"(v) => emits('upsert:scope', v)\" />\n </DataTableRow>\n\n <DataTableRow\n v-if=\"!hideActions\"\n class=\"min-w-full\">\n <div class=\"flex h-8 w-full items-center justify-end border-t\">\n <!-- Allow clearing the oauth section and going back to discovery -->\n <ScalarButton\n v-if=\"scheme.type === 'openIdConnect'\"\n class=\"mr-1 p-0 px-2 py-0.5\"\n :disabled=\"loader.isLoading\"\n size=\"sm\"\n variant=\"outlined\"\n @click=\"clearOauth2Secrets\">\n {{ translate('apiClient.oauth2.resetDiscovery') }}\n </ScalarButton>\n\n <ScalarButton\n class=\"mr-0.75 p-0 px-2 py-0.5\"\n :loader\n size=\"sm\"\n variant=\"outlined\"\n @click=\"handleAuthorize\">\n {{ translate('apiClient.oauth2.authorize') }}\n </ScalarButton>\n </div>\n </DataTableRow>\n </template>\n</template>\n"],"mappings":"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"}
|
package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments';
|
|
2
2
|
import type { VueClassProp } from '../../../../types/vue';
|
|
3
3
|
type __VLS_Props = {
|
|
4
|
+
/** Restore this credential's current document or configured default. */
|
|
5
|
+
canReset?: boolean;
|
|
4
6
|
containerClass?: VueClassProp;
|
|
5
7
|
environment: XScalarEnvironment;
|
|
6
8
|
readOnly?: boolean;
|
|
@@ -20,10 +22,12 @@ type __VLS_Slots = {} & {
|
|
|
20
22
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
21
23
|
"update:modelValue": (value: string) => any;
|
|
22
24
|
} & {
|
|
25
|
+
reset: () => any;
|
|
23
26
|
selectVariable: (value: string) => any;
|
|
24
27
|
inputFocus: () => any;
|
|
25
28
|
inputBlur: () => any;
|
|
26
29
|
}, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
|
|
30
|
+
onReset?: (() => any) | undefined;
|
|
27
31
|
"onUpdate:modelValue"?: ((value: string) => any) | undefined;
|
|
28
32
|
onSelectVariable?: ((value: string) => any) | undefined;
|
|
29
33
|
onInputFocus?: (() => any) | undefined;
|
package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequestAuthDataTableInput.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RequestAuthDataTableInput.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue"],"names":[],"mappings":"AAgFA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AAGnH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAI/C,KAAK,WAAW,GAAG;IACjB,wEAAwE;IACxE,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,cAAc,CAAC,EAAE,YAAY,CAAA;IAC7B,WAAW,EAAE,kBAAkB,CAAA;IAC/B,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAC;AAiCF,KAAK,gBAAgB,GAAG;IACxB,UAAU,EAAE,MAAM,CAAC;CAClB,CAAC;AAKF,KAAK,iBAAiB,GAAG,WAAW,GAAG,gBAAgB,CAAC;AA6IxD,QAAA,IAAI,QAAQ,IAAW,EAAE,QAAQ,IAAY,CAAE;AAC/C,KAAK,WAAW,GAAG,EAAE,GACnB;IAAE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,GAC7C;IAAE,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,QAAQ,KAAK,GAAG,CAAA;CAAE,CAAC;AAK7C,QAAA,MAAM,UAAU;;;;;;;;;;;;;kFAGd,CAAC;AACH,QAAA,MAAM,YAAY,EAAS,eAAe,CAAC,OAAO,UAAU,EAAE,WAAW,CAAC,CAAC;wBACtD,OAAO,YAAY;AAAxC,wBAAyC;AACzC,KAAK,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;IAChC,QAAO;QACN,MAAM,EAAE,CAAC,CAAC;KACV,CAAA;CACD,CAAC"}
|
package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequestAuthDataTableInput.vue.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { useId } from 'vue'\n\nimport type { VueClassProp } from '@/types/vue'\nimport { DataTableInput } from '@/v2/components/data-table'\n\nconst {\n containerClass,\n environment,\n readOnly = false,\n required = false,\n type,\n} = defineProps<{\n containerClass?: VueClassProp\n environment: XScalarEnvironment\n readOnly?: boolean\n required?: boolean\n type?: string\n}>()\n\nconst emit = defineEmits<{\n (e: 'inputFocus'): void\n (e: 'inputBlur'): void\n (e: 'selectVariable', value: string): void\n}>()\n\nconst modelValue = defineModel<string>({ default: '', required: true })\nconst id = useId()\n/**\n * The unmasked editor is a contenteditable div, which a <label for> cannot\n * name, so the field points back at the visible label via aria-labelledby.\n * The masked native input
|
|
1
|
+
{"version":3,"file":"RequestAuthDataTableInput.vue.js","names":[],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarIconButton } from '@scalar/components/icon-button'\nimport { ScalarIconArrowCounterClockwise } from '@scalar/icons'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { useId } from 'vue'\n\nimport type { VueClassProp } from '@/types/vue'\nimport { DataTableInput } from '@/v2/components/data-table'\nimport { useLocalization } from '@/v2/features/localization'\n\nconst {\n canReset = false,\n containerClass,\n environment,\n readOnly = false,\n required = false,\n type,\n} = defineProps<{\n /** Restore this credential's current document or configured default. */\n canReset?: boolean\n containerClass?: VueClassProp\n environment: XScalarEnvironment\n readOnly?: boolean\n required?: boolean\n type?: string\n}>()\n\nconst emit = defineEmits<{\n (e: 'reset'): void\n (e: 'inputFocus'): void\n (e: 'inputBlur'): void\n (e: 'selectVariable', value: string): void\n}>()\n\nconst modelValue = defineModel<string>({ default: '', required: true })\nconst id = useId()\nconst { translate } = useLocalization()\n/**\n * The unmasked editor is a contenteditable div, which a <label for> cannot\n * name, so the field points back at the visible label via aria-labelledby.\n * The masked native input is named the same way.\n */\nconst labelId = `${id}-label`\n</script>\n<template>\n <DataTableInput\n :id=\"id\"\n v-bind=\"$attrs\"\n v-model=\"modelValue\"\n :aria-labelledby=\"labelId\"\n :canAddCustomEnumValue=\"!readOnly\"\n :containerClass=\"containerClass\"\n :environment=\"environment\"\n :readOnly=\"readOnly\"\n :required=\"required\"\n :type=\"type\"\n @inputBlur=\"emit('inputBlur')\"\n @inputFocus=\"emit('inputFocus')\"\n @selectVariable=\"emit('selectVariable', $event)\">\n <template #default>\n <label :id=\"labelId\">\n <slot />\n </label>\n </template>\n <template #icon>\n <slot name=\"icon\" />\n <ScalarIconButton\n v-if=\"canReset && !readOnly\"\n class=\"h-6 w-6 self-center p-1.25\"\n :icon=\"ScalarIconArrowCounterClockwise\"\n :label=\"translate('apiClient.dataTableInput.resetValue')\"\n @click=\"emit('reset')\" />\n </template>\n </DataTableInput>\n</template>\n"],"mappings":""}
|
package/dist/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue.script.js
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
|
+
import { useLocalization } from "../../../features/localization/index.js";
|
|
1
2
|
import DataTableInput_default from "../../../components/data-table/DataTableInput.vue.js";
|
|
2
|
-
import { createBlock, createElementVNode, defineComponent, mergeModels, mergeProps, openBlock, renderSlot, unref, useId, useModel, withCtx } from "vue";
|
|
3
|
+
import { createBlock, createCommentVNode, createElementVNode, defineComponent, mergeModels, mergeProps, openBlock, renderSlot, unref, useId, useModel, withCtx } from "vue";
|
|
4
|
+
import { ScalarIconArrowCounterClockwise } from "@scalar/icons";
|
|
5
|
+
import { ScalarIconButton } from "@scalar/components/icon-button";
|
|
3
6
|
//#region src/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue?vue&type=script&setup=true&lang.ts
|
|
4
|
-
var _hoisted_1 = ["for"];
|
|
5
7
|
var RequestAuthDataTableInput_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineComponent({
|
|
6
8
|
__name: "RequestAuthDataTableInput",
|
|
7
9
|
props: /*@__PURE__*/ mergeModels({
|
|
10
|
+
canReset: {
|
|
11
|
+
type: Boolean,
|
|
12
|
+
default: false
|
|
13
|
+
},
|
|
8
14
|
containerClass: {},
|
|
9
15
|
environment: {},
|
|
10
16
|
readOnly: {
|
|
@@ -24,6 +30,7 @@ var RequestAuthDataTableInput_vue_vue_type_script_setup_true_lang_default = /*@_
|
|
|
24
30
|
"modelModifiers": {}
|
|
25
31
|
}),
|
|
26
32
|
emits: /*@__PURE__*/ mergeModels([
|
|
33
|
+
"reset",
|
|
27
34
|
"inputFocus",
|
|
28
35
|
"inputBlur",
|
|
29
36
|
"selectVariable"
|
|
@@ -32,16 +39,17 @@ var RequestAuthDataTableInput_vue_vue_type_script_setup_true_lang_default = /*@_
|
|
|
32
39
|
const emit = __emit;
|
|
33
40
|
const modelValue = useModel(__props, "modelValue");
|
|
34
41
|
const id = useId();
|
|
42
|
+
const { translate } = useLocalization();
|
|
35
43
|
/**
|
|
36
44
|
* The unmasked editor is a contenteditable div, which a <label for> cannot
|
|
37
45
|
* name, so the field points back at the visible label via aria-labelledby.
|
|
38
|
-
* The masked native input
|
|
46
|
+
* The masked native input is named the same way.
|
|
39
47
|
*/
|
|
40
48
|
const labelId = `${id}-label`;
|
|
41
49
|
return (_ctx, _cache) => {
|
|
42
50
|
return openBlock(), createBlock(unref(DataTableInput_default), mergeProps({ id: unref(id) }, _ctx.$attrs, {
|
|
43
51
|
modelValue: modelValue.value,
|
|
44
|
-
"onUpdate:modelValue": _cache[
|
|
52
|
+
"onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => modelValue.value = $event),
|
|
45
53
|
"aria-labelledby": labelId,
|
|
46
54
|
canAddCustomEnumValue: !__props.readOnly,
|
|
47
55
|
containerClass: __props.containerClass,
|
|
@@ -49,15 +57,18 @@ var RequestAuthDataTableInput_vue_vue_type_script_setup_true_lang_default = /*@_
|
|
|
49
57
|
readOnly: __props.readOnly,
|
|
50
58
|
required: __props.required,
|
|
51
59
|
type: __props.type,
|
|
52
|
-
onInputBlur: _cache[
|
|
53
|
-
onInputFocus: _cache[
|
|
54
|
-
onSelectVariable: _cache[
|
|
60
|
+
onInputBlur: _cache[2] || (_cache[2] = ($event) => emit("inputBlur")),
|
|
61
|
+
onInputFocus: _cache[3] || (_cache[3] = ($event) => emit("inputFocus")),
|
|
62
|
+
onSelectVariable: _cache[4] || (_cache[4] = ($event) => emit("selectVariable", $event))
|
|
55
63
|
}), {
|
|
56
|
-
default: withCtx(() => [createElementVNode("label", {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
64
|
+
default: withCtx(() => [createElementVNode("label", { id: labelId }, [renderSlot(_ctx.$slots, "default")])]),
|
|
65
|
+
icon: withCtx(() => [renderSlot(_ctx.$slots, "icon"), __props.canReset && !__props.readOnly ? (openBlock(), createBlock(unref(ScalarIconButton), {
|
|
66
|
+
key: 0,
|
|
67
|
+
class: "h-6 w-6 self-center p-1.25",
|
|
68
|
+
icon: unref(ScalarIconArrowCounterClockwise),
|
|
69
|
+
label: unref(translate)("apiClient.dataTableInput.resetValue"),
|
|
70
|
+
onClick: _cache[0] || (_cache[0] = ($event) => emit("reset"))
|
|
71
|
+
}, null, 8, ["icon", "label"])) : createCommentVNode("", true)]),
|
|
61
72
|
_: 3
|
|
62
73
|
}, 16, [
|
|
63
74
|
"id",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequestAuthDataTableInput.vue.script.js","names":["$attrs"],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { useId } from 'vue'\n\nimport type { VueClassProp } from '@/types/vue'\nimport { DataTableInput } from '@/v2/components/data-table'\n\nconst {\n containerClass,\n environment,\n readOnly = false,\n required = false,\n type,\n} = defineProps<{\n containerClass?: VueClassProp\n environment: XScalarEnvironment\n readOnly?: boolean\n required?: boolean\n type?: string\n}>()\n\nconst emit = defineEmits<{\n (e: 'inputFocus'): void\n (e: 'inputBlur'): void\n (e: 'selectVariable', value: string): void\n}>()\n\nconst modelValue = defineModel<string>({ default: '', required: true })\nconst id = useId()\n/**\n * The unmasked editor is a contenteditable div, which a <label for> cannot\n * name, so the field points back at the visible label via aria-labelledby.\n * The masked native input
|
|
1
|
+
{"version":3,"file":"RequestAuthDataTableInput.vue.script.js","names":["$attrs"],"sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthDataTableInput.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ScalarIconButton } from '@scalar/components/icon-button'\nimport { ScalarIconArrowCounterClockwise } from '@scalar/icons'\nimport type { XScalarEnvironment } from '@scalar/workspace-store/schemas/extensions/document/x-scalar-environments'\nimport { useId } from 'vue'\n\nimport type { VueClassProp } from '@/types/vue'\nimport { DataTableInput } from '@/v2/components/data-table'\nimport { useLocalization } from '@/v2/features/localization'\n\nconst {\n canReset = false,\n containerClass,\n environment,\n readOnly = false,\n required = false,\n type,\n} = defineProps<{\n /** Restore this credential's current document or configured default. */\n canReset?: boolean\n containerClass?: VueClassProp\n environment: XScalarEnvironment\n readOnly?: boolean\n required?: boolean\n type?: string\n}>()\n\nconst emit = defineEmits<{\n (e: 'reset'): void\n (e: 'inputFocus'): void\n (e: 'inputBlur'): void\n (e: 'selectVariable', value: string): void\n}>()\n\nconst modelValue = defineModel<string>({ default: '', required: true })\nconst id = useId()\nconst { translate } = useLocalization()\n/**\n * The unmasked editor is a contenteditable div, which a <label for> cannot\n * name, so the field points back at the visible label via aria-labelledby.\n * The masked native input is named the same way.\n */\nconst labelId = `${id}-label`\n</script>\n<template>\n <DataTableInput\n :id=\"id\"\n v-bind=\"$attrs\"\n v-model=\"modelValue\"\n :aria-labelledby=\"labelId\"\n :canAddCustomEnumValue=\"!readOnly\"\n :containerClass=\"containerClass\"\n :environment=\"environment\"\n :readOnly=\"readOnly\"\n :required=\"required\"\n :type=\"type\"\n @inputBlur=\"emit('inputBlur')\"\n @inputFocus=\"emit('inputFocus')\"\n @selectVariable=\"emit('selectVariable', $event)\">\n <template #default>\n <label :id=\"labelId\">\n <slot />\n </label>\n </template>\n <template #icon>\n <slot name=\"icon\" />\n <ScalarIconButton\n v-if=\"canReset && !readOnly\"\n class=\"h-6 w-6 self-center p-1.25\"\n :icon=\"ScalarIconArrowCounterClockwise\"\n :label=\"translate('apiClient.dataTableInput.resetValue')\"\n @click=\"emit('reset')\" />\n </template>\n </DataTableInput>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA2BA,MAAM,OAAO;EAOb,MAAM,aAAa,SAAmB,SAAA,YAAgC;EACtE,MAAM,KAAK,MAAM;EACjB,MAAM,EAAE,cAAc,gBAAgB;;;;;;EAMtC,MAAM,UAAU,GAAG,GAAG;;uBAGpB,YA4BiB,MAAA,sBAAA,GA5BjB,WA4BiB,EA3Bd,IAAI,MAAA,EAAA,EAAE,GACCA,KAAAA,QAAM;gBACL,WAAA;4EAAU,QAAA;IAClB,mBAAiB;IACjB,uBAAqB,CAAG,QAAA;IACxB,gBAAgB,QAAA;IAChB,aAAa,QAAA;IACb,UAAU,QAAA;IACV,UAAU,QAAA;IACV,MAAM,QAAA;IACN,aAAS,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,WAAA;IACf,cAAU,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,YAAA;IAChB,kBAAc,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,kBAAmB,MAAM;;IACnC,SAAO,cAGR,CAFR,mBAEQ,SAAA,EAFA,IAAI,QAAO,GAAA,CACjB,WAAQ,KAAA,QAAA,SAAA,CAAA,CAAA,CAAA,CAAA;IAGD,MAAI,cACO,CAApB,WAAoB,KAAA,QAAA,MAAA,GAEZ,QAAA,YAAQ,CAAK,QAAA,YAAA,UAAA,GADrB,YAK2B,MAAA,gBAAA,GAAA;;KAHzB,OAAM;KACL,MAAM,MAAA,+BAAA;KACN,OAAO,MAAA,SAAA,CAAS,CAAA,qCAAA;KAChB,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,OAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RequestAuthTab.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"RequestAuthTab.vue.d.ts","sourceRoot":"","sources":["../../../../../src/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue"],"names":[],"mappings":"AAkvBA,OAAO,KAAK,EAEV,iBAAiB,EAClB,MAAM,gCAAgC,CAAA;AAEvC,OAAO,EAEL,KAAK,qBAAqB,EAG3B,MAAM,yCAAyC,CAAA;AAChD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2EAA2E,CAAA;AAEnH,OAAO,KAAK,EAEV,yBAAyB,EACzB,YAAY,EACb,MAAM,8DAA8D,CAAA;AAiBrE,OAAe,EAAE,KAAK,aAAa,EAAE,MAAM,cAAc,CAAA;AAKzD,KAAK,WAAW,GAAG;IACjB,wCAAwC;IACxC,WAAW,EAAE,kBAAkB,CAAA;IAC/B,yFAAyF;IACzF,QAAQ,EAAE,OAAO,CAAA;IACjB,gBAAgB;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,+BAA+B;IAC/B,uBAAuB,EAAE,yBAAyB,CAAA;IAClD,oGAAoG;IACpG,eAAe,EAAE,qBAAqB,CAAA;IACtC,mCAAmC;IACnC,MAAM,EAAE,YAAY,GAAG,IAAI,CAAA;IAC3B,2CAA2C;IAC3C,QAAQ,EAAE,iBAAiB,CAAA;IAC3B,uDAAuD;IACvD,OAAO,CAAC,EAAE,aAAa,CAAA;IACvB,yFAAyF;IACzF,YAAY,CAAC,EAAE,SAAS,GAAG,UAAU,CAAA;CACtC,CAAC;AAi2CF,QAAA,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kFAGhB,CAAC;wBACkB,OAAO,YAAY;AAAxC,wBAAyC"}
|
|
@@ -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 :containerClass=\"getStaticBorderClass()\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n :placeholder=\"translate('apiClient.requestAuthTab.token')\"\n type=\"password\"\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 px-3\">\n <span class=\"text-c-3 mr-auto text-xs\">{{\n translate('apiClient.requestAuthTab.getAToken')\n }}</span>\n <ScalarButton\n class=\"p-0 px-2 py-0.5\"\n :loader=\"acquisitionLoader\"\n size=\"sm\"\n type=\"button\"\n variant=\"outlined\"\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=\"p-0 px-2 py-0.5\"\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 <ScalarIconButton\n :icon=\"ScalarIconGear\"\n :label=\"\n translate('apiClient.requestAuthTab.configure', {\n name: oauth2Target.name,\n })\n \"\n size=\"xs\"\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 class=\"text-c-2\"\n :environment\n :modelValue=\"scheme['x-scalar-secret-username']\"\n placeholder=\"janedoe\"\n required\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 :environment\n :modelValue=\"scheme['x-scalar-secret-password']\"\n placeholder=\"********\"\n type=\"password\"\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 :containerClass=\"\n apiKeyHasName(scheme) ? undefined : getStaticBorderClass()\n \"\n :environment\n :modelValue=\"scheme['x-scalar-secret-token']\"\n placeholder=\"QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT\"\n type=\"password\"\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 { 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":""}
|
|
@@ -24,8 +24,8 @@ import { getDocumentTypeLabel } from "@scalar/workspace-store/schemas/type-guard
|
|
|
24
24
|
//#region src/v2/blocks/scalar-auth-selector-block/components/RequestAuthTab.vue?vue&type=script&setup=true&lang.ts
|
|
25
25
|
var _hoisted_1 = { class: "bg-b-1 min-w-0 flex-1 px-3 py-1.25" };
|
|
26
26
|
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
|
|
28
|
-
var _hoisted_4 = { class: "text-c-
|
|
27
|
+
var _hoisted_3 = { class: "flex h-8 items-center gap-2 border-t pl-3 text-base" };
|
|
28
|
+
var _hoisted_4 = { class: "text-c-1 mr-auto" };
|
|
29
29
|
var _hoisted_5 = { class: "flex min-h-8 border-t text-base" };
|
|
30
30
|
var _hoisted_6 = { class: "flex h-8 max-w-full gap-2.5 overflow-x-auto px-3" };
|
|
31
31
|
var _hoisted_7 = ["onClick"];
|
|
@@ -290,11 +290,16 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
|
|
|
290
290
|
}, 1024)) : createCommentVNode("", true),
|
|
291
291
|
scheme?.type === "http" ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [scheme.scheme === "bearer" ? (openBlock(), createBlock(unref(DataTableRow_default), { key: 0 }, {
|
|
292
292
|
default: withCtx(() => [createVNode(RequestAuthDataTableInput_default, {
|
|
293
|
+
canReset: "",
|
|
293
294
|
containerClass: getStaticBorderClass(),
|
|
294
295
|
environment: __props.environment,
|
|
295
296
|
modelValue: scheme["x-scalar-secret-token"],
|
|
296
297
|
placeholder: unref(translate)("apiClient.requestAuthTab.token"),
|
|
297
298
|
type: "password",
|
|
299
|
+
onReset: ($event) => __props.eventBus.emit("auth:reset:security-scheme-secret", {
|
|
300
|
+
name,
|
|
301
|
+
field: "x-scalar-secret-token"
|
|
302
|
+
}),
|
|
298
303
|
"onUpdate:modelValue": (v) => handleHttpSecretsUpdate({ "x-scalar-secret-token": v }, name)
|
|
299
304
|
}, {
|
|
300
305
|
default: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.requestAuthTab.bearerToken")), 1)]),
|
|
@@ -304,6 +309,7 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
|
|
|
304
309
|
"environment",
|
|
305
310
|
"modelValue",
|
|
306
311
|
"placeholder",
|
|
312
|
+
"onReset",
|
|
307
313
|
"onUpdate:modelValue"
|
|
308
314
|
])]),
|
|
309
315
|
_: 2
|
|
@@ -311,11 +317,11 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
|
|
|
311
317
|
default: withCtx(() => [createElementVNode("div", _hoisted_3, [
|
|
312
318
|
createElementVNode("span", _hoisted_4, toDisplayString(unref(translate)("apiClient.requestAuthTab.getAToken")), 1),
|
|
313
319
|
createVNode(unref(ScalarButton), {
|
|
314
|
-
class: "
|
|
320
|
+
class: "text-c-1 px-3 py-1",
|
|
315
321
|
loader: unref(acquisitionLoader),
|
|
316
322
|
size: "sm",
|
|
317
323
|
type: "button",
|
|
318
|
-
variant: "
|
|
324
|
+
variant: "gradient",
|
|
319
325
|
onClick: ($event) => handleAcquisitionAuthorize(name)
|
|
320
326
|
}, {
|
|
321
327
|
default: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.requestAuthTab.authorizeVia", { name: oauth2Target.value.name })), 1)]),
|
|
@@ -323,7 +329,7 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
|
|
|
323
329
|
}, 1032, ["loader", "onClick"]),
|
|
324
330
|
scheme["x-scalar-secret-token"] && oauth2Target.value.flowType === "authorizationCode" ? (openBlock(), createBlock(unref(ScalarButton), {
|
|
325
331
|
key: 0,
|
|
326
|
-
class: "
|
|
332
|
+
class: "px-3 py-1",
|
|
327
333
|
disabled: unref(acquisitionLoader).isLoading,
|
|
328
334
|
size: "sm",
|
|
329
335
|
type: "button",
|
|
@@ -334,9 +340,9 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
|
|
|
334
340
|
_: 1
|
|
335
341
|
}, 8, ["disabled", "onClick"])) : createCommentVNode("", true),
|
|
336
342
|
createVNode(unref(ScalarIconButton), {
|
|
343
|
+
class: "mr-1.25 h-6 w-6 p-1.25",
|
|
337
344
|
icon: unref(ScalarIconGear),
|
|
338
345
|
label: unref(translate)("apiClient.requestAuthTab.configure", { name: oauth2Target.value.name }),
|
|
339
|
-
size: "xs",
|
|
340
346
|
onClick: ($event) => openAcquisitionConfig(name)
|
|
341
347
|
}, null, 8, [
|
|
342
348
|
"icon",
|
|
@@ -347,11 +353,16 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
|
|
|
347
353
|
_: 2
|
|
348
354
|
}, 1024)) : scheme?.scheme === "basic" ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createVNode(unref(DataTableRow_default), null, {
|
|
349
355
|
default: withCtx(() => [createVNode(RequestAuthDataTableInput_default, {
|
|
356
|
+
canReset: "",
|
|
350
357
|
class: "text-c-2",
|
|
351
358
|
environment: __props.environment,
|
|
352
359
|
modelValue: scheme["x-scalar-secret-username"],
|
|
353
360
|
placeholder: "janedoe",
|
|
354
361
|
required: "",
|
|
362
|
+
onReset: ($event) => __props.eventBus.emit("auth:reset:security-scheme-secret", {
|
|
363
|
+
name,
|
|
364
|
+
field: "x-scalar-secret-username"
|
|
365
|
+
}),
|
|
355
366
|
"onUpdate:modelValue": (v) => handleHttpSecretsUpdate({ "x-scalar-secret-username": v }, name)
|
|
356
367
|
}, {
|
|
357
368
|
default: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.requestAuthTab.username")), 1)]),
|
|
@@ -359,15 +370,21 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
|
|
|
359
370
|
}, 8, [
|
|
360
371
|
"environment",
|
|
361
372
|
"modelValue",
|
|
373
|
+
"onReset",
|
|
362
374
|
"onUpdate:modelValue"
|
|
363
375
|
])]),
|
|
364
376
|
_: 2
|
|
365
377
|
}, 1024), createVNode(unref(DataTableRow_default), null, {
|
|
366
378
|
default: withCtx(() => [createVNode(RequestAuthDataTableInput_default, {
|
|
379
|
+
canReset: "",
|
|
367
380
|
environment: __props.environment,
|
|
368
381
|
modelValue: scheme["x-scalar-secret-password"],
|
|
369
382
|
placeholder: "********",
|
|
370
383
|
type: "password",
|
|
384
|
+
onReset: ($event) => __props.eventBus.emit("auth:reset:security-scheme-secret", {
|
|
385
|
+
name,
|
|
386
|
+
field: "x-scalar-secret-password"
|
|
387
|
+
}),
|
|
371
388
|
"onUpdate:modelValue": (v) => handleHttpSecretsUpdate({ "x-scalar-secret-password": v }, name)
|
|
372
389
|
}, {
|
|
373
390
|
default: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.requestAuthTab.password")), 1)]),
|
|
@@ -375,6 +392,7 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
|
|
|
375
392
|
}, 8, [
|
|
376
393
|
"environment",
|
|
377
394
|
"modelValue",
|
|
395
|
+
"onReset",
|
|
378
396
|
"onUpdate:modelValue"
|
|
379
397
|
])]),
|
|
380
398
|
_: 2
|
|
@@ -397,11 +415,16 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
|
|
|
397
415
|
_: 2
|
|
398
416
|
}, 1024)) : createCommentVNode("", true), createVNode(unref(DataTableRow_default), null, {
|
|
399
417
|
default: withCtx(() => [createVNode(RequestAuthDataTableInput_default, {
|
|
418
|
+
canReset: "",
|
|
400
419
|
containerClass: apiKeyHasName(scheme) ? void 0 : getStaticBorderClass(),
|
|
401
420
|
environment: __props.environment,
|
|
402
421
|
modelValue: scheme["x-scalar-secret-token"],
|
|
403
422
|
placeholder: "QUxMIFlPVVIgQkFTRSBBUkUgQkVMT05HIFRPIFVT",
|
|
404
423
|
type: "password",
|
|
424
|
+
onReset: ($event) => __props.eventBus.emit("auth:reset:security-scheme-secret", {
|
|
425
|
+
name,
|
|
426
|
+
field: "x-scalar-secret-token"
|
|
427
|
+
}),
|
|
405
428
|
"onUpdate:modelValue": (v) => handleApiKeySecretsUpdate({ "x-scalar-secret-token": v }, name)
|
|
406
429
|
}, {
|
|
407
430
|
default: withCtx(() => [createTextVNode(toDisplayString(unref(translate)("apiClient.requestAuthTab.value")), 1)]),
|
|
@@ -410,6 +433,7 @@ var RequestAuthTab_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ d
|
|
|
410
433
|
"containerClass",
|
|
411
434
|
"environment",
|
|
412
435
|
"modelValue",
|
|
436
|
+
"onReset",
|
|
413
437
|
"onUpdate:modelValue"
|
|
414
438
|
])]),
|
|
415
439
|
_: 2
|