Skip to content

Commit 0a2e3c4

Browse files
committed
spec change for free/pro users
1 parent e86f067 commit 0a2e3c4

10 files changed

Lines changed: 1603 additions & 47 deletions

File tree

defillama-openapi.json

Lines changed: 1514 additions & 15 deletions
Large diffs are not rendered by default.

examples/web/src/components/ApiKeyInput.vue

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ const isProUser = computed(() => {
1818
return !!apiKey.value?.trim()
1919
})
2020
21+
const emit = defineEmits<{
22+
(e: 'apiKeyChange', key: string | null): void
23+
}>()
24+
2125
/** Load API key from API key manager on mount */
2226
onMounted(() => {
2327
const stored = getApiKey(WORKSPACE_ID)
@@ -26,6 +30,9 @@ onMounted(() => {
2630
previousApiKey.value = stored.key || ''
2731
}
2832
isInitialized.value = true
33+
34+
// Emit initial state
35+
emit('apiKeyChange', apiKey.value.trim() || null)
2936
})
3037
3138
/** Save API key when it changes */
@@ -52,6 +59,9 @@ const handleApiKeyChange = async () => {
5259
5360
// Update previous value
5461
previousApiKey.value = apiKey.value
62+
63+
// Emit the change
64+
emit('apiKeyChange', trimmedKey || null)
5565
}
5666
5767
/** Debounced API key change handler */

examples/web/src/pages/StandaloneApiReferencePage.vue

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,29 @@
11
<script setup lang="ts">
22
import { ApiReference } from '@scalar/api-reference'
33
import { apiReferenceConfigurationSchema } from '@scalar/types/api-reference'
4-
import { reactive } from 'vue'
4+
import { ref } from 'vue'
55
66
// Import the defillama-openapi.json file
77
import specContent from '../../../../defillama-openapi.json'
88
import ApiKeyInput from '../components/ApiKeyInput.vue'
99
import SlotPlaceholder from '../components/SlotPlaceholder.vue'
1010
11-
const configuration = reactive(
11+
// Create a deep copy of the spec to avoid mutating the original
12+
const getUpdatedSpec = (baseUrl: string) => {
13+
const spec = JSON.parse(JSON.stringify(specContent))
14+
15+
// Update the base server URL
16+
spec.servers = [{
17+
url: baseUrl
18+
}]
19+
20+
return spec
21+
}
22+
23+
// Track the current base URL to prevent unnecessary reloads
24+
const currentBaseUrl = ref<string>('https://api.llama.fi')
25+
26+
const configuration = ref(
1227
apiReferenceConfigurationSchema.parse({
1328
isEditable: false,
1429
// Add path routing option
@@ -17,13 +32,28 @@ const configuration = reactive(
1732
pathRouting: { basePath: '/path-routing' },
1833
}
1934
: {}),
20-
content: specContent,
35+
content: getUpdatedSpec(currentBaseUrl.value),
2136
}),
2237
)
38+
39+
// Handle API key changes from the input component
40+
const handleApiKeyChange = (apiKey: string | null) => {
41+
const newBaseUrl = apiKey ? 'https://pro-api.llama.fi' : 'https://api.llama.fi'
42+
43+
// Only update if the base URL would actually change
44+
if (currentBaseUrl.value !== newBaseUrl) {
45+
currentBaseUrl.value = newBaseUrl
46+
configuration.value = apiReferenceConfigurationSchema.parse({
47+
...configuration.value,
48+
content: getUpdatedSpec(newBaseUrl),
49+
})
50+
}
51+
}
2352
</script>
53+
2454
<template>
2555
<div class="standalone-api-reference-page">
26-
<ApiKeyInput />
56+
<ApiKeyInput @api-key-change="handleApiKeyChange" />
2757
<ApiReference :configuration="configuration">
2858
<template #footer><SlotPlaceholder>footer</SlotPlaceholder></template>
2959
</ApiReference>

packages/api-client/src/views/Request/libs/oauth2.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import type { Oauth2Flow, Server } from '@scalar/oas-utils/entities/spec'
33
import { shouldUseProxy } from '@scalar/oas-utils/helpers'
44

55
/** Oauth2 security schemes which are not implicit */
6-
type NonImplicitFlow = Exclude<Oauth2Flow, { type: 'implicit' }>
6+
type NonImplicitFlow = Exclude<Oauth2Flow, { type: 'implicit' }> & {
7+
'x-scalar-security-body'?: Record<string, string>
8+
}
79

810
type PKCEState = {
911
codeVerifier: string

packages/api-reference/src/components/Content/ClientLibraries/ClientLibraries.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ function handleChange(i: number) {
5454
// Restore selected client from localStorage
5555
onMounted(() => {
5656
const storedClient = localStorage.getItem(
57-
REFERENCE_LS_KEYS.SELECTED_CLIENT_DEPRECATED,
57+
REFERENCE_LS_KEYS.SELECTED_CLIENT,
5858
)
5959
if (storedClient) {
6060
setHttpClient(JSON.parse(storedClient))

packages/api-reference/src/stores/useHttpClientStore.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ const setHttpClient = (newState: Partial<HttpClientState>) => {
167167
})
168168

169169
// Save to localStorage
170-
safeLocalStorage().setItem(REFERENCE_LS_KEYS.SELECTED_CLIENT_DEPRECATED, JSON.stringify(httpClient))
170+
safeLocalStorage().setItem(REFERENCE_LS_KEYS.SELECTED_CLIENT, JSON.stringify(httpClient))
171171
}
172172

173173
/** Keep track of the available and the selected HTTP client(s) */
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { z } from 'zod'
2+
3+
export const DescriptionSchema = z.object({
4+
/**
5+
* A description for security scheme. CommonMark syntax MAY be used for rich text representation.
6+
*/
7+
description: z.string().optional(),
8+
})

packages/openapi-types/src/schemas/3.1/processed/security-scheme-object.ts

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
import { z } from 'zod'
2-
3-
const DescriptionSchema = z.object({
4-
/**
5-
* A description for security scheme. CommonMark syntax MAY be used for rich text representation.
6-
*/
7-
description: z.string().optional(),
8-
})
2+
import { DescriptionSchema } from './description-object'
3+
import { XScalarSecurityBody } from '../../extensions/x-scalar-security-body'
94

105
export const ApiKeyInValues = ['query', 'header', 'cookie'] as const
116

@@ -80,18 +75,20 @@ const tokenUrl = z.string().default('')
8075
*
8176
* Configuration details for a supported OAuth Flow
8277
*/
83-
export const OAuthFlowObjectSchema = z.object({
84-
/**
85-
* The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL. The OAuth2 standard requires
86-
* the use of TLS.
87-
*/
88-
refreshUrl: z.string().optional(),
89-
/**
90-
* REQUIRED. The available scopes for the OAuth2 security scheme. A map
91-
* between the scope name and a short description for it. The map MAY be empty.
92-
*/
93-
scopes: z.record(z.string(), z.string().optional()).optional().default({}).catch({}),
94-
})
78+
export const OAuthFlowObjectSchema = z
79+
.object({
80+
/**
81+
* The URL to be used for obtaining refresh tokens. This MUST be in the form of a URL. The OAuth2 standard requires
82+
* the use of TLS.
83+
*/
84+
refreshUrl: z.string().optional(),
85+
/**
86+
* REQUIRED. The available scopes for the OAuth2 security scheme. A map
87+
* between the scope name and a short description for it. The map MAY be empty.
88+
*/
89+
scopes: z.record(z.string(), z.string().optional()).optional().default({}).catch({}),
90+
})
91+
.merge(XScalarSecurityBody)
9592

9693
export const ImplicitFlowSchema = OAuthFlowObjectSchema.extend({
9794
type: z.literal('implicit').optional(),
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
import { z } from 'zod'
22

33
/**
4-
* An OpenAPI extension to set any additional body parameters for the OAuth token request
4+
* An OpenAPI extension to specify additional request body parameters for OAuth2 flows
55
*
66
* @example
77
* ```yaml
8-
* x-scalar-security-body: {
9-
* audience: 'https://api.example.com',
10-
* resource: 'user-profile'
11-
* }
8+
* x-scalar-security-body:
9+
* audience: 'https://api.example.com'
10+
* custom_param: 'custom_value'
1211
* ```
1312
*/
1413
export const XScalarSecurityBody = z.object({
15-
'x-scalar-security-body': z.record(z.string(), z.string()).optional(),
14+
'x-scalar-security-body': z.record(z.string()).optional(),
1615
})

packages/types/src/api-reference/api-reference-configuration.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,17 @@ const _apiReferenceConfigurationSchema = apiClientConfigurationSchema.merge(
462462
operationsSorter: z
463463
.union([z.literal('alpha'), z.literal('method'), z.function().args(z.any(), z.any()).returns(z.number())])
464464
.optional(),
465+
/**
466+
* Callback fired when the API key changes
467+
* @param apiKey - The new API key value or null if removed
468+
* @param currentBaseUrl - The current base URL being used
469+
* @returns void or Promise<void>
470+
*/
471+
onApiKeyChange: z
472+
.function()
473+
.args(z.string().nullable(), z.string())
474+
.returns(z.void().or(z.void().promise()))
475+
.optional(),
465476
}),
466477
)
467478

0 commit comments

Comments
 (0)