@gitbook/react-openapi 1.1.10 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/InteractiveSection.d.ts +4 -0
- package/dist/InteractiveSection.jsx +11 -11
- package/dist/OpenAPICodeSample.d.ts +2 -1
- package/dist/OpenAPICodeSample.jsx +6 -5
- package/dist/OpenAPICodeSampleInteractive.d.ts +3 -0
- package/dist/OpenAPICodeSampleInteractive.jsx +19 -43
- package/dist/OpenAPICodeSampleSelector.d.ts +3 -4
- package/dist/OpenAPICodeSampleSelector.jsx +6 -11
- package/dist/OpenAPICopyButton.d.ts +2 -0
- package/dist/OpenAPICopyButton.jsx +5 -2
- package/dist/OpenAPIDisclosure.d.ts +4 -3
- package/dist/OpenAPIDisclosure.jsx +8 -11
- package/dist/OpenAPIDisclosureGroup.d.ts +7 -3
- package/dist/OpenAPIDisclosureGroup.jsx +18 -18
- package/dist/OpenAPIExample.d.ts +4 -22
- package/dist/OpenAPIExample.jsx +5 -72
- package/dist/OpenAPIMediaType.d.ts +21 -0
- package/dist/OpenAPIMediaType.jsx +61 -0
- package/dist/OpenAPIOperation.d.ts +3 -2
- package/dist/OpenAPIOperation.jsx +9 -68
- package/dist/OpenAPIOperationDescription.d.ts +9 -0
- package/dist/OpenAPIOperationDescription.jsx +22 -0
- package/dist/OpenAPIOperationStability.d.ts +9 -0
- package/dist/OpenAPIOperationStability.jsx +27 -0
- package/dist/OpenAPIPath.d.ts +2 -0
- package/dist/OpenAPIPath.jsx +3 -2
- package/dist/OpenAPIRequestBody.d.ts +3 -1
- package/dist/OpenAPIRequestBody.jsx +4 -3
- package/dist/OpenAPIResponse.d.ts +1 -1
- package/dist/OpenAPIResponse.jsx +1 -1
- package/dist/OpenAPIResponseExample.d.ts +3 -2
- package/dist/OpenAPIResponseExample.jsx +24 -63
- package/dist/OpenAPIResponseExampleContent.d.ts +19 -0
- package/dist/OpenAPIResponseExampleContent.jsx +57 -0
- package/dist/OpenAPIResponses.d.ts +1 -1
- package/dist/OpenAPIResponses.jsx +49 -36
- package/dist/OpenAPISchema.d.ts +1 -1
- package/dist/OpenAPISchema.jsx +103 -15
- package/dist/OpenAPISchemaName.d.ts +2 -0
- package/dist/OpenAPISchemaName.jsx +19 -10
- package/dist/OpenAPISchemaServer.d.ts +1 -1
- package/dist/OpenAPISecurities.d.ts +2 -1
- package/dist/OpenAPISecurities.jsx +11 -10
- package/dist/OpenAPISelect.d.ts +10 -3
- package/dist/OpenAPISelect.jsx +20 -9
- package/dist/OpenAPISpec.d.ts +3 -2
- package/dist/OpenAPISpec.jsx +11 -9
- package/dist/OpenAPIWebhook.d.ts +10 -0
- package/dist/OpenAPIWebhook.jsx +23 -0
- package/dist/OpenAPIWebhookExample.d.ts +6 -0
- package/dist/OpenAPIWebhookExample.jsx +41 -0
- package/dist/ScalarApiButton.d.ts +2 -0
- package/dist/ScalarApiButton.jsx +4 -3
- package/dist/StaticSection.d.ts +4 -1
- package/dist/StaticSection.jsx +13 -4
- package/dist/code-samples.js +57 -39
- package/dist/common/OpenAPIColumnSpec.d.ts +6 -0
- package/dist/common/OpenAPIColumnSpec.jsx +20 -0
- package/dist/common/OpenAPIOperationDescription.d.ts +6 -0
- package/dist/common/OpenAPIOperationDescription.jsx +19 -0
- package/dist/common/OpenAPIStability.d.ts +4 -0
- package/dist/common/OpenAPIStability.jsx +15 -0
- package/dist/common/OpenAPISummary.d.ts +6 -0
- package/dist/common/OpenAPISummary.jsx +30 -0
- package/dist/context.d.ts +23 -2
- package/dist/context.js +32 -0
- package/dist/getOrCreateStoreByKey.d.ts +1 -1
- package/dist/getOrCreateStoreByKey.js +0 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +3 -0
- package/dist/resolveOpenAPIWebhook.d.ts +11 -0
- package/dist/resolveOpenAPIWebhook.js +127 -0
- package/dist/schemas/OpenAPISchemas.d.ts +2 -2
- package/dist/schemas/OpenAPISchemas.jsx +19 -23
- package/dist/stringifyOpenAPI.d.ts +1 -1
- package/dist/stringifyOpenAPI.js +6 -3
- package/dist/translate.d.ts +10 -0
- package/dist/translate.jsx +75 -0
- package/dist/translations/de.d.ts +37 -0
- package/dist/translations/de.js +37 -0
- package/dist/translations/en.d.ts +37 -0
- package/dist/translations/en.js +37 -0
- package/dist/translations/es.d.ts +37 -0
- package/dist/translations/es.js +37 -0
- package/dist/translations/fr.d.ts +37 -0
- package/dist/translations/fr.js +37 -0
- package/dist/translations/index.d.ts +341 -0
- package/dist/translations/index.js +27 -0
- package/dist/translations/ja.d.ts +37 -0
- package/dist/translations/ja.js +37 -0
- package/dist/translations/nl.d.ts +37 -0
- package/dist/translations/nl.js +37 -0
- package/dist/translations/no.d.ts +37 -0
- package/dist/translations/no.js +37 -0
- package/dist/translations/pt-br.d.ts +37 -0
- package/dist/translations/pt-br.js +37 -0
- package/dist/translations/types.d.ts +5 -0
- package/dist/translations/types.js +1 -0
- package/dist/translations/zh.d.ts +37 -0
- package/dist/translations/zh.js +37 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types.d.ts +8 -50
- package/dist/util/example.d.ts +35 -0
- package/dist/util/example.jsx +103 -0
- package/dist/utils.d.ts +18 -0
- package/dist/utils.js +57 -0
- package/package.json +3 -3
- package/src/InteractiveSection.tsx +16 -14
- package/src/OpenAPICodeSample.tsx +22 -4
- package/src/OpenAPICodeSampleInteractive.tsx +38 -58
- package/src/OpenAPICodeSampleSelector.tsx +19 -12
- package/src/OpenAPICopyButton.tsx +7 -2
- package/src/OpenAPIDisclosure.tsx +20 -22
- package/src/OpenAPIDisclosureGroup.tsx +41 -22
- package/src/OpenAPIExample.tsx +8 -82
- package/src/OpenAPIMediaType.tsx +139 -0
- package/src/OpenAPIOperation.tsx +11 -100
- package/src/OpenAPIOperationDescription.tsx +34 -0
- package/src/OpenAPIOperationStability.tsx +39 -0
- package/src/OpenAPIPath.tsx +4 -1
- package/src/OpenAPIRequestBody.tsx +9 -4
- package/src/OpenAPIResponse.tsx +2 -2
- package/src/OpenAPIResponseExample.tsx +39 -108
- package/src/OpenAPIResponseExampleContent.tsx +123 -0
- package/src/OpenAPIResponses.tsx +84 -62
- package/src/OpenAPISchema.test.ts +80 -0
- package/src/OpenAPISchema.tsx +123 -16
- package/src/OpenAPISchemaName.tsx +26 -11
- package/src/OpenAPISchemaServer.tsx +1 -1
- package/src/OpenAPISecurities.tsx +33 -12
- package/src/OpenAPISelect.tsx +42 -16
- package/src/OpenAPISpec.tsx +21 -10
- package/src/OpenAPIWebhook.tsx +33 -0
- package/src/OpenAPIWebhookExample.tsx +60 -0
- package/src/ScalarApiButton.tsx +6 -6
- package/src/StaticSection.tsx +37 -5
- package/src/code-samples.test.ts +3 -1
- package/src/code-samples.ts +67 -54
- package/src/common/OpenAPIColumnSpec.tsx +31 -0
- package/src/common/OpenAPIOperationDescription.tsx +31 -0
- package/src/common/OpenAPIStability.tsx +23 -0
- package/src/common/OpenAPISummary.tsx +45 -0
- package/src/context.ts +37 -2
- package/src/getOrCreateStoreByKey.ts +1 -3
- package/src/index.ts +5 -1
- package/src/resolveOpenAPIWebhook.ts +99 -0
- package/src/schemas/OpenAPISchemas.tsx +34 -34
- package/src/stringifyOpenAPI.ts +11 -3
- package/src/translate.tsx +80 -0
- package/src/translations/de.ts +37 -0
- package/src/translations/en.ts +37 -0
- package/src/translations/es.ts +37 -0
- package/src/translations/fr.ts +37 -0
- package/src/translations/index.ts +33 -0
- package/src/translations/ja.ts +37 -0
- package/src/translations/nl.ts +37 -0
- package/src/translations/no.ts +37 -0
- package/src/translations/pt-br.ts +37 -0
- package/src/translations/types.ts +7 -0
- package/src/translations/zh.ts +37 -0
- package/src/types.ts +11 -53
- package/src/util/example.tsx +129 -0
- package/src/utils.ts +67 -0
|
@@ -35,6 +35,86 @@ describe('getSchemaAlternatives', () => {
|
|
|
35
35
|
]);
|
|
36
36
|
});
|
|
37
37
|
|
|
38
|
+
it('merges string enum', () => {
|
|
39
|
+
expect(
|
|
40
|
+
getSchemaAlternatives({
|
|
41
|
+
oneOf: [
|
|
42
|
+
{
|
|
43
|
+
oneOf: [
|
|
44
|
+
{
|
|
45
|
+
type: 'string',
|
|
46
|
+
enum: ['a', 'b'],
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
type: 'string',
|
|
50
|
+
enum: ['c', 'd'],
|
|
51
|
+
nullable: true,
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
],
|
|
56
|
+
})
|
|
57
|
+
).toEqual([
|
|
58
|
+
{
|
|
59
|
+
type: 'string',
|
|
60
|
+
enum: ['a', 'b', 'c', 'd'],
|
|
61
|
+
nullable: true,
|
|
62
|
+
},
|
|
63
|
+
]);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('merges objects with allOf', () => {
|
|
67
|
+
expect(
|
|
68
|
+
getSchemaAlternatives({
|
|
69
|
+
allOf: [
|
|
70
|
+
{
|
|
71
|
+
type: 'object',
|
|
72
|
+
properties: {
|
|
73
|
+
name: {
|
|
74
|
+
type: 'string',
|
|
75
|
+
},
|
|
76
|
+
map: {
|
|
77
|
+
type: 'string',
|
|
78
|
+
},
|
|
79
|
+
description: {
|
|
80
|
+
type: 'string',
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
required: ['name'],
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
type: 'object',
|
|
87
|
+
properties: {
|
|
88
|
+
externalId: {
|
|
89
|
+
type: 'string',
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
required: ['map', 'externalId'],
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
})
|
|
96
|
+
).toEqual([
|
|
97
|
+
{
|
|
98
|
+
type: 'object',
|
|
99
|
+
properties: {
|
|
100
|
+
name: {
|
|
101
|
+
type: 'string',
|
|
102
|
+
},
|
|
103
|
+
map: {
|
|
104
|
+
type: 'string',
|
|
105
|
+
},
|
|
106
|
+
description: {
|
|
107
|
+
type: 'string',
|
|
108
|
+
},
|
|
109
|
+
externalId: {
|
|
110
|
+
type: 'string',
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
required: ['name', 'map', 'externalId'],
|
|
114
|
+
},
|
|
115
|
+
]);
|
|
116
|
+
});
|
|
117
|
+
|
|
38
118
|
it('should not flatten oneOf and allOf', () => {
|
|
39
119
|
expect(
|
|
40
120
|
getSchemaAlternatives({
|
package/src/OpenAPISchema.tsx
CHANGED
|
@@ -10,9 +10,10 @@ import { Markdown } from './Markdown';
|
|
|
10
10
|
import { OpenAPICopyButton } from './OpenAPICopyButton';
|
|
11
11
|
import { OpenAPIDisclosure } from './OpenAPIDisclosure';
|
|
12
12
|
import { OpenAPISchemaName } from './OpenAPISchemaName';
|
|
13
|
+
import type { OpenAPIClientContext } from './context';
|
|
13
14
|
import { retrocycle } from './decycle';
|
|
14
15
|
import { stringifyOpenAPI } from './stringifyOpenAPI';
|
|
15
|
-
import
|
|
16
|
+
import { tString } from './translate';
|
|
16
17
|
import { checkIsReference, resolveDescription, resolveFirstExample } from './utils';
|
|
17
18
|
|
|
18
19
|
type CircularRefsIds = Map<OpenAPIV3.SchemaObject, string>;
|
|
@@ -40,7 +41,7 @@ function OpenAPISchemaProperty(props: {
|
|
|
40
41
|
|
|
41
42
|
return (
|
|
42
43
|
<div id={id} className={clsx('openapi-schema', className)}>
|
|
43
|
-
<OpenAPISchemaPresentation property={property} />
|
|
44
|
+
<OpenAPISchemaPresentation context={context} property={property} />
|
|
44
45
|
{(() => {
|
|
45
46
|
const circularRefId = parentCircularRefs.get(schema);
|
|
46
47
|
// Avoid recursing infinitely, and instead render a link to the parent schema
|
|
@@ -54,7 +55,12 @@ function OpenAPISchemaProperty(props: {
|
|
|
54
55
|
const properties = getSchemaProperties(schema);
|
|
55
56
|
if (properties?.length) {
|
|
56
57
|
return (
|
|
57
|
-
<OpenAPIDisclosure
|
|
58
|
+
<OpenAPIDisclosure
|
|
59
|
+
icon={context.icons.plus}
|
|
60
|
+
label={(isExpanded) =>
|
|
61
|
+
getDisclosureLabel({ schema, isExpanded, context })
|
|
62
|
+
}
|
|
63
|
+
>
|
|
58
64
|
<OpenAPISchemaProperties
|
|
59
65
|
properties={properties}
|
|
60
66
|
circularRefs={circularRefs}
|
|
@@ -208,7 +214,10 @@ function OpenAPISchemaAlternative(props: {
|
|
|
208
214
|
{description ? (
|
|
209
215
|
<Markdown source={description} className="openapi-schema-description" />
|
|
210
216
|
) : null}
|
|
211
|
-
<OpenAPIDisclosure
|
|
217
|
+
<OpenAPIDisclosure
|
|
218
|
+
icon={context.icons.plus}
|
|
219
|
+
label={(isExpanded) => getDisclosureLabel({ schema, isExpanded, context })}
|
|
220
|
+
>
|
|
212
221
|
{properties?.length ? (
|
|
213
222
|
<OpenAPISchemaProperties
|
|
214
223
|
properties={properties}
|
|
@@ -246,8 +255,9 @@ function OpenAPISchemaCircularRef(props: { id: string; schema: OpenAPIV3.SchemaO
|
|
|
246
255
|
*/
|
|
247
256
|
function OpenAPISchemaEnum(props: {
|
|
248
257
|
schema: OpenAPIV3.SchemaObject & OpenAPICustomOperationProperties;
|
|
258
|
+
context: OpenAPIClientContext;
|
|
249
259
|
}) {
|
|
250
|
-
const { schema } = props;
|
|
260
|
+
const { schema, context } = props;
|
|
251
261
|
|
|
252
262
|
const enumValues = (() => {
|
|
253
263
|
// Render x-gitbook-enum first, as it has a different format
|
|
@@ -290,6 +300,7 @@ function OpenAPISchemaEnum(props: {
|
|
|
290
300
|
value={item.value}
|
|
291
301
|
label={item.description}
|
|
292
302
|
withTooltip={!!item.description}
|
|
303
|
+
context={context}
|
|
293
304
|
>
|
|
294
305
|
<code>{`${item.value}`}</code>
|
|
295
306
|
</OpenAPICopyButton>
|
|
@@ -302,9 +313,13 @@ function OpenAPISchemaEnum(props: {
|
|
|
302
313
|
/**
|
|
303
314
|
* Render the top row of a schema. e.g: name, type, and required status.
|
|
304
315
|
*/
|
|
305
|
-
function OpenAPISchemaPresentation(props: {
|
|
316
|
+
function OpenAPISchemaPresentation(props: {
|
|
317
|
+
property: OpenAPISchemaPropertyEntry;
|
|
318
|
+
context: OpenAPIClientContext;
|
|
319
|
+
}) {
|
|
306
320
|
const {
|
|
307
321
|
property: { schema, propertyName, required },
|
|
322
|
+
context,
|
|
308
323
|
} = props;
|
|
309
324
|
|
|
310
325
|
const description = resolveDescription(schema);
|
|
@@ -317,6 +332,7 @@ function OpenAPISchemaPresentation(props: { property: OpenAPISchemaPropertyEntry
|
|
|
317
332
|
type={getSchemaTitle(schema)}
|
|
318
333
|
propertyName={propertyName}
|
|
319
334
|
required={required}
|
|
335
|
+
context={context}
|
|
320
336
|
/>
|
|
321
337
|
{typeof schema['x-deprecated-sunset'] === 'string' ? (
|
|
322
338
|
<div className="openapi-deprecated-sunset openapi-schema-description openapi-markdown">
|
|
@@ -349,7 +365,7 @@ function OpenAPISchemaPresentation(props: { property: OpenAPISchemaPropertyEntry
|
|
|
349
365
|
Pattern: <code>{schema.pattern}</code>
|
|
350
366
|
</span>
|
|
351
367
|
) : null}
|
|
352
|
-
<OpenAPISchemaEnum schema={schema} />
|
|
368
|
+
<OpenAPISchemaEnum schema={schema} context={context} />
|
|
353
369
|
</div>
|
|
354
370
|
);
|
|
355
371
|
}
|
|
@@ -444,7 +460,91 @@ export function getSchemaAlternatives(
|
|
|
444
460
|
}
|
|
445
461
|
|
|
446
462
|
const [type, schemas] = alternatives;
|
|
447
|
-
return
|
|
463
|
+
return mergeAlternatives(
|
|
464
|
+
type,
|
|
465
|
+
flattenAlternatives(type, schemas, new Set(ancestors).add(schema))
|
|
466
|
+
);
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Merge alternatives of the same type into a single schema.
|
|
471
|
+
* - Merge string enums
|
|
472
|
+
*/
|
|
473
|
+
function mergeAlternatives(
|
|
474
|
+
alternativeType: AlternativeType,
|
|
475
|
+
schemasOrRefs: OpenAPIV3.SchemaObject[]
|
|
476
|
+
): OpenAPIV3.SchemaObject[] | null {
|
|
477
|
+
switch (alternativeType) {
|
|
478
|
+
case 'oneOf': {
|
|
479
|
+
return schemasOrRefs.reduce<OpenAPIV3.SchemaObject[]>((acc, schemaOrRef) => {
|
|
480
|
+
const latest = acc.at(-1);
|
|
481
|
+
|
|
482
|
+
if (
|
|
483
|
+
latest &&
|
|
484
|
+
latest.type === 'string' &&
|
|
485
|
+
latest.enum &&
|
|
486
|
+
schemaOrRef.type === 'string' &&
|
|
487
|
+
schemaOrRef.enum
|
|
488
|
+
) {
|
|
489
|
+
latest.enum = Array.from(new Set([...latest.enum, ...schemaOrRef.enum]));
|
|
490
|
+
latest.nullable = latest.nullable || schemaOrRef.nullable;
|
|
491
|
+
return acc;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
acc.push(schemaOrRef);
|
|
495
|
+
return acc;
|
|
496
|
+
}, []);
|
|
497
|
+
}
|
|
498
|
+
case 'allOf': {
|
|
499
|
+
return schemasOrRefs.reduce<OpenAPIV3.SchemaObject[]>((acc, schemaOrRef) => {
|
|
500
|
+
const latest = acc.at(-1);
|
|
501
|
+
|
|
502
|
+
if (
|
|
503
|
+
latest &&
|
|
504
|
+
latest.type === 'string' &&
|
|
505
|
+
latest.enum &&
|
|
506
|
+
schemaOrRef.type === 'string' &&
|
|
507
|
+
schemaOrRef.enum
|
|
508
|
+
) {
|
|
509
|
+
const keys = Object.keys(schemaOrRef);
|
|
510
|
+
if (keys.every((key) => ['type', 'enum', 'nullable'].includes(key))) {
|
|
511
|
+
latest.enum = Array.from(new Set([...latest.enum, ...schemaOrRef.enum]));
|
|
512
|
+
latest.nullable = latest.nullable || schemaOrRef.nullable;
|
|
513
|
+
return acc;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
if (latest && latest.type === 'object' && schemaOrRef.type === 'object') {
|
|
518
|
+
const keys = Object.keys(schemaOrRef);
|
|
519
|
+
if (
|
|
520
|
+
keys.every((key) =>
|
|
521
|
+
['type', 'properties', 'required', 'nullable'].includes(key)
|
|
522
|
+
)
|
|
523
|
+
) {
|
|
524
|
+
latest.properties = {
|
|
525
|
+
...latest.properties,
|
|
526
|
+
...schemaOrRef.properties,
|
|
527
|
+
};
|
|
528
|
+
latest.required = Array.from(
|
|
529
|
+
new Set([
|
|
530
|
+
...(Array.isArray(latest.required) ? latest.required : []),
|
|
531
|
+
...(Array.isArray(schemaOrRef.required)
|
|
532
|
+
? schemaOrRef.required
|
|
533
|
+
: []),
|
|
534
|
+
])
|
|
535
|
+
);
|
|
536
|
+
latest.nullable = latest.nullable || schemaOrRef.nullable;
|
|
537
|
+
return acc;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
acc.push(schemaOrRef);
|
|
542
|
+
return acc;
|
|
543
|
+
}, []);
|
|
544
|
+
}
|
|
545
|
+
default:
|
|
546
|
+
return schemasOrRefs;
|
|
547
|
+
}
|
|
448
548
|
}
|
|
449
549
|
|
|
450
550
|
function flattenAlternatives(
|
|
@@ -502,19 +602,26 @@ function getSchemaTitle(schema: OpenAPIV3.SchemaObject): string {
|
|
|
502
602
|
return type;
|
|
503
603
|
}
|
|
504
604
|
|
|
505
|
-
function getDisclosureLabel(
|
|
605
|
+
function getDisclosureLabel(props: {
|
|
606
|
+
schema: OpenAPIV3.SchemaObject;
|
|
607
|
+
isExpanded: boolean;
|
|
608
|
+
context: OpenAPIClientContext;
|
|
609
|
+
}) {
|
|
610
|
+
const { schema, isExpanded, context } = props;
|
|
611
|
+
let label: string;
|
|
506
612
|
if (schema.type === 'array' && !!schema.items) {
|
|
507
613
|
if (schema.items.oneOf) {
|
|
508
|
-
|
|
614
|
+
label = tString(context.translation, 'available_items').toLowerCase();
|
|
509
615
|
}
|
|
510
|
-
|
|
511
616
|
// Fallback to "child attributes" for enums and objects
|
|
512
|
-
if (schema.items.enum || schema.items.type === 'object') {
|
|
513
|
-
|
|
617
|
+
else if (schema.items.enum || schema.items.type === 'object') {
|
|
618
|
+
label = tString(context.translation, 'child_attributes').toLowerCase();
|
|
619
|
+
} else {
|
|
620
|
+
label = schema.items.title ?? schema.title ?? getSchemaTitle(schema.items);
|
|
514
621
|
}
|
|
515
|
-
|
|
516
|
-
|
|
622
|
+
} else {
|
|
623
|
+
label = schema.title || tString(context.translation, 'child_attributes').toLowerCase();
|
|
517
624
|
}
|
|
518
625
|
|
|
519
|
-
return
|
|
626
|
+
return `${isExpanded ? tString(context.translation, 'hide') : tString(context.translation, 'show')} ${label}`;
|
|
520
627
|
}
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import type { OpenAPIV3 } from '@gitbook/openapi-parser';
|
|
2
2
|
import type React from 'react';
|
|
3
|
+
import type { OpenAPIClientContext } from './context';
|
|
4
|
+
import { t, tString } from './translate';
|
|
3
5
|
|
|
4
6
|
interface OpenAPISchemaNameProps {
|
|
5
7
|
schema?: OpenAPIV3.SchemaObject;
|
|
6
8
|
propertyName?: string | React.JSX.Element;
|
|
7
9
|
required?: boolean;
|
|
8
10
|
type?: string;
|
|
11
|
+
context: OpenAPIClientContext;
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
/**
|
|
@@ -13,9 +16,9 @@ interface OpenAPISchemaNameProps {
|
|
|
13
16
|
* It includes the property name, type, required and deprecated status.
|
|
14
17
|
*/
|
|
15
18
|
export function OpenAPISchemaName(props: OpenAPISchemaNameProps) {
|
|
16
|
-
const { schema, type, propertyName, required } = props;
|
|
19
|
+
const { schema, type, propertyName, required, context } = props;
|
|
17
20
|
|
|
18
|
-
const additionalItems = schema && getAdditionalItems(schema);
|
|
21
|
+
const additionalItems = schema && getAdditionalItems(schema, context);
|
|
19
22
|
|
|
20
23
|
return (
|
|
21
24
|
<span className="openapi-schema-name">
|
|
@@ -30,33 +33,45 @@ export function OpenAPISchemaName(props: OpenAPISchemaNameProps) {
|
|
|
30
33
|
<span className="openapi-schema-type">{additionalItems}</span>
|
|
31
34
|
) : null}
|
|
32
35
|
</span>
|
|
33
|
-
{schema?.readOnly ?
|
|
36
|
+
{schema?.readOnly ? (
|
|
37
|
+
<span className="openapi-schema-readonly">
|
|
38
|
+
{t(context.translation, 'read_only')}
|
|
39
|
+
</span>
|
|
40
|
+
) : null}
|
|
34
41
|
{schema?.writeOnly ? (
|
|
35
|
-
<span className="openapi-schema-writeonly">
|
|
42
|
+
<span className="openapi-schema-writeonly">
|
|
43
|
+
{t(context.translation, 'write_only')}
|
|
44
|
+
</span>
|
|
36
45
|
) : null}
|
|
37
46
|
{required ? (
|
|
38
|
-
<span className="openapi-schema-required">
|
|
47
|
+
<span className="openapi-schema-required">
|
|
48
|
+
{t(context.translation, 'required')}
|
|
49
|
+
</span>
|
|
39
50
|
) : (
|
|
40
|
-
<span className="openapi-schema-optional">
|
|
51
|
+
<span className="openapi-schema-optional">
|
|
52
|
+
{t(context.translation, 'optional')}
|
|
53
|
+
</span>
|
|
41
54
|
)}
|
|
42
|
-
{schema?.deprecated ?
|
|
55
|
+
{schema?.deprecated ? (
|
|
56
|
+
<span className="openapi-deprecated">{t(context.translation, 'deprecated')}</span>
|
|
57
|
+
) : null}
|
|
43
58
|
</span>
|
|
44
59
|
);
|
|
45
60
|
}
|
|
46
61
|
|
|
47
|
-
function getAdditionalItems(schema: OpenAPIV3.SchemaObject): string {
|
|
62
|
+
function getAdditionalItems(schema: OpenAPIV3.SchemaObject, context: OpenAPIClientContext): string {
|
|
48
63
|
let additionalItems = '';
|
|
49
64
|
|
|
50
65
|
if (schema.minimum || schema.minLength || schema.minItems) {
|
|
51
|
-
additionalItems += ` · min: ${schema.minimum || schema.minLength || schema.minItems}`;
|
|
66
|
+
additionalItems += ` · ${tString(context.translation, 'min').toLowerCase()}: ${schema.minimum || schema.minLength || schema.minItems}`;
|
|
52
67
|
}
|
|
53
68
|
|
|
54
69
|
if (schema.maximum || schema.maxLength || schema.maxItems) {
|
|
55
|
-
additionalItems += ` · max: ${schema.maximum || schema.maxLength || schema.maxItems}`;
|
|
70
|
+
additionalItems += ` · ${tString(context.translation, 'max').toLowerCase()}: ${schema.maximum || schema.maxLength || schema.maxItems}`;
|
|
56
71
|
}
|
|
57
72
|
|
|
58
73
|
if (schema.nullable) {
|
|
59
|
-
additionalItems =
|
|
74
|
+
additionalItems = ` | ${tString(context.translation, 'nullable').toLowerCase()}`;
|
|
60
75
|
}
|
|
61
76
|
|
|
62
77
|
return additionalItems;
|
|
@@ -4,8 +4,8 @@ import {
|
|
|
4
4
|
OpenAPISchemaPropertiesFromServer,
|
|
5
5
|
type OpenAPISchemaPropertyEntry,
|
|
6
6
|
} from './OpenAPISchema';
|
|
7
|
+
import type { OpenAPIClientContext } from './context';
|
|
7
8
|
import { decycle } from './decycle';
|
|
8
|
-
import type { OpenAPIClientContext } from './types';
|
|
9
9
|
|
|
10
10
|
export function OpenAPISchemaProperties(props: {
|
|
11
11
|
id?: string;
|
|
@@ -1,12 +1,10 @@
|
|
|
1
1
|
import { InteractiveSection } from './InteractiveSection';
|
|
2
2
|
import { Markdown } from './Markdown';
|
|
3
3
|
import { OpenAPISchemaName } from './OpenAPISchemaName';
|
|
4
|
-
import type {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
} from './types';
|
|
9
|
-
import { resolveDescription } from './utils';
|
|
4
|
+
import type { OpenAPIClientContext } from './context';
|
|
5
|
+
import { t } from './translate';
|
|
6
|
+
import type { OpenAPIOperationData, OpenAPISecurityWithRequired } from './types';
|
|
7
|
+
import { createStateKey, resolveDescription } from './utils';
|
|
10
8
|
|
|
11
9
|
/**
|
|
12
10
|
* Present securities authorization that can be used for this operation.
|
|
@@ -23,10 +21,12 @@ export function OpenAPISecurities(props: {
|
|
|
23
21
|
|
|
24
22
|
return (
|
|
25
23
|
<InteractiveSection
|
|
26
|
-
header=
|
|
24
|
+
header={t(context.translation, 'authorizations')}
|
|
25
|
+
stateKey={createStateKey('securities', context.blockKey)}
|
|
27
26
|
toggeable
|
|
28
27
|
defaultOpened={false}
|
|
29
28
|
toggleIcon={context.icons.chevronRight}
|
|
29
|
+
selectIcon={context.icons.chevronDown}
|
|
30
30
|
className="openapi-securities"
|
|
31
31
|
tabs={securities.map(([key, security]) => {
|
|
32
32
|
const description = resolveDescription(security);
|
|
@@ -36,7 +36,7 @@ export function OpenAPISecurities(props: {
|
|
|
36
36
|
body: (
|
|
37
37
|
<div className="openapi-schema">
|
|
38
38
|
<div className="openapi-schema-presentation">
|
|
39
|
-
{getLabelForType(security)}
|
|
39
|
+
{getLabelForType(security, context)}
|
|
40
40
|
|
|
41
41
|
{description ? (
|
|
42
42
|
<Markdown
|
|
@@ -53,11 +53,12 @@ export function OpenAPISecurities(props: {
|
|
|
53
53
|
);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
function getLabelForType(security: OpenAPISecurityWithRequired) {
|
|
56
|
+
function getLabelForType(security: OpenAPISecurityWithRequired, context: OpenAPIClientContext) {
|
|
57
57
|
switch (security.type) {
|
|
58
58
|
case 'apiKey':
|
|
59
59
|
return (
|
|
60
60
|
<OpenAPISchemaName
|
|
61
|
+
context={context}
|
|
61
62
|
propertyName={security.name ?? 'apiKey'}
|
|
62
63
|
type="string"
|
|
63
64
|
required={security.required}
|
|
@@ -67,6 +68,7 @@ function getLabelForType(security: OpenAPISecurityWithRequired) {
|
|
|
67
68
|
if (security.scheme === 'basic') {
|
|
68
69
|
return (
|
|
69
70
|
<OpenAPISchemaName
|
|
71
|
+
context={context}
|
|
70
72
|
propertyName="Authorization"
|
|
71
73
|
type="string"
|
|
72
74
|
required={security.required}
|
|
@@ -79,6 +81,7 @@ function getLabelForType(security: OpenAPISecurityWithRequired) {
|
|
|
79
81
|
return (
|
|
80
82
|
<>
|
|
81
83
|
<OpenAPISchemaName
|
|
84
|
+
context={context}
|
|
82
85
|
propertyName="Authorization"
|
|
83
86
|
type="string"
|
|
84
87
|
required={security.required}
|
|
@@ -94,11 +97,29 @@ function getLabelForType(security: OpenAPISecurityWithRequired) {
|
|
|
94
97
|
);
|
|
95
98
|
}
|
|
96
99
|
|
|
97
|
-
return
|
|
100
|
+
return (
|
|
101
|
+
<OpenAPISchemaName
|
|
102
|
+
context={context}
|
|
103
|
+
propertyName="HTTP"
|
|
104
|
+
required={security.required}
|
|
105
|
+
/>
|
|
106
|
+
);
|
|
98
107
|
case 'oauth2':
|
|
99
|
-
return
|
|
108
|
+
return (
|
|
109
|
+
<OpenAPISchemaName
|
|
110
|
+
context={context}
|
|
111
|
+
propertyName="OAuth2"
|
|
112
|
+
required={security.required}
|
|
113
|
+
/>
|
|
114
|
+
);
|
|
100
115
|
case 'openIdConnect':
|
|
101
|
-
return
|
|
116
|
+
return (
|
|
117
|
+
<OpenAPISchemaName
|
|
118
|
+
context={context}
|
|
119
|
+
propertyName="OpenID Connect"
|
|
120
|
+
required={security.required}
|
|
121
|
+
/>
|
|
122
|
+
);
|
|
102
123
|
default:
|
|
103
124
|
// @ts-ignore
|
|
104
125
|
return security.type;
|
package/src/OpenAPISelect.tsx
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import clsx from 'clsx';
|
|
4
|
+
import { useCallback } from 'react';
|
|
4
5
|
import {
|
|
5
6
|
Button,
|
|
6
7
|
type Key,
|
|
@@ -13,38 +14,63 @@ import {
|
|
|
13
14
|
type SelectProps,
|
|
14
15
|
SelectValue,
|
|
15
16
|
} from 'react-aria-components';
|
|
17
|
+
import { useStore } from 'zustand';
|
|
18
|
+
import { getOrCreateStoreByKey } from './getOrCreateStoreByKey';
|
|
16
19
|
|
|
17
20
|
export type OpenAPISelectItem = {
|
|
18
21
|
key: Key;
|
|
19
|
-
label: string;
|
|
22
|
+
label: string | React.ReactNode;
|
|
20
23
|
};
|
|
21
24
|
|
|
22
25
|
interface OpenAPISelectProps<T extends OpenAPISelectItem> extends Omit<SelectProps<T>, 'children'> {
|
|
23
26
|
items: T[];
|
|
24
27
|
children: React.ReactNode | ((item: T) => React.ReactNode);
|
|
25
|
-
selectedKey?: Key;
|
|
26
|
-
onChange?: (key: string | number) => void;
|
|
27
28
|
placement?: PopoverProps['placement'];
|
|
29
|
+
stateKey?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Icon to display in the select button.
|
|
32
|
+
*/
|
|
33
|
+
icon?: React.ReactNode;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function useSelectState(stateKey = 'select-state', initialKey?: Key) {
|
|
37
|
+
const store = useStore(getOrCreateStoreByKey(stateKey, initialKey));
|
|
38
|
+
return {
|
|
39
|
+
key: store.key,
|
|
40
|
+
setKey: useCallback((key: Key | null) => store.setKey(key), [store.setKey]),
|
|
41
|
+
};
|
|
28
42
|
}
|
|
29
43
|
|
|
30
44
|
export function OpenAPISelect<T extends OpenAPISelectItem>(props: OpenAPISelectProps<T>) {
|
|
31
|
-
const {
|
|
45
|
+
const {
|
|
46
|
+
icon = '▼',
|
|
47
|
+
items,
|
|
48
|
+
children,
|
|
49
|
+
className,
|
|
50
|
+
placement,
|
|
51
|
+
stateKey,
|
|
52
|
+
selectedKey,
|
|
53
|
+
onSelectionChange,
|
|
54
|
+
} = props;
|
|
55
|
+
|
|
56
|
+
const state = useSelectState(stateKey, items[0]?.key);
|
|
57
|
+
|
|
58
|
+
const selected = items.find((item) => item.key === state.key) || items[0];
|
|
32
59
|
|
|
33
60
|
return (
|
|
34
|
-
<Select
|
|
61
|
+
<Select
|
|
62
|
+
aria-label="OpenAPI Select"
|
|
63
|
+
{...props}
|
|
64
|
+
selectedKey={selectedKey || selected?.key}
|
|
65
|
+
onSelectionChange={(key) => {
|
|
66
|
+
onSelectionChange?.(key);
|
|
67
|
+
state.setKey(key);
|
|
68
|
+
}}
|
|
69
|
+
className={clsx('openapi-select', className)}
|
|
70
|
+
>
|
|
35
71
|
<Button>
|
|
36
72
|
<SelectValue />
|
|
37
|
-
|
|
38
|
-
<svg
|
|
39
|
-
className="gb-icon"
|
|
40
|
-
style={{
|
|
41
|
-
maskImage:
|
|
42
|
-
"url('https://ka-p.fontawesome.com/releases/v6.6.0/svgs/regular/chevron-down.svg?v=2&token=a463935e93')",
|
|
43
|
-
maskRepeat: 'no-repeat',
|
|
44
|
-
maskPosition: 'center center',
|
|
45
|
-
}}
|
|
46
|
-
/>
|
|
47
|
-
</span>
|
|
73
|
+
{icon}
|
|
48
74
|
</Button>
|
|
49
75
|
<Popover placement={placement} className="openapi-select-popover">
|
|
50
76
|
<ListBox className="openapi-select-listbox" items={items}>
|
package/src/OpenAPISpec.tsx
CHANGED
|
@@ -5,16 +5,23 @@ import { OpenAPIResponses } from './OpenAPIResponses';
|
|
|
5
5
|
import { OpenAPISchemaProperties } from './OpenAPISchemaServer';
|
|
6
6
|
import { OpenAPISecurities } from './OpenAPISecurities';
|
|
7
7
|
import { StaticSection } from './StaticSection';
|
|
8
|
-
import type { OpenAPIClientContext
|
|
8
|
+
import type { OpenAPIClientContext } from './context';
|
|
9
|
+
import { tString } from './translate';
|
|
10
|
+
import type { OpenAPIOperationData, OpenAPIWebhookData } from './types';
|
|
9
11
|
import { parameterToProperty } from './utils';
|
|
10
12
|
|
|
11
|
-
export function OpenAPISpec(props: {
|
|
13
|
+
export function OpenAPISpec(props: {
|
|
14
|
+
data: OpenAPIOperationData | OpenAPIWebhookData;
|
|
15
|
+
context: OpenAPIClientContext;
|
|
16
|
+
}) {
|
|
12
17
|
const { data, context } = props;
|
|
13
18
|
|
|
14
|
-
const { operation
|
|
19
|
+
const { operation } = data;
|
|
15
20
|
|
|
16
21
|
const parameters = operation.parameters ?? [];
|
|
17
|
-
const parameterGroups = groupParameters(parameters);
|
|
22
|
+
const parameterGroups = groupParameters(parameters, context);
|
|
23
|
+
|
|
24
|
+
const securities = 'securities' in data ? data.securities : [];
|
|
18
25
|
|
|
19
26
|
return (
|
|
20
27
|
<>
|
|
@@ -42,6 +49,7 @@ export function OpenAPISpec(props: { data: OpenAPIOperationData; context: OpenAP
|
|
|
42
49
|
key="body"
|
|
43
50
|
requestBody={operation.requestBody}
|
|
44
51
|
context={context}
|
|
52
|
+
data={data}
|
|
45
53
|
/>
|
|
46
54
|
) : null}
|
|
47
55
|
{operation.responses ? (
|
|
@@ -55,7 +63,10 @@ export function OpenAPISpec(props: { data: OpenAPIOperationData; context: OpenAP
|
|
|
55
63
|
);
|
|
56
64
|
}
|
|
57
65
|
|
|
58
|
-
function groupParameters(
|
|
66
|
+
function groupParameters(
|
|
67
|
+
parameters: OpenAPI.Parameters,
|
|
68
|
+
context: OpenAPIClientContext
|
|
69
|
+
): Array<{
|
|
59
70
|
key: string;
|
|
60
71
|
label: string;
|
|
61
72
|
parameters: OpenAPI.Parameters;
|
|
@@ -72,7 +83,7 @@ function groupParameters(parameters: OpenAPI.Parameters): Array<{
|
|
|
72
83
|
.filter((parameter) => parameter.in)
|
|
73
84
|
.forEach((parameter) => {
|
|
74
85
|
const key = parameter.in;
|
|
75
|
-
const label = getParameterGroupName(parameter.in);
|
|
86
|
+
const label = getParameterGroupName(parameter.in, context);
|
|
76
87
|
const group = groups.find((group) => group.key === key);
|
|
77
88
|
if (group) {
|
|
78
89
|
group.parameters.push(parameter);
|
|
@@ -90,14 +101,14 @@ function groupParameters(parameters: OpenAPI.Parameters): Array<{
|
|
|
90
101
|
return groups;
|
|
91
102
|
}
|
|
92
103
|
|
|
93
|
-
function getParameterGroupName(paramIn: string): string {
|
|
104
|
+
function getParameterGroupName(paramIn: string, context: OpenAPIClientContext): string {
|
|
94
105
|
switch (paramIn) {
|
|
95
106
|
case 'path':
|
|
96
|
-
return
|
|
107
|
+
return tString(context.translation, 'path_parameters');
|
|
97
108
|
case 'query':
|
|
98
|
-
return
|
|
109
|
+
return tString(context.translation, 'query_parameters');
|
|
99
110
|
case 'header':
|
|
100
|
-
return
|
|
111
|
+
return tString(context.translation, 'header_parameters');
|
|
101
112
|
default:
|
|
102
113
|
return paramIn;
|
|
103
114
|
}
|