@gitbook/react-openapi 1.0.3 → 1.0.4
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 +8 -0
- package/dist/OpenAPICodeSample.jsx +6 -7
- package/dist/OpenAPIDisclosure.d.ts +2 -1
- package/dist/OpenAPIDisclosure.jsx +1 -1
- package/dist/OpenAPIDisclosureGroup.d.ts +1 -1
- package/dist/OpenAPIDisclosureGroup.jsx +2 -2
- package/dist/OpenAPIOperation.jsx +2 -2
- package/dist/OpenAPIPath.d.ts +3 -2
- package/dist/OpenAPIPath.jsx +4 -15
- package/dist/OpenAPIRequestBody.jsx +1 -1
- package/dist/OpenAPIResponse.jsx +1 -1
- package/dist/OpenAPIResponseExample.jsx +3 -3
- package/dist/OpenAPIResponses.d.ts +1 -1
- package/dist/OpenAPIResponses.jsx +2 -2
- package/dist/OpenAPISchema.d.ts +5 -1
- package/dist/OpenAPISchema.jsx +29 -20
- package/dist/OpenAPISchemaName.d.ts +4 -3
- package/dist/OpenAPISchemaName.jsx +1 -1
- package/dist/OpenAPISecurities.jsx +2 -2
- package/dist/OpenAPITabs.d.ts +3 -3
- package/dist/OpenAPITabs.jsx +11 -12
- package/dist/ScalarApiButton.jsx +1 -1
- package/dist/code-samples.js +11 -11
- package/dist/generateSchemaExample.js +2 -1
- package/dist/resolveOpenAPIOperation.d.ts +3 -3
- package/dist/resolveOpenAPIOperation.js +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/util/server.d.ts +1 -1
- package/dist/util/server.js +1 -3
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +4 -6
- package/package.json +2 -7
- package/src/InteractiveSection.tsx +4 -4
- package/src/OpenAPICodeSample.tsx +9 -10
- package/src/OpenAPIDisclosure.tsx +4 -3
- package/src/OpenAPIDisclosureGroup.tsx +5 -5
- package/src/OpenAPIOperation.tsx +3 -3
- package/src/OpenAPIOperationContext.tsx +1 -1
- package/src/OpenAPIPath.tsx +11 -10
- package/src/OpenAPIRequestBody.tsx +2 -2
- package/src/OpenAPIResponse.tsx +3 -3
- package/src/OpenAPIResponseExample.tsx +5 -5
- package/src/OpenAPIResponses.tsx +4 -4
- package/src/OpenAPISchema.test.ts +5 -5
- package/src/OpenAPISchema.tsx +75 -25
- package/src/OpenAPISchemaName.tsx +5 -4
- package/src/OpenAPISecurities.tsx +3 -3
- package/src/OpenAPITabs.tsx +15 -15
- package/src/ScalarApiButton.tsx +3 -3
- package/src/code-samples.test.ts +66 -66
- package/src/code-samples.ts +14 -14
- package/src/generateSchemaExample.ts +3 -3
- package/src/json2xml.test.ts +1 -1
- package/src/resolveOpenAPIOperation.test.ts +6 -6
- package/src/resolveOpenAPIOperation.ts +7 -7
- package/src/stringifyOpenAPI.ts +1 -1
- package/src/util/server.test.ts +3 -3
- package/src/util/server.ts +2 -3
- package/src/utils.ts +4 -4
package/src/OpenAPITabs.tsx
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
3
|
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
|
4
|
-
import { Key, Tab, TabList, TabPanel, Tabs, TabsProps } from 'react-aria-components';
|
|
4
|
+
import { type Key, Tab, TabList, TabPanel, Tabs, type TabsProps } from 'react-aria-components';
|
|
5
|
+
import { useIntersectionObserver } from 'usehooks-ts';
|
|
5
6
|
import { Markdown } from './Markdown';
|
|
6
7
|
import { useSyncedTabsGlobalState } from './useSyncedTabsGlobalState';
|
|
7
|
-
import { useIntersectionObserver } from 'usehooks-ts';
|
|
8
8
|
|
|
9
|
-
export type
|
|
9
|
+
export type TabItem = {
|
|
10
10
|
key: Key;
|
|
11
11
|
label: string;
|
|
12
12
|
body: React.ReactNode;
|
|
@@ -14,8 +14,8 @@ export type Tab = {
|
|
|
14
14
|
};
|
|
15
15
|
|
|
16
16
|
type OpenAPITabsContextData = {
|
|
17
|
-
items:
|
|
18
|
-
selectedTab:
|
|
17
|
+
items: TabItem[];
|
|
18
|
+
selectedTab: TabItem;
|
|
19
19
|
};
|
|
20
20
|
|
|
21
21
|
const OpenAPITabsContext = createContext<OpenAPITabsContextData | null>(null);
|
|
@@ -32,17 +32,16 @@ function useOpenAPITabsContext() {
|
|
|
32
32
|
* The OpenAPI Tabs wrapper component.
|
|
33
33
|
*/
|
|
34
34
|
export function OpenAPITabs(
|
|
35
|
-
props: React.PropsWithChildren<TabsProps & { items:
|
|
35
|
+
props: React.PropsWithChildren<TabsProps & { items: TabItem[]; stateKey?: string }>
|
|
36
36
|
) {
|
|
37
37
|
const { children, items, stateKey } = props;
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
const [syncedTabs, setSyncedTabs] = useSyncedTabsGlobalState<Tab>();
|
|
38
|
+
const [ref, isIntersectionVisible] = useIntersectionObserver({
|
|
39
|
+
threshold: 0.1,
|
|
40
|
+
rootMargin: '200px',
|
|
41
|
+
});
|
|
42
|
+
const isVisible = stateKey ? isIntersectionVisible : true;
|
|
43
|
+
const defaultTab = items[0] as TabItem;
|
|
44
|
+
const [syncedTabs, setSyncedTabs] = useSyncedTabsGlobalState<TabItem>();
|
|
46
45
|
const [selectedTabKey, setSelectedTabKey] = useState(() => {
|
|
47
46
|
if (isVisible && stateKey && syncedTabs && syncedTabs.has(stateKey)) {
|
|
48
47
|
const tabFromState = syncedTabs.get(stateKey);
|
|
@@ -50,7 +49,7 @@ export function OpenAPITabs(
|
|
|
50
49
|
}
|
|
51
50
|
return items[0]?.key;
|
|
52
51
|
});
|
|
53
|
-
const [selectedTab, setSelectedTab] = useState<
|
|
52
|
+
const [selectedTab, setSelectedTab] = useState<TabItem>(defaultTab);
|
|
54
53
|
|
|
55
54
|
const handleSelectionChange = (key: Key) => {
|
|
56
55
|
setSelectedTabKey(key);
|
|
@@ -94,6 +93,7 @@ export function OpenAPITabs(
|
|
|
94
93
|
return (
|
|
95
94
|
<OpenAPITabsContext.Provider value={contextValue}>
|
|
96
95
|
<Tabs
|
|
96
|
+
ref={ref}
|
|
97
97
|
className="openapi-tabs"
|
|
98
98
|
onSelectionChange={handleSelectionChange}
|
|
99
99
|
selectedKey={selectedTab?.key}
|
package/src/ScalarApiButton.tsx
CHANGED
|
@@ -4,8 +4,8 @@ import { ApiClientModalProvider, useApiClientModal } from '@scalar/api-client-re
|
|
|
4
4
|
import { useEffect, useImperativeHandle, useRef, useState } from 'react';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
6
6
|
|
|
7
|
-
import { useOpenAPIOperationContext } from './OpenAPIOperationContext';
|
|
8
7
|
import { useEventCallback } from 'usehooks-ts';
|
|
8
|
+
import { useOpenAPIOperationContext } from './OpenAPIOperationContext';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* Button which launches the Scalar API Client
|
|
@@ -48,7 +48,7 @@ export function ScalarApiButton({
|
|
|
48
48
|
path={path}
|
|
49
49
|
specUrl={specUrl}
|
|
50
50
|
/>,
|
|
51
|
-
document.body
|
|
51
|
+
document.body
|
|
52
52
|
)}
|
|
53
53
|
</div>
|
|
54
54
|
);
|
|
@@ -88,7 +88,7 @@ function ScalarModalController(props: {
|
|
|
88
88
|
useImperativeHandle(
|
|
89
89
|
props.controllerRef,
|
|
90
90
|
() => ({ openClient: openClient ? () => openClient() : undefined }),
|
|
91
|
-
[openClient]
|
|
91
|
+
[openClient]
|
|
92
92
|
);
|
|
93
93
|
|
|
94
94
|
// Open the client when the component is mounted.
|
package/src/code-samples.test.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { describe, expect, it } from 'bun:test';
|
|
2
|
+
import { type CodeSampleInput, codeSampleGenerators, parseHostAndPath } from './code-samples';
|
|
3
3
|
|
|
4
4
|
it('should parse host and path on url strings properly', () => {
|
|
5
5
|
const testUrls = [
|
|
@@ -67,10 +67,10 @@ describe('curL code sample generator', () => {
|
|
|
67
67
|
},
|
|
68
68
|
};
|
|
69
69
|
|
|
70
|
-
const output = generator
|
|
70
|
+
const output = generator?.generate(input);
|
|
71
71
|
|
|
72
72
|
expect(output).toBe(
|
|
73
|
-
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: application/x-www-form-urlencoded' \\\n --data 'key=value'"
|
|
73
|
+
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: application/x-www-form-urlencoded' \\\n --data 'key=value'"
|
|
74
74
|
);
|
|
75
75
|
});
|
|
76
76
|
|
|
@@ -86,10 +86,10 @@ describe('curL code sample generator', () => {
|
|
|
86
86
|
},
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
-
const output = generator
|
|
89
|
+
const output = generator?.generate(input);
|
|
90
90
|
|
|
91
91
|
expect(output).toBe(
|
|
92
|
-
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"key\": \"value\"\n }'"
|
|
92
|
+
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: application/json' \\\n --data '{\n \"key\": \"value\"\n }'"
|
|
93
93
|
);
|
|
94
94
|
});
|
|
95
95
|
|
|
@@ -103,10 +103,10 @@ describe('curL code sample generator', () => {
|
|
|
103
103
|
body: '<key>value</key>',
|
|
104
104
|
};
|
|
105
105
|
|
|
106
|
-
const output = generator
|
|
106
|
+
const output = generator?.generate(input);
|
|
107
107
|
|
|
108
108
|
expect(output).toBe(
|
|
109
|
-
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: application/xml' \\\n --data-binary $'<key>value</key>'"
|
|
109
|
+
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: application/xml' \\\n --data-binary $'<key>value</key>'"
|
|
110
110
|
);
|
|
111
111
|
});
|
|
112
112
|
|
|
@@ -120,10 +120,10 @@ describe('curL code sample generator', () => {
|
|
|
120
120
|
body: '{ key }',
|
|
121
121
|
};
|
|
122
122
|
|
|
123
|
-
const output = generator
|
|
123
|
+
const output = generator?.generate(input);
|
|
124
124
|
|
|
125
125
|
expect(output).toBe(
|
|
126
|
-
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: application/json' \\\n --data '\"{ key }\"'"
|
|
126
|
+
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: application/json' \\\n --data '\"{ key }\"'"
|
|
127
127
|
);
|
|
128
128
|
});
|
|
129
129
|
|
|
@@ -137,10 +137,10 @@ describe('curL code sample generator', () => {
|
|
|
137
137
|
body: 'key,value',
|
|
138
138
|
};
|
|
139
139
|
|
|
140
|
-
const output = generator
|
|
140
|
+
const output = generator?.generate(input);
|
|
141
141
|
|
|
142
142
|
expect(output).toBe(
|
|
143
|
-
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: text/csv' \\\n --data-binary $'key,value'"
|
|
143
|
+
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: text/csv' \\\n --data-binary $'key,value'"
|
|
144
144
|
);
|
|
145
145
|
});
|
|
146
146
|
|
|
@@ -154,10 +154,10 @@ describe('curL code sample generator', () => {
|
|
|
154
154
|
body: 'file',
|
|
155
155
|
};
|
|
156
156
|
|
|
157
|
-
const output = generator
|
|
157
|
+
const output = generator?.generate(input);
|
|
158
158
|
|
|
159
159
|
expect(output).toBe(
|
|
160
|
-
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: application/pdf' \\\n --data-binary '@file'"
|
|
160
|
+
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: application/pdf' \\\n --data-binary '@file'"
|
|
161
161
|
);
|
|
162
162
|
});
|
|
163
163
|
|
|
@@ -171,10 +171,10 @@ describe('curL code sample generator', () => {
|
|
|
171
171
|
body: 'value',
|
|
172
172
|
};
|
|
173
173
|
|
|
174
|
-
const output = generator
|
|
174
|
+
const output = generator?.generate(input);
|
|
175
175
|
|
|
176
176
|
expect(output).toBe(
|
|
177
|
-
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: text/plain' \\\n --data 'value'"
|
|
177
|
+
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: text/plain' \\\n --data 'value'"
|
|
178
178
|
);
|
|
179
179
|
});
|
|
180
180
|
|
|
@@ -190,10 +190,10 @@ describe('curL code sample generator', () => {
|
|
|
190
190
|
},
|
|
191
191
|
};
|
|
192
192
|
|
|
193
|
-
const output = generator
|
|
193
|
+
const output = generator?.generate(input);
|
|
194
194
|
|
|
195
195
|
expect(output).toBe(
|
|
196
|
-
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: multipart/form-data' \\\n --form 'key=value'"
|
|
196
|
+
"curl -L \\\n --url 'https://example.com/path' \\\n --header 'Content-Type: multipart/form-data' \\\n --form 'key=value'"
|
|
197
197
|
);
|
|
198
198
|
});
|
|
199
199
|
});
|
|
@@ -215,10 +215,10 @@ describe('javascript code sample generator', () => {
|
|
|
215
215
|
},
|
|
216
216
|
};
|
|
217
217
|
|
|
218
|
-
const output = generator
|
|
218
|
+
const output = generator?.generate(input);
|
|
219
219
|
|
|
220
220
|
expect(output).toBe(
|
|
221
|
-
'const params = new URLSearchParams();\n\nparams.append("key", "value");\n\nconst response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "application/x-www-form-urlencoded"\n },\n body: params.toString()\n});\n\nconst data = await response.json();'
|
|
221
|
+
'const params = new URLSearchParams();\n\nparams.append("key", "value");\n\nconst response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "application/x-www-form-urlencoded"\n },\n body: params.toString()\n});\n\nconst data = await response.json();'
|
|
222
222
|
);
|
|
223
223
|
});
|
|
224
224
|
|
|
@@ -234,10 +234,10 @@ describe('javascript code sample generator', () => {
|
|
|
234
234
|
},
|
|
235
235
|
};
|
|
236
236
|
|
|
237
|
-
const output = generator
|
|
237
|
+
const output = generator?.generate(input);
|
|
238
238
|
|
|
239
239
|
expect(output).toBe(
|
|
240
|
-
'const response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "application/json"\n },\n body: JSON.stringify({\n "key": "value"\n })\n});\n\nconst data = await response.json();'
|
|
240
|
+
'const response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "application/json"\n },\n body: JSON.stringify({\n "key": "value"\n })\n});\n\nconst data = await response.json();'
|
|
241
241
|
);
|
|
242
242
|
});
|
|
243
243
|
|
|
@@ -251,10 +251,10 @@ describe('javascript code sample generator', () => {
|
|
|
251
251
|
body: '<key>value</key>',
|
|
252
252
|
};
|
|
253
253
|
|
|
254
|
-
const output = generator
|
|
254
|
+
const output = generator?.generate(input);
|
|
255
255
|
|
|
256
256
|
expect(output).toBe(
|
|
257
|
-
'const xml = `\n <key>value</key>`;\n\nconst response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "application/xml"\n },\n body: xml\n});\n\nconst data = await response.json();'
|
|
257
|
+
'const xml = `\n <key>value</key>`;\n\nconst response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "application/xml"\n },\n body: xml\n});\n\nconst data = await response.json();'
|
|
258
258
|
);
|
|
259
259
|
});
|
|
260
260
|
|
|
@@ -268,10 +268,10 @@ describe('javascript code sample generator', () => {
|
|
|
268
268
|
body: '{ key }',
|
|
269
269
|
};
|
|
270
270
|
|
|
271
|
-
const output = generator
|
|
271
|
+
const output = generator?.generate(input);
|
|
272
272
|
|
|
273
273
|
expect(output).toBe(
|
|
274
|
-
'const query = `\n { key }`;\n\nconst response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "application/graphql"\n },\n body: JSON.stringify(query)\n});\n\nconst data = await response.json();'
|
|
274
|
+
'const query = `\n { key }`;\n\nconst response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "application/graphql"\n },\n body: JSON.stringify(query)\n});\n\nconst data = await response.json();'
|
|
275
275
|
);
|
|
276
276
|
});
|
|
277
277
|
|
|
@@ -285,10 +285,10 @@ describe('javascript code sample generator', () => {
|
|
|
285
285
|
body: 'key,value',
|
|
286
286
|
};
|
|
287
287
|
|
|
288
|
-
const output = generator
|
|
288
|
+
const output = generator?.generate(input);
|
|
289
289
|
|
|
290
290
|
expect(output).toBe(
|
|
291
|
-
'const csv = `\n key,value`;\n\nconst response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "text/csv"\n },\n body: csv\n});\n\nconst data = await response.json();'
|
|
291
|
+
'const csv = `\n key,value`;\n\nconst response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "text/csv"\n },\n body: csv\n});\n\nconst data = await response.json();'
|
|
292
292
|
);
|
|
293
293
|
});
|
|
294
294
|
|
|
@@ -302,10 +302,10 @@ describe('javascript code sample generator', () => {
|
|
|
302
302
|
body: 'file',
|
|
303
303
|
};
|
|
304
304
|
|
|
305
|
-
const output = generator
|
|
305
|
+
const output = generator?.generate(input);
|
|
306
306
|
|
|
307
307
|
expect(output).toBe(
|
|
308
|
-
'const formData = new FormData();\n\nformData.append("file", "file");\n\nconst response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "application/pdf"\n },\n body: formData\n});\n\nconst data = await response.json();'
|
|
308
|
+
'const formData = new FormData();\n\nformData.append("file", "file");\n\nconst response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "application/pdf"\n },\n body: formData\n});\n\nconst data = await response.json();'
|
|
309
309
|
);
|
|
310
310
|
});
|
|
311
311
|
|
|
@@ -319,10 +319,10 @@ describe('javascript code sample generator', () => {
|
|
|
319
319
|
body: 'value',
|
|
320
320
|
};
|
|
321
321
|
|
|
322
|
-
const output = generator
|
|
322
|
+
const output = generator?.generate(input);
|
|
323
323
|
|
|
324
324
|
expect(output).toBe(
|
|
325
|
-
'const response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "text/plain"\n },\n body: "value"\n});\n\nconst data = await response.json();'
|
|
325
|
+
'const response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "text/plain"\n },\n body: "value"\n});\n\nconst data = await response.json();'
|
|
326
326
|
);
|
|
327
327
|
});
|
|
328
328
|
|
|
@@ -338,10 +338,10 @@ describe('javascript code sample generator', () => {
|
|
|
338
338
|
},
|
|
339
339
|
};
|
|
340
340
|
|
|
341
|
-
const output = generator
|
|
341
|
+
const output = generator?.generate(input);
|
|
342
342
|
|
|
343
343
|
expect(output).toBe(
|
|
344
|
-
'const formData = new FormData();\n\nformData.append("key", "value");\n\nconst response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "multipart/form-data"\n },\n body: formData\n});\n\nconst data = await response.json();'
|
|
344
|
+
'const formData = new FormData();\n\nformData.append("key", "value");\n\nconst response = await fetch(\'https://example.com/path\', {\n method: \'GET\',\n headers: {\n "Content-Type": "multipart/form-data"\n },\n body: formData\n});\n\nconst data = await response.json();'
|
|
345
345
|
);
|
|
346
346
|
});
|
|
347
347
|
});
|
|
@@ -363,10 +363,10 @@ describe('python code sample generator', () => {
|
|
|
363
363
|
},
|
|
364
364
|
};
|
|
365
365
|
|
|
366
|
-
const output = generator
|
|
366
|
+
const output = generator?.generate(input);
|
|
367
367
|
|
|
368
368
|
expect(output).toBe(
|
|
369
|
-
'import requests\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"application/x-www-form-urlencoded"},\n data={"key":"value"}\n)\n\ndata = response.json()'
|
|
369
|
+
'import requests\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"application/x-www-form-urlencoded"},\n data={"key":"value"}\n)\n\ndata = response.json()'
|
|
370
370
|
);
|
|
371
371
|
});
|
|
372
372
|
|
|
@@ -382,10 +382,10 @@ describe('python code sample generator', () => {
|
|
|
382
382
|
},
|
|
383
383
|
};
|
|
384
384
|
|
|
385
|
-
const output = generator
|
|
385
|
+
const output = generator?.generate(input);
|
|
386
386
|
|
|
387
387
|
expect(output).toBe(
|
|
388
|
-
'import requests\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"application/json"},\n data={"key":"value"}\n)\n\ndata = response.json()'
|
|
388
|
+
'import requests\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"application/json"},\n data={"key":"value"}\n)\n\ndata = response.json()'
|
|
389
389
|
);
|
|
390
390
|
});
|
|
391
391
|
|
|
@@ -399,10 +399,10 @@ describe('python code sample generator', () => {
|
|
|
399
399
|
body: '<key>value</key>',
|
|
400
400
|
};
|
|
401
401
|
|
|
402
|
-
const output = generator
|
|
402
|
+
const output = generator?.generate(input);
|
|
403
403
|
|
|
404
404
|
expect(output).toBe(
|
|
405
|
-
'import requests\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"application/xml"},\n data="<key>value</key>"\n)\n\ndata = response.json()'
|
|
405
|
+
'import requests\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"application/xml"},\n data="<key>value</key>"\n)\n\ndata = response.json()'
|
|
406
406
|
);
|
|
407
407
|
});
|
|
408
408
|
|
|
@@ -416,10 +416,10 @@ describe('python code sample generator', () => {
|
|
|
416
416
|
body: '{ key }',
|
|
417
417
|
};
|
|
418
418
|
|
|
419
|
-
const output = generator
|
|
419
|
+
const output = generator?.generate(input);
|
|
420
420
|
|
|
421
421
|
expect(output).toBe(
|
|
422
|
-
'import requests\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"application/graphql"},\n data="{ key }"\n)\n\ndata = response.json()'
|
|
422
|
+
'import requests\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"application/graphql"},\n data="{ key }"\n)\n\ndata = response.json()'
|
|
423
423
|
);
|
|
424
424
|
});
|
|
425
425
|
|
|
@@ -433,10 +433,10 @@ describe('python code sample generator', () => {
|
|
|
433
433
|
body: 'key,value',
|
|
434
434
|
};
|
|
435
435
|
|
|
436
|
-
const output = generator
|
|
436
|
+
const output = generator?.generate(input);
|
|
437
437
|
|
|
438
438
|
expect(output).toBe(
|
|
439
|
-
'import requests\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"text/csv"},\n data="key,value"\n)\n\ndata = response.json()'
|
|
439
|
+
'import requests\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"text/csv"},\n data="key,value"\n)\n\ndata = response.json()'
|
|
440
440
|
);
|
|
441
441
|
});
|
|
442
442
|
|
|
@@ -450,10 +450,10 @@ describe('python code sample generator', () => {
|
|
|
450
450
|
body: 'file',
|
|
451
451
|
};
|
|
452
452
|
|
|
453
|
-
const output = generator
|
|
453
|
+
const output = generator?.generate(input);
|
|
454
454
|
|
|
455
455
|
expect(output).toBe(
|
|
456
|
-
'import requests\n\nfiles = {\n "file": "file",\n}\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"application/pdf"},\n files=files\n)\n\ndata = response.json()'
|
|
456
|
+
'import requests\n\nfiles = {\n "file": "file",\n}\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"application/pdf"},\n files=files\n)\n\ndata = response.json()'
|
|
457
457
|
);
|
|
458
458
|
});
|
|
459
459
|
|
|
@@ -467,10 +467,10 @@ describe('python code sample generator', () => {
|
|
|
467
467
|
body: 'value',
|
|
468
468
|
};
|
|
469
469
|
|
|
470
|
-
const output = generator
|
|
470
|
+
const output = generator?.generate(input);
|
|
471
471
|
|
|
472
472
|
expect(output).toBe(
|
|
473
|
-
'import requests\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"text/plain"},\n data="value"\n)\n\ndata = response.json()'
|
|
473
|
+
'import requests\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"text/plain"},\n data="value"\n)\n\ndata = response.json()'
|
|
474
474
|
);
|
|
475
475
|
});
|
|
476
476
|
|
|
@@ -486,10 +486,10 @@ describe('python code sample generator', () => {
|
|
|
486
486
|
},
|
|
487
487
|
};
|
|
488
488
|
|
|
489
|
-
const output = generator
|
|
489
|
+
const output = generator?.generate(input);
|
|
490
490
|
|
|
491
491
|
expect(output).toBe(
|
|
492
|
-
'import requests\n\nfiles = {\n "key": "value",\n}\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"multipart/form-data"},\n files=files\n)\n\ndata = response.json()'
|
|
492
|
+
'import requests\n\nfiles = {\n "key": "value",\n}\n\nresponse = requests.get(\n "https://example.com/path",\n headers={"Content-Type":"multipart/form-data"},\n files=files\n)\n\ndata = response.json()'
|
|
493
493
|
);
|
|
494
494
|
});
|
|
495
495
|
});
|
|
@@ -511,10 +511,10 @@ describe('http code sample generator', () => {
|
|
|
511
511
|
},
|
|
512
512
|
};
|
|
513
513
|
|
|
514
|
-
const output = generator
|
|
514
|
+
const output = generator?.generate(input);
|
|
515
515
|
|
|
516
516
|
expect(output).toBe(
|
|
517
|
-
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: application/x-www-form-urlencoded\nContent-Length: 15\nAccept: */*\n\n"key=value"'
|
|
517
|
+
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: application/x-www-form-urlencoded\nContent-Length: 15\nAccept: */*\n\n"key=value"'
|
|
518
518
|
);
|
|
519
519
|
});
|
|
520
520
|
|
|
@@ -530,10 +530,10 @@ describe('http code sample generator', () => {
|
|
|
530
530
|
},
|
|
531
531
|
};
|
|
532
532
|
|
|
533
|
-
const output = generator
|
|
533
|
+
const output = generator?.generate(input);
|
|
534
534
|
|
|
535
535
|
expect(output).toBe(
|
|
536
|
-
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: application/json\nContent-Length: 15\nAccept: */*\n\n{\n "key": "value"\n}'
|
|
536
|
+
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: application/json\nContent-Length: 15\nAccept: */*\n\n{\n "key": "value"\n}'
|
|
537
537
|
);
|
|
538
538
|
});
|
|
539
539
|
|
|
@@ -547,10 +547,10 @@ describe('http code sample generator', () => {
|
|
|
547
547
|
body: '<key>value</key>',
|
|
548
548
|
};
|
|
549
549
|
|
|
550
|
-
const output = generator
|
|
550
|
+
const output = generator?.generate(input);
|
|
551
551
|
|
|
552
552
|
expect(output).toBe(
|
|
553
|
-
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: application/xml\nContent-Length: 18\nAccept: */*\n\n"<key>value</key>"'
|
|
553
|
+
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: application/xml\nContent-Length: 18\nAccept: */*\n\n"<key>value</key>"'
|
|
554
554
|
);
|
|
555
555
|
});
|
|
556
556
|
|
|
@@ -564,10 +564,10 @@ describe('http code sample generator', () => {
|
|
|
564
564
|
body: '{ key }',
|
|
565
565
|
};
|
|
566
566
|
|
|
567
|
-
const output = generator
|
|
567
|
+
const output = generator?.generate(input);
|
|
568
568
|
|
|
569
569
|
expect(output).toBe(
|
|
570
|
-
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: application/graphql\nContent-Length: 9\nAccept: */*\n\n"{ key }"'
|
|
570
|
+
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: application/graphql\nContent-Length: 9\nAccept: */*\n\n"{ key }"'
|
|
571
571
|
);
|
|
572
572
|
});
|
|
573
573
|
|
|
@@ -581,10 +581,10 @@ describe('http code sample generator', () => {
|
|
|
581
581
|
body: 'key,value',
|
|
582
582
|
};
|
|
583
583
|
|
|
584
|
-
const output = generator
|
|
584
|
+
const output = generator?.generate(input);
|
|
585
585
|
|
|
586
586
|
expect(output).toBe(
|
|
587
|
-
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: text/csv\nContent-Length: 11\nAccept: */*\n\n"key,value"'
|
|
587
|
+
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: text/csv\nContent-Length: 11\nAccept: */*\n\n"key,value"'
|
|
588
588
|
);
|
|
589
589
|
});
|
|
590
590
|
|
|
@@ -598,10 +598,10 @@ describe('http code sample generator', () => {
|
|
|
598
598
|
body: 'file',
|
|
599
599
|
};
|
|
600
600
|
|
|
601
|
-
const output = generator
|
|
601
|
+
const output = generator?.generate(input);
|
|
602
602
|
|
|
603
603
|
expect(output).toBe(
|
|
604
|
-
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: application/pdf\nContent-Length: 6\nAccept: */*\n\n"file"'
|
|
604
|
+
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: application/pdf\nContent-Length: 6\nAccept: */*\n\n"file"'
|
|
605
605
|
);
|
|
606
606
|
});
|
|
607
607
|
|
|
@@ -615,10 +615,10 @@ describe('http code sample generator', () => {
|
|
|
615
615
|
body: 'value',
|
|
616
616
|
};
|
|
617
617
|
|
|
618
|
-
const output = generator
|
|
618
|
+
const output = generator?.generate(input);
|
|
619
619
|
|
|
620
620
|
expect(output).toBe(
|
|
621
|
-
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: text/plain\nContent-Length: 7\nAccept: */*\n\n"value"'
|
|
621
|
+
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: text/plain\nContent-Length: 7\nAccept: */*\n\n"value"'
|
|
622
622
|
);
|
|
623
623
|
});
|
|
624
624
|
|
|
@@ -634,10 +634,10 @@ describe('http code sample generator', () => {
|
|
|
634
634
|
},
|
|
635
635
|
};
|
|
636
636
|
|
|
637
|
-
const output = generator
|
|
637
|
+
const output = generator?.generate(input);
|
|
638
638
|
|
|
639
639
|
expect(output).toBe(
|
|
640
|
-
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: multipart/form-data\nContent-Length: 15\nAccept: */*\n\n{\n "key": "value"\n}'
|
|
640
|
+
'GET /path HTTP/1.1\nHost: example.com\nContent-Type: multipart/form-data\nContent-Length: 15\nAccept: */*\n\n{\n "key": "value"\n}'
|
|
641
641
|
);
|
|
642
642
|
});
|
|
643
643
|
});
|
package/src/code-samples.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
+
isCSV,
|
|
2
3
|
isFormData,
|
|
3
|
-
isPDF,
|
|
4
4
|
isFormUrlEncoded,
|
|
5
|
-
isText,
|
|
6
|
-
isXML,
|
|
7
|
-
isCSV,
|
|
8
5
|
isGraphQL,
|
|
6
|
+
isPDF,
|
|
9
7
|
isPlainObject,
|
|
8
|
+
isText,
|
|
9
|
+
isXML,
|
|
10
10
|
} from './contentTypeChecks';
|
|
11
11
|
import { stringifyOpenAPI } from './stringifyOpenAPI';
|
|
12
12
|
|
|
@@ -95,8 +95,8 @@ export const codeSampleGenerators: CodeSampleGenerator[] = [
|
|
|
95
95
|
code += indent(`body: ${body}\n`, 4);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
code +=
|
|
99
|
-
code +=
|
|
98
|
+
code += '});\n\n';
|
|
99
|
+
code += 'const data = await response.json();';
|
|
100
100
|
|
|
101
101
|
return code;
|
|
102
102
|
},
|
|
@@ -135,7 +135,7 @@ export const codeSampleGenerators: CodeSampleGenerator[] = [
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
code += ')\n\n';
|
|
138
|
-
code +=
|
|
138
|
+
code += 'data = response.json()';
|
|
139
139
|
return code;
|
|
140
140
|
},
|
|
141
141
|
},
|
|
@@ -169,11 +169,11 @@ export const codeSampleGenerators: CodeSampleGenerator[] = [
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
const headerString = headers
|
|
172
|
-
? Object.entries(headers)
|
|
172
|
+
? `${Object.entries(headers)
|
|
173
173
|
.map(([key, value]) =>
|
|
174
|
-
key.toLowerCase() !== 'host' ? `${key}: ${value}` :
|
|
174
|
+
key.toLowerCase() !== 'host' ? `${key}: ${value}` : ''
|
|
175
175
|
)
|
|
176
|
-
.join('\n')
|
|
176
|
+
.join('\n')}\n`
|
|
177
177
|
: '';
|
|
178
178
|
|
|
179
179
|
const bodyString = body ? `\n${body}` : '';
|
|
@@ -200,7 +200,7 @@ export function parseHostAndPath(url: string) {
|
|
|
200
200
|
const urlObj = new URL(url);
|
|
201
201
|
const path = urlObj.pathname || '/';
|
|
202
202
|
return { host: urlObj.host, path };
|
|
203
|
-
} catch (
|
|
203
|
+
} catch (_e) {
|
|
204
204
|
// If the URL was invalid do our best to parse the URL.
|
|
205
205
|
// Check for the protocol part and pull it off to grab the host
|
|
206
206
|
const splitted = url.split('//');
|
|
@@ -211,7 +211,7 @@ export function parseHostAndPath(url: string) {
|
|
|
211
211
|
// pull off the host (mutates)
|
|
212
212
|
const host = parts.shift();
|
|
213
213
|
// add a leading slash and join the paths again
|
|
214
|
-
const path =
|
|
214
|
+
const path = `/${parts.join('/')}`;
|
|
215
215
|
|
|
216
216
|
return { host, path };
|
|
217
217
|
}
|
|
@@ -332,7 +332,7 @@ const BodyGenerators = {
|
|
|
332
332
|
code += 'files = {\n';
|
|
333
333
|
if (isPlainObject(body)) {
|
|
334
334
|
Object.entries(body).forEach(([key, value]) => {
|
|
335
|
-
code += indent(`"${key}": "${String(value)}",`, 4)
|
|
335
|
+
code += `${indent(`"${key}": "${String(value)}",`, 4)}\n`;
|
|
336
336
|
});
|
|
337
337
|
}
|
|
338
338
|
code += '}\n\n';
|
|
@@ -341,7 +341,7 @@ const BodyGenerators = {
|
|
|
341
341
|
|
|
342
342
|
if (isPDF(contentType)) {
|
|
343
343
|
code += 'files = {\n';
|
|
344
|
-
code += indent(`"file": "${body}",`, 4)
|
|
344
|
+
code += `${indent(`"file": "${body}",`, 4)}\n`;
|
|
345
345
|
code += '}\n\n';
|
|
346
346
|
body = 'files';
|
|
347
347
|
}
|
|
@@ -14,7 +14,7 @@ type GenerateSchemaExampleOptions = Pick<
|
|
|
14
14
|
*/
|
|
15
15
|
export function generateSchemaExample(
|
|
16
16
|
schema: OpenAPIV3.SchemaObject,
|
|
17
|
-
options?: GenerateSchemaExampleOptions
|
|
17
|
+
options?: GenerateSchemaExampleOptions
|
|
18
18
|
): JSONValue | undefined {
|
|
19
19
|
return getExampleFromSchema(
|
|
20
20
|
schema,
|
|
@@ -35,7 +35,7 @@ export function generateSchemaExample(
|
|
|
35
35
|
},
|
|
36
36
|
...options,
|
|
37
37
|
},
|
|
38
|
-
3
|
|
38
|
+
3 // Max depth for circular references
|
|
39
39
|
);
|
|
40
40
|
}
|
|
41
41
|
|
|
@@ -44,7 +44,7 @@ export function generateSchemaExample(
|
|
|
44
44
|
*/
|
|
45
45
|
export function generateMediaTypeExample(
|
|
46
46
|
mediaType: OpenAPIV3.MediaTypeObject,
|
|
47
|
-
options?: GenerateSchemaExampleOptions
|
|
47
|
+
options?: GenerateSchemaExampleOptions
|
|
48
48
|
): JSONValue | undefined {
|
|
49
49
|
if (mediaType.example) {
|
|
50
50
|
return mediaType.example;
|
package/src/json2xml.test.ts
CHANGED
|
@@ -19,7 +19,7 @@ describe('getUrlFromServerState', () => {
|
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
expect(xml).toBe(
|
|
22
|
-
'<?xml version="1.0"?>\n<urls>\n\t<url>https://example.com</url>\n\t<url>https://example.com</url>\n</urls>\n'
|
|
22
|
+
'<?xml version="1.0"?>\n<urls>\n\t<url>https://example.com</url>\n\t<url>https://example.com</url>\n</urls>\n'
|
|
23
23
|
);
|
|
24
24
|
});
|
|
25
25
|
|