@gitbook/react-openapi 1.1.10 → 1.2.0
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 +14 -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 +40 -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 +83 -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
package/dist/types.d.ts
CHANGED
|
@@ -1,54 +1,4 @@
|
|
|
1
1
|
import type { OpenAPICustomOperationProperties, OpenAPICustomSpecProperties, OpenAPIV3 } from '@gitbook/openapi-parser';
|
|
2
|
-
export interface OpenAPIClientContext {
|
|
3
|
-
/**
|
|
4
|
-
* Icons used in the block.
|
|
5
|
-
*/
|
|
6
|
-
icons: {
|
|
7
|
-
chevronDown: React.ReactNode;
|
|
8
|
-
chevronRight: React.ReactNode;
|
|
9
|
-
plus: React.ReactNode;
|
|
10
|
-
};
|
|
11
|
-
/**
|
|
12
|
-
* Force all sections to be opened by default.
|
|
13
|
-
* @default false
|
|
14
|
-
*/
|
|
15
|
-
defaultInteractiveOpened?: boolean;
|
|
16
|
-
/**
|
|
17
|
-
* The key of the block
|
|
18
|
-
*/
|
|
19
|
-
blockKey?: string;
|
|
20
|
-
/**
|
|
21
|
-
* Optional id attached to the heading and used as an anchor.
|
|
22
|
-
*/
|
|
23
|
-
id?: string;
|
|
24
|
-
}
|
|
25
|
-
export interface OpenAPIContext extends OpenAPIClientContext {
|
|
26
|
-
/**
|
|
27
|
-
* Render a code block.
|
|
28
|
-
*/
|
|
29
|
-
renderCodeBlock: (props: {
|
|
30
|
-
code: string;
|
|
31
|
-
syntax: string;
|
|
32
|
-
}) => React.ReactNode;
|
|
33
|
-
/**
|
|
34
|
-
* Render the heading of the operation.
|
|
35
|
-
*/
|
|
36
|
-
renderHeading: (props: {
|
|
37
|
-
deprecated?: boolean;
|
|
38
|
-
title: string;
|
|
39
|
-
stability?: string;
|
|
40
|
-
}) => React.ReactNode;
|
|
41
|
-
/**
|
|
42
|
-
* Render the document of the operation.
|
|
43
|
-
*/
|
|
44
|
-
renderDocument: (props: {
|
|
45
|
-
document: object;
|
|
46
|
-
}) => React.ReactNode;
|
|
47
|
-
/**
|
|
48
|
-
* Specification URL.
|
|
49
|
-
*/
|
|
50
|
-
specUrl: string;
|
|
51
|
-
}
|
|
52
2
|
export type OpenAPISecurityWithRequired = OpenAPIV3.SecuritySchemeObject & {
|
|
53
3
|
required?: boolean;
|
|
54
4
|
};
|
|
@@ -62,3 +12,11 @@ export interface OpenAPIOperationData extends OpenAPICustomSpecProperties {
|
|
|
62
12
|
/** Securities that should be used for this operation */
|
|
63
13
|
securities: [string, OpenAPISecurityWithRequired][];
|
|
64
14
|
}
|
|
15
|
+
export interface OpenAPIWebhookData extends OpenAPICustomSpecProperties {
|
|
16
|
+
name: string;
|
|
17
|
+
method: string;
|
|
18
|
+
/** Servers to be used for this operation */
|
|
19
|
+
servers: OpenAPIV3.ServerObject[];
|
|
20
|
+
/** Spec of the webhook */
|
|
21
|
+
operation: OpenAPIV3.OperationObject<OpenAPICustomOperationProperties>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { OpenAPIV3 } from '@gitbook/openapi-parser';
|
|
2
|
+
import type { OpenAPIContext } from '../context';
|
|
3
|
+
/**
|
|
4
|
+
* Generate an example from a reference object.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getExampleFromReference(ref: OpenAPIV3.ReferenceObject, context: OpenAPIContext): OpenAPIV3.ExampleObject;
|
|
7
|
+
/**
|
|
8
|
+
* Get examples from a media type object.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getExamplesFromMediaTypeObject(args: {
|
|
11
|
+
mediaType: string;
|
|
12
|
+
mediaTypeObject: OpenAPIV3.MediaTypeObject;
|
|
13
|
+
context: OpenAPIContext;
|
|
14
|
+
}): {
|
|
15
|
+
key: string;
|
|
16
|
+
example: OpenAPIV3.ExampleObject;
|
|
17
|
+
}[];
|
|
18
|
+
/**
|
|
19
|
+
* Get example from a schema object.
|
|
20
|
+
*/
|
|
21
|
+
export declare function getExampleFromSchema(args: {
|
|
22
|
+
schema: OpenAPIV3.SchemaObject;
|
|
23
|
+
}): OpenAPIV3.ExampleObject;
|
|
24
|
+
/**
|
|
25
|
+
* Get the examples from a media type object.
|
|
26
|
+
*/
|
|
27
|
+
export declare function getExamples(props: {
|
|
28
|
+
mediaTypeObject: OpenAPIV3.MediaTypeObject;
|
|
29
|
+
mediaType: string;
|
|
30
|
+
context: OpenAPIContext;
|
|
31
|
+
}): {
|
|
32
|
+
key: string;
|
|
33
|
+
label: string;
|
|
34
|
+
body: import("react").JSX.Element;
|
|
35
|
+
}[];
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { OpenAPIExample } from '../OpenAPIExample';
|
|
2
|
+
import { generateSchemaExample } from '../generateSchemaExample';
|
|
3
|
+
import { tString } from '../translate';
|
|
4
|
+
import { checkIsReference } from '../utils';
|
|
5
|
+
/**
|
|
6
|
+
* Generate an example from a reference object.
|
|
7
|
+
*/
|
|
8
|
+
export function getExampleFromReference(ref, context) {
|
|
9
|
+
return {
|
|
10
|
+
summary: tString(context.translation, 'unresolved_reference'),
|
|
11
|
+
value: { $ref: ref.$ref },
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Get examples from a media type object.
|
|
16
|
+
*/
|
|
17
|
+
export function getExamplesFromMediaTypeObject(args) {
|
|
18
|
+
var _a;
|
|
19
|
+
var _b, _c;
|
|
20
|
+
var mediaTypeObject = args.mediaTypeObject, mediaType = args.mediaType, context = args.context;
|
|
21
|
+
if (mediaTypeObject.examples) {
|
|
22
|
+
return Object.entries(mediaTypeObject.examples).map(function (_a) {
|
|
23
|
+
var key = _a[0], example = _a[1];
|
|
24
|
+
return {
|
|
25
|
+
key: key,
|
|
26
|
+
example: checkIsReference(example)
|
|
27
|
+
? getExampleFromReference(example, context)
|
|
28
|
+
: example,
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
if (mediaTypeObject.example) {
|
|
33
|
+
return [{ key: 'default', example: { value: mediaTypeObject.example } }];
|
|
34
|
+
}
|
|
35
|
+
if (mediaTypeObject.schema) {
|
|
36
|
+
if (mediaType === 'application/xml') {
|
|
37
|
+
// @TODO normally we should use the name of the schema but we don't have it
|
|
38
|
+
// fix it when we got the reference name
|
|
39
|
+
var root = (_c = (_b = mediaTypeObject.schema.xml) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : 'object';
|
|
40
|
+
return [
|
|
41
|
+
{
|
|
42
|
+
key: 'default',
|
|
43
|
+
example: {
|
|
44
|
+
value: (_a = {},
|
|
45
|
+
_a[root] = generateSchemaExample(mediaTypeObject.schema, {
|
|
46
|
+
xml: mediaType === 'application/xml',
|
|
47
|
+
mode: 'read',
|
|
48
|
+
}),
|
|
49
|
+
_a),
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
return [
|
|
55
|
+
{
|
|
56
|
+
key: 'default',
|
|
57
|
+
example: {
|
|
58
|
+
value: generateSchemaExample(mediaTypeObject.schema, {
|
|
59
|
+
mode: 'read',
|
|
60
|
+
}),
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Get example from a schema object.
|
|
69
|
+
*/
|
|
70
|
+
export function getExampleFromSchema(args) {
|
|
71
|
+
var schema = args.schema;
|
|
72
|
+
if (schema.example) {
|
|
73
|
+
return { value: schema.example };
|
|
74
|
+
}
|
|
75
|
+
return { value: generateSchemaExample(schema, { mode: 'read' }) };
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Get the examples from a media type object.
|
|
79
|
+
*/
|
|
80
|
+
export function getExamples(props) {
|
|
81
|
+
var mediaTypeObject = props.mediaTypeObject, mediaType = props.mediaType, context = props.context;
|
|
82
|
+
var examples = getExamplesFromMediaTypeObject({ mediaTypeObject: mediaTypeObject, mediaType: mediaType, context: context });
|
|
83
|
+
var syntax = getSyntaxFromMediaType(mediaType);
|
|
84
|
+
return examples.map(function (example) {
|
|
85
|
+
return {
|
|
86
|
+
key: example.key,
|
|
87
|
+
label: example.example.summary || example.key,
|
|
88
|
+
body: (<OpenAPIExample example={example.example} context={props.context} syntax={syntax}/>),
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Get the syntax from a media type.
|
|
94
|
+
*/
|
|
95
|
+
function getSyntaxFromMediaType(mediaType) {
|
|
96
|
+
if (mediaType.includes('json')) {
|
|
97
|
+
return 'json';
|
|
98
|
+
}
|
|
99
|
+
if (mediaType === 'application/xml') {
|
|
100
|
+
return 'xml';
|
|
101
|
+
}
|
|
102
|
+
return 'text';
|
|
103
|
+
}
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AnyObject, OpenAPIV3, OpenAPIV3_1 } from '@gitbook/openapi-parser';
|
|
2
|
+
import type { OpenAPIUniversalContext } from './context';
|
|
2
3
|
export declare function checkIsReference(input: unknown): input is OpenAPIV3.ReferenceObject;
|
|
3
4
|
export declare function createStateKey(key: string, scope?: string): string;
|
|
4
5
|
/**
|
|
@@ -29,3 +30,20 @@ export declare function parameterToProperty(parameter: OpenAPIV3.ParameterObject
|
|
|
29
30
|
schema: OpenAPIV3.SchemaObject;
|
|
30
31
|
required: boolean | undefined;
|
|
31
32
|
};
|
|
33
|
+
/**
|
|
34
|
+
* Get the class name for a status code.
|
|
35
|
+
* 1xx: informational
|
|
36
|
+
* 2xx: success
|
|
37
|
+
* 3xx: redirect
|
|
38
|
+
* 4xx, 5xx: error
|
|
39
|
+
*/
|
|
40
|
+
export declare function getStatusCodeClassName(statusCode: number | string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Get a default label for a status code.
|
|
43
|
+
* This is used when there is no label provided in the OpenAPI spec.
|
|
44
|
+
* 1xx: Information
|
|
45
|
+
* 2xx: Success
|
|
46
|
+
* 3xx: Redirect
|
|
47
|
+
* 4xx, 5xx: Error
|
|
48
|
+
*/
|
|
49
|
+
export declare function getStatusCodeDefaultLabel(statusCode: number | string, context: OpenAPIUniversalContext): string;
|
package/dist/utils.js
CHANGED
|
@@ -10,6 +10,7 @@ var __assign = (this && this.__assign) || function () {
|
|
|
10
10
|
return __assign.apply(this, arguments);
|
|
11
11
|
};
|
|
12
12
|
import { stringifyOpenAPI } from './stringifyOpenAPI';
|
|
13
|
+
import { tString } from './translate';
|
|
13
14
|
export function checkIsReference(input) {
|
|
14
15
|
return typeof input === 'object' && !!input && '$ref' in input;
|
|
15
16
|
}
|
|
@@ -127,3 +128,59 @@ function shouldDisplayExample(schema) {
|
|
|
127
128
|
schema.example !== null &&
|
|
128
129
|
Object.keys(schema.example).length > 0));
|
|
129
130
|
}
|
|
131
|
+
/**
|
|
132
|
+
* Get the class name for a status code.
|
|
133
|
+
* 1xx: informational
|
|
134
|
+
* 2xx: success
|
|
135
|
+
* 3xx: redirect
|
|
136
|
+
* 4xx, 5xx: error
|
|
137
|
+
*/
|
|
138
|
+
export function getStatusCodeClassName(statusCode) {
|
|
139
|
+
var category = getStatusCodeCategory(statusCode);
|
|
140
|
+
switch (category) {
|
|
141
|
+
case 1:
|
|
142
|
+
return 'informational';
|
|
143
|
+
case 2:
|
|
144
|
+
return 'success';
|
|
145
|
+
case 3:
|
|
146
|
+
return 'redirect';
|
|
147
|
+
case 4:
|
|
148
|
+
case 5:
|
|
149
|
+
return 'error';
|
|
150
|
+
default:
|
|
151
|
+
return 'unknown';
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Get a default label for a status code.
|
|
156
|
+
* This is used when there is no label provided in the OpenAPI spec.
|
|
157
|
+
* 1xx: Information
|
|
158
|
+
* 2xx: Success
|
|
159
|
+
* 3xx: Redirect
|
|
160
|
+
* 4xx, 5xx: Error
|
|
161
|
+
*/
|
|
162
|
+
export function getStatusCodeDefaultLabel(statusCode, context) {
|
|
163
|
+
var category = getStatusCodeCategory(statusCode);
|
|
164
|
+
switch (category) {
|
|
165
|
+
case 1:
|
|
166
|
+
return tString(context.translation, 'information');
|
|
167
|
+
case 2:
|
|
168
|
+
return tString(context.translation, 'success');
|
|
169
|
+
case 3:
|
|
170
|
+
return tString(context.translation, 'redirect');
|
|
171
|
+
case 4:
|
|
172
|
+
case 5:
|
|
173
|
+
return tString(context.translation, 'error');
|
|
174
|
+
default:
|
|
175
|
+
return '';
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
function getStatusCodeCategory(statusCode) {
|
|
179
|
+
var code = typeof statusCode === 'string' ? Number.parseInt(statusCode, 10) : statusCode;
|
|
180
|
+
if (Number.isNaN(code) || code < 100 || code >= 600) {
|
|
181
|
+
return 'unknown';
|
|
182
|
+
}
|
|
183
|
+
// Determine the category of the status code based on the first digit
|
|
184
|
+
var category = Math.floor(code / 100);
|
|
185
|
+
return category;
|
|
186
|
+
}
|
package/package.json
CHANGED
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"default": "./dist/index.js"
|
|
9
9
|
}
|
|
10
10
|
},
|
|
11
|
-
"version": "1.
|
|
11
|
+
"version": "1.2.0",
|
|
12
12
|
"sideEffects": false,
|
|
13
13
|
"dependencies": {
|
|
14
14
|
"@gitbook/openapi-parser": "workspace:*",
|
|
15
|
-
"@scalar/api-client-react": "^1.2.
|
|
16
|
-
"@scalar/oas-utils": "^0.2.
|
|
15
|
+
"@scalar/api-client-react": "^1.2.19",
|
|
16
|
+
"@scalar/oas-utils": "^0.2.130",
|
|
17
17
|
"clsx": "^2.1.1",
|
|
18
18
|
"flatted": "^3.2.9",
|
|
19
19
|
"json-xml-parse": "^1.3.0",
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import clsx from 'clsx';
|
|
4
|
-
import { useRef
|
|
4
|
+
import { useRef } from 'react';
|
|
5
5
|
import { mergeProps, useButton, useDisclosure, useFocusRing } from 'react-aria';
|
|
6
6
|
import { useDisclosureState } from 'react-stately';
|
|
7
|
-
import { OpenAPISelect, OpenAPISelectItem } from './OpenAPISelect';
|
|
7
|
+
import { OpenAPISelect, OpenAPISelectItem, useSelectState } from './OpenAPISelect';
|
|
8
8
|
import { Section, SectionBody, SectionHeader, SectionHeaderContent } from './StaticSection';
|
|
9
9
|
|
|
10
10
|
interface InteractiveSectionTab {
|
|
@@ -35,6 +35,10 @@ export function InteractiveSection(props: {
|
|
|
35
35
|
header?: React.ReactNode;
|
|
36
36
|
/** Children to display within the container */
|
|
37
37
|
overlay?: React.ReactNode;
|
|
38
|
+
/** State key to use with a store */
|
|
39
|
+
stateKey?: string;
|
|
40
|
+
/** Icon for the tabs select */
|
|
41
|
+
selectIcon?: React.ReactNode;
|
|
38
42
|
}) {
|
|
39
43
|
const {
|
|
40
44
|
id,
|
|
@@ -46,12 +50,9 @@ export function InteractiveSection(props: {
|
|
|
46
50
|
header,
|
|
47
51
|
overlay,
|
|
48
52
|
toggleIcon = '▶',
|
|
53
|
+
selectIcon,
|
|
54
|
+
stateKey = 'interactive-section',
|
|
49
55
|
} = props;
|
|
50
|
-
|
|
51
|
-
const [selectedTabKey, setSelectedTab] = useState(defaultTab);
|
|
52
|
-
const selectedTab: InteractiveSectionTab | undefined =
|
|
53
|
-
tabs.find((tab) => tab.key === selectedTabKey) ?? tabs[0];
|
|
54
|
-
|
|
55
56
|
const state = useDisclosureState({
|
|
56
57
|
defaultExpanded: defaultOpened,
|
|
57
58
|
});
|
|
@@ -60,6 +61,10 @@ export function InteractiveSection(props: {
|
|
|
60
61
|
const { buttonProps: triggerProps, panelProps } = useDisclosure({}, state, panelRef);
|
|
61
62
|
const { buttonProps } = useButton(triggerProps, triggerRef);
|
|
62
63
|
const { isFocusVisible, focusProps } = useFocusRing();
|
|
64
|
+
const store = useSelectState(stateKey, defaultTab);
|
|
65
|
+
|
|
66
|
+
const selectedTab: InteractiveSectionTab | undefined =
|
|
67
|
+
tabs.find((tab) => tab.key === store.key) ?? tabs[0];
|
|
63
68
|
|
|
64
69
|
return (
|
|
65
70
|
<Section
|
|
@@ -97,6 +102,7 @@ export function InteractiveSection(props: {
|
|
|
97
102
|
) : null}
|
|
98
103
|
{header}
|
|
99
104
|
</SectionHeaderContent>
|
|
105
|
+
{/* biome-ignore lint/a11y/useKeyWithClickEvents: we prevent default here */}
|
|
100
106
|
<div
|
|
101
107
|
className={clsx(
|
|
102
108
|
'openapi-section-header-controls',
|
|
@@ -108,16 +114,12 @@ export function InteractiveSection(props: {
|
|
|
108
114
|
>
|
|
109
115
|
{tabs.length > 1 ? (
|
|
110
116
|
<OpenAPISelect
|
|
111
|
-
|
|
112
|
-
'openapi-section-select',
|
|
113
|
-
`${className}-tabs-select`
|
|
114
|
-
)}
|
|
117
|
+
stateKey={stateKey}
|
|
115
118
|
items={tabs}
|
|
116
|
-
|
|
117
|
-
onSelectionChange={(key) => {
|
|
118
|
-
setSelectedTab(String(key));
|
|
119
|
+
onSelectionChange={() => {
|
|
119
120
|
state.expand();
|
|
120
121
|
}}
|
|
122
|
+
icon={selectIcon}
|
|
121
123
|
placement="bottom end"
|
|
122
124
|
>
|
|
123
125
|
{tabs.map((tab) => (
|
|
@@ -6,9 +6,10 @@ import {
|
|
|
6
6
|
import { OpenAPICodeSampleBody } from './OpenAPICodeSampleSelector';
|
|
7
7
|
import { ScalarApiButton } from './ScalarApiButton';
|
|
8
8
|
import { type CodeSampleGenerator, codeSampleGenerators } from './code-samples';
|
|
9
|
+
import { type OpenAPIContext, getOpenAPIClientContext } from './context';
|
|
9
10
|
import { generateMediaTypeExamples, generateSchemaExample } from './generateSchemaExample';
|
|
10
11
|
import { stringifyOpenAPI } from './stringifyOpenAPI';
|
|
11
|
-
import type {
|
|
12
|
+
import type { OpenAPIOperationData } from './types';
|
|
12
13
|
import { getDefaultServerURL } from './util/server';
|
|
13
14
|
import { checkIsReference } from './utils';
|
|
14
15
|
|
|
@@ -22,7 +23,7 @@ export function OpenAPICodeSample(props: {
|
|
|
22
23
|
data: OpenAPIOperationData;
|
|
23
24
|
context: OpenAPIContext;
|
|
24
25
|
}) {
|
|
25
|
-
const { data } = props;
|
|
26
|
+
const { data, context } = props;
|
|
26
27
|
|
|
27
28
|
// If code samples are disabled at operation level, we don't display the code samples.
|
|
28
29
|
if (data.operation['x-codeSamples'] === false) {
|
|
@@ -43,7 +44,14 @@ export function OpenAPICodeSample(props: {
|
|
|
43
44
|
return null;
|
|
44
45
|
}
|
|
45
46
|
|
|
46
|
-
return
|
|
47
|
+
return (
|
|
48
|
+
<OpenAPICodeSampleBody
|
|
49
|
+
context={getOpenAPIClientContext(context)}
|
|
50
|
+
data={data}
|
|
51
|
+
items={samples}
|
|
52
|
+
selectIcon={context.icons.chevronDown}
|
|
53
|
+
/>
|
|
54
|
+
);
|
|
47
55
|
}
|
|
48
56
|
|
|
49
57
|
/**
|
|
@@ -146,6 +154,7 @@ function generateCodeSamples(props: {
|
|
|
146
154
|
method={data.method}
|
|
147
155
|
path={data.path}
|
|
148
156
|
renderers={renderers}
|
|
157
|
+
blockKey={context.blockKey}
|
|
149
158
|
/>
|
|
150
159
|
),
|
|
151
160
|
footer: (
|
|
@@ -206,11 +215,20 @@ function OpenAPICodeSampleFooter(props: {
|
|
|
206
215
|
method={data.method}
|
|
207
216
|
path={data.path}
|
|
208
217
|
renderers={renderers}
|
|
218
|
+
selectIcon={context.icons.chevronDown}
|
|
219
|
+
blockKey={context.blockKey}
|
|
209
220
|
/>
|
|
210
221
|
) : (
|
|
211
222
|
<span />
|
|
212
223
|
)}
|
|
213
|
-
{!hideTryItPanel &&
|
|
224
|
+
{!hideTryItPanel && (
|
|
225
|
+
<ScalarApiButton
|
|
226
|
+
context={getOpenAPIClientContext(context)}
|
|
227
|
+
method={method}
|
|
228
|
+
path={path}
|
|
229
|
+
specUrl={specUrl}
|
|
230
|
+
/>
|
|
231
|
+
)}
|
|
214
232
|
</div>
|
|
215
233
|
);
|
|
216
234
|
}
|
|
@@ -1,70 +1,43 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import clsx from 'clsx';
|
|
3
|
-
import { useCallback } from 'react';
|
|
4
|
-
import { useStore } from 'zustand';
|
|
5
3
|
import type { MediaTypeRenderer } from './OpenAPICodeSample';
|
|
6
|
-
import { OpenAPISelect, OpenAPISelectItem } from './OpenAPISelect';
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
type MediaTypeState = {
|
|
10
|
-
mediaType: string;
|
|
11
|
-
setMediaType: (mediaType: string) => void;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
function useMediaTypeState(
|
|
15
|
-
data: { method: string; path: string },
|
|
16
|
-
defaultKey: string
|
|
17
|
-
): MediaTypeState {
|
|
18
|
-
const { method, path } = data;
|
|
19
|
-
const store = useStore(getOrCreateStoreByKey(`media-type-${method}-${path}`, defaultKey));
|
|
20
|
-
if (typeof store.key !== 'string') {
|
|
21
|
-
throw new Error('Media type key is not a string');
|
|
22
|
-
}
|
|
23
|
-
return {
|
|
24
|
-
mediaType: store.key,
|
|
25
|
-
setMediaType: useCallback((index: string) => store.setKey(index), [store.setKey]),
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
function useMediaTypeSampleIndexState(data: { method: string; path: string }, mediaType: string) {
|
|
30
|
-
const { method, path } = data;
|
|
31
|
-
const store = useStore(
|
|
32
|
-
getOrCreateStoreByKey(`media-type-sample-${mediaType}-${method}-${path}`, 0)
|
|
33
|
-
);
|
|
34
|
-
if (typeof store.key !== 'number') {
|
|
35
|
-
throw new Error('Example key is not a number');
|
|
36
|
-
}
|
|
37
|
-
return {
|
|
38
|
-
index: store.key,
|
|
39
|
-
setIndex: useCallback((index: number) => store.setKey(index), [store.setKey]),
|
|
40
|
-
};
|
|
41
|
-
}
|
|
4
|
+
import { OpenAPISelect, OpenAPISelectItem, useSelectState } from './OpenAPISelect';
|
|
5
|
+
import { createStateKey } from './utils';
|
|
42
6
|
|
|
43
7
|
export function OpenAPIMediaTypeExamplesSelector(props: {
|
|
44
8
|
method: string;
|
|
45
9
|
path: string;
|
|
46
10
|
renderers: MediaTypeRenderer[];
|
|
11
|
+
selectIcon?: React.ReactNode;
|
|
12
|
+
blockKey?: string;
|
|
47
13
|
}) {
|
|
48
|
-
const { method, path, renderers } = props;
|
|
14
|
+
const { method, path, renderers, selectIcon, blockKey } = props;
|
|
49
15
|
if (!renderers[0]) {
|
|
50
16
|
throw new Error('No renderers provided');
|
|
51
17
|
}
|
|
52
|
-
const
|
|
53
|
-
const
|
|
18
|
+
const stateKey = createStateKey('request-body-media-type', blockKey);
|
|
19
|
+
const state = useSelectState(stateKey, renderers[0].mediaType);
|
|
20
|
+
const selected = renderers.find((r) => r.mediaType === state.key) || renderers[0];
|
|
54
21
|
|
|
55
22
|
return (
|
|
56
23
|
<div className="openapi-codesample-selectors">
|
|
57
|
-
<MediaTypeSelector
|
|
58
|
-
<ExamplesSelector
|
|
24
|
+
<MediaTypeSelector selectIcon={selectIcon} stateKey={stateKey} renderers={renderers} />
|
|
25
|
+
<ExamplesSelector
|
|
26
|
+
selectIcon={selectIcon}
|
|
27
|
+
method={method}
|
|
28
|
+
path={path}
|
|
29
|
+
renderer={selected}
|
|
30
|
+
/>
|
|
59
31
|
</div>
|
|
60
32
|
);
|
|
61
33
|
}
|
|
62
34
|
|
|
63
35
|
function MediaTypeSelector(props: {
|
|
64
|
-
|
|
36
|
+
stateKey: string;
|
|
65
37
|
renderers: MediaTypeRenderer[];
|
|
38
|
+
selectIcon?: React.ReactNode;
|
|
66
39
|
}) {
|
|
67
|
-
const { renderers,
|
|
40
|
+
const { renderers, stateKey, selectIcon } = props;
|
|
68
41
|
|
|
69
42
|
if (renderers.length < 2) {
|
|
70
43
|
return null;
|
|
@@ -78,12 +51,12 @@ function MediaTypeSelector(props: {
|
|
|
78
51
|
return (
|
|
79
52
|
<OpenAPISelect
|
|
80
53
|
className={clsx('openapi-select')}
|
|
81
|
-
selectedKey={state.mediaType}
|
|
82
54
|
items={renderers.map((renderer) => ({
|
|
83
55
|
key: renderer.mediaType,
|
|
84
56
|
label: renderer.mediaType,
|
|
85
57
|
}))}
|
|
86
|
-
|
|
58
|
+
icon={selectIcon}
|
|
59
|
+
stateKey={stateKey}
|
|
87
60
|
placement="bottom start"
|
|
88
61
|
>
|
|
89
62
|
{items.map((item) => (
|
|
@@ -99,9 +72,9 @@ function ExamplesSelector(props: {
|
|
|
99
72
|
method: string;
|
|
100
73
|
path: string;
|
|
101
74
|
renderer: MediaTypeRenderer;
|
|
75
|
+
selectIcon?: React.ReactNode;
|
|
102
76
|
}) {
|
|
103
|
-
const { method, path, renderer } = props;
|
|
104
|
-
const state = useMediaTypeSampleIndexState({ method, path }, renderer.mediaType);
|
|
77
|
+
const { method, path, renderer, selectIcon } = props;
|
|
105
78
|
if (renderer.examples.length < 2) {
|
|
106
79
|
return null;
|
|
107
80
|
}
|
|
@@ -114,8 +87,8 @@ function ExamplesSelector(props: {
|
|
|
114
87
|
return (
|
|
115
88
|
<OpenAPISelect
|
|
116
89
|
items={items}
|
|
117
|
-
|
|
118
|
-
|
|
90
|
+
icon={selectIcon}
|
|
91
|
+
stateKey={`media-type-sample-${renderer.mediaType}-${method}-${path}`}
|
|
119
92
|
placement="bottom start"
|
|
120
93
|
>
|
|
121
94
|
{items.map((item) => (
|
|
@@ -131,14 +104,18 @@ export function OpenAPIMediaTypeExamplesBody(props: {
|
|
|
131
104
|
method: string;
|
|
132
105
|
path: string;
|
|
133
106
|
renderers: MediaTypeRenderer[];
|
|
107
|
+
blockKey?: string;
|
|
134
108
|
}) {
|
|
135
|
-
const { renderers, method, path } = props;
|
|
109
|
+
const { renderers, method, path, blockKey } = props;
|
|
136
110
|
if (!renderers[0]) {
|
|
137
111
|
throw new Error('No renderers provided');
|
|
138
112
|
}
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
|
|
113
|
+
|
|
114
|
+
const mediaTypeState = useSelectState(
|
|
115
|
+
createStateKey('request-body-media-type', blockKey),
|
|
116
|
+
renderers[0].mediaType
|
|
117
|
+
);
|
|
118
|
+
const selected = renderers.find((r) => r.mediaType === mediaTypeState.key) ?? renderers[0];
|
|
142
119
|
if (selected.examples.length === 0) {
|
|
143
120
|
return selected.element;
|
|
144
121
|
}
|
|
@@ -147,10 +124,13 @@ export function OpenAPIMediaTypeExamplesBody(props: {
|
|
|
147
124
|
|
|
148
125
|
function ExamplesBody(props: { method: string; path: string; renderer: MediaTypeRenderer }) {
|
|
149
126
|
const { method, path, renderer } = props;
|
|
150
|
-
const exampleState =
|
|
151
|
-
|
|
127
|
+
const exampleState = useSelectState(
|
|
128
|
+
`media-type-sample-${renderer.mediaType}-${method}-${path}`,
|
|
129
|
+
renderer.mediaType
|
|
130
|
+
);
|
|
131
|
+
const example = renderer.examples[Number(exampleState.key)] ?? renderer.examples[0];
|
|
152
132
|
if (!example) {
|
|
153
|
-
throw new Error(`No example found for
|
|
133
|
+
throw new Error(`No example found for key ${exampleState.key}`);
|
|
154
134
|
}
|
|
155
135
|
return example.element;
|
|
156
136
|
}
|