@gitbook/react-openapi 1.1.8 → 1.1.10
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.jsx +7 -6
- package/dist/OpenAPICodeSample.d.ts +2 -2
- package/dist/OpenAPICodeSample.jsx +3 -8
- package/dist/OpenAPICodeSampleInteractive.jsx +31 -19
- package/dist/OpenAPICodeSampleSelector.d.ts +15 -0
- package/dist/OpenAPICodeSampleSelector.jsx +49 -0
- package/dist/OpenAPIExample.d.ts +34 -0
- package/dist/OpenAPIExample.jsx +103 -0
- package/dist/OpenAPIOperation.d.ts +2 -2
- package/dist/OpenAPIOperation.jsx +3 -7
- package/dist/OpenAPIPath.d.ts +10 -2
- package/dist/OpenAPIPath.jsx +9 -4
- package/dist/OpenAPIResponse.jsx +3 -3
- package/dist/OpenAPIResponseExample.d.ts +2 -2
- package/dist/OpenAPIResponseExample.jsx +4 -90
- package/dist/OpenAPIResponses.jsx +23 -10
- package/dist/OpenAPISchema.jsx +26 -15
- package/dist/OpenAPISchemaName.jsx +2 -7
- package/dist/OpenAPISecurities.jsx +6 -6
- package/dist/OpenAPISelect.d.ts +15 -0
- package/dist/OpenAPISelect.jsx +32 -0
- package/dist/OpenAPITabs.jsx +9 -9
- package/dist/context.d.ts +54 -0
- package/dist/context.js +11 -0
- package/dist/generateSchemaExample.d.ts +1 -1
- package/dist/generateSchemaExample.js +28 -26
- package/dist/getOrCreateStoreByKey.d.ts +10 -0
- package/dist/getOrCreateStoreByKey.js +20 -0
- package/dist/index.d.ts +1 -1
- package/dist/resolveOpenAPIOperation.js +10 -5
- package/dist/schemas/OpenAPISchemas.d.ts +5 -6
- package/dist/schemas/OpenAPISchemas.jsx +45 -38
- package/dist/schemas/resolveOpenAPISchemas.d.ts +4 -3
- package/dist/schemas/resolveOpenAPISchemas.js +0 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types.d.ts +32 -26
- package/package.json +1 -1
- package/src/InteractiveSection.tsx +10 -8
- package/src/OpenAPICodeSample.tsx +8 -15
- package/src/OpenAPICodeSampleInteractive.tsx +43 -26
- package/src/OpenAPICodeSampleSelector.tsx +87 -0
- package/src/OpenAPIExample.tsx +129 -0
- package/src/OpenAPIOperation.tsx +6 -10
- package/src/OpenAPIPath.tsx +23 -6
- package/src/OpenAPIResponse.tsx +9 -7
- package/src/OpenAPIResponseExample.tsx +13 -113
- package/src/OpenAPIResponses.tsx +37 -12
- package/src/OpenAPISchema.tsx +40 -25
- package/src/OpenAPISchemaName.tsx +2 -8
- package/src/OpenAPISecurities.tsx +22 -9
- package/src/OpenAPISelect.tsx +70 -0
- package/src/OpenAPITabs.tsx +9 -9
- package/src/context.ts +64 -0
- package/src/generateSchemaExample.test.ts +1020 -0
- package/src/generateSchemaExample.ts +103 -36
- package/src/getOrCreateStoreByKey.ts +35 -0
- package/src/index.ts +1 -1
- package/src/resolveOpenAPIOperation.ts +14 -3
- package/src/schemas/OpenAPISchemas.tsx +75 -70
- package/src/schemas/resolveOpenAPISchemas.ts +4 -5
- package/src/types.ts +36 -29
- package/dist/useSyncedTabsGlobalState.d.ts +0 -10
- package/dist/useSyncedTabsGlobalState.js +0 -20
- package/src/useSyncedTabsGlobalState.ts +0 -35
|
@@ -16,14 +16,10 @@ export function generateSchemaExample(
|
|
|
16
16
|
schema: OpenAPIV3.SchemaObject,
|
|
17
17
|
options?: GenerateSchemaExampleOptions
|
|
18
18
|
): JSONValue | undefined {
|
|
19
|
-
return getExampleFromSchema(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
...options,
|
|
24
|
-
},
|
|
25
|
-
3 // Max depth for circular references
|
|
26
|
-
);
|
|
19
|
+
return getExampleFromSchema(schema, {
|
|
20
|
+
emptyString: 'text',
|
|
21
|
+
...options,
|
|
22
|
+
});
|
|
27
23
|
}
|
|
28
24
|
|
|
29
25
|
/**
|
|
@@ -103,21 +99,6 @@ function guessFromFormat(schema: Record<string, any>, fallback = '') {
|
|
|
103
99
|
return genericExampleValues[schema.format] ?? fallback;
|
|
104
100
|
}
|
|
105
101
|
|
|
106
|
-
/** Map of all the results */
|
|
107
|
-
const resultCache = new WeakMap<Record<string, any>, any>();
|
|
108
|
-
|
|
109
|
-
/** Store result in the cache, and return the result */
|
|
110
|
-
function cache(schema: Record<string, any>, result: unknown) {
|
|
111
|
-
// Avoid unnecessary WeakMap operations for primitive values
|
|
112
|
-
if (typeof result !== 'object' || result === null) {
|
|
113
|
-
return result;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
resultCache.set(schema, result);
|
|
117
|
-
|
|
118
|
-
return result;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
102
|
/**
|
|
122
103
|
* This function takes an OpenAPI schema and generates an example from it
|
|
123
104
|
* Forked from : https://github.com/scalar/scalar/blob/main/packages/oas-utils/src/spec-getters/getExampleFromSchema.ts
|
|
@@ -152,8 +133,20 @@ const getExampleFromSchema = (
|
|
|
152
133
|
},
|
|
153
134
|
level = 0,
|
|
154
135
|
parentSchema?: Record<string, any>,
|
|
155
|
-
name?: string
|
|
136
|
+
name?: string,
|
|
137
|
+
resultCache = new WeakMap<Record<string, any>, any>()
|
|
156
138
|
): any => {
|
|
139
|
+
// Store result in the cache, and return the result
|
|
140
|
+
function cache(schema: Record<string, any>, result: unknown) {
|
|
141
|
+
// Avoid unnecessary WeakMap operations for primitive values
|
|
142
|
+
if (typeof result !== 'object' || result === null) {
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
resultCache.set(schema, result);
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
|
|
157
150
|
// Check if the result is already cached
|
|
158
151
|
if (resultCache.has(schema)) {
|
|
159
152
|
return resultCache.get(schema);
|
|
@@ -173,6 +166,11 @@ const getExampleFromSchema = (
|
|
|
173
166
|
// But if `emptyString` is set, we do want to see some values.
|
|
174
167
|
const makeUpRandomData = !!options?.emptyString;
|
|
175
168
|
|
|
169
|
+
// If the property is deprecated we don't show it in examples.
|
|
170
|
+
if (schema.deprecated) {
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
|
|
176
174
|
// Check if the property is read-only/write-only
|
|
177
175
|
if (
|
|
178
176
|
(options?.mode === 'write' && schema.readOnly) ||
|
|
@@ -245,7 +243,8 @@ const getExampleFromSchema = (
|
|
|
245
243
|
options,
|
|
246
244
|
level + 1,
|
|
247
245
|
schema,
|
|
248
|
-
propertyName
|
|
246
|
+
propertyName,
|
|
247
|
+
resultCache
|
|
249
248
|
);
|
|
250
249
|
|
|
251
250
|
if (typeof response[propertyXmlTagName ?? propertyName] === 'undefined') {
|
|
@@ -269,7 +268,8 @@ const getExampleFromSchema = (
|
|
|
269
268
|
options,
|
|
270
269
|
level + 1,
|
|
271
270
|
schema,
|
|
272
|
-
exampleKey
|
|
271
|
+
exampleKey,
|
|
272
|
+
resultCache
|
|
273
273
|
);
|
|
274
274
|
}
|
|
275
275
|
}
|
|
@@ -290,21 +290,51 @@ const getExampleFromSchema = (
|
|
|
290
290
|
response.ANY_ADDITIONAL_PROPERTY = getExampleFromSchema(
|
|
291
291
|
schema.additionalProperties,
|
|
292
292
|
options,
|
|
293
|
-
level + 1
|
|
293
|
+
level + 1,
|
|
294
|
+
undefined,
|
|
295
|
+
undefined,
|
|
296
|
+
resultCache
|
|
294
297
|
);
|
|
295
298
|
}
|
|
296
299
|
}
|
|
297
300
|
|
|
298
301
|
if (schema.anyOf !== undefined) {
|
|
299
|
-
Object.assign(
|
|
302
|
+
Object.assign(
|
|
303
|
+
response,
|
|
304
|
+
getExampleFromSchema(
|
|
305
|
+
schema.anyOf[0],
|
|
306
|
+
options,
|
|
307
|
+
level + 1,
|
|
308
|
+
undefined,
|
|
309
|
+
undefined,
|
|
310
|
+
resultCache
|
|
311
|
+
)
|
|
312
|
+
);
|
|
300
313
|
} else if (schema.oneOf !== undefined) {
|
|
301
|
-
Object.assign(
|
|
314
|
+
Object.assign(
|
|
315
|
+
response,
|
|
316
|
+
getExampleFromSchema(
|
|
317
|
+
schema.oneOf[0],
|
|
318
|
+
options,
|
|
319
|
+
level + 1,
|
|
320
|
+
undefined,
|
|
321
|
+
undefined,
|
|
322
|
+
resultCache
|
|
323
|
+
)
|
|
324
|
+
);
|
|
302
325
|
} else if (schema.allOf !== undefined) {
|
|
303
326
|
Object.assign(
|
|
304
327
|
response,
|
|
305
328
|
...schema.allOf
|
|
306
329
|
.map((item: Record<string, any>) =>
|
|
307
|
-
getExampleFromSchema(
|
|
330
|
+
getExampleFromSchema(
|
|
331
|
+
item,
|
|
332
|
+
options,
|
|
333
|
+
level + 1,
|
|
334
|
+
schema,
|
|
335
|
+
undefined,
|
|
336
|
+
resultCache
|
|
337
|
+
)
|
|
308
338
|
)
|
|
309
339
|
.filter((item: any) => item !== undefined)
|
|
310
340
|
);
|
|
@@ -335,7 +365,9 @@ const getExampleFromSchema = (
|
|
|
335
365
|
{ type: 'object', allOf: schema.items.allOf },
|
|
336
366
|
options,
|
|
337
367
|
level + 1,
|
|
338
|
-
schema
|
|
368
|
+
schema,
|
|
369
|
+
undefined,
|
|
370
|
+
resultCache
|
|
339
371
|
);
|
|
340
372
|
|
|
341
373
|
return cache(
|
|
@@ -346,7 +378,14 @@ const getExampleFromSchema = (
|
|
|
346
378
|
// For non-objects (like strings), collect all examples
|
|
347
379
|
const examples = schema.items.allOf
|
|
348
380
|
.map((item: Record<string, any>) =>
|
|
349
|
-
getExampleFromSchema(
|
|
381
|
+
getExampleFromSchema(
|
|
382
|
+
item,
|
|
383
|
+
options,
|
|
384
|
+
level + 1,
|
|
385
|
+
schema,
|
|
386
|
+
undefined,
|
|
387
|
+
resultCache
|
|
388
|
+
)
|
|
350
389
|
)
|
|
351
390
|
.filter((item: any) => item !== undefined);
|
|
352
391
|
|
|
@@ -368,7 +407,14 @@ const getExampleFromSchema = (
|
|
|
368
407
|
const schemas = schema.items[rule].slice(0, 1);
|
|
369
408
|
const exampleFromRule = schemas
|
|
370
409
|
.map((item: Record<string, any>) =>
|
|
371
|
-
getExampleFromSchema(
|
|
410
|
+
getExampleFromSchema(
|
|
411
|
+
item,
|
|
412
|
+
options,
|
|
413
|
+
level + 1,
|
|
414
|
+
schema,
|
|
415
|
+
undefined,
|
|
416
|
+
resultCache
|
|
417
|
+
)
|
|
372
418
|
)
|
|
373
419
|
.filter((item: any) => item !== undefined);
|
|
374
420
|
|
|
@@ -380,7 +426,14 @@ const getExampleFromSchema = (
|
|
|
380
426
|
}
|
|
381
427
|
|
|
382
428
|
if (schema.items?.type) {
|
|
383
|
-
const exampleFromSchema = getExampleFromSchema(
|
|
429
|
+
const exampleFromSchema = getExampleFromSchema(
|
|
430
|
+
schema.items,
|
|
431
|
+
options,
|
|
432
|
+
level + 1,
|
|
433
|
+
undefined,
|
|
434
|
+
undefined,
|
|
435
|
+
resultCache
|
|
436
|
+
);
|
|
384
437
|
|
|
385
438
|
return wrapItems ? [{ [itemsXmlTagName]: exampleFromSchema }] : [exampleFromSchema];
|
|
386
439
|
}
|
|
@@ -407,7 +460,14 @@ const getExampleFromSchema = (
|
|
|
407
460
|
const firstOneOfItem = discriminateSchema[0];
|
|
408
461
|
|
|
409
462
|
// Return an example for the first item
|
|
410
|
-
return getExampleFromSchema(
|
|
463
|
+
return getExampleFromSchema(
|
|
464
|
+
firstOneOfItem,
|
|
465
|
+
options,
|
|
466
|
+
level + 1,
|
|
467
|
+
undefined,
|
|
468
|
+
undefined,
|
|
469
|
+
resultCache
|
|
470
|
+
);
|
|
411
471
|
}
|
|
412
472
|
|
|
413
473
|
// Check if schema has the `allOf` key
|
|
@@ -417,7 +477,14 @@ const getExampleFromSchema = (
|
|
|
417
477
|
// Loop through all `allOf` schemas
|
|
418
478
|
schema.allOf.forEach((allOfItem: Record<string, any>) => {
|
|
419
479
|
// Return an example from the schema
|
|
420
|
-
const newExample = getExampleFromSchema(
|
|
480
|
+
const newExample = getExampleFromSchema(
|
|
481
|
+
allOfItem,
|
|
482
|
+
options,
|
|
483
|
+
level + 1,
|
|
484
|
+
undefined,
|
|
485
|
+
undefined,
|
|
486
|
+
resultCache
|
|
487
|
+
);
|
|
421
488
|
|
|
422
489
|
// Merge or overwrite the example
|
|
423
490
|
example =
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { createStore } from 'zustand';
|
|
4
|
+
|
|
5
|
+
type Key = string | number;
|
|
6
|
+
|
|
7
|
+
type State = {
|
|
8
|
+
key: Key | null;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
type Actions = { setKey: (key: Key | null) => void };
|
|
12
|
+
|
|
13
|
+
type Store = State & Actions;
|
|
14
|
+
|
|
15
|
+
const createStateStore = (initial?: Key) => {
|
|
16
|
+
return createStore<Store>()((set) => ({
|
|
17
|
+
key: initial ?? null,
|
|
18
|
+
setKey: (key) => {
|
|
19
|
+
set(() => ({ key }));
|
|
20
|
+
},
|
|
21
|
+
}));
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const defaultStores = new Map<string, ReturnType<typeof createStateStore>>();
|
|
25
|
+
|
|
26
|
+
const createStateStoreFactory = (stores: typeof defaultStores) => {
|
|
27
|
+
return (storeKey: string, initialKey?: Key) => {
|
|
28
|
+
if (!stores.has(storeKey)) {
|
|
29
|
+
stores.set(storeKey, createStateStore(initialKey));
|
|
30
|
+
}
|
|
31
|
+
return stores.get(storeKey)!;
|
|
32
|
+
};
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const getOrCreateStoreByKey = createStateStoreFactory(defaultStores);
|
package/src/index.ts
CHANGED
|
@@ -2,4 +2,4 @@ export * from './schemas';
|
|
|
2
2
|
export * from './OpenAPIOperation';
|
|
3
3
|
export * from './OpenAPIOperationContext';
|
|
4
4
|
export * from './resolveOpenAPIOperation';
|
|
5
|
-
export type {
|
|
5
|
+
export type { OpenAPIOperationData, OpenAPIContext } from './types';
|
|
@@ -40,16 +40,27 @@ export async function resolveOpenAPIOperation(
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
const servers = 'servers' in schema ? (schema.servers ?? []) : [];
|
|
43
|
-
const security
|
|
43
|
+
const security: OpenAPIV3_1.SecurityRequirementObject[] =
|
|
44
|
+
operation.security ?? schema.security ?? [];
|
|
45
|
+
|
|
46
|
+
// If security includes an empty object, it means that the security is optional
|
|
47
|
+
const isOptionalSecurity = security.some((entry) => Object.keys(entry).length === 0);
|
|
48
|
+
const flatSecurities = flattenSecurities(security);
|
|
44
49
|
|
|
45
50
|
// Resolve securities
|
|
46
51
|
const securities: OpenAPIOperationData['securities'] = [];
|
|
47
|
-
for (const entry of
|
|
52
|
+
for (const entry of flatSecurities) {
|
|
48
53
|
const securityKey = Object.keys(entry)[0];
|
|
49
54
|
if (securityKey) {
|
|
50
55
|
const securityScheme = schema.components?.securitySchemes?.[securityKey];
|
|
51
56
|
if (securityScheme && !checkIsReference(securityScheme)) {
|
|
52
|
-
securities.push([
|
|
57
|
+
securities.push([
|
|
58
|
+
securityKey,
|
|
59
|
+
{
|
|
60
|
+
...securityScheme,
|
|
61
|
+
required: !isOptionalSecurity,
|
|
62
|
+
},
|
|
63
|
+
]);
|
|
53
64
|
}
|
|
54
65
|
}
|
|
55
66
|
}
|
|
@@ -1,99 +1,104 @@
|
|
|
1
|
+
import type { OpenAPISchema } from '@gitbook/openapi-parser';
|
|
1
2
|
import clsx from 'clsx';
|
|
2
3
|
import { OpenAPIDisclosureGroup } from '../OpenAPIDisclosureGroup';
|
|
4
|
+
import { OpenAPIExample, getExampleFromSchema } from '../OpenAPIExample';
|
|
3
5
|
import { OpenAPIRootSchema } from '../OpenAPISchemaServer';
|
|
4
|
-
import { Section, SectionBody } from '../StaticSection';
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
type OpenAPISchemasContextProps = Omit<
|
|
8
|
-
OpenAPIContextProps,
|
|
9
|
-
'renderCodeBlock' | 'renderHeading' | 'renderDocument'
|
|
10
|
-
>;
|
|
6
|
+
import { Section, SectionBody, StaticSection } from '../StaticSection';
|
|
7
|
+
import { getOpenAPIClientContext } from '../context';
|
|
8
|
+
import type { OpenAPIContext } from '../types';
|
|
11
9
|
|
|
12
10
|
/**
|
|
13
|
-
*
|
|
11
|
+
* OpenAPI Schemas component.
|
|
14
12
|
*/
|
|
15
13
|
export function OpenAPISchemas(props: {
|
|
16
14
|
className?: string;
|
|
17
|
-
|
|
18
|
-
context:
|
|
15
|
+
schemas: OpenAPISchema[];
|
|
16
|
+
context: OpenAPIContext;
|
|
19
17
|
/**
|
|
20
18
|
* Whether to show the schema directly if there is only one.
|
|
21
19
|
*/
|
|
22
20
|
grouped?: boolean;
|
|
23
21
|
}) {
|
|
24
|
-
const {
|
|
25
|
-
const { schemas } = data;
|
|
22
|
+
const { schemas, context, grouped, className } = props;
|
|
26
23
|
|
|
27
|
-
const
|
|
28
|
-
defaultInteractiveOpened: context.defaultInteractiveOpened,
|
|
29
|
-
icons: context.icons,
|
|
30
|
-
blockKey: context.blockKey,
|
|
31
|
-
};
|
|
24
|
+
const firstSchema = schemas[0];
|
|
32
25
|
|
|
33
|
-
if (!
|
|
26
|
+
if (!firstSchema) {
|
|
34
27
|
return null;
|
|
35
28
|
}
|
|
36
29
|
|
|
37
|
-
|
|
38
|
-
<div className={clsx('openapi-schemas', className)}>
|
|
39
|
-
<OpenAPIRootSchemasSchema grouped={grouped} schemas={schemas} context={clientContext} />
|
|
40
|
-
</div>
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Root schema for OpenAPI schemas.
|
|
46
|
-
* It displays a single model or a disclosure group for multiple schemas.
|
|
47
|
-
*/
|
|
48
|
-
function OpenAPIRootSchemasSchema(props: {
|
|
49
|
-
schemas: OpenAPISchemasData['schemas'];
|
|
50
|
-
context: OpenAPIClientContext;
|
|
51
|
-
grouped?: boolean;
|
|
52
|
-
}) {
|
|
53
|
-
const { schemas, context, grouped } = props;
|
|
30
|
+
const clientContext = getOpenAPIClientContext(context);
|
|
54
31
|
|
|
55
32
|
// If there is only one model and we are not grouping, we show it directly.
|
|
56
33
|
if (schemas.length === 1 && !grouped) {
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
if (!schema) {
|
|
60
|
-
return null;
|
|
61
|
-
}
|
|
62
|
-
|
|
34
|
+
const title = `The ${firstSchema.name} object`;
|
|
63
35
|
return (
|
|
64
|
-
<
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
36
|
+
<div className={clsx('openapi-schemas', className)}>
|
|
37
|
+
<div className="openapi-summary" id={context.id}>
|
|
38
|
+
{context.renderHeading({
|
|
39
|
+
title,
|
|
40
|
+
})}
|
|
41
|
+
</div>
|
|
42
|
+
<div className="openapi-columns">
|
|
43
|
+
<div className="openapi-column-spec">
|
|
44
|
+
<StaticSection className="openapi-parameters" header="Attributes">
|
|
45
|
+
<OpenAPIRootSchema
|
|
46
|
+
schema={firstSchema.schema}
|
|
47
|
+
context={clientContext}
|
|
48
|
+
/>
|
|
49
|
+
</StaticSection>
|
|
50
|
+
</div>
|
|
51
|
+
<div className="openapi-column-preview">
|
|
52
|
+
<div className="openapi-column-preview-body">
|
|
53
|
+
<div className="openapi-panel">
|
|
54
|
+
<h4 className="openapi-panel-heading">{title}</h4>
|
|
55
|
+
<div className="openapi-panel-body">
|
|
56
|
+
<OpenAPIExample
|
|
57
|
+
example={getExampleFromSchema({
|
|
58
|
+
schema: firstSchema.schema,
|
|
59
|
+
})}
|
|
60
|
+
context={context}
|
|
61
|
+
syntax="json"
|
|
62
|
+
/>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
69
|
);
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
// If there are multiple schemas, we use a disclosure group to show them all.
|
|
73
73
|
return (
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
<
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
<
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
74
|
+
<div className={clsx('openapi-schemas', className)}>
|
|
75
|
+
<OpenAPIDisclosureGroup
|
|
76
|
+
allowsMultipleExpanded
|
|
77
|
+
icon={context.icons.chevronRight}
|
|
78
|
+
groups={schemas.map(({ name, schema }) => ({
|
|
79
|
+
id: name,
|
|
80
|
+
label: (
|
|
81
|
+
<div className="openapi-response-tab-content" key={`model-${name}`}>
|
|
82
|
+
<span className="openapi-response-statuscode">{name}</span>
|
|
83
|
+
</div>
|
|
84
|
+
),
|
|
85
|
+
tabs: [
|
|
86
|
+
{
|
|
87
|
+
id: 'model',
|
|
88
|
+
body: (
|
|
89
|
+
<Section className="openapi-section-schemas">
|
|
90
|
+
<SectionBody>
|
|
91
|
+
<OpenAPIRootSchema
|
|
92
|
+
schema={schema}
|
|
93
|
+
context={clientContext}
|
|
94
|
+
/>
|
|
95
|
+
</SectionBody>
|
|
96
|
+
</Section>
|
|
97
|
+
),
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
}))}
|
|
101
|
+
/>
|
|
102
|
+
</div>
|
|
98
103
|
);
|
|
99
104
|
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
import type { Filesystem, OpenAPIV3xDocument } from '@gitbook/openapi-parser';
|
|
1
|
+
import type { Filesystem, OpenAPISchema, OpenAPIV3xDocument } from '@gitbook/openapi-parser';
|
|
2
2
|
import { filterSelectedOpenAPISchemas } from '@gitbook/openapi-parser';
|
|
3
3
|
import { dereferenceFilesystem } from '../dereference';
|
|
4
|
-
import type { OpenAPISchemasData } from '../types';
|
|
5
|
-
|
|
6
|
-
//!!TODO: We should return only the schemas that are used in the block. Still a WIP awaiting future work.
|
|
7
4
|
|
|
8
5
|
/**
|
|
9
6
|
* Resolve an OpenAPI schemas from a file and compile it to a more usable format.
|
|
@@ -14,7 +11,9 @@ export async function resolveOpenAPISchemas(
|
|
|
14
11
|
options: {
|
|
15
12
|
schemas: string[];
|
|
16
13
|
}
|
|
17
|
-
): Promise<
|
|
14
|
+
): Promise<{
|
|
15
|
+
schemas: OpenAPISchema[];
|
|
16
|
+
} | null> {
|
|
18
17
|
const { schemas: selectedSchemas } = options;
|
|
19
18
|
|
|
20
19
|
const schema = await dereferenceFilesystem(filesystem);
|
package/src/types.ts
CHANGED
|
@@ -1,33 +1,13 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
OpenAPICustomOperationProperties,
|
|
3
3
|
OpenAPICustomSpecProperties,
|
|
4
|
-
OpenAPISchema,
|
|
5
4
|
OpenAPIV3,
|
|
6
5
|
} from '@gitbook/openapi-parser';
|
|
7
6
|
|
|
8
|
-
export interface
|
|
9
|
-
/**
|
|
10
|
-
* Render a code block.
|
|
11
|
-
*/
|
|
12
|
-
renderCodeBlock: (props: { code: string; syntax: string }) => React.ReactNode;
|
|
13
|
-
/**
|
|
14
|
-
* Render the heading of the operation.
|
|
15
|
-
*/
|
|
16
|
-
renderHeading: (props: {
|
|
17
|
-
deprecated: boolean;
|
|
18
|
-
title: string;
|
|
19
|
-
stability?: string;
|
|
20
|
-
}) => React.ReactNode;
|
|
7
|
+
export interface OpenAPIClientContext {
|
|
21
8
|
/**
|
|
22
|
-
*
|
|
9
|
+
* Icons used in the block.
|
|
23
10
|
*/
|
|
24
|
-
renderDocument: (props: { document: object }) => React.ReactNode;
|
|
25
|
-
|
|
26
|
-
/** Spec url for the Scalar Api Client */
|
|
27
|
-
specUrl: string;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface OpenAPIClientContext {
|
|
31
11
|
icons: {
|
|
32
12
|
chevronDown: React.ReactNode;
|
|
33
13
|
chevronRight: React.ReactNode;
|
|
@@ -39,14 +19,46 @@ export interface OpenAPIClientContext {
|
|
|
39
19
|
* @default false
|
|
40
20
|
*/
|
|
41
21
|
defaultInteractiveOpened?: boolean;
|
|
22
|
+
|
|
42
23
|
/**
|
|
43
24
|
* The key of the block
|
|
44
25
|
*/
|
|
45
26
|
blockKey?: string;
|
|
46
|
-
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Optional id attached to the heading and used as an anchor.
|
|
30
|
+
*/
|
|
47
31
|
id?: string;
|
|
48
32
|
}
|
|
49
33
|
|
|
34
|
+
export interface OpenAPIContext extends OpenAPIClientContext {
|
|
35
|
+
/**
|
|
36
|
+
* Render a code block.
|
|
37
|
+
*/
|
|
38
|
+
renderCodeBlock: (props: { code: string; syntax: string }) => React.ReactNode;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Render the heading of the operation.
|
|
42
|
+
*/
|
|
43
|
+
renderHeading: (props: {
|
|
44
|
+
deprecated?: boolean;
|
|
45
|
+
title: string;
|
|
46
|
+
stability?: string;
|
|
47
|
+
}) => React.ReactNode;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Render the document of the operation.
|
|
51
|
+
*/
|
|
52
|
+
renderDocument: (props: { document: object }) => React.ReactNode;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Specification URL.
|
|
56
|
+
*/
|
|
57
|
+
specUrl: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export type OpenAPISecurityWithRequired = OpenAPIV3.SecuritySchemeObject & { required?: boolean };
|
|
61
|
+
|
|
50
62
|
export interface OpenAPIOperationData extends OpenAPICustomSpecProperties {
|
|
51
63
|
path: string;
|
|
52
64
|
method: string;
|
|
@@ -58,10 +70,5 @@ export interface OpenAPIOperationData extends OpenAPICustomSpecProperties {
|
|
|
58
70
|
operation: OpenAPIV3.OperationObject<OpenAPICustomOperationProperties>;
|
|
59
71
|
|
|
60
72
|
/** Securities that should be used for this operation */
|
|
61
|
-
securities: [string,
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
export interface OpenAPISchemasData {
|
|
65
|
-
/** Components schemas to be used for schemas */
|
|
66
|
-
schemas: OpenAPISchema[];
|
|
73
|
+
securities: [string, OpenAPISecurityWithRequired][];
|
|
67
74
|
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
type Key = string | number;
|
|
2
|
-
type TabState = {
|
|
3
|
-
tabKey: Key | null;
|
|
4
|
-
};
|
|
5
|
-
type TabActions = {
|
|
6
|
-
setTabKey: (tab: Key | null) => void;
|
|
7
|
-
};
|
|
8
|
-
type TabStore = TabState & TabActions;
|
|
9
|
-
export declare const getOrCreateTabStoreByKey: (storeKey: string, initialKey?: Key) => import("zustand").StoreApi<TabStore>;
|
|
10
|
-
export {};
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { createStore } from 'zustand';
|
|
3
|
-
var createTabStore = function (initialTab) {
|
|
4
|
-
return createStore()(function (set) { return ({
|
|
5
|
-
tabKey: initialTab !== null && initialTab !== void 0 ? initialTab : null,
|
|
6
|
-
setTabKey: function (tabKey) {
|
|
7
|
-
set(function () { return ({ tabKey: tabKey }); });
|
|
8
|
-
},
|
|
9
|
-
}); });
|
|
10
|
-
};
|
|
11
|
-
var defaultTabStores = new Map();
|
|
12
|
-
var createTabStoreFactory = function (stores) {
|
|
13
|
-
return function (storeKey, initialKey) {
|
|
14
|
-
if (!stores.has(storeKey)) {
|
|
15
|
-
stores.set(storeKey, createTabStore(initialKey));
|
|
16
|
-
}
|
|
17
|
-
return stores.get(storeKey);
|
|
18
|
-
};
|
|
19
|
-
};
|
|
20
|
-
export var getOrCreateTabStoreByKey = createTabStoreFactory(defaultTabStores);
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
|
|
3
|
-
import { createStore } from 'zustand';
|
|
4
|
-
|
|
5
|
-
type Key = string | number;
|
|
6
|
-
|
|
7
|
-
type TabState = {
|
|
8
|
-
tabKey: Key | null;
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
type TabActions = { setTabKey: (tab: Key | null) => void };
|
|
12
|
-
|
|
13
|
-
type TabStore = TabState & TabActions;
|
|
14
|
-
|
|
15
|
-
const createTabStore = (initialTab?: Key) => {
|
|
16
|
-
return createStore<TabStore>()((set) => ({
|
|
17
|
-
tabKey: initialTab ?? null,
|
|
18
|
-
setTabKey: (tabKey) => {
|
|
19
|
-
set(() => ({ tabKey }));
|
|
20
|
-
},
|
|
21
|
-
}));
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
const defaultTabStores = new Map<string, ReturnType<typeof createTabStore>>();
|
|
25
|
-
|
|
26
|
-
const createTabStoreFactory = (stores: typeof defaultTabStores) => {
|
|
27
|
-
return (storeKey: string, initialKey?: Key) => {
|
|
28
|
-
if (!stores.has(storeKey)) {
|
|
29
|
-
stores.set(storeKey, createTabStore(initialKey));
|
|
30
|
-
}
|
|
31
|
-
return stores.get(storeKey)!;
|
|
32
|
-
};
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export const getOrCreateTabStoreByKey = createTabStoreFactory(defaultTabStores);
|