11import type { OpenAPIV3 } from '@gitbook/openapi-parser' ;
2+ import { Fragment } from 'react' ;
23import { InteractiveSection } from './InteractiveSection' ;
34import { Markdown } from './Markdown' ;
45import { OpenAPICopyButton } from './OpenAPICopyButton' ;
56import { OpenAPISchemaName } from './OpenAPISchemaName' ;
67import type { OpenAPIClientContext } from './context' ;
78import { t } from './translate' ;
8- import type { OpenAPISecuritySchemeWithRequired } from './types' ;
9+ import type { OpenAPICustomSecurityScheme , OpenAPISecurityScope } from './types' ;
910import type { OpenAPIOperationData } from './types' ;
1011import { createStateKey , extractOperationSecurityInfo , resolveDescription } from './utils' ;
1112
@@ -53,6 +54,12 @@ export function OpenAPISecurities(props: {
5354 className = "openapi-securities-description"
5455 />
5556 ) : null }
57+ { security . scopes ?. length ? (
58+ < OpenAPISchemaScopes
59+ scopes = { security . scopes }
60+ context = { context }
61+ />
62+ ) : null }
5663 </ div >
5764 ) ;
5865 } ) }
@@ -63,10 +70,7 @@ export function OpenAPISecurities(props: {
6370 ) ;
6471}
6572
66- function getLabelForType (
67- security : OpenAPISecuritySchemeWithRequired ,
68- context : OpenAPIClientContext
69- ) {
73+ function getLabelForType ( security : OpenAPICustomSecurityScheme , context : OpenAPIClientContext ) {
7074 switch ( security . type ) {
7175 case 'apiKey' :
7276 return (
@@ -90,7 +94,6 @@ function getLabelForType(
9094 }
9195
9296 if ( security . scheme === 'bearer' ) {
93- const description = resolveDescription ( security ) ;
9497 return (
9598 < >
9699 < OpenAPISchemaName
@@ -100,7 +103,7 @@ function getLabelForType(
100103 required = { security . required }
101104 />
102105 { /** Show a default description if none is provided */ }
103- { ! description ? (
106+ { ! security . description ? (
104107 < Markdown
105108 source = { `Bearer authentication header of the form Bearer ${ '<token>' } .` }
106109 className = "openapi-securities-description"
@@ -139,18 +142,20 @@ function OpenAPISchemaOAuth2Flows(props: {
139142} ) {
140143 const { context, security } = props ;
141144
142- const flows = Object . entries ( security . flows ?? { } ) ;
145+ const flows = security . flows ? Object . entries ( security . flows ) : [ ] ;
143146
144147 return (
145148 < div className = "openapi-securities-oauth-flows" >
146149 { flows . map ( ( [ name , flow ] , index ) => (
147- < OpenAPISchemaOAuth2Item
148- key = { index }
149- flow = { flow }
150- name = { name }
151- context = { context }
152- security = { security }
153- />
150+ < Fragment key = { index } >
151+ < OpenAPISchemaOAuth2Item
152+ flow = { flow }
153+ name = { name }
154+ context = { context }
155+ security = { security }
156+ />
157+ { index < flows . length - 1 ? < hr /> : null }
158+ </ Fragment >
154159 ) ) }
155160 </ div >
156161 ) ;
@@ -170,7 +175,7 @@ function OpenAPISchemaOAuth2Item(props: {
170175 return null ;
171176 }
172177
173- const scopes = Object . entries ( flow ? .scopes ?? { } ) ;
178+ const scopes = flow . scopes ? Object . entries ( flow . scopes ) : [ ] ;
174179
175180 return (
176181 < div >
@@ -221,22 +226,62 @@ function OpenAPISchemaOAuth2Item(props: {
221226 </ OpenAPICopyButton >
222227 </ span >
223228 ) : null }
224- { scopes . length ? (
225- < div >
226- { t ( context . translation , 'available_scopes' ) } :{ ' ' }
227- < ul >
228- { scopes . map ( ( [ key , value ] ) => (
229- < li key = { key } >
230- < OpenAPICopyButton value = { key } context = { context } withTooltip >
231- < code > { key } </ code >
232- </ OpenAPICopyButton >
233- : { value }
234- </ li >
235- ) ) }
236- </ ul >
237- </ div >
238- ) : null }
229+ { scopes . length ? < OpenAPISchemaScopes scopes = { scopes } context = { context } /> : null }
239230 </ div >
240231 </ div >
241232 ) ;
242233}
234+
235+ /**
236+ * Render a list of available scopes.
237+ */
238+ function OpenAPISchemaScopes ( props : {
239+ scopes : OpenAPISecurityScope [ ] ;
240+ context : OpenAPIClientContext ;
241+ } ) {
242+ const { scopes, context } = props ;
243+
244+ return (
245+ < div className = "openapi-securities-scopes openapi-markdown" >
246+ < span > { t ( context . translation , 'required_scopes' ) } : </ span >
247+ < ul >
248+ { scopes . map ( ( scope ) => (
249+ < OpenAPIScopeItem key = { scope [ 0 ] } scope = { scope } context = { context } />
250+ ) ) }
251+ </ ul >
252+ </ div >
253+ ) ;
254+ }
255+
256+ /**
257+ * Display a scope item. Either a key-value pair or a single string.
258+ */
259+ function OpenAPIScopeItem ( props : {
260+ scope : OpenAPISecurityScope ;
261+ context : OpenAPIClientContext ;
262+ } ) {
263+ const { scope, context } = props ;
264+
265+ return (
266+ < li >
267+ < OpenAPIScopeItemKey name = { scope [ 0 ] } context = { context } />
268+ { scope [ 1 ] ? `: ${ scope [ 1 ] } ` : null }
269+ </ li >
270+ ) ;
271+ }
272+
273+ /**
274+ * Displays the scope name within a copyable button.
275+ */
276+ function OpenAPIScopeItemKey ( props : {
277+ name : string ;
278+ context : OpenAPIClientContext ;
279+ } ) {
280+ const { name, context } = props ;
281+
282+ return (
283+ < OpenAPICopyButton value = { name } context = { context } withTooltip >
284+ < code > { name } </ code >
285+ </ OpenAPICopyButton >
286+ ) ;
287+ }
0 commit comments