@gitbook/react-openapi 1.0.1 → 1.0.3

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.
Files changed (53) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/dist/OpenAPICodeSample.jsx +11 -7
  3. package/dist/OpenAPIOperation.jsx +25 -8
  4. package/dist/OpenAPIResponse.jsx +16 -14
  5. package/dist/OpenAPIResponseExample.jsx +157 -47
  6. package/dist/OpenAPISchema.d.ts +2 -2
  7. package/dist/OpenAPISchema.jsx +50 -39
  8. package/dist/OpenAPISchemaName.d.ts +2 -1
  9. package/dist/OpenAPISchemaName.jsx +25 -4
  10. package/dist/OpenAPISpec.jsx +2 -26
  11. package/dist/OpenAPITabs.jsx +6 -2
  12. package/dist/code-samples.js +232 -10
  13. package/dist/contentTypeChecks.d.ts +9 -0
  14. package/dist/contentTypeChecks.js +27 -0
  15. package/dist/generateSchemaExample.d.ts +5 -6
  16. package/dist/generateSchemaExample.js +13 -8
  17. package/dist/json2xml.d.ts +4 -0
  18. package/dist/json2xml.js +7 -0
  19. package/dist/stringifyOpenAPI.d.ts +1 -1
  20. package/dist/stringifyOpenAPI.js +8 -2
  21. package/dist/tsconfig.build.tsbuildinfo +1 -1
  22. package/dist/types.d.ts +18 -2
  23. package/dist/util/server.d.ts +9 -0
  24. package/dist/{OpenAPIServerURL.jsx → util/server.js} +7 -28
  25. package/dist/utils.d.ts +27 -3
  26. package/dist/utils.js +75 -3
  27. package/package.json +3 -2
  28. package/src/OpenAPICodeSample.tsx +11 -7
  29. package/src/OpenAPIOperation.tsx +36 -11
  30. package/src/OpenAPIResponse.tsx +6 -12
  31. package/src/OpenAPIResponseExample.tsx +237 -69
  32. package/src/OpenAPISchema.tsx +81 -58
  33. package/src/OpenAPISchemaName.tsx +37 -5
  34. package/src/OpenAPISpec.tsx +2 -17
  35. package/src/OpenAPITabs.tsx +8 -2
  36. package/src/__snapshots__/json2xml.test.ts.snap +18 -0
  37. package/src/code-samples.test.ts +594 -2
  38. package/src/code-samples.ts +231 -10
  39. package/src/contentTypeChecks.ts +35 -0
  40. package/src/generateSchemaExample.ts +28 -22
  41. package/src/json2xml.test.ts +46 -0
  42. package/src/json2xml.ts +8 -0
  43. package/src/resolveOpenAPIOperation.test.ts +1 -1
  44. package/src/stringifyOpenAPI.ts +13 -2
  45. package/src/types.ts +12 -1
  46. package/src/util/server.test.ts +58 -0
  47. package/src/util/server.ts +48 -0
  48. package/src/utils.ts +86 -6
  49. package/dist/OpenAPIServerURL.d.ts +0 -11
  50. package/dist/OpenAPIServerURLVariable.d.ts +0 -8
  51. package/dist/OpenAPIServerURLVariable.jsx +0 -8
  52. package/src/OpenAPIServerURL.tsx +0 -73
  53. package/src/OpenAPIServerURLVariable.tsx +0 -14
package/dist/types.d.ts CHANGED
@@ -1,9 +1,25 @@
1
1
  import type { OpenAPICustomOperationProperties, OpenAPICustomSpecProperties, OpenAPIV3 } from '@gitbook/openapi-parser';
2
2
  export interface OpenAPIContextProps extends OpenAPIClientContext {
3
- CodeBlock: React.ComponentType<{
3
+ /**
4
+ * Render a code block.
5
+ */
6
+ renderCodeBlock: (props: {
4
7
  code: string;
5
8
  syntax: string;
6
- }>;
9
+ }) => React.ReactNode;
10
+ /**
11
+ * Render the heading of the operation.
12
+ */
13
+ renderHeading: (props: {
14
+ deprecated: boolean;
15
+ title: string;
16
+ }) => React.ReactNode;
17
+ /**
18
+ * Render the document of the operation.
19
+ */
20
+ renderDocument: (props: {
21
+ document: object;
22
+ }) => React.ReactNode;
7
23
  /** Spec url for the Scalar Api Client */
8
24
  specUrl: string;
9
25
  }
@@ -0,0 +1,9 @@
1
+ import { OpenAPIV3 } from '@gitbook/openapi-parser';
2
+ /**
3
+ * Get the default URL for the server.
4
+ */
5
+ export declare function getDefaultServerURL(servers: OpenAPIV3.ServerObject[]): string;
6
+ /**
7
+ * Interpolate the server URL with the default values of the variables.
8
+ */
9
+ export declare function interpolateServerURL(server: OpenAPIV3.ServerObject): string;
@@ -1,40 +1,19 @@
1
- import { OpenAPIServerURLVariable } from './OpenAPIServerURLVariable';
2
1
  /**
3
- * Show the url of the server with variables replaced by their default values.
2
+ * Get the default URL for the server.
4
3
  */
5
- export function OpenAPIServerURL(props) {
6
- var _a;
7
- var servers = props.servers;
4
+ export function getDefaultServerURL(servers) {
8
5
  var server = servers[0];
9
6
  if (!server) {
10
- return null;
7
+ // Return empty string if no server is found to display nothing
8
+ return '';
11
9
  }
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>);
10
+ return interpolateServerURL(server);
28
11
  }
29
12
  /**
30
- * Get the default URL for the server.
13
+ * Interpolate the server URL with the default values of the variables.
31
14
  */
32
- export function getServersURL(servers) {
15
+ export function interpolateServerURL(server) {
33
16
  var _a;
34
- var server = servers[0];
35
- if (!server) {
36
- return '';
37
- }
38
17
  var parts = parseServerURL((_a = server === null || server === void 0 ? void 0 : server.url) !== null && _a !== void 0 ? _a : '');
39
18
  return parts
40
19
  .map(function (part) {
package/dist/utils.d.ts CHANGED
@@ -1,7 +1,31 @@
1
- import type { AnyObject, OpenAPIV3 } from '@gitbook/openapi-parser';
2
- export declare function checkIsReference(input: unknown): input is OpenAPIV3.ReferenceObject;
1
+ import type { AnyObject, OpenAPIV3, OpenAPIV3_1 } from '@gitbook/openapi-parser';
2
+ export declare function checkIsReference(input: unknown): input is OpenAPIV3.ReferenceObject | OpenAPIV3_1.ReferenceObject;
3
3
  export declare function createStateKey(key: string, scope?: string): string;
4
4
  /**
5
5
  * Resolve the description of an object.
6
6
  */
7
- export declare function resolveDescription(object: AnyObject): string | undefined;
7
+ export declare function resolveDescription(object: OpenAPIV3.SchemaObject | AnyObject): string | undefined;
8
+ /**
9
+ * Extract descriptions from an object.
10
+ */
11
+ export declare function extractDescriptions(object: AnyObject): {
12
+ description: any;
13
+ "x-gitbook-description-html": any;
14
+ };
15
+ /**
16
+ * Resolve the first example from an object.
17
+ */
18
+ export declare function resolveFirstExample(object: AnyObject): any;
19
+ /**
20
+ * Resolve the schema of a parameter.
21
+ * Extract the description, example and deprecated from parameter.
22
+ */
23
+ export declare function resolveParameterSchema(parameter: OpenAPIV3.ParameterBaseObject): OpenAPIV3.SchemaObject;
24
+ /**
25
+ * Transform a parameter object to a property object.
26
+ */
27
+ export declare function parameterToProperty(parameter: OpenAPIV3.ParameterObject | OpenAPIV3.ReferenceObject | OpenAPIV3_1.ReferenceObject): {
28
+ propertyName: string | undefined;
29
+ schema: OpenAPIV3.SchemaObject;
30
+ required: boolean | undefined;
31
+ };
package/dist/utils.js CHANGED
@@ -1,3 +1,14 @@
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
+ };
1
12
  export function checkIsReference(input) {
2
13
  return typeof input === 'object' && !!input && '$ref' in input;
3
14
  }
@@ -8,9 +19,70 @@ export function createStateKey(key, scope) {
8
19
  * Resolve the description of an object.
9
20
  */
10
21
  export function resolveDescription(object) {
11
- return 'x-description-html' in object && typeof object['x-description-html'] === 'string'
12
- ? object['x-description-html']
22
+ if ('items' in object && object.items) {
23
+ return resolveDescription(object.items);
24
+ }
25
+ return 'x-gitbook-description-html' in object &&
26
+ typeof object['x-gitbook-description-html'] === 'string'
27
+ ? object['x-gitbook-description-html'].trim()
13
28
  : typeof object.description === 'string'
14
- ? object.description
29
+ ? object.description.trim()
15
30
  : undefined;
16
31
  }
32
+ /**
33
+ * Extract descriptions from an object.
34
+ */
35
+ export function extractDescriptions(object) {
36
+ var _a;
37
+ return _a = {
38
+ description: object.description
39
+ },
40
+ _a['x-gitbook-description-html'] = 'x-gitbook-description-html' in object
41
+ ? object['x-gitbook-description-html']
42
+ : undefined,
43
+ _a;
44
+ }
45
+ /**
46
+ * Resolve the first example from an object.
47
+ */
48
+ export function resolveFirstExample(object) {
49
+ if ('examples' in object && typeof object.examples === 'object' && object.examples) {
50
+ var keys = Object.keys(object.examples);
51
+ var firstKey = keys[0];
52
+ if (firstKey && object.examples[firstKey]) {
53
+ return object.examples[firstKey];
54
+ }
55
+ }
56
+ if ('example' in object && object.example !== undefined) {
57
+ return object.example;
58
+ }
59
+ return undefined;
60
+ }
61
+ /**
62
+ * Resolve the schema of a parameter.
63
+ * Extract the description, example and deprecated from parameter.
64
+ */
65
+ export function resolveParameterSchema(parameter) {
66
+ var schema = checkIsReference(parameter.schema) ? undefined : parameter.schema;
67
+ return __assign(__assign(__assign({}, extractDescriptions(parameter)), { example: resolveFirstExample(parameter),
68
+ // Deprecated can be defined at the parameter level
69
+ deprecated: parameter.deprecated }), schema);
70
+ }
71
+ /**
72
+ * Transform a parameter object to a property object.
73
+ */
74
+ export function parameterToProperty(parameter) {
75
+ var _a;
76
+ if (checkIsReference(parameter)) {
77
+ return {
78
+ propertyName: (_a = parameter.$ref) !== null && _a !== void 0 ? _a : 'Unknown ref',
79
+ schema: {},
80
+ required: undefined,
81
+ };
82
+ }
83
+ return {
84
+ propertyName: parameter.name,
85
+ schema: resolveParameterSchema(parameter),
86
+ required: parameter.required,
87
+ };
88
+ }
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "default": "./dist/index.js"
9
9
  }
10
10
  },
11
- "version": "1.0.1",
11
+ "version": "1.0.3",
12
12
  "sideEffects": false,
13
13
  "dependencies": {
14
14
  "@gitbook/openapi-parser": "workspace:*",
@@ -16,6 +16,7 @@
16
16
  "@scalar/oas-utils": "^0.2.101",
17
17
  "clsx": "^2.1.1",
18
18
  "flatted": "^3.2.9",
19
+ "json-xml-parse": "^1.3.0",
19
20
  "react-aria-components": "^1.6.0",
20
21
  "react-aria": "^3.37.0",
21
22
  "usehooks-ts": "^3.1.0",
@@ -29,7 +30,7 @@
29
30
  "react": "*"
30
31
  },
31
32
  "scripts": {
32
- "build": "tsc --project tsconfig.build.json",
33
+ "build": "rm -rf ./dist && tsc --project tsconfig.build.json",
33
34
  "typecheck": "tsc --noEmit",
34
35
  "unit": "bun test",
35
36
  "dev": "bun run build -- --watch",
@@ -1,12 +1,12 @@
1
1
  import { CodeSampleInput, codeSampleGenerators } from './code-samples';
2
2
  import { generateMediaTypeExample, generateSchemaExample } from './generateSchemaExample';
3
3
  import { InteractiveSection } from './InteractiveSection';
4
- import { getServersURL } from './OpenAPIServerURL';
5
4
  import type { OpenAPIContextProps, OpenAPIOperationData } from './types';
6
5
  import { createStateKey } from './utils';
7
6
  import { stringifyOpenAPI } from './stringifyOpenAPI';
8
7
  import { OpenAPITabs, OpenAPITabsList, OpenAPITabsPanels } from './OpenAPITabs';
9
8
  import { checkIsReference } from './utils';
9
+ import { getDefaultServerURL } from './util/server';
10
10
 
11
11
  /**
12
12
  * Display code samples to execute the operation.
@@ -53,13 +53,11 @@ export function OpenAPICodeSample(props: {
53
53
 
54
54
  const input: CodeSampleInput = {
55
55
  url:
56
- getServersURL(data.servers) +
56
+ getDefaultServerURL(data.servers) +
57
57
  data.path +
58
58
  (searchParams.size ? `?${searchParams.toString()}` : ''),
59
59
  method: data.method,
60
- body: requestBodyContent
61
- ? generateMediaTypeExample(requestBodyContent[1], { onlyRequired: true })
62
- : undefined,
60
+ body: requestBodyContent ? generateMediaTypeExample(requestBodyContent[1]) : undefined,
63
61
  headers: {
64
62
  ...getSecurityHeaders(data.securities),
65
63
  ...headersObject,
@@ -74,7 +72,10 @@ export function OpenAPICodeSample(props: {
74
72
  const autoCodeSamples = codeSampleGenerators.map((generator) => ({
75
73
  key: `default-${generator.id}`,
76
74
  label: generator.label,
77
- body: <context.CodeBlock code={generator.generate(input)} syntax={generator.syntax} />,
75
+ body: context.renderCodeBlock({
76
+ code: generator.generate(input),
77
+ syntax: generator.syntax,
78
+ }),
78
79
  }));
79
80
 
80
81
  // Use custom samples if defined
@@ -97,7 +98,10 @@ export function OpenAPICodeSample(props: {
97
98
  .map((sample) => ({
98
99
  key: `redocly-${sample.lang}`,
99
100
  label: sample.label,
100
- body: <context.CodeBlock code={sample.source} syntax={sample.lang} />,
101
+ body: context.renderCodeBlock({
102
+ code: sample.source,
103
+ syntax: sample.lang,
104
+ }),
101
105
  }));
102
106
  }
103
107
  });
@@ -7,6 +7,7 @@ import { OpenAPISpec } from './OpenAPISpec';
7
7
  import type { OpenAPIClientContext, OpenAPIContextProps, OpenAPIOperationData } from './types';
8
8
  import { OpenAPIPath } from './OpenAPIPath';
9
9
  import { resolveDescription } from './utils';
10
+ import { OpenAPICustomOperationProperties, OpenAPIV3 } from '@gitbook/openapi-parser';
10
11
 
11
12
  /**
12
13
  * Display an interactive OpenAPI operation.
@@ -25,14 +26,15 @@ export function OpenAPIOperation(props: {
25
26
  blockKey: context.blockKey,
26
27
  };
27
28
 
28
- const description = resolveDescription(operation)?.trim();
29
-
30
29
  return (
31
30
  <div className={clsx('openapi-operation', className)}>
32
- <div className="openapi-summary" id={context.id}>
33
- <h2 className="openapi-summary-title" data-deprecated={operation.deprecated}>
34
- {operation.summary}
35
- </h2>
31
+ <div className="openapi-summary" id={operation.summary ? undefined : context.id}>
32
+ {operation.summary
33
+ ? context.renderHeading({
34
+ deprecated: operation.deprecated ?? false,
35
+ title: operation.summary,
36
+ })
37
+ : null}
36
38
  {operation.deprecated && <div className="openapi-deprecated">Deprecated</div>}
37
39
  </div>
38
40
  <div className="openapi-columns">
@@ -46,11 +48,7 @@ export function OpenAPIOperation(props: {
46
48
  {`.`}
47
49
  </div>
48
50
  ) : null}
49
- {description ? (
50
- <div className="openapi-intro">
51
- <Markdown className="openapi-description" source={description} />
52
- </div>
53
- ) : null}
51
+ <OpenAPIOperationDescription operation={operation} context={context} />
54
52
  <OpenAPIPath data={data} context={context} />
55
53
  <OpenAPISpec data={data} context={clientContext} />
56
54
  </div>
@@ -64,3 +62,30 @@ export function OpenAPIOperation(props: {
64
62
  </div>
65
63
  );
66
64
  }
65
+
66
+ function OpenAPIOperationDescription(props: {
67
+ operation: OpenAPIV3.OperationObject<OpenAPICustomOperationProperties>;
68
+ context: OpenAPIContextProps;
69
+ }) {
70
+ const { operation } = props;
71
+ if (operation['x-gitbook-description-document']) {
72
+ return (
73
+ <div className="openapi-intro">
74
+ {props.context.renderDocument({
75
+ document: operation['x-gitbook-description-document'],
76
+ })}
77
+ </div>
78
+ );
79
+ }
80
+
81
+ const description = resolveDescription(operation);
82
+ if (!description) {
83
+ return null;
84
+ }
85
+
86
+ return (
87
+ <div className="openapi-intro">
88
+ <Markdown className="openapi-description" source={description} />
89
+ </div>
90
+ );
91
+ }
@@ -1,6 +1,6 @@
1
1
  import type { OpenAPIV3 } from '@gitbook/openapi-parser';
2
2
  import { OpenAPISchemaProperties } from './OpenAPISchema';
3
- import { resolveDescription } from './utils';
3
+ import { parameterToProperty, resolveDescription } from './utils';
4
4
  import type { OpenAPIClientContext } from './types';
5
5
  import { OpenAPIDisclosure } from './OpenAPIDisclosure';
6
6
 
@@ -27,13 +27,11 @@ export function OpenAPIResponse(props: {
27
27
  return (
28
28
  <div className="openapi-response-body">
29
29
  {headers.length > 0 ? (
30
- <OpenAPIDisclosure context={context} label={'Headers'}>
30
+ <OpenAPIDisclosure context={context} label="Headers">
31
31
  <OpenAPISchemaProperties
32
- properties={headers.map(([name, header]) => ({
33
- propertyName: name,
34
- schema: header.schema ?? {},
35
- required: header.required,
36
- }))}
32
+ properties={headers.map(([name, header]) => {
33
+ return parameterToProperty({ name, ...header });
34
+ })}
37
35
  context={context}
38
36
  />
39
37
  </OpenAPIDisclosure>
@@ -41,11 +39,7 @@ export function OpenAPIResponse(props: {
41
39
  <div className="openapi-responsebody">
42
40
  <OpenAPISchemaProperties
43
41
  id={`response-${context.blockKey}`}
44
- properties={[
45
- {
46
- schema: mediaType.schema ?? {},
47
- },
48
- ]}
42
+ properties={mediaType.schema ? [{ schema: mediaType.schema }] : []}
49
43
  context={context}
50
44
  />
51
45
  </div>