@gitbook/react-openapi 0.7.1 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/dist/InteractiveSection.d.ts +4 -8
- package/dist/InteractiveSection.jsx +60 -0
- package/dist/Markdown.d.ts +1 -2
- package/dist/Markdown.jsx +5 -0
- package/dist/OpenAPICodeSample.d.ts +2 -4
- package/dist/OpenAPICodeSample.jsx +141 -0
- package/dist/OpenAPIDisclosure.d.ts +12 -0
- package/dist/OpenAPIDisclosure.jsx +32 -0
- package/dist/OpenAPIDisclosureGroup.d.ts +19 -0
- package/dist/OpenAPIDisclosureGroup.jsx +81 -0
- package/dist/OpenAPIOperation.d.ts +2 -4
- package/dist/OpenAPIOperation.jsx +51 -0
- package/dist/OpenAPIOperationContext.d.ts +16 -0
- package/dist/OpenAPIOperationContext.jsx +26 -0
- package/dist/OpenAPIPath.d.ts +8 -0
- package/dist/OpenAPIPath.jsx +54 -0
- package/dist/OpenAPIRequestBody.d.ts +4 -5
- package/dist/OpenAPIRequestBody.jsx +22 -0
- package/dist/OpenAPIResponse.d.ts +4 -4
- package/dist/OpenAPIResponse.jsx +39 -0
- package/dist/OpenAPIResponseExample.d.ts +2 -4
- package/dist/OpenAPIResponseExample.jsx +108 -0
- package/dist/OpenAPIResponses.d.ts +3 -4
- package/dist/OpenAPIResponses.jsx +35 -0
- package/dist/OpenAPISchema.d.ts +11 -8
- package/dist/OpenAPISchema.jsx +285 -0
- package/dist/OpenAPISchemaName.d.ts +12 -0
- package/dist/OpenAPISchemaName.jsx +15 -0
- package/dist/OpenAPISecurities.d.ts +2 -4
- package/dist/OpenAPISecurities.jsx +55 -0
- package/dist/OpenAPIServerURL.d.ts +2 -3
- package/dist/OpenAPIServerURL.jsx +67 -0
- package/dist/OpenAPIServerURLVariable.d.ts +2 -3
- package/dist/OpenAPIServerURLVariable.jsx +8 -0
- package/dist/OpenAPISpec.d.ts +3 -4
- package/dist/OpenAPISpec.jsx +91 -0
- package/dist/OpenAPITabs.d.ts +26 -0
- package/dist/OpenAPITabs.jsx +103 -0
- package/dist/ScalarApiButton.d.ts +3 -3
- package/dist/ScalarApiButton.jsx +51 -0
- package/dist/code-samples.d.ts +4 -0
- package/dist/code-samples.js +103 -38
- package/dist/generateSchemaExample.d.ts +2 -2
- package/dist/generateSchemaExample.js +29 -102
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/resolveOpenAPIOperation.d.ts +11 -0
- package/dist/resolveOpenAPIOperation.js +194 -0
- package/dist/stringifyOpenAPI.d.ts +4 -0
- package/dist/stringifyOpenAPI.js +6 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/dist/types.d.ts +11 -12
- package/dist/useSyncedTabsGlobalState.d.ts +1 -0
- package/dist/useSyncedTabsGlobalState.js +16 -0
- package/dist/utils.d.ts +6 -2
- package/dist/utils.js +13 -6
- package/package.json +12 -10
- package/src/InteractiveSection.tsx +90 -86
- package/src/Markdown.tsx +2 -3
- package/src/OpenAPICodeSample.tsx +43 -31
- package/src/OpenAPIDisclosure.tsx +50 -0
- package/src/OpenAPIDisclosureGroup.tsx +136 -0
- package/src/OpenAPIOperation.tsx +36 -42
- package/src/OpenAPIOperationContext.tsx +45 -0
- package/src/OpenAPIPath.tsx +65 -0
- package/src/OpenAPIRequestBody.tsx +10 -17
- package/src/OpenAPIResponse.tsx +27 -45
- package/src/OpenAPIResponseExample.tsx +89 -31
- package/src/OpenAPIResponses.tsx +48 -17
- package/src/OpenAPISchema.test.ts +1 -1
- package/src/OpenAPISchema.tsx +129 -108
- package/src/OpenAPISchemaName.tsx +27 -0
- package/src/OpenAPISecurities.tsx +45 -24
- package/src/OpenAPIServerURL.tsx +17 -10
- package/src/OpenAPIServerURLVariable.tsx +2 -4
- package/src/OpenAPISpec.tsx +58 -58
- package/src/OpenAPITabs.tsx +153 -0
- package/src/ScalarApiButton.tsx +84 -7
- package/src/code-samples.test.ts +51 -0
- package/src/code-samples.ts +95 -31
- package/src/generateSchemaExample.ts +26 -153
- package/src/index.ts +3 -2
- package/src/resolveOpenAPIOperation.test.ts +177 -0
- package/src/resolveOpenAPIOperation.ts +164 -0
- package/src/stringifyOpenAPI.ts +6 -0
- package/src/types.ts +17 -10
- package/src/useSyncedTabsGlobalState.ts +23 -0
- package/src/utils.ts +14 -7
- package/dist/InteractiveSection.js +0 -47
- package/dist/Markdown.js +0 -6
- package/dist/OpenAPICodeSample.js +0 -110
- package/dist/OpenAPIOperation.js +0 -38
- package/dist/OpenAPIRequestBody.js +0 -18
- package/dist/OpenAPIResponse.js +0 -32
- package/dist/OpenAPIResponseExample.js +0 -54
- package/dist/OpenAPIResponses.js +0 -18
- package/dist/OpenAPISchema.js +0 -235
- package/dist/OpenAPISchema.test.d.ts +0 -1
- package/dist/OpenAPISchema.test.js +0 -91
- package/dist/OpenAPISecurities.js +0 -42
- package/dist/OpenAPIServerURL.js +0 -51
- package/dist/OpenAPIServerURLVariable.js +0 -10
- package/dist/OpenAPISpec.js +0 -70
- package/dist/ScalarApiButton.js +0 -14
- package/dist/fetchOpenAPIOperation.d.ts +0 -72
- package/dist/fetchOpenAPIOperation.js +0 -124
- package/dist/fetchOpenAPIOperation.test.d.ts +0 -1
- package/dist/fetchOpenAPIOperation.test.js +0 -152
- package/dist/resolveOpenAPIPath.d.ts +0 -7
- package/dist/resolveOpenAPIPath.js +0 -112
- package/dist/resolveOpenAPIPath.test.d.ts +0 -1
- package/dist/resolveOpenAPIPath.test.js +0 -39
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/src/fetchOpenAPIOperation.test.ts +0 -185
- package/src/fetchOpenAPIOperation.ts +0 -230
- package/src/resolveOpenAPIPath.test.ts +0 -60
- package/src/resolveOpenAPIPath.ts +0 -145
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { InteractiveSection } from './InteractiveSection';
|
|
2
|
+
import { Markdown } from './Markdown';
|
|
3
|
+
import { OpenAPISchemaName } from './OpenAPISchemaName';
|
|
4
|
+
import { resolveDescription } from './utils';
|
|
5
|
+
/**
|
|
6
|
+
* Present securities authorization that can be used for this operation.
|
|
7
|
+
*/
|
|
8
|
+
export function OpenAPISecurities(props) {
|
|
9
|
+
var securities = props.securities, context = props.context;
|
|
10
|
+
if (securities.length === 0) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
return (<InteractiveSection header="Authorizations" toggeable defaultOpened={false} toggleIcon={context.icons.chevronRight} className="openapi-securities" tabs={securities.map(function (_a) {
|
|
14
|
+
var key = _a[0], security = _a[1];
|
|
15
|
+
var description = resolveDescription(security);
|
|
16
|
+
return {
|
|
17
|
+
key: key,
|
|
18
|
+
label: key,
|
|
19
|
+
body: (<div className="openapi-schema-body">
|
|
20
|
+
<div className="openapi-schema-presentation">
|
|
21
|
+
{getLabelForType(security)}
|
|
22
|
+
|
|
23
|
+
{description ? (<Markdown source={description} className="openapi-securities-description"/>) : null}
|
|
24
|
+
</div>
|
|
25
|
+
</div>),
|
|
26
|
+
};
|
|
27
|
+
})}/>);
|
|
28
|
+
}
|
|
29
|
+
function getLabelForType(security) {
|
|
30
|
+
var _a;
|
|
31
|
+
switch (security.type) {
|
|
32
|
+
case 'apiKey':
|
|
33
|
+
return (<OpenAPISchemaName propertyName={(_a = security.name) !== null && _a !== void 0 ? _a : 'apiKey'} type="string" required/>);
|
|
34
|
+
case 'http':
|
|
35
|
+
if (security.scheme === 'basic') {
|
|
36
|
+
return <OpenAPISchemaName propertyName="Authorization" type="string" required/>;
|
|
37
|
+
}
|
|
38
|
+
if (security.scheme == 'bearer') {
|
|
39
|
+
var description = resolveDescription(security);
|
|
40
|
+
return (<>
|
|
41
|
+
<OpenAPISchemaName propertyName="Authorization" type="string" required/>
|
|
42
|
+
{/** Show a default description if none is provided */}
|
|
43
|
+
{!description ? (<Markdown source={"Bearer authentication header of the form Bearer ".concat("<token>", ".")} className="openapi-securities-description"/>) : null}
|
|
44
|
+
</>);
|
|
45
|
+
}
|
|
46
|
+
return <OpenAPISchemaName propertyName="HTTP" required/>;
|
|
47
|
+
case 'oauth2':
|
|
48
|
+
return <OpenAPISchemaName propertyName="OAuth2" required/>;
|
|
49
|
+
case 'openIdConnect':
|
|
50
|
+
return <OpenAPISchemaName propertyName="OpenID Connect" required/>;
|
|
51
|
+
default:
|
|
52
|
+
// @ts-ignore
|
|
53
|
+
return security.type;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { OpenAPIV3 } from 'openapi-types';
|
|
1
|
+
import type { OpenAPIV3 } from '@gitbook/openapi-parser';
|
|
3
2
|
/**
|
|
4
3
|
* Show the url of the server with variables replaced by their default values.
|
|
5
4
|
*/
|
|
6
5
|
export declare function OpenAPIServerURL(props: {
|
|
7
6
|
servers: OpenAPIV3.ServerObject[];
|
|
8
|
-
}):
|
|
7
|
+
}): import("react").JSX.Element | null;
|
|
9
8
|
/**
|
|
10
9
|
* Get the default URL for the server.
|
|
11
10
|
*/
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { OpenAPIServerURLVariable } from './OpenAPIServerURLVariable';
|
|
2
|
+
/**
|
|
3
|
+
* Show the url of the server with variables replaced by their default values.
|
|
4
|
+
*/
|
|
5
|
+
export function OpenAPIServerURL(props) {
|
|
6
|
+
var _a;
|
|
7
|
+
var servers = props.servers;
|
|
8
|
+
var server = servers[0];
|
|
9
|
+
if (!server) {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
var parts = parseServerURL((_a = server === null || server === void 0 ? void 0 : server.url) !== null && _a !== void 0 ? _a : '');
|
|
13
|
+
return (<span>
|
|
14
|
+
{parts.map(function (part, i) {
|
|
15
|
+
var _a;
|
|
16
|
+
if (part.kind === 'text') {
|
|
17
|
+
return <span key={i}>{part.text}</span>;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
var variable = (_a = server.variables) === null || _a === void 0 ? void 0 : _a[part.name];
|
|
21
|
+
if (!variable) {
|
|
22
|
+
return <span key={i}>{"{".concat(part.name, "}")}</span>;
|
|
23
|
+
}
|
|
24
|
+
return (<OpenAPIServerURLVariable key={i} name={part.name} variable={variable}/>);
|
|
25
|
+
}
|
|
26
|
+
})}
|
|
27
|
+
</span>);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get the default URL for the server.
|
|
31
|
+
*/
|
|
32
|
+
export function getServersURL(servers) {
|
|
33
|
+
var _a;
|
|
34
|
+
var server = servers[0];
|
|
35
|
+
if (!server) {
|
|
36
|
+
return '';
|
|
37
|
+
}
|
|
38
|
+
var parts = parseServerURL((_a = server === null || server === void 0 ? void 0 : server.url) !== null && _a !== void 0 ? _a : '');
|
|
39
|
+
return parts
|
|
40
|
+
.map(function (part) {
|
|
41
|
+
var _a, _b, _c;
|
|
42
|
+
if (part.kind === 'text') {
|
|
43
|
+
return part.text;
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
return (_c = (_b = (_a = server.variables) === null || _a === void 0 ? void 0 : _a[part.name]) === null || _b === void 0 ? void 0 : _b.default) !== null && _c !== void 0 ? _c : "{".concat(part.name, "}");
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
.join('');
|
|
50
|
+
}
|
|
51
|
+
function parseServerURL(url) {
|
|
52
|
+
var parts = url.split(/{([^}]+)}/g);
|
|
53
|
+
var result = [];
|
|
54
|
+
for (var i = 0; i < parts.length; i++) {
|
|
55
|
+
var part = parts[i];
|
|
56
|
+
if (!part) {
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (i % 2 === 0) {
|
|
60
|
+
result.push({ kind: 'text', text: part });
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
result.push({ kind: 'variable', name: part });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { OpenAPIV3 } from 'openapi-types';
|
|
1
|
+
import type { OpenAPIV3 } from '@gitbook/openapi-parser';
|
|
3
2
|
/**
|
|
4
3
|
* Interactive component to show the value of a server variable and let the user change it.
|
|
5
4
|
*/
|
|
6
5
|
export declare function OpenAPIServerURLVariable(props: {
|
|
7
6
|
name: string;
|
|
8
7
|
variable: OpenAPIV3.ServerVariableObject;
|
|
9
|
-
}):
|
|
8
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
/**
|
|
3
|
+
* Interactive component to show the value of a server variable and let the user change it.
|
|
4
|
+
*/
|
|
5
|
+
export function OpenAPIServerURLVariable(props) {
|
|
6
|
+
var variable = props.variable;
|
|
7
|
+
return <span className="openapi-url-var">{variable.default}</span>;
|
|
8
|
+
}
|
package/dist/OpenAPISpec.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { OpenAPIClientContext } from './types';
|
|
1
|
+
import type { OpenAPIClientContext, OpenAPIOperationData } from './types';
|
|
3
2
|
/**
|
|
4
3
|
* Client component to render the spec for the request and response.
|
|
5
4
|
*
|
|
@@ -7,6 +6,6 @@ import { OpenAPIClientContext } from './types';
|
|
|
7
6
|
* (the entire schema is rendered at once, while the client component only renders the visible part)
|
|
8
7
|
*/
|
|
9
8
|
export declare function OpenAPISpec(props: {
|
|
10
|
-
|
|
9
|
+
data: OpenAPIOperationData;
|
|
11
10
|
context: OpenAPIClientContext;
|
|
12
|
-
}):
|
|
11
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
var __assign = (this && this.__assign) || function () {
|
|
3
|
+
__assign = Object.assign || function(t) {
|
|
4
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
+
s = arguments[i];
|
|
6
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
+
t[p] = s[p];
|
|
8
|
+
}
|
|
9
|
+
return t;
|
|
10
|
+
};
|
|
11
|
+
return __assign.apply(this, arguments);
|
|
12
|
+
};
|
|
13
|
+
import { InteractiveSection } from './InteractiveSection';
|
|
14
|
+
import { OpenAPIRequestBody } from './OpenAPIRequestBody';
|
|
15
|
+
import { OpenAPIResponses } from './OpenAPIResponses';
|
|
16
|
+
import { OpenAPISchemaProperties } from './OpenAPISchema';
|
|
17
|
+
import { OpenAPISecurities } from './OpenAPISecurities';
|
|
18
|
+
import { resolveDescription } from './utils';
|
|
19
|
+
/**
|
|
20
|
+
* Client component to render the spec for the request and response.
|
|
21
|
+
*
|
|
22
|
+
* We use a client component as rendering recursive JSON schema in the server is expensive
|
|
23
|
+
* (the entire schema is rendered at once, while the client component only renders the visible part)
|
|
24
|
+
*/
|
|
25
|
+
export function OpenAPISpec(props) {
|
|
26
|
+
var _a;
|
|
27
|
+
var data = props.data, context = props.context;
|
|
28
|
+
var operation = data.operation, securities = data.securities;
|
|
29
|
+
var parameters = (_a = operation.parameters) !== null && _a !== void 0 ? _a : [];
|
|
30
|
+
var parameterGroups = groupParameters(parameters);
|
|
31
|
+
return (<>
|
|
32
|
+
{securities.length > 0 ? (<OpenAPISecurities securities={securities} context={context}/>) : null}
|
|
33
|
+
|
|
34
|
+
{parameterGroups.map(function (group) {
|
|
35
|
+
return (<InteractiveSection key={group.key} className="openapi-parameters" header={group.label}>
|
|
36
|
+
<OpenAPISchemaProperties properties={group.parameters.map(function (parameter) {
|
|
37
|
+
var _a;
|
|
38
|
+
var description = resolveDescription(parameter);
|
|
39
|
+
return {
|
|
40
|
+
propertyName: parameter.name,
|
|
41
|
+
schema: __assign({
|
|
42
|
+
// Description of the parameter is defined at the parameter level
|
|
43
|
+
// we use display it if the schema doesn't override it
|
|
44
|
+
description: description, example: parameter.example,
|
|
45
|
+
// Deprecated can be defined at the parameter level
|
|
46
|
+
deprecated: parameter.deprecated }, ((_a = parameter.schema) !== null && _a !== void 0 ? _a : {})),
|
|
47
|
+
required: parameter.required,
|
|
48
|
+
};
|
|
49
|
+
})} context={context}/>
|
|
50
|
+
</InteractiveSection>);
|
|
51
|
+
})}
|
|
52
|
+
|
|
53
|
+
{operation.requestBody ? (<OpenAPIRequestBody requestBody={operation.requestBody} context={context}/>) : null}
|
|
54
|
+
{operation.responses ? (<OpenAPIResponses responses={operation.responses} context={context}/>) : null}
|
|
55
|
+
</>);
|
|
56
|
+
}
|
|
57
|
+
function groupParameters(parameters) {
|
|
58
|
+
var sorted = ['path', 'query', 'header'];
|
|
59
|
+
var groups = [];
|
|
60
|
+
parameters
|
|
61
|
+
.filter(function (parameter) { return parameter.in; })
|
|
62
|
+
.forEach(function (parameter) {
|
|
63
|
+
var key = parameter.in;
|
|
64
|
+
var label = getParameterGroupName(parameter.in);
|
|
65
|
+
var group = groups.find(function (group) { return group.key === key; });
|
|
66
|
+
if (group) {
|
|
67
|
+
group.parameters.push(parameter);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
groups.push({
|
|
71
|
+
key: key,
|
|
72
|
+
label: label,
|
|
73
|
+
parameters: [parameter],
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
groups.sort(function (a, b) { return sorted.indexOf(a.key) - sorted.indexOf(b.key); });
|
|
78
|
+
return groups;
|
|
79
|
+
}
|
|
80
|
+
function getParameterGroupName(paramIn) {
|
|
81
|
+
switch (paramIn) {
|
|
82
|
+
case 'path':
|
|
83
|
+
return 'Path parameters';
|
|
84
|
+
case 'query':
|
|
85
|
+
return 'Query parameters';
|
|
86
|
+
case 'header':
|
|
87
|
+
return 'Header parameters';
|
|
88
|
+
default:
|
|
89
|
+
return paramIn;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Key, TabsProps } from 'react-aria-components';
|
|
2
|
+
export type Tab = {
|
|
3
|
+
key: Key;
|
|
4
|
+
label: string;
|
|
5
|
+
body: React.ReactNode;
|
|
6
|
+
description?: string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* The OpenAPI Tabs wrapper component.
|
|
10
|
+
*/
|
|
11
|
+
export declare function OpenAPITabs(props: React.PropsWithChildren<TabsProps & {
|
|
12
|
+
items: Tab[];
|
|
13
|
+
stateKey?: string;
|
|
14
|
+
}>): import("react").JSX.Element;
|
|
15
|
+
/**
|
|
16
|
+
* The OpenAPI Tabs list component.
|
|
17
|
+
* This component should be used as a child of the OpenAPITabs component.
|
|
18
|
+
* It renders the list of tabs.
|
|
19
|
+
*/
|
|
20
|
+
export declare function OpenAPITabsList(): import("react").JSX.Element;
|
|
21
|
+
/**
|
|
22
|
+
* The OpenAPI Tabs panels component.
|
|
23
|
+
* This component should be used as a child of the OpenAPITabs component.
|
|
24
|
+
* It renders the content of the selected tab.
|
|
25
|
+
*/
|
|
26
|
+
export declare function OpenAPITabsPanels(): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { createContext, useContext, useEffect, useMemo, useState } from 'react';
|
|
3
|
+
import { Tab, TabList, TabPanel, Tabs } from 'react-aria-components';
|
|
4
|
+
import { Markdown } from './Markdown';
|
|
5
|
+
import { useSyncedTabsGlobalState } from './useSyncedTabsGlobalState';
|
|
6
|
+
import { useIntersectionObserver } from 'usehooks-ts';
|
|
7
|
+
var OpenAPITabsContext = createContext(null);
|
|
8
|
+
function useOpenAPITabsContext() {
|
|
9
|
+
var context = useContext(OpenAPITabsContext);
|
|
10
|
+
if (!context) {
|
|
11
|
+
throw new Error('OpenAPITabsContext is missing');
|
|
12
|
+
}
|
|
13
|
+
return context;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The OpenAPI Tabs wrapper component.
|
|
17
|
+
*/
|
|
18
|
+
export function OpenAPITabs(props) {
|
|
19
|
+
var children = props.children, items = props.items, stateKey = props.stateKey;
|
|
20
|
+
var isVisible = stateKey
|
|
21
|
+
? useIntersectionObserver({
|
|
22
|
+
threshold: 0.1,
|
|
23
|
+
rootMargin: '200px',
|
|
24
|
+
})
|
|
25
|
+
: true;
|
|
26
|
+
var defaultTab = items[0];
|
|
27
|
+
var _a = useSyncedTabsGlobalState(), syncedTabs = _a[0], setSyncedTabs = _a[1];
|
|
28
|
+
var _b = useState(function () {
|
|
29
|
+
var _a, _b, _c;
|
|
30
|
+
if (isVisible && stateKey && syncedTabs && syncedTabs.has(stateKey)) {
|
|
31
|
+
var tabFromState = syncedTabs.get(stateKey);
|
|
32
|
+
return (_a = tabFromState === null || tabFromState === void 0 ? void 0 : tabFromState.key) !== null && _a !== void 0 ? _a : (_b = items[0]) === null || _b === void 0 ? void 0 : _b.key;
|
|
33
|
+
}
|
|
34
|
+
return (_c = items[0]) === null || _c === void 0 ? void 0 : _c.key;
|
|
35
|
+
}), selectedTabKey = _b[0], setSelectedTabKey = _b[1];
|
|
36
|
+
var _c = useState(defaultTab), selectedTab = _c[0], setSelectedTab = _c[1];
|
|
37
|
+
var handleSelectionChange = function (key) {
|
|
38
|
+
setSelectedTabKey(key);
|
|
39
|
+
if (stateKey) {
|
|
40
|
+
var tab_1 = items.find(function (item) { return item.key === key; });
|
|
41
|
+
if (!tab_1) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
setSyncedTabs(function (state) {
|
|
45
|
+
var newState = new Map(state);
|
|
46
|
+
newState.set(stateKey, tab_1);
|
|
47
|
+
return newState;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
useEffect(function () {
|
|
52
|
+
if (isVisible && stateKey && syncedTabs && syncedTabs.has(stateKey)) {
|
|
53
|
+
var tabFromState_1 = syncedTabs.get(stateKey);
|
|
54
|
+
if (!items.some(function (item) { return item.key === (tabFromState_1 === null || tabFromState_1 === void 0 ? void 0 : tabFromState_1.key); })) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
if (tabFromState_1 && (tabFromState_1 === null || tabFromState_1 === void 0 ? void 0 : tabFromState_1.key) !== (selectedTab === null || selectedTab === void 0 ? void 0 : selectedTab.key)) {
|
|
58
|
+
setSelectedTab(tabFromState_1);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}, [isVisible, stateKey, syncedTabs, selectedTabKey]);
|
|
62
|
+
var contextValue = useMemo(function () { return ({ items: items, selectedTab: selectedTab }); }, [items, selectedTab]);
|
|
63
|
+
return (<OpenAPITabsContext.Provider value={contextValue}>
|
|
64
|
+
<Tabs className="openapi-tabs" onSelectionChange={handleSelectionChange} selectedKey={selectedTab === null || selectedTab === void 0 ? void 0 : selectedTab.key}>
|
|
65
|
+
{children}
|
|
66
|
+
</Tabs>
|
|
67
|
+
</OpenAPITabsContext.Provider>);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* The OpenAPI Tabs list component.
|
|
71
|
+
* This component should be used as a child of the OpenAPITabs component.
|
|
72
|
+
* It renders the list of tabs.
|
|
73
|
+
*/
|
|
74
|
+
export function OpenAPITabsList() {
|
|
75
|
+
var items = useOpenAPITabsContext().items;
|
|
76
|
+
return (<TabList className="openapi-tabs-list">
|
|
77
|
+
{items.map(function (tab) { return (<Tab style={function (_a) {
|
|
78
|
+
var isFocusVisible = _a.isFocusVisible;
|
|
79
|
+
return ({
|
|
80
|
+
outline: isFocusVisible
|
|
81
|
+
? '2px solid rgb(var(--primary-color-500)/0.4)'
|
|
82
|
+
: 'none',
|
|
83
|
+
});
|
|
84
|
+
}} className="openapi-tabs-tab" key={"Tab-".concat(tab.key)} id={tab.key}>
|
|
85
|
+
{tab.label}
|
|
86
|
+
</Tab>); })}
|
|
87
|
+
</TabList>);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The OpenAPI Tabs panels component.
|
|
91
|
+
* This component should be used as a child of the OpenAPITabs component.
|
|
92
|
+
* It renders the content of the selected tab.
|
|
93
|
+
*/
|
|
94
|
+
export function OpenAPITabsPanels() {
|
|
95
|
+
var selectedTab = useOpenAPITabsContext().selectedTab;
|
|
96
|
+
if (!selectedTab) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
return (<TabPanel key={"TabPanel-".concat(selectedTab.key)} id={selectedTab.key.toString()} className="openapi-tabs-panel">
|
|
100
|
+
{selectedTab.body}
|
|
101
|
+
{selectedTab.description ? (<Markdown source={selectedTab.description} className="openapi-tabs-footer"/>) : null}
|
|
102
|
+
</TabPanel>);
|
|
103
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
/**
|
|
3
2
|
* Button which launches the Scalar API Client
|
|
4
3
|
*/
|
|
5
|
-
export declare function ScalarApiButton({ method, path }: {
|
|
4
|
+
export declare function ScalarApiButton({ method, path, specUrl, }: {
|
|
6
5
|
method: string;
|
|
7
6
|
path: string;
|
|
8
|
-
|
|
7
|
+
specUrl: string;
|
|
8
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { ApiClientModalProvider, useApiClientModal } from '@scalar/api-client-react';
|
|
3
|
+
import { useEffect, useImperativeHandle, useRef, useState } from 'react';
|
|
4
|
+
import { createPortal } from 'react-dom';
|
|
5
|
+
import { useOpenAPIOperationContext } from './OpenAPIOperationContext';
|
|
6
|
+
import { useEventCallback } from 'usehooks-ts';
|
|
7
|
+
/**
|
|
8
|
+
* Button which launches the Scalar API Client
|
|
9
|
+
*/
|
|
10
|
+
export function ScalarApiButton(_a) {
|
|
11
|
+
var method = _a.method, path = _a.path, specUrl = _a.specUrl;
|
|
12
|
+
var _b = useState(false), isOpen = _b[0], setIsOpen = _b[1];
|
|
13
|
+
var controllerRef = useRef(null);
|
|
14
|
+
return (<div className="scalar scalar-activate">
|
|
15
|
+
<button className="scalar-activate-button button" onClick={function () {
|
|
16
|
+
var _a, _b;
|
|
17
|
+
(_b = (_a = controllerRef.current) === null || _a === void 0 ? void 0 : _a.openClient) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
18
|
+
setIsOpen(true);
|
|
19
|
+
}}>
|
|
20
|
+
<svg xmlns="http://www.w3.org/2000/svg" width="10" height="12" fill="none">
|
|
21
|
+
<path stroke="currentColor" strokeWidth="1.5" d="M1 10.05V1.43c0-.2.2-.31.37-.22l7.26 4.08c.17.1.17.33.01.43l-7.26 4.54a.25.25 0 0 1-.38-.21Z"/>
|
|
22
|
+
</svg>
|
|
23
|
+
Test it
|
|
24
|
+
</button>
|
|
25
|
+
|
|
26
|
+
{isOpen &&
|
|
27
|
+
createPortal(<ScalarModal controllerRef={controllerRef} method={method} path={path} specUrl={specUrl}/>, document.body)}
|
|
28
|
+
</div>);
|
|
29
|
+
}
|
|
30
|
+
function ScalarModal(props) {
|
|
31
|
+
return (<ApiClientModalProvider configuration={{ spec: { url: props.specUrl } }} initialRequest={{ path: props.path, method: props.method }}>
|
|
32
|
+
<ScalarModalController method={props.method} path={props.path} controllerRef={props.controllerRef}/>
|
|
33
|
+
</ApiClientModalProvider>);
|
|
34
|
+
}
|
|
35
|
+
function ScalarModalController(props) {
|
|
36
|
+
var client = useApiClientModal();
|
|
37
|
+
var openClient = client === null || client === void 0 ? void 0 : client.open;
|
|
38
|
+
useImperativeHandle(props.controllerRef, function () { return ({ openClient: openClient ? function () { return openClient(); } : undefined }); }, [openClient]);
|
|
39
|
+
// Open the client when the component is mounted.
|
|
40
|
+
var onOpenClient = useOpenAPIOperationContext().onOpenClient;
|
|
41
|
+
var trackOpening = useEventCallback(function () {
|
|
42
|
+
onOpenClient({ method: props.method, path: props.path });
|
|
43
|
+
});
|
|
44
|
+
useEffect(function () {
|
|
45
|
+
if (openClient) {
|
|
46
|
+
openClient();
|
|
47
|
+
trackOpening();
|
|
48
|
+
}
|
|
49
|
+
}, [openClient]);
|
|
50
|
+
return null;
|
|
51
|
+
}
|
package/dist/code-samples.d.ts
CHANGED
|
@@ -11,4 +11,8 @@ interface CodeSampleGenerator {
|
|
|
11
11
|
generate: (operation: CodeSampleInput) => string;
|
|
12
12
|
}
|
|
13
13
|
export declare const codeSampleGenerators: CodeSampleGenerator[];
|
|
14
|
+
export declare function parseHostAndPath(url: string): {
|
|
15
|
+
host: string | undefined;
|
|
16
|
+
path: string;
|
|
17
|
+
};
|
|
14
18
|
export {};
|
package/dist/code-samples.js
CHANGED
|
@@ -1,69 +1,134 @@
|
|
|
1
|
-
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
import { stringifyOpenAPI } from './stringifyOpenAPI';
|
|
13
|
+
export var codeSampleGenerators = [
|
|
2
14
|
{
|
|
3
|
-
id: '
|
|
4
|
-
label: '
|
|
5
|
-
syntax: '
|
|
6
|
-
generate: (
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
15
|
+
id: 'curl',
|
|
16
|
+
label: 'cURL',
|
|
17
|
+
syntax: 'bash',
|
|
18
|
+
generate: function (_a) {
|
|
19
|
+
var method = _a.method, url = _a.url, headers = _a.headers, body = _a.body;
|
|
20
|
+
var separator = ' \\\n';
|
|
21
|
+
var lines = ['curl -L'];
|
|
22
|
+
if (method.toUpperCase() !== 'GET') {
|
|
23
|
+
lines.push("--request ".concat(method.toUpperCase()));
|
|
24
|
+
}
|
|
25
|
+
lines.push("--url '".concat(url, "'"));
|
|
10
26
|
if (headers) {
|
|
11
|
-
|
|
27
|
+
Object.entries(headers).forEach(function (_a) {
|
|
28
|
+
var key = _a[0], value = _a[1];
|
|
29
|
+
lines.push("--header '".concat(key, ": ").concat(value, "'"));
|
|
30
|
+
});
|
|
12
31
|
}
|
|
13
|
-
if (body) {
|
|
14
|
-
|
|
32
|
+
if (body && Object.keys(body).length > 0) {
|
|
33
|
+
lines.push("--data '".concat(stringifyOpenAPI(body), "'"));
|
|
15
34
|
}
|
|
16
|
-
|
|
17
|
-
code += `const data = await response.json();`;
|
|
18
|
-
return code;
|
|
35
|
+
return lines.map(function (line, index) { return (index > 0 ? indent(line, 2) : line); }).join(separator);
|
|
19
36
|
},
|
|
20
37
|
},
|
|
21
38
|
{
|
|
22
|
-
id: '
|
|
23
|
-
label: '
|
|
24
|
-
syntax: '
|
|
25
|
-
generate: (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
lines.push(`-X ${method.toUpperCase()}`);
|
|
30
|
-
}
|
|
39
|
+
id: 'javascript',
|
|
40
|
+
label: 'JavaScript',
|
|
41
|
+
syntax: 'javascript',
|
|
42
|
+
generate: function (_a) {
|
|
43
|
+
var method = _a.method, url = _a.url, headers = _a.headers, body = _a.body;
|
|
44
|
+
var code = '';
|
|
45
|
+
code += "const response = await fetch('".concat(url, "', {\n method: '").concat(method.toUpperCase(), "',\n");
|
|
31
46
|
if (headers) {
|
|
32
|
-
|
|
33
|
-
lines.push(`-H '${key}: ${value}'`);
|
|
34
|
-
});
|
|
47
|
+
code += indent("headers: ".concat(stringifyOpenAPI(headers, null, 2), ",\n"), 4);
|
|
35
48
|
}
|
|
36
|
-
lines.push(`'${url}'`);
|
|
37
49
|
if (body) {
|
|
38
|
-
|
|
50
|
+
code += indent("body: JSON.stringify(".concat(stringifyOpenAPI(body, null, 2), "),\n"), 4);
|
|
39
51
|
}
|
|
40
|
-
|
|
52
|
+
code += "});\n";
|
|
53
|
+
code += "const data = await response.json();";
|
|
54
|
+
return code;
|
|
41
55
|
},
|
|
42
56
|
},
|
|
43
57
|
{
|
|
44
58
|
id: 'python',
|
|
45
59
|
label: 'Python',
|
|
46
60
|
syntax: 'python',
|
|
47
|
-
generate: (
|
|
48
|
-
|
|
49
|
-
code
|
|
50
|
-
code +=
|
|
61
|
+
generate: function (_a) {
|
|
62
|
+
var method = _a.method, url = _a.url, headers = _a.headers, body = _a.body;
|
|
63
|
+
var code = 'import requests\n\n';
|
|
64
|
+
code += "response = requests.".concat(method.toLowerCase(), "(\n");
|
|
65
|
+
code += indent("\"".concat(url, "\",\n"), 4);
|
|
51
66
|
if (headers) {
|
|
52
|
-
code += indent(
|
|
67
|
+
code += indent("headers=".concat(stringifyOpenAPI(headers), ",\n"), 4);
|
|
53
68
|
}
|
|
54
69
|
if (body) {
|
|
55
|
-
code += indent(
|
|
70
|
+
code += indent("json=".concat(stringifyOpenAPI(body), "\n"), 4);
|
|
56
71
|
}
|
|
57
72
|
code += ')\n';
|
|
58
|
-
code +=
|
|
73
|
+
code += "data = response.json()";
|
|
59
74
|
return code;
|
|
60
75
|
},
|
|
61
76
|
},
|
|
77
|
+
{
|
|
78
|
+
id: 'http',
|
|
79
|
+
label: 'HTTP',
|
|
80
|
+
syntax: 'bash',
|
|
81
|
+
generate: function (_a) {
|
|
82
|
+
var method = _a.method, url = _a.url, _b = _a.headers, headers = _b === void 0 ? {} : _b, body = _a.body;
|
|
83
|
+
var _c = parseHostAndPath(url), host = _c.host, path = _c.path;
|
|
84
|
+
if (body) {
|
|
85
|
+
// if we had a body add a content length header
|
|
86
|
+
var bodyContent = body ? stringifyOpenAPI(body) : '';
|
|
87
|
+
// handle unicode chars with a text encoder
|
|
88
|
+
var encoder = new TextEncoder();
|
|
89
|
+
headers = __assign(__assign({}, headers), { 'Content-Length': encoder.encode(bodyContent).length.toString() });
|
|
90
|
+
}
|
|
91
|
+
if (!headers.hasOwnProperty('Accept')) {
|
|
92
|
+
headers.Accept = '*/*';
|
|
93
|
+
}
|
|
94
|
+
var headerString = headers
|
|
95
|
+
? Object.entries(headers)
|
|
96
|
+
.map(function (_a) {
|
|
97
|
+
var key = _a[0], value = _a[1];
|
|
98
|
+
return key.toLowerCase() !== 'host' ? "".concat(key, ": ").concat(value) : "";
|
|
99
|
+
})
|
|
100
|
+
.join('\n') + '\n'
|
|
101
|
+
: '';
|
|
102
|
+
var bodyString = body ? "\n".concat(stringifyOpenAPI(body, null, 2)) : '';
|
|
103
|
+
var httpRequest = "".concat(method.toUpperCase(), " ").concat(decodeURI(path), " HTTP/1.1\nHost: ").concat(host, "\n").concat(headerString).concat(bodyString);
|
|
104
|
+
return httpRequest;
|
|
105
|
+
},
|
|
106
|
+
},
|
|
62
107
|
];
|
|
63
108
|
function indent(code, spaces) {
|
|
64
|
-
|
|
109
|
+
var indent = ' '.repeat(spaces);
|
|
65
110
|
return code
|
|
66
111
|
.split('\n')
|
|
67
|
-
.map((line)
|
|
112
|
+
.map(function (line) { return (line ? indent + line : ''); })
|
|
68
113
|
.join('\n');
|
|
69
114
|
}
|
|
115
|
+
export function parseHostAndPath(url) {
|
|
116
|
+
try {
|
|
117
|
+
var urlObj = new URL(url);
|
|
118
|
+
var path = urlObj.pathname || '/';
|
|
119
|
+
return { host: urlObj.host, path: path };
|
|
120
|
+
}
|
|
121
|
+
catch (e) {
|
|
122
|
+
// If the URL was invalid do our best to parse the URL.
|
|
123
|
+
// Check for the protocol part and pull it off to grab the host
|
|
124
|
+
var splitted = url.split('//');
|
|
125
|
+
var fullUrl = splitted[1] ? splitted[1] : url;
|
|
126
|
+
// separate paths from the first element (host)
|
|
127
|
+
var parts = fullUrl.split('/');
|
|
128
|
+
// pull off the host (mutates)
|
|
129
|
+
var host = parts.shift();
|
|
130
|
+
// add a leading slash and join the paths again
|
|
131
|
+
var path = '/' + parts.join('/');
|
|
132
|
+
return { host: host, path: path };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { OpenAPIV3 } from 'openapi-
|
|
1
|
+
import type { OpenAPIV3 } from '@gitbook/openapi-parser';
|
|
2
2
|
type JSONValue = string | number | boolean | null | JSONValue[] | {
|
|
3
3
|
[key: string]: JSONValue;
|
|
4
4
|
};
|
|
@@ -7,7 +7,7 @@ type JSONValue = string | number | boolean | null | JSONValue[] | {
|
|
|
7
7
|
*/
|
|
8
8
|
export declare function generateSchemaExample(schema: OpenAPIV3.SchemaObject, options?: {
|
|
9
9
|
onlyRequired?: boolean;
|
|
10
|
-
}
|
|
10
|
+
}): JSONValue | undefined;
|
|
11
11
|
/**
|
|
12
12
|
* Generate an example for a media type.
|
|
13
13
|
*/
|