docusaurus-theme-openapi-docs 4.5.0 → 4.6.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.
Files changed (119) hide show
  1. package/lib/markdown/schema.js +9 -1
  2. package/lib/theme/ApiExplorer/Accept/slice.d.ts +5 -2
  3. package/lib/theme/ApiExplorer/Authorization/index.js +50 -9
  4. package/lib/theme/ApiExplorer/Authorization/slice.d.ts +145 -3
  5. package/lib/theme/ApiExplorer/Authorization/slice.js +3 -1
  6. package/lib/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.d.ts +7 -0
  7. package/lib/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.js +126 -0
  8. package/lib/theme/ApiExplorer/Body/FormBodyItem/index.d.ts +9 -0
  9. package/lib/theme/ApiExplorer/Body/FormBodyItem/index.js +110 -0
  10. package/lib/theme/ApiExplorer/Body/index.js +94 -100
  11. package/lib/theme/ApiExplorer/Body/slice.d.ts +1056 -11
  12. package/lib/theme/ApiExplorer/Body/slice.js +22 -2
  13. package/lib/theme/ApiExplorer/CodeSnippets/index.d.ts +2 -1
  14. package/lib/theme/ApiExplorer/CodeSnippets/index.js +37 -26
  15. package/lib/theme/ApiExplorer/CodeTabs/_CodeTabs.scss +5 -1
  16. package/lib/theme/ApiExplorer/CodeTabs/index.d.ts +3 -3
  17. package/lib/theme/ApiExplorer/CodeTabs/index.js +2 -2
  18. package/lib/theme/ApiExplorer/ContentType/slice.d.ts +5 -2
  19. package/lib/theme/ApiExplorer/FormFileUpload/index.js +6 -1
  20. package/lib/theme/ApiExplorer/FormItem/index.js +6 -1
  21. package/lib/theme/ApiExplorer/FormTextInput/index.d.ts +2 -0
  22. package/lib/theme/ApiExplorer/FormTextInput/index.js +8 -1
  23. package/lib/theme/ApiExplorer/LiveEditor/index.js +11 -4
  24. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.js +15 -5
  25. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.js +11 -3
  26. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.js +12 -4
  27. package/lib/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.js +11 -2
  28. package/lib/theme/ApiExplorer/ParamOptions/index.js +11 -1
  29. package/lib/theme/ApiExplorer/ParamOptions/slice.d.ts +0 -4
  30. package/lib/theme/ApiExplorer/ParamOptions/slice.js +4 -4
  31. package/lib/theme/ApiExplorer/Request/index.js +110 -17
  32. package/lib/theme/ApiExplorer/Request/makeRequest.d.ts +7 -1
  33. package/lib/theme/ApiExplorer/Request/makeRequest.js +94 -24
  34. package/lib/theme/ApiExplorer/Response/index.js +34 -14
  35. package/lib/theme/ApiExplorer/Response/slice.d.ts +31 -7
  36. package/lib/theme/ApiExplorer/SecuritySchemes/index.js +208 -69
  37. package/lib/theme/ApiExplorer/Server/index.js +16 -2
  38. package/lib/theme/ApiExplorer/Server/slice.d.ts +49 -3
  39. package/lib/theme/ApiExplorer/buildPostmanRequest.js +46 -57
  40. package/lib/theme/ApiExplorer/index.js +11 -1
  41. package/lib/theme/ApiExplorer/persistenceMiddleware.d.ts +19 -0
  42. package/lib/theme/ApiExplorer/{persistanceMiddleware.js → persistenceMiddleware.js} +16 -9
  43. package/lib/theme/ApiExplorer/storage-utils.d.ts +2 -2
  44. package/lib/theme/ApiExplorer/storage-utils.js +3 -3
  45. package/lib/theme/ApiItem/Layout/index.d.ts +1 -1
  46. package/lib/theme/ApiItem/hooks.d.ts +9 -9
  47. package/lib/theme/ApiItem/index.js +12 -8
  48. package/lib/theme/ApiItem/store.d.ts +55 -43
  49. package/lib/theme/ApiTabs/index.js +6 -1
  50. package/lib/theme/Example/_Example.scss +11 -0
  51. package/lib/theme/Example/index.d.ts +24 -0
  52. package/lib/theme/Example/index.js +170 -0
  53. package/lib/theme/ParamsDetails/index.js +9 -1
  54. package/lib/theme/ParamsItem/index.d.ts +1 -1
  55. package/lib/theme/ParamsItem/index.js +43 -74
  56. package/lib/theme/RequestSchema/index.js +18 -4
  57. package/lib/theme/ResponseExamples/index.js +23 -3
  58. package/lib/theme/ResponseSchema/index.js +97 -82
  59. package/lib/theme/Schema/index.js +106 -23
  60. package/lib/theme/SchemaItem/index.js +64 -36
  61. package/lib/theme/SchemaTabs/index.js +4 -1
  62. package/lib/theme/StatusCodes/index.js +11 -2
  63. package/lib/theme/styles.scss +5 -0
  64. package/lib/theme/translationIds.d.ts +90 -0
  65. package/lib/theme/translationIds.js +114 -0
  66. package/lib/types.d.ts +9 -1
  67. package/package.json +28 -28
  68. package/src/markdown/schema.ts +11 -1
  69. package/src/theme/ApiExplorer/Authorization/index.tsx +51 -10
  70. package/src/theme/ApiExplorer/Authorization/slice.ts +1 -1
  71. package/src/theme/ApiExplorer/Body/FileArrayFormBodyItem/index.tsx +77 -0
  72. package/src/theme/ApiExplorer/Body/FormBodyItem/index.tsx +120 -0
  73. package/src/theme/ApiExplorer/Body/index.tsx +87 -107
  74. package/src/theme/ApiExplorer/Body/json2xml.d.ts +8 -0
  75. package/src/theme/ApiExplorer/Body/slice.ts +40 -1
  76. package/src/theme/ApiExplorer/CodeSnippets/index.tsx +43 -29
  77. package/src/theme/ApiExplorer/CodeTabs/_CodeTabs.scss +5 -1
  78. package/src/theme/ApiExplorer/CodeTabs/index.tsx +6 -5
  79. package/src/theme/ApiExplorer/ContentType/index.tsx +1 -1
  80. package/src/theme/ApiExplorer/FormFileUpload/index.tsx +6 -1
  81. package/src/theme/ApiExplorer/FormItem/index.tsx +8 -1
  82. package/src/theme/ApiExplorer/FormTextInput/index.tsx +10 -1
  83. package/src/theme/ApiExplorer/LiveEditor/index.tsx +11 -4
  84. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem.tsx +16 -6
  85. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem.tsx +12 -4
  86. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamMultiSelectFormItem.tsx +12 -4
  87. package/src/theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem.tsx +12 -3
  88. package/src/theme/ApiExplorer/ParamOptions/index.tsx +10 -2
  89. package/src/theme/ApiExplorer/ParamOptions/slice.ts +1 -1
  90. package/src/theme/ApiExplorer/Request/index.tsx +108 -17
  91. package/src/theme/ApiExplorer/Request/makeRequest.ts +106 -25
  92. package/src/theme/ApiExplorer/Response/index.tsx +30 -8
  93. package/src/theme/ApiExplorer/SecuritySchemes/index.tsx +157 -69
  94. package/src/theme/ApiExplorer/Server/index.tsx +12 -4
  95. package/src/theme/ApiExplorer/buildPostmanRequest.ts +47 -63
  96. package/src/theme/ApiExplorer/index.tsx +10 -1
  97. package/src/theme/ApiExplorer/{persistanceMiddleware.ts → persistenceMiddleware.ts} +23 -13
  98. package/src/theme/ApiExplorer/storage-utils.ts +4 -4
  99. package/src/theme/ApiItem/Layout/index.tsx +1 -1
  100. package/src/theme/ApiItem/index.tsx +12 -7
  101. package/src/theme/ApiTabs/index.tsx +6 -1
  102. package/src/theme/Example/_Example.scss +11 -0
  103. package/src/theme/Example/index.tsx +168 -0
  104. package/src/theme/Markdown/index.d.ts +8 -0
  105. package/src/theme/ParamsDetails/index.tsx +10 -1
  106. package/src/theme/ParamsItem/index.tsx +38 -54
  107. package/src/theme/RequestSchema/index.tsx +19 -4
  108. package/src/theme/ResponseExamples/index.tsx +23 -3
  109. package/src/theme/ResponseSchema/index.tsx +73 -61
  110. package/src/theme/Schema/index.tsx +128 -33
  111. package/src/theme/SchemaItem/index.tsx +51 -33
  112. package/src/theme/SchemaTabs/index.tsx +4 -1
  113. package/src/theme/StatusCodes/index.tsx +13 -2
  114. package/src/theme/styles.scss +5 -0
  115. package/src/theme/translationIds.ts +111 -0
  116. package/src/theme-openapi.d.ts +7 -275
  117. package/src/types.ts +9 -1
  118. package/tsconfig.tsbuildinfo +1 -1
  119. package/lib/theme/ApiExplorer/persistanceMiddleware.d.ts +0 -3
@@ -7,6 +7,9 @@
7
7
 
8
8
  import React from "react";
9
9
 
10
+ import { translate } from "@docusaurus/Translate";
11
+ import { OPENAPI_SCHEMA_ITEM } from "@theme/translationIds";
12
+
10
13
  import clsx from "clsx";
11
14
 
12
15
  export interface Props {
@@ -24,7 +27,11 @@ function FormItem({ label, type, required, children, className }: Props) {
24
27
  <label className="openapi-explorer__form-item-label">{label}</label>
25
28
  )}
26
29
  {type && <span style={{ opacity: 0.6 }}> — {type}</span>}
27
- {required && <span className="openapi-schema__required">required</span>}
30
+ {required && (
31
+ <span className="openapi-schema__required">
32
+ {translate({ id: OPENAPI_SCHEMA_ITEM.REQUIRED, message: "required" })}
33
+ </span>
34
+ )}
28
35
  <div>{children}</div>
29
36
  </div>
30
37
  );
@@ -8,7 +8,9 @@
8
8
  // @ts-nocheck
9
9
  import React from "react";
10
10
 
11
+ import { translate } from "@docusaurus/Translate";
11
12
  import { ErrorMessage } from "@hookform/error-message";
13
+ import { OPENAPI_FORM } from "@theme/translationIds";
12
14
  import clsx from "clsx";
13
15
  import { useFormContext } from "react-hook-form";
14
16
 
@@ -17,6 +19,8 @@ export interface Props {
17
19
  placeholder?: string;
18
20
  password?: boolean;
19
21
  onChange?: React.ChangeEventHandler<HTMLInputElement>;
22
+ paramName?: string;
23
+ isRequired?: boolean;
20
24
  }
21
25
 
22
26
  function FormTextInput({
@@ -41,7 +45,12 @@ function FormTextInput({
41
45
  {paramName ? (
42
46
  <input
43
47
  {...register(paramName, {
44
- required: isRequired ? "This field is required" : false,
48
+ required: isRequired
49
+ ? translate({
50
+ id: OPENAPI_FORM.FIELD_REQUIRED,
51
+ message: "This field is required",
52
+ })
53
+ : false,
45
54
  })}
46
55
  className={clsx("openapi-explorer__form-item-input", {
47
56
  error: showErrorMessage,
@@ -8,9 +8,10 @@
8
8
  import React, { type JSX, useEffect, useState } from "react";
9
9
 
10
10
  import { usePrismTheme } from "@docusaurus/theme-common";
11
+ import { translate } from "@docusaurus/Translate";
11
12
  import useIsBrowser from "@docusaurus/useIsBrowser";
12
13
  import { ErrorMessage } from "@hookform/error-message";
13
- import { setStringRawBody } from "@theme/ApiExplorer/Body/slice";
14
+ import { OPENAPI_FORM } from "@theme/translationIds";
14
15
  import clsx from "clsx";
15
16
  import { Controller, useFormContext } from "react-hook-form";
16
17
  import { LiveProvider, LiveEditor, withLive } from "react-live";
@@ -54,8 +55,8 @@ function App({
54
55
  const [code, setCode] = React.useState(children.replace(/\n$/, ""));
55
56
 
56
57
  useEffect(() => {
57
- action(setStringRawBody(code));
58
- }, [action, code]);
58
+ action(code);
59
+ }, [code]);
59
60
 
60
61
  const {
61
62
  control,
@@ -85,7 +86,13 @@ function App({
85
86
  <Controller
86
87
  control={control}
87
88
  rules={{
88
- required: isRequired && !code ? "This field is required" : false,
89
+ required:
90
+ isRequired && !code
91
+ ? translate({
92
+ id: OPENAPI_FORM.FIELD_REQUIRED,
93
+ message: "This field is required",
94
+ })
95
+ : false,
89
96
  }}
90
97
  name="requestBody"
91
98
  render={({ field: { onChange, name } }) => (
@@ -7,12 +7,14 @@
7
7
 
8
8
  import React, { useEffect, useState } from "react";
9
9
 
10
+ import { translate } from "@docusaurus/Translate";
10
11
  import { ErrorMessage } from "@hookform/error-message";
11
12
  import { nanoid } from "@reduxjs/toolkit";
12
13
  import FormSelect from "@theme/ApiExplorer/FormSelect";
13
14
  import FormTextInput from "@theme/ApiExplorer/FormTextInput";
14
15
  import { Param, setParam } from "@theme/ApiExplorer/ParamOptions/slice";
15
16
  import { useTypedDispatch } from "@theme/ApiItem/hooks";
17
+ import { OPENAPI_FORM } from "@theme/translationIds";
16
18
  import { Controller, useFormContext } from "react-hook-form";
17
19
 
18
20
  export interface ParamProps {
@@ -30,7 +32,7 @@ function ArrayItem({
30
32
  return (
31
33
  <FormSelect
32
34
  options={["---", "true", "false"]}
33
- onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
35
+ onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
34
36
  const val = e.target.value;
35
37
  onChange(val === "---" ? undefined : val);
36
38
  }}
@@ -87,15 +89,16 @@ export default function ParamArrayFormItem({ param }: ParamProps) {
87
89
  }, [items]);
88
90
 
89
91
  useEffect(() => {
90
- if (param.schema?.example?.length > 0) {
91
- const examplesWithIds = param.schema.example.map((item: any) => ({
92
+ const example = param.schema?.example;
93
+ if (Array.isArray(example) && example.length > 0) {
94
+ const examplesWithIds = example.map((item: any) => ({
92
95
  id: nanoid(),
93
96
  value: item.toString(),
94
97
  }));
95
98
 
96
99
  setItems(examplesWithIds);
97
100
  }
98
- }, [param.schema.example, param.schema.length]);
101
+ }, [param.schema?.example]);
99
102
 
100
103
  function handleDeleteItem(itemToDelete: { id: string }) {
101
104
  return () => {
@@ -121,9 +124,16 @@ export default function ParamArrayFormItem({ param }: ParamProps) {
121
124
  <>
122
125
  <Controller
123
126
  control={control}
124
- rules={{ required: param.required ? "This field is required" : false }}
127
+ rules={{
128
+ required: param.required
129
+ ? translate({
130
+ id: OPENAPI_FORM.FIELD_REQUIRED,
131
+ message: "This field is required",
132
+ })
133
+ : false,
134
+ }}
125
135
  name="paramArray"
126
- render={({ field: { onChange, name } }) => (
136
+ render={({ field: { onChange } }) => (
127
137
  <>
128
138
  {items.map((item) => (
129
139
  <div key={item.id} style={{ display: "flex" }}>
@@ -7,10 +7,12 @@
7
7
 
8
8
  import React from "react";
9
9
 
10
+ import { translate } from "@docusaurus/Translate";
10
11
  import { ErrorMessage } from "@hookform/error-message";
11
12
  import FormSelect from "@theme/ApiExplorer/FormSelect";
12
13
  import { Param, setParam } from "@theme/ApiExplorer/ParamOptions/slice";
13
14
  import { useTypedDispatch } from "@theme/ApiItem/hooks";
15
+ import { OPENAPI_FORM } from "@theme/translationIds";
14
16
  import { Controller, useFormContext } from "react-hook-form";
15
17
 
16
18
  export interface ParamProps {
@@ -31,13 +33,19 @@ export default function ParamBooleanFormItem({ param }: ParamProps) {
31
33
  <>
32
34
  <Controller
33
35
  control={control}
34
- rules={{ required: param.required ? "This field is required" : false }}
36
+ rules={{
37
+ required: param.required
38
+ ? translate({
39
+ id: OPENAPI_FORM.FIELD_REQUIRED,
40
+ message: "This field is required",
41
+ })
42
+ : false,
43
+ }}
35
44
  name="paramBoolean"
36
- render={({ field: { onChange, name } }) => (
45
+ render={({ field: { onChange } }) => (
37
46
  <FormSelect
38
- name={name}
39
47
  options={["---", "true", "false"]}
40
- onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
48
+ onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
41
49
  const val = e.target.value;
42
50
  dispatch(
43
51
  setParam({
@@ -7,10 +7,12 @@
7
7
 
8
8
  import React from "react";
9
9
 
10
+ import { translate } from "@docusaurus/Translate";
10
11
  import { ErrorMessage } from "@hookform/error-message";
11
12
  import FormMultiSelect from "@theme/ApiExplorer/FormMultiSelect";
12
13
  import { Param, setParam } from "@theme/ApiExplorer/ParamOptions/slice";
13
14
  import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
15
+ import { OPENAPI_FORM } from "@theme/translationIds";
14
16
  import { Controller, useFormContext } from "react-hook-form";
15
17
 
16
18
  export interface ParamProps {
@@ -61,14 +63,20 @@ export default function ParamMultiSelectFormItem({ param }: ParamProps) {
61
63
  <>
62
64
  <Controller
63
65
  control={control}
64
- rules={{ required: param.required ? "This field is required" : false }}
66
+ rules={{
67
+ required: param.required
68
+ ? translate({
69
+ id: OPENAPI_FORM.FIELD_REQUIRED,
70
+ message: "This field is required",
71
+ })
72
+ : false,
73
+ }}
65
74
  name="paramMultiSelect"
66
- render={({ field: { onChange, name } }) => (
75
+ render={({ field: { onChange } }) => (
67
76
  <FormMultiSelect
68
77
  options={options as string[]}
69
- name={name}
70
78
  onChange={(e: any) => handleChange(e, onChange)}
71
- showErrors={showErrorMessage}
79
+ showErrors={!!showErrorMessage}
72
80
  />
73
81
  )}
74
82
  />
@@ -7,10 +7,12 @@
7
7
 
8
8
  import React from "react";
9
9
 
10
+ import { translate } from "@docusaurus/Translate";
10
11
  import { ErrorMessage } from "@hookform/error-message";
11
12
  import FormSelect from "@theme/ApiExplorer/FormSelect";
12
13
  import { Param, setParam } from "@theme/ApiExplorer/ParamOptions/slice";
13
14
  import { useTypedDispatch } from "@theme/ApiItem/hooks";
15
+ import { OPENAPI_FORM } from "@theme/translationIds";
14
16
  import { Controller, useFormContext } from "react-hook-form";
15
17
 
16
18
  export interface ParamProps {
@@ -33,12 +35,19 @@ export default function ParamSelectFormItem({ param }: ParamProps) {
33
35
  <>
34
36
  <Controller
35
37
  control={control}
36
- rules={{ required: param.required ? "This field is required" : false }}
38
+ rules={{
39
+ required: param.required
40
+ ? translate({
41
+ id: OPENAPI_FORM.FIELD_REQUIRED,
42
+ message: "This field is required",
43
+ })
44
+ : false,
45
+ }}
37
46
  name="paramSelect"
38
- render={({ field: { onChange, name } }) => (
47
+ render={({ field: { onChange } }) => (
39
48
  <FormSelect
40
49
  options={["---", ...(options as string[])]}
41
- onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
50
+ onChange={(e: React.ChangeEvent<HTMLSelectElement>) => {
42
51
  const val = e.target.value;
43
52
  dispatch(
44
53
  setParam({
@@ -7,6 +7,7 @@
7
7
 
8
8
  import React, { useState } from "react";
9
9
 
10
+ import { translate } from "@docusaurus/Translate";
10
11
  import FormItem from "@theme/ApiExplorer/FormItem";
11
12
  import ParamArrayFormItem from "@theme/ApiExplorer/ParamOptions/ParamFormItems/ParamArrayFormItem";
12
13
  import ParamBooleanFormItem from "@theme/ApiExplorer/ParamOptions/ParamFormItems/ParamBooleanFormItem";
@@ -14,6 +15,7 @@ import ParamMultiSelectFormItem from "@theme/ApiExplorer/ParamOptions/ParamFormI
14
15
  import ParamSelectFormItem from "@theme/ApiExplorer/ParamOptions/ParamFormItems/ParamSelectFormItem";
15
16
  import ParamTextFormItem from "@theme/ApiExplorer/ParamOptions/ParamFormItems/ParamTextFormItem";
16
17
  import { useTypedSelector } from "@theme/ApiItem/hooks";
18
+ import { OPENAPI_PARAM_OPTIONS } from "@theme/translationIds";
17
19
 
18
20
  import { Param } from "./slice";
19
21
 
@@ -119,8 +121,14 @@ function ParamOptions() {
119
121
  </span>
120
122
  </span>
121
123
  {showOptional
122
- ? "Hide optional parameters"
123
- : "Show optional parameters"}
124
+ ? translate({
125
+ id: OPENAPI_PARAM_OPTIONS.HIDE_OPTIONAL,
126
+ message: "Hide optional parameters",
127
+ })
128
+ : translate({
129
+ id: OPENAPI_PARAM_OPTIONS.SHOW_OPTIONAL,
130
+ message: "Show optional parameters",
131
+ })}
124
132
  </button>
125
133
 
126
134
  <div
@@ -19,7 +19,7 @@ export interface State {
19
19
 
20
20
  const initialState: State = {} as any;
21
21
 
22
- export const slice = createSlice({
22
+ const slice = createSlice({
23
23
  name: "params",
24
24
  initialState,
25
25
  reducers: {
@@ -9,6 +9,8 @@
9
9
  import React, { useState } from "react";
10
10
 
11
11
  import { useDoc } from "@docusaurus/plugin-content-docs/client";
12
+ import { translate } from "@docusaurus/Translate";
13
+ import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
12
14
  import Accept from "@theme/ApiExplorer/Accept";
13
15
  import Authorization from "@theme/ApiExplorer/Authorization";
14
16
  import Body from "@theme/ApiExplorer/Body";
@@ -24,17 +26,25 @@ import {
24
26
  } from "@theme/ApiExplorer/Response/slice";
25
27
  import Server from "@theme/ApiExplorer/Server";
26
28
  import { useTypedDispatch, useTypedSelector } from "@theme/ApiItem/hooks";
29
+ import { OPENAPI_REQUEST } from "@theme/translationIds";
27
30
  import { ParameterObject } from "docusaurus-plugin-openapi-docs/src/openapi/types";
28
31
  import { ApiItem } from "docusaurus-plugin-openapi-docs/src/types";
32
+ import type { ThemeConfig } from "docusaurus-theme-openapi-docs/src/types";
29
33
  import * as sdk from "postman-collection";
30
34
  import { FormProvider, useForm } from "react-hook-form";
31
35
 
32
- import makeRequest from "./makeRequest";
36
+ import makeRequest, { RequestError, RequestErrorType } from "./makeRequest";
33
37
 
34
38
  function Request({ item }: { item: ApiItem }) {
35
39
  const postman = new sdk.Request(item.postman);
36
40
  const metadata = useDoc();
37
- const { proxy, hide_send_button: hideSendButton } = metadata.frontMatter;
41
+ const { proxy: frontMatterProxy, hide_send_button: hideSendButton } =
42
+ metadata.frontMatter;
43
+ const { siteConfig } = useDocusaurusContext();
44
+ const themeConfig = siteConfig.themeConfig as ThemeConfig;
45
+ const requestTimeout = themeConfig.api?.requestTimeout;
46
+ // Frontmatter proxy (per-spec) takes precedence over theme config proxy (site-wide)
47
+ const proxy = frontMatterProxy ?? themeConfig.api?.proxy;
38
48
 
39
49
  const pathParams = useTypedSelector((state: any) => state.params.path);
40
50
  const queryParams = useTypedSelector((state: any) => state.params.query);
@@ -116,11 +126,53 @@ function Request({ item }: { item: ApiItem }) {
116
126
  res.headers && dispatch(setHeaders(Object.fromEntries(res.headers)));
117
127
  };
118
128
 
129
+ const getErrorMessage = (errorType: RequestErrorType): string => {
130
+ switch (errorType) {
131
+ case "timeout":
132
+ return translate({
133
+ id: OPENAPI_REQUEST.ERROR_TIMEOUT,
134
+ message:
135
+ "The request timed out waiting for the server to respond. Please try again. If the issue persists, try using a different client (e.g., curl) with a longer timeout.",
136
+ });
137
+ case "network":
138
+ return translate({
139
+ id: OPENAPI_REQUEST.ERROR_NETWORK,
140
+ message:
141
+ "Unable to reach the server. Please check your network connection and verify the server URL is correct. If the server is running, this may be a CORS issue.",
142
+ });
143
+ case "cors":
144
+ return translate({
145
+ id: OPENAPI_REQUEST.ERROR_CORS,
146
+ message:
147
+ "The request was blocked, possibly due to CORS restrictions. Ensure the server allows requests from this origin, or try using a proxy.",
148
+ });
149
+ case "unknown":
150
+ default:
151
+ return translate({
152
+ id: OPENAPI_REQUEST.ERROR_UNKNOWN,
153
+ message:
154
+ "An unexpected error occurred while making the request. Please try again.",
155
+ });
156
+ }
157
+ };
158
+
119
159
  const onSubmit = async (data) => {
120
- dispatch(setResponse("Fetching..."));
160
+ dispatch(
161
+ setResponse(
162
+ translate({
163
+ id: OPENAPI_REQUEST.FETCHING_MESSAGE,
164
+ message: "Fetching...",
165
+ })
166
+ )
167
+ );
121
168
  try {
122
169
  await delay(1200);
123
- const res = await makeRequest(postmanRequest, proxy, body);
170
+ const res = await makeRequest(
171
+ postmanRequest,
172
+ proxy,
173
+ body,
174
+ requestTimeout
175
+ );
124
176
  if (res.headers.get("content-type")?.includes("text/event-stream")) {
125
177
  await handleEventStream(res);
126
178
  } else {
@@ -128,7 +180,18 @@ function Request({ item }: { item: ApiItem }) {
128
180
  }
129
181
  } catch (e) {
130
182
  console.log(e);
131
- dispatch(setResponse("Connection failed"));
183
+
184
+ let errorMessage: string;
185
+ if (e instanceof RequestError) {
186
+ errorMessage = getErrorMessage(e.type);
187
+ } else {
188
+ errorMessage = translate({
189
+ id: OPENAPI_REQUEST.CONNECTION_FAILED,
190
+ message: "Connection failed",
191
+ });
192
+ }
193
+
194
+ dispatch(setResponse(errorMessage));
132
195
  dispatch(clearCode());
133
196
  dispatch(clearHeaders());
134
197
  }
@@ -137,7 +200,7 @@ function Request({ item }: { item: ApiItem }) {
137
200
  const showServerOptions = serverOptions.length > 0;
138
201
  const showAcceptOptions = acceptOptions.length > 1;
139
202
  const showRequestBody = contentType !== undefined;
140
- const showRequestButton = item.servers && !hideSendButton;
203
+ const showRequestButton = (item.servers || proxy) && !hideSendButton;
141
204
  const showAuth = authSelected !== undefined;
142
205
  const showParams = allParams.length > 0;
143
206
  const requestBodyRequired = item.requestBody?.required;
@@ -147,7 +210,8 @@ function Request({ item }: { item: ApiItem }) {
147
210
  !showAuth &&
148
211
  !showParams &&
149
212
  !showRequestBody &&
150
- !showServerOptions
213
+ !showServerOptions &&
214
+ !showRequestButton
151
215
  ) {
152
216
  return null;
153
217
  }
@@ -178,20 +242,31 @@ function Request({ item }: { item: ApiItem }) {
178
242
  onSubmit={methods.handleSubmit(onSubmit)}
179
243
  >
180
244
  <div className="openapi-explorer__request-header-container">
181
- <span className="openapi-explorer__request-title">Request </span>
245
+ <span className="openapi-explorer__request-title">
246
+ {translate({
247
+ id: OPENAPI_REQUEST.REQUEST_TITLE,
248
+ message: "Request",
249
+ })}
250
+ </span>
182
251
  {allDetailsExpanded ? (
183
252
  <span
184
253
  className="openapi-explorer__expand-details-btn"
185
254
  onClick={collapseAllDetails}
186
255
  >
187
- Collapse all
256
+ {translate({
257
+ id: OPENAPI_REQUEST.COLLAPSE_ALL,
258
+ message: "Collapse all",
259
+ })}
188
260
  </span>
189
261
  ) : (
190
262
  <span
191
263
  className="openapi-explorer__expand-details-btn"
192
264
  onClick={expandAllDetails}
193
265
  >
194
- Expand all
266
+ {translate({
267
+ id: OPENAPI_REQUEST.EXPAND_ALL,
268
+ message: "Expand all",
269
+ })}
195
270
  </span>
196
271
  )}
197
272
  </div>
@@ -208,7 +283,10 @@ function Request({ item }: { item: ApiItem }) {
208
283
  setExpandServer(!expandServer);
209
284
  }}
210
285
  >
211
- Base URL
286
+ {translate({
287
+ id: OPENAPI_REQUEST.BASE_URL_TITLE,
288
+ message: "Base URL",
289
+ })}
212
290
  </summary>
213
291
  <Server />
214
292
  </details>
@@ -225,7 +303,7 @@ function Request({ item }: { item: ApiItem }) {
225
303
  setExpandAuth(!expandAuth);
226
304
  }}
227
305
  >
228
- Auth
306
+ {translate({ id: OPENAPI_REQUEST.AUTH_TITLE, message: "Auth" })}
229
307
  </summary>
230
308
  <Authorization />
231
309
  </details>
@@ -244,7 +322,10 @@ function Request({ item }: { item: ApiItem }) {
244
322
  setExpandParams(!expandParams);
245
323
  }}
246
324
  >
247
- Parameters
325
+ {translate({
326
+ id: OPENAPI_REQUEST.PARAMETERS_TITLE,
327
+ message: "Parameters",
328
+ })}
248
329
  </summary>
249
330
  <ParamOptions />
250
331
  </details>
@@ -261,10 +342,14 @@ function Request({ item }: { item: ApiItem }) {
261
342
  setExpandBody(!expandBody);
262
343
  }}
263
344
  >
264
- Body
345
+ {translate({ id: OPENAPI_REQUEST.BODY_TITLE, message: "Body" })}
265
346
  {requestBodyRequired && (
266
347
  <span className="openapi-schema__required">
267
- &nbsp;required
348
+ &nbsp;
349
+ {translate({
350
+ id: OPENAPI_REQUEST.REQUIRED_LABEL,
351
+ message: "required",
352
+ })}
268
353
  </span>
269
354
  )}
270
355
  </summary>
@@ -290,14 +375,20 @@ function Request({ item }: { item: ApiItem }) {
290
375
  setExpandAccept(!expandAccept);
291
376
  }}
292
377
  >
293
- Accept
378
+ {translate({
379
+ id: OPENAPI_REQUEST.ACCEPT_TITLE,
380
+ message: "Accept",
381
+ })}
294
382
  </summary>
295
383
  <Accept />
296
384
  </details>
297
385
  )}
298
386
  {showRequestButton && item.method !== "event" && (
299
387
  <button className="openapi-explorer__request-btn" type="submit">
300
- Send API Request
388
+ {translate({
389
+ id: OPENAPI_REQUEST.SEND_BUTTON,
390
+ message: "Send API Request",
391
+ })}
301
392
  </button>
302
393
  )}
303
394
  </div>