@gitbook/react-openapi 0.5.0 → 0.7.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 +31 -0
- package/dist/InteractiveSection.d.ts +9 -5
- package/dist/InteractiveSection.js +22 -7
- package/dist/OpenAPICodeSample.js +43 -11
- package/dist/OpenAPIOperation.js +4 -3
- package/dist/OpenAPIResponseExample.js +22 -16
- package/dist/OpenAPIResponses.js +2 -2
- package/dist/OpenAPISchema.js +4 -1
- package/dist/ScalarApiButton.d.ts +1 -10
- package/dist/ScalarApiButton.js +4 -79
- package/dist/code-samples.js +19 -0
- package/dist/fetchOpenAPIOperation.d.ts +1 -1
- package/dist/generateSchemaExample.js +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types.d.ts +8 -0
- package/dist/utils.d.ts +1 -0
- package/dist/utils.js +3 -0
- package/package.json +9 -7
- package/src/InteractiveSection.tsx +34 -12
- package/src/OpenAPICodeSample.tsx +57 -16
- package/src/OpenAPIOperation.tsx +10 -4
- package/src/OpenAPIResponseExample.tsx +39 -24
- package/src/OpenAPIResponses.tsx +2 -1
- package/src/OpenAPISchema.tsx +5 -0
- package/src/ScalarApiButton.tsx +5 -138
- package/src/code-samples.ts +19 -0
- package/src/fetchOpenAPIOperation.ts +1 -1
- package/src/generateSchemaExample.ts +1 -1
- package/src/types.ts +9 -0
- package/src/utils.ts +4 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
3
|
import { CodeSampleInput, codeSampleGenerators } from './code-samples';
|
|
4
|
-
import { OpenAPIOperationData
|
|
5
|
-
import { generateMediaTypeExample } from './generateSchemaExample';
|
|
4
|
+
import { OpenAPIOperationData } from './fetchOpenAPIOperation';
|
|
5
|
+
import { generateMediaTypeExample, generateSchemaExample } from './generateSchemaExample';
|
|
6
6
|
import { InteractiveSection } from './InteractiveSection';
|
|
7
7
|
import { getServersURL } from './OpenAPIServerURL';
|
|
8
8
|
import { ScalarApiButton } from './ScalarApiButton';
|
|
@@ -19,17 +19,51 @@ export function OpenAPICodeSample(props: {
|
|
|
19
19
|
}) {
|
|
20
20
|
const { data, context } = props;
|
|
21
21
|
|
|
22
|
+
const searchParams = new URLSearchParams();
|
|
23
|
+
const headersObject: { [k: string]: string } = {};
|
|
24
|
+
|
|
25
|
+
data.operation.parameters?.forEach((rawParam) => {
|
|
26
|
+
const param = noReference(rawParam);
|
|
27
|
+
if (!param) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (param.in === 'header' && param.required) {
|
|
32
|
+
const example = param.schema
|
|
33
|
+
? generateSchemaExample(noReference(param.schema))
|
|
34
|
+
: undefined;
|
|
35
|
+
if (example !== undefined) {
|
|
36
|
+
headersObject[param.name] =
|
|
37
|
+
typeof example !== 'string' ? JSON.stringify(example) : example;
|
|
38
|
+
}
|
|
39
|
+
} else if (param.in === 'query' && param.required) {
|
|
40
|
+
const example = param.schema
|
|
41
|
+
? generateSchemaExample(noReference(param.schema))
|
|
42
|
+
: undefined;
|
|
43
|
+
if (example !== undefined) {
|
|
44
|
+
searchParams.append(
|
|
45
|
+
param.name,
|
|
46
|
+
String(Array.isArray(example) ? example[0] : example),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
|
|
22
52
|
const requestBody = noReference(data.operation.requestBody);
|
|
23
53
|
const requestBodyContent = requestBody ? Object.entries(requestBody.content)[0] : undefined;
|
|
24
54
|
|
|
25
55
|
const input: CodeSampleInput = {
|
|
26
|
-
url:
|
|
56
|
+
url:
|
|
57
|
+
getServersURL(data.servers) +
|
|
58
|
+
data.path +
|
|
59
|
+
(searchParams.size ? `?${searchParams.toString()}` : ''),
|
|
27
60
|
method: data.method,
|
|
28
61
|
body: requestBodyContent
|
|
29
62
|
? generateMediaTypeExample(requestBodyContent[1], { onlyRequired: true })
|
|
30
63
|
: undefined,
|
|
31
64
|
headers: {
|
|
32
65
|
...getSecurityHeaders(data.securities),
|
|
66
|
+
...headersObject,
|
|
33
67
|
...(requestBodyContent
|
|
34
68
|
? {
|
|
35
69
|
'Content-Type': requestBodyContent[0],
|
|
@@ -52,25 +86,32 @@ export function OpenAPICodeSample(props: {
|
|
|
52
86
|
}> = null;
|
|
53
87
|
(['x-custom-examples', 'x-code-samples', 'x-codeSamples'] as const).forEach((key) => {
|
|
54
88
|
const customSamples = data.operation[key];
|
|
55
|
-
if (customSamples) {
|
|
56
|
-
customCodeSamples = customSamples
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
89
|
+
if (customSamples && Array.isArray(customSamples)) {
|
|
90
|
+
customCodeSamples = customSamples
|
|
91
|
+
.filter((sample) => {
|
|
92
|
+
return (
|
|
93
|
+
typeof sample.label === 'string' &&
|
|
94
|
+
typeof sample.source === 'string' &&
|
|
95
|
+
typeof sample.lang === 'string'
|
|
96
|
+
);
|
|
97
|
+
})
|
|
98
|
+
.map((sample) => ({
|
|
99
|
+
key: `redocly-${sample.lang}`,
|
|
100
|
+
label: sample.label,
|
|
101
|
+
body: <context.CodeBlock code={sample.source} syntax={sample.lang} />,
|
|
102
|
+
}));
|
|
61
103
|
}
|
|
62
104
|
});
|
|
63
105
|
|
|
64
|
-
|
|
106
|
+
// Code samples can be disabled at the top-level or at the operation level
|
|
107
|
+
// If code samples are defined at the operation level, it will override the top-level setting
|
|
108
|
+
const codeSamplesDisabled =
|
|
109
|
+
data['x-codeSamples'] === false || data.operation['x-codeSamples'] === false;
|
|
110
|
+
const samples = customCodeSamples ?? (!codeSamplesDisabled ? autoCodeSamples : []);
|
|
65
111
|
if (samples.length === 0) {
|
|
66
112
|
return null;
|
|
67
113
|
}
|
|
68
114
|
|
|
69
|
-
async function fetchOperationData() {
|
|
70
|
-
'use server';
|
|
71
|
-
return toJSON(data);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
115
|
return (
|
|
75
116
|
<InteractiveSection
|
|
76
117
|
header="Request"
|
|
@@ -78,7 +119,7 @@ export function OpenAPICodeSample(props: {
|
|
|
78
119
|
tabs={samples}
|
|
79
120
|
overlay={
|
|
80
121
|
data['x-hideTryItPanel'] || data.operation['x-hideTryItPanel'] ? null : (
|
|
81
|
-
<ScalarApiButton
|
|
122
|
+
<ScalarApiButton />
|
|
82
123
|
)
|
|
83
124
|
}
|
|
84
125
|
/>
|
package/src/OpenAPIOperation.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
|
+
import { ApiClientModalProvider } from '@scalar/api-client-react';
|
|
3
4
|
|
|
4
5
|
import { OpenAPIOperationData, toJSON } from './fetchOpenAPIOperation';
|
|
5
6
|
import { Markdown } from './Markdown';
|
|
@@ -7,7 +8,6 @@ import { OpenAPICodeSample } from './OpenAPICodeSample';
|
|
|
7
8
|
import { OpenAPIResponseExample } from './OpenAPIResponseExample';
|
|
8
9
|
import { OpenAPIServerURL } from './OpenAPIServerURL';
|
|
9
10
|
import { OpenAPISpec } from './OpenAPISpec';
|
|
10
|
-
import { ScalarApiClient } from './ScalarApiButton';
|
|
11
11
|
import { OpenAPIClientContext, OpenAPIContextProps } from './types';
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -24,13 +24,19 @@ export function OpenAPIOperation(props: {
|
|
|
24
24
|
const clientContext: OpenAPIClientContext = {
|
|
25
25
|
defaultInteractiveOpened: context.defaultInteractiveOpened,
|
|
26
26
|
icons: context.icons,
|
|
27
|
+
blockKey: context.blockKey,
|
|
27
28
|
};
|
|
28
29
|
|
|
29
30
|
return (
|
|
30
|
-
<
|
|
31
|
+
<ApiClientModalProvider
|
|
32
|
+
configuration={{ spec: { url: context.specUrl } }}
|
|
33
|
+
initialRequest={{ path: data.path, method: data.method }}
|
|
34
|
+
>
|
|
31
35
|
<div className={classNames('openapi-operation', className)}>
|
|
32
36
|
<div className="openapi-intro">
|
|
33
|
-
<h2 className="openapi-summary"
|
|
37
|
+
<h2 className="openapi-summary" id={context.id}>
|
|
38
|
+
{operation.summary}
|
|
39
|
+
</h2>
|
|
34
40
|
{operation.description ? (
|
|
35
41
|
<Markdown className="openapi-description" source={operation.description} />
|
|
36
42
|
) : null}
|
|
@@ -61,6 +67,6 @@ export function OpenAPIOperation(props: {
|
|
|
61
67
|
</div>
|
|
62
68
|
</div>
|
|
63
69
|
</div>
|
|
64
|
-
</
|
|
70
|
+
</ApiClientModalProvider>
|
|
65
71
|
);
|
|
66
72
|
}
|
|
@@ -3,7 +3,7 @@ import { InteractiveSection } from './InteractiveSection';
|
|
|
3
3
|
import { OpenAPIOperationData } from './fetchOpenAPIOperation';
|
|
4
4
|
import { generateSchemaExample } from './generateSchemaExample';
|
|
5
5
|
import { OpenAPIContextProps } from './types';
|
|
6
|
-
import { noReference } from './utils';
|
|
6
|
+
import { createStateKey, noReference } from './utils';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Display an example of the response content.
|
|
@@ -36,37 +36,52 @@ export function OpenAPIResponseExample(props: {
|
|
|
36
36
|
}
|
|
37
37
|
return Number(a) - Number(b);
|
|
38
38
|
});
|
|
39
|
-
// Take the first one
|
|
40
|
-
const response = responses[0];
|
|
41
39
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
const examples = responses
|
|
41
|
+
.map((response) => {
|
|
42
|
+
const responseObject = noReference(response[1]);
|
|
45
43
|
|
|
46
|
-
|
|
44
|
+
const schema = noReference(
|
|
45
|
+
(
|
|
46
|
+
responseObject.content?.['application/json'] ??
|
|
47
|
+
responseObject.content?.[Object.keys(responseObject.content)[0]]
|
|
48
|
+
)?.schema,
|
|
49
|
+
);
|
|
47
50
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
responseObject.content?.[Object.keys(responseObject.content)[0]]
|
|
52
|
-
)?.schema,
|
|
53
|
-
);
|
|
51
|
+
if (!schema) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
const example = generateSchemaExample(schema);
|
|
56
|
+
if (example === undefined) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
key: `${response[0]}`,
|
|
62
|
+
label: `${response[0]}`,
|
|
63
|
+
body: (
|
|
64
|
+
<context.CodeBlock
|
|
65
|
+
code={
|
|
66
|
+
typeof example === 'string' ? example : JSON.stringify(example, null, 2)
|
|
67
|
+
}
|
|
68
|
+
syntax="json"
|
|
69
|
+
/>
|
|
70
|
+
),
|
|
71
|
+
};
|
|
72
|
+
})
|
|
73
|
+
.filter((val): val is { key: string; label: string; body: any } => Boolean(val));
|
|
58
74
|
|
|
59
|
-
|
|
60
|
-
if (example === undefined) {
|
|
75
|
+
if (examples.length === 0) {
|
|
61
76
|
return null;
|
|
62
77
|
}
|
|
63
78
|
|
|
64
79
|
return (
|
|
65
|
-
<InteractiveSection
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
80
|
+
<InteractiveSection
|
|
81
|
+
stateKey={createStateKey('response', context.blockKey)}
|
|
82
|
+
header="Response"
|
|
83
|
+
className="openapi-response-example"
|
|
84
|
+
tabs={examples}
|
|
85
|
+
/>
|
|
71
86
|
);
|
|
72
87
|
}
|
package/src/OpenAPIResponses.tsx
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
import classNames from 'classnames';
|
|
3
3
|
import { OpenAPIV3 } from 'openapi-types';
|
|
4
|
-
import { noReference } from './utils';
|
|
4
|
+
import { createStateKey, noReference } from './utils';
|
|
5
5
|
import { OpenAPIResponse } from './OpenAPIResponse';
|
|
6
6
|
import { OpenAPIClientContext } from './types';
|
|
7
7
|
import { InteractiveSection } from './InteractiveSection';
|
|
@@ -17,6 +17,7 @@ export function OpenAPIResponses(props: {
|
|
|
17
17
|
|
|
18
18
|
return (
|
|
19
19
|
<InteractiveSection
|
|
20
|
+
stateKey={createStateKey('response', context.blockKey)}
|
|
20
21
|
header="Response"
|
|
21
22
|
className={classNames('openapi-responses')}
|
|
22
23
|
tabs={Object.entries(responses).map(([statusCode, response]) => {
|
package/src/OpenAPISchema.tsx
CHANGED
|
@@ -104,6 +104,11 @@ export function OpenAPISchemaProperty(
|
|
|
104
104
|
Example: <code>{JSON.stringify(schema.example)}</code>
|
|
105
105
|
</span>
|
|
106
106
|
) : null}
|
|
107
|
+
{schema.pattern ? (
|
|
108
|
+
<div className="openapi-schema-pattern">
|
|
109
|
+
Pattern: <code>{schema.pattern}</code>
|
|
110
|
+
</div>
|
|
111
|
+
) : null}
|
|
107
112
|
</div>
|
|
108
113
|
}
|
|
109
114
|
>
|
package/src/ScalarApiButton.tsx
CHANGED
|
@@ -1,44 +1,17 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import {
|
|
3
|
-
Cookie,
|
|
4
|
-
getHarRequest,
|
|
5
|
-
getParametersFromOperation,
|
|
6
|
-
type TransformedOperation,
|
|
7
|
-
getRequestFromOperation,
|
|
8
|
-
Query,
|
|
9
|
-
Header,
|
|
10
|
-
RequestBody,
|
|
11
|
-
} from '@scalar/oas-utils';
|
|
12
|
-
import React from 'react';
|
|
13
|
-
|
|
14
|
-
import { OpenAPIOperationData, fromJSON } from './fetchOpenAPIOperation';
|
|
15
2
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return { default: mod.ApiClientReact };
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
const ScalarContext = React.createContext<
|
|
22
|
-
(fetchOperationData: () => Promise<OpenAPIOperationData>) => void
|
|
23
|
-
>(() => {});
|
|
3
|
+
import { useApiClientModal } from '@scalar/api-client-react';
|
|
4
|
+
import React from 'react';
|
|
24
5
|
|
|
25
6
|
/**
|
|
26
7
|
* Button which launches the Scalar API Client
|
|
27
8
|
*/
|
|
28
|
-
export function ScalarApiButton(
|
|
29
|
-
|
|
30
|
-
}) {
|
|
31
|
-
const { fetchOperationData } = props;
|
|
32
|
-
const open = React.useContext(ScalarContext);
|
|
9
|
+
export function ScalarApiButton() {
|
|
10
|
+
const client = useApiClientModal();
|
|
33
11
|
|
|
34
12
|
return (
|
|
35
13
|
<div className="scalar scalar-activate">
|
|
36
|
-
<button
|
|
37
|
-
className="scalar-activate-button"
|
|
38
|
-
onClick={() => {
|
|
39
|
-
open(fetchOperationData);
|
|
40
|
-
}}
|
|
41
|
-
>
|
|
14
|
+
<button className="scalar-activate-button" onClick={() => client?.open()}>
|
|
42
15
|
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="12" fill="none">
|
|
43
16
|
<path
|
|
44
17
|
stroke="currentColor"
|
|
@@ -51,109 +24,3 @@ export function ScalarApiButton(props: {
|
|
|
51
24
|
</div>
|
|
52
25
|
);
|
|
53
26
|
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Wrap the rendering with a context to open the scalar modal.
|
|
57
|
-
*/
|
|
58
|
-
export function ScalarApiClient(props: { children: React.ReactNode }) {
|
|
59
|
-
const { children } = props;
|
|
60
|
-
|
|
61
|
-
const [active, setActive] = React.useState<null | {
|
|
62
|
-
operationData: OpenAPIOperationData | null;
|
|
63
|
-
}>(null);
|
|
64
|
-
|
|
65
|
-
const proxy = '/~scalar/proxy';
|
|
66
|
-
|
|
67
|
-
const open = React.useCallback(
|
|
68
|
-
async (fetchOperationData: () => Promise<OpenAPIOperationData>) => {
|
|
69
|
-
setActive({ operationData: null });
|
|
70
|
-
const operationData = fromJSON(await fetchOperationData());
|
|
71
|
-
setActive({ operationData });
|
|
72
|
-
},
|
|
73
|
-
[],
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
const onClose = React.useCallback(() => {
|
|
77
|
-
setActive(null);
|
|
78
|
-
}, []);
|
|
79
|
-
|
|
80
|
-
const request = React.useMemo(() => {
|
|
81
|
-
const operationData = active?.operationData;
|
|
82
|
-
|
|
83
|
-
if (!operationData) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const operationId =
|
|
88
|
-
operationData.operation.operationId ?? operationData.method + operationData.path;
|
|
89
|
-
|
|
90
|
-
const operation = {
|
|
91
|
-
...operationData,
|
|
92
|
-
httpVerb: operationData.method,
|
|
93
|
-
pathParameters: operationData.operation.parameters,
|
|
94
|
-
} as TransformedOperation;
|
|
95
|
-
|
|
96
|
-
const variables = getParametersFromOperation(operation, 'path', false);
|
|
97
|
-
|
|
98
|
-
const request = getHarRequest(
|
|
99
|
-
{
|
|
100
|
-
url: operationData.path,
|
|
101
|
-
},
|
|
102
|
-
getRequestFromOperation(
|
|
103
|
-
{
|
|
104
|
-
...operation,
|
|
105
|
-
information: {
|
|
106
|
-
requestBody: operationData.operation.requestBody as RequestBody,
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
{ requiredOnly: false },
|
|
110
|
-
),
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
id: operationId,
|
|
115
|
-
type: operationData.method,
|
|
116
|
-
path: operationData.path,
|
|
117
|
-
variables,
|
|
118
|
-
cookies: request.cookies.map((cookie: Cookie) => {
|
|
119
|
-
return { ...cookie, enabled: true };
|
|
120
|
-
}),
|
|
121
|
-
query: request.queryString.map((queryString: Query) => {
|
|
122
|
-
const query: typeof queryString & { required?: boolean } = queryString;
|
|
123
|
-
return { ...queryString, enabled: query.required ?? true };
|
|
124
|
-
}),
|
|
125
|
-
headers: request.headers.map((header: Header) => {
|
|
126
|
-
return { ...header, enabled: true };
|
|
127
|
-
}),
|
|
128
|
-
url: operationData.servers[0]?.url,
|
|
129
|
-
body: request.postData?.text,
|
|
130
|
-
};
|
|
131
|
-
}, [active]);
|
|
132
|
-
|
|
133
|
-
return (
|
|
134
|
-
<ScalarContext.Provider value={open}>
|
|
135
|
-
{children}
|
|
136
|
-
{active ? (
|
|
137
|
-
<div className="scalar">
|
|
138
|
-
<div className="scalar-container">
|
|
139
|
-
<div className="scalar-app">
|
|
140
|
-
<React.Suspense fallback={<ScalarLoading />}>
|
|
141
|
-
<ApiClientReact
|
|
142
|
-
close={onClose}
|
|
143
|
-
proxy={proxy}
|
|
144
|
-
isOpen={true}
|
|
145
|
-
request={request}
|
|
146
|
-
/>
|
|
147
|
-
</React.Suspense>
|
|
148
|
-
</div>
|
|
149
|
-
<div onClick={() => onClose()} className="scalar-app-exit"></div>
|
|
150
|
-
</div>
|
|
151
|
-
</div>
|
|
152
|
-
) : null}
|
|
153
|
-
</ScalarContext.Provider>
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function ScalarLoading() {
|
|
158
|
-
return <div className="scalar-app-loading">Loading...</div>;
|
|
159
|
-
}
|
package/src/code-samples.ts
CHANGED
|
@@ -65,6 +65,25 @@ export const codeSampleGenerators: CodeSampleGenerator[] = [
|
|
|
65
65
|
return lines.map((line, index) => (index > 0 ? indent(line, 2) : line)).join(separator);
|
|
66
66
|
},
|
|
67
67
|
},
|
|
68
|
+
{
|
|
69
|
+
id: 'python',
|
|
70
|
+
label: 'Python',
|
|
71
|
+
syntax: 'python',
|
|
72
|
+
generate: ({ method, url, headers, body }) => {
|
|
73
|
+
let code = 'import requests\n\n';
|
|
74
|
+
code += `response = requests.${method.toLowerCase()}(\n`;
|
|
75
|
+
code += indent(`"${url}",\n`, 4);
|
|
76
|
+
if (headers) {
|
|
77
|
+
code += indent(`headers=${JSON.stringify(headers)},\n`, 4);
|
|
78
|
+
}
|
|
79
|
+
if (body) {
|
|
80
|
+
code += indent(`json=${JSON.stringify(body)}\n`, 4);
|
|
81
|
+
}
|
|
82
|
+
code += ')\n';
|
|
83
|
+
code += `data = response.json()`;
|
|
84
|
+
return code;
|
|
85
|
+
},
|
|
86
|
+
},
|
|
68
87
|
];
|
|
69
88
|
|
|
70
89
|
function indent(code: string, spaces: number) {
|
|
@@ -43,7 +43,7 @@ export interface OpenAPICustomSpecProperties {
|
|
|
43
43
|
*/
|
|
44
44
|
export interface OpenAPICustomOperationProperties {
|
|
45
45
|
'x-code-samples'?: OpenAPICustomCodeSample[];
|
|
46
|
-
'x-codeSamples'?: OpenAPICustomCodeSample[];
|
|
46
|
+
'x-codeSamples'?: OpenAPICustomCodeSample[] | false;
|
|
47
47
|
'x-custom-examples'?: OpenAPICustomCodeSample[];
|
|
48
48
|
|
|
49
49
|
/**
|
|
@@ -104,7 +104,7 @@ export function generateSchemaExample(
|
|
|
104
104
|
|
|
105
105
|
if (schema.properties) {
|
|
106
106
|
const example: { [key: string]: JSONValue } = {};
|
|
107
|
-
const props = onlyRequired ? schema.required ?? [] : Object.keys(schema.properties);
|
|
107
|
+
const props = onlyRequired ? (schema.required ?? []) : Object.keys(schema.properties);
|
|
108
108
|
|
|
109
109
|
for (const key of props) {
|
|
110
110
|
const property = noReference(schema.properties[key]);
|
package/src/types.ts
CHANGED
|
@@ -2,6 +2,9 @@ export type IconComponent = React.ComponentType<{ className?: string }>;
|
|
|
2
2
|
|
|
3
3
|
export interface OpenAPIContextProps extends OpenAPIClientContext {
|
|
4
4
|
CodeBlock: React.ComponentType<{ code: string; syntax: string }>;
|
|
5
|
+
|
|
6
|
+
/** Spec url for the Scalar Api Client */
|
|
7
|
+
specUrl: string;
|
|
5
8
|
}
|
|
6
9
|
|
|
7
10
|
export interface OpenAPIClientContext {
|
|
@@ -15,6 +18,12 @@ export interface OpenAPIClientContext {
|
|
|
15
18
|
* @default false
|
|
16
19
|
*/
|
|
17
20
|
defaultInteractiveOpened?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* The key of the block
|
|
23
|
+
*/
|
|
24
|
+
blockKey?: string;
|
|
25
|
+
/** Optional id attached to the OpenAPI Operation heading and used as an anchor */
|
|
26
|
+
id?: string;
|
|
18
27
|
}
|
|
19
28
|
|
|
20
29
|
export interface OpenAPIFetcher {
|