@djangocfg/ui-tools 2.1.285 → 2.1.287
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/dist/DocsLayout-BCVU6TTX.cjs +2027 -0
- package/dist/DocsLayout-BCVU6TTX.cjs.map +1 -0
- package/dist/DocsLayout-ERETJLLV.mjs +2020 -0
- package/dist/DocsLayout-ERETJLLV.mjs.map +1 -0
- package/dist/{PlaygroundLayout-O52C6HK5.css → DocsLayout-MBFIB4NO.css} +1 -1
- package/dist/{PrettyCode.client-SGDGQTYT.cjs → PrettyCode.client-5GABIN2I.cjs} +57 -35
- package/dist/PrettyCode.client-5GABIN2I.cjs.map +1 -0
- package/dist/{PrettyCode.client-DW5LTG47.mjs → PrettyCode.client-IZTXXYHG.mjs} +57 -35
- package/dist/PrettyCode.client-IZTXXYHG.mjs.map +1 -0
- package/dist/chunk-IULI4XII.cjs +1129 -0
- package/dist/chunk-IULI4XII.cjs.map +1 -0
- package/dist/chunk-VZGQC3NG.mjs +1100 -0
- package/dist/chunk-VZGQC3NG.mjs.map +1 -0
- package/dist/index.cjs +88 -552
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -6
- package/dist/index.d.ts +18 -6
- package/dist/index.mjs +25 -496
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
- package/src/tools/OpenapiViewer/.claude/.sidecar/activity.jsonl +6 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/history/2026-04-22.md +35 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/map_cache.json +30 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/review.md +35 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/scan.log +3 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/tasks/T-001.md +18 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/tasks/T-002.md +18 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/tasks/T-003.md +18 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/tasks/T-004.md +18 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/tasks/T-005.md +18 -0
- package/src/tools/OpenapiViewer/.claude/.sidecar/usage.json +5 -0
- package/src/tools/OpenapiViewer/.claude/project-map.md +23 -0
- package/src/tools/OpenapiViewer/OpenapiViewer.story.tsx +28 -2
- package/src/tools/OpenapiViewer/README.md +104 -51
- package/src/tools/OpenapiViewer/components/DocsLayout/ApiIntroSection.tsx +64 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/DocsView.tsx +137 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/EndpointDoc.tsx +268 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/SchemaCopyMenu.tsx +139 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/Sidebar.tsx +211 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/SlideInPlayground.tsx +101 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/TryItSheet.tsx +57 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/anchor.ts +11 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/grouping.ts +71 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/index.tsx +166 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/schemaFields.ts +121 -0
- package/src/tools/OpenapiViewer/components/DocsLayout/sidebarLabel.ts +60 -0
- package/src/tools/OpenapiViewer/components/index.ts +5 -2
- package/src/tools/OpenapiViewer/components/shared/BodyFormEditor.tsx +422 -0
- package/src/tools/OpenapiViewer/components/shared/EndpointDraftSync.tsx +108 -0
- package/src/tools/OpenapiViewer/components/shared/EndpointResetButton.tsx +50 -0
- package/src/tools/OpenapiViewer/components/{PlaygroundLayout → shared}/RequestPanel.tsx +174 -87
- package/src/tools/OpenapiViewer/components/shared/SendButton.tsx +91 -0
- package/src/tools/OpenapiViewer/components/{PlaygroundLayout → shared}/ui.tsx +5 -4
- package/src/tools/OpenapiViewer/context/PlaygroundContext.tsx +82 -8
- package/src/tools/OpenapiViewer/hooks/useEndpointDraft.ts +142 -0
- package/src/tools/OpenapiViewer/hooks/useOpenApiSchema.ts +126 -13
- package/src/tools/OpenapiViewer/index.tsx +3 -7
- package/src/tools/OpenapiViewer/lazy.tsx +6 -27
- package/src/tools/OpenapiViewer/types.ts +44 -0
- package/src/tools/OpenapiViewer/utils/formatters.ts +2 -23
- package/src/tools/OpenapiViewer/utils/index.ts +3 -1
- package/src/tools/OpenapiViewer/utils/schemaExport.ts +206 -0
- package/src/tools/OpenapiViewer/utils/url.ts +202 -0
- package/src/tools/PrettyCode/PrettyCode.client.tsx +42 -8
- package/src/tools/PrettyCode/index.tsx +6 -0
- package/dist/PlaygroundLayout-DHUATCHB.cjs +0 -798
- package/dist/PlaygroundLayout-DHUATCHB.cjs.map +0 -1
- package/dist/PlaygroundLayout-NONWOVQR.mjs +0 -791
- package/dist/PlaygroundLayout-NONWOVQR.mjs.map +0 -1
- package/dist/PrettyCode.client-DW5LTG47.mjs.map +0 -1
- package/dist/PrettyCode.client-SGDGQTYT.cjs.map +0 -1
- package/dist/chunk-5FKE7OME.cjs +0 -369
- package/dist/chunk-5FKE7OME.cjs.map +0 -1
- package/dist/chunk-BKWDHJKF.mjs +0 -356
- package/dist/chunk-BKWDHJKF.mjs.map +0 -1
- package/src/tools/OpenapiViewer/components/PlaygroundLayout/EndpointList.tsx +0 -228
- package/src/tools/OpenapiViewer/components/PlaygroundLayout/index.tsx +0 -107
- /package/dist/{PlaygroundLayout-O52C6HK5.css.map → DocsLayout-MBFIB4NO.css.map} +0 -0
- /package/src/tools/OpenapiViewer/components/{PlaygroundLayout → shared}/ResponsePanel.tsx +0 -0
|
@@ -0,0 +1,1129 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkWGEGR3DF_cjs = require('./chunk-WGEGR3DF.cjs');
|
|
4
|
+
var React3 = require('react');
|
|
5
|
+
require('@djangocfg/ui-core/styles/palette');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
var ReactMarkdown = require('react-markdown');
|
|
8
|
+
var remarkGfm = require('remark-gfm');
|
|
9
|
+
var components = require('@djangocfg/ui-core/components');
|
|
10
|
+
var hooks = require('@djangocfg/ui-core/hooks');
|
|
11
|
+
var consola = require('consola');
|
|
12
|
+
|
|
13
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
+
|
|
15
|
+
var React3__default = /*#__PURE__*/_interopDefault(React3);
|
|
16
|
+
var ReactMarkdown__default = /*#__PURE__*/_interopDefault(ReactMarkdown);
|
|
17
|
+
var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
|
|
18
|
+
var consola__default = /*#__PURE__*/_interopDefault(consola);
|
|
19
|
+
|
|
20
|
+
var MermaidClient = React3.lazy(() => import('./Mermaid.client-RSWUUHIL.cjs'));
|
|
21
|
+
var LoadingFallback = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center items-center min-h-[100px]", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-spin rounded-full h-6 w-6 border-b-2 border-primary" }) }), "LoadingFallback");
|
|
22
|
+
var Mermaid = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((props) => {
|
|
23
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React3.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(LoadingFallback, {}), children: /* @__PURE__ */ jsxRuntime.jsx(MermaidClient, { ...props }) });
|
|
24
|
+
}, "Mermaid");
|
|
25
|
+
var Mermaid_default = Mermaid;
|
|
26
|
+
var PrettyCodeClient = React3.lazy(() => import('./PrettyCode.client-5GABIN2I.cjs'));
|
|
27
|
+
var LoadingFallback2 = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative rounded-sm border border-border overflow-hidden bg-muted dark:bg-zinc-900", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
28
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "animate-pulse h-4 w-4 rounded-full bg-muted-foreground/20" }),
|
|
29
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground", children: "Loading code..." })
|
|
30
|
+
] }) }) }), "LoadingFallback");
|
|
31
|
+
var PrettyCode = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((props) => {
|
|
32
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React3.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(LoadingFallback2, {}), children: /* @__PURE__ */ jsxRuntime.jsx(PrettyCodeClient, { ...props }) });
|
|
33
|
+
}, "PrettyCode");
|
|
34
|
+
var PrettyCode_default = PrettyCode;
|
|
35
|
+
function smartTruncate(content, maxLength) {
|
|
36
|
+
if (content.length <= maxLength) {
|
|
37
|
+
return content;
|
|
38
|
+
}
|
|
39
|
+
let breakPoint = maxLength;
|
|
40
|
+
while (breakPoint > maxLength - 50 && breakPoint > 0) {
|
|
41
|
+
const char = content[breakPoint];
|
|
42
|
+
if (char === " " || char === "\n" || char === " ") {
|
|
43
|
+
break;
|
|
44
|
+
}
|
|
45
|
+
breakPoint--;
|
|
46
|
+
}
|
|
47
|
+
if (breakPoint <= maxLength - 50) {
|
|
48
|
+
breakPoint = maxLength;
|
|
49
|
+
}
|
|
50
|
+
let truncated = content.slice(0, breakPoint).trimEnd();
|
|
51
|
+
truncated = fixUnclosedMarkdown(truncated);
|
|
52
|
+
return truncated;
|
|
53
|
+
}
|
|
54
|
+
chunkWGEGR3DF_cjs.__name(smartTruncate, "smartTruncate");
|
|
55
|
+
function truncateByLines(content, maxLines) {
|
|
56
|
+
const lines = content.split("\n");
|
|
57
|
+
if (lines.length <= maxLines) {
|
|
58
|
+
return content;
|
|
59
|
+
}
|
|
60
|
+
let truncated = lines.slice(0, maxLines).join("\n").trimEnd();
|
|
61
|
+
truncated = fixUnclosedMarkdown(truncated);
|
|
62
|
+
return truncated;
|
|
63
|
+
}
|
|
64
|
+
chunkWGEGR3DF_cjs.__name(truncateByLines, "truncateByLines");
|
|
65
|
+
function fixUnclosedMarkdown(content) {
|
|
66
|
+
let result = content;
|
|
67
|
+
const countOccurrences = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((str, marker) => {
|
|
68
|
+
const escaped = marker.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
69
|
+
const matches = str.match(new RegExp(escaped, "g"));
|
|
70
|
+
return matches ? matches.length : 0;
|
|
71
|
+
}, "countOccurrences");
|
|
72
|
+
const boldCount = countOccurrences(result, "**");
|
|
73
|
+
if (boldCount % 2 !== 0) {
|
|
74
|
+
result += "**";
|
|
75
|
+
}
|
|
76
|
+
const withoutBold = result.replace(/\*\*/g, "");
|
|
77
|
+
const italicCount = countOccurrences(withoutBold, "*");
|
|
78
|
+
if (italicCount % 2 !== 0) {
|
|
79
|
+
result += "*";
|
|
80
|
+
}
|
|
81
|
+
const codeCount = countOccurrences(result, "`");
|
|
82
|
+
const tripleCount = countOccurrences(result, "```");
|
|
83
|
+
const singleCodeCount = codeCount - tripleCount * 3;
|
|
84
|
+
if (singleCodeCount % 2 !== 0) {
|
|
85
|
+
result += "`";
|
|
86
|
+
}
|
|
87
|
+
if (tripleCount % 2 !== 0) {
|
|
88
|
+
result += "\n```";
|
|
89
|
+
}
|
|
90
|
+
const strikeCount = countOccurrences(result, "~~");
|
|
91
|
+
if (strikeCount % 2 !== 0) {
|
|
92
|
+
result += "~~";
|
|
93
|
+
}
|
|
94
|
+
const underlineBoldCount = countOccurrences(result, "__");
|
|
95
|
+
if (underlineBoldCount % 2 !== 0) {
|
|
96
|
+
result += "__";
|
|
97
|
+
}
|
|
98
|
+
const withoutUnderlineBold = result.replace(/__/g, "");
|
|
99
|
+
const underlineItalicCount = countOccurrences(withoutUnderlineBold, "_");
|
|
100
|
+
if (underlineItalicCount % 2 !== 0) {
|
|
101
|
+
result += "_";
|
|
102
|
+
}
|
|
103
|
+
return result;
|
|
104
|
+
}
|
|
105
|
+
chunkWGEGR3DF_cjs.__name(fixUnclosedMarkdown, "fixUnclosedMarkdown");
|
|
106
|
+
function useCollapsibleContent(content, options = {}) {
|
|
107
|
+
const { maxLength, maxLines, defaultExpanded = false } = options;
|
|
108
|
+
const [isCollapsed, setIsCollapsed] = React3.useState(!defaultExpanded);
|
|
109
|
+
const originalLength = content.length;
|
|
110
|
+
const originalLineCount = content.split("\n").length;
|
|
111
|
+
const { shouldCollapse, truncatedContent } = React3.useMemo(() => {
|
|
112
|
+
if (maxLength === void 0 && maxLines === void 0) {
|
|
113
|
+
return { shouldCollapse: false, truncatedContent: content };
|
|
114
|
+
}
|
|
115
|
+
let needsCollapse = false;
|
|
116
|
+
let result = content;
|
|
117
|
+
if (maxLines !== void 0 && originalLineCount > maxLines) {
|
|
118
|
+
needsCollapse = true;
|
|
119
|
+
result = truncateByLines(result, maxLines);
|
|
120
|
+
}
|
|
121
|
+
if (maxLength !== void 0 && result.length > maxLength) {
|
|
122
|
+
needsCollapse = true;
|
|
123
|
+
result = smartTruncate(result, maxLength);
|
|
124
|
+
}
|
|
125
|
+
return { shouldCollapse: needsCollapse, truncatedContent: result };
|
|
126
|
+
}, [content, maxLength, maxLines, originalLineCount]);
|
|
127
|
+
const displayContent = React3.useMemo(() => {
|
|
128
|
+
if (!shouldCollapse || !isCollapsed) {
|
|
129
|
+
return content;
|
|
130
|
+
}
|
|
131
|
+
return truncatedContent;
|
|
132
|
+
}, [content, truncatedContent, shouldCollapse, isCollapsed]);
|
|
133
|
+
const toggleCollapsed = React3.useCallback(() => {
|
|
134
|
+
setIsCollapsed((prev) => !prev);
|
|
135
|
+
}, []);
|
|
136
|
+
const setCollapsed = React3.useCallback((collapsed) => {
|
|
137
|
+
setIsCollapsed(collapsed);
|
|
138
|
+
}, []);
|
|
139
|
+
return {
|
|
140
|
+
isCollapsed,
|
|
141
|
+
toggleCollapsed,
|
|
142
|
+
setCollapsed,
|
|
143
|
+
displayContent,
|
|
144
|
+
shouldCollapse,
|
|
145
|
+
originalLength,
|
|
146
|
+
originalLineCount
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
chunkWGEGR3DF_cjs.__name(useCollapsibleContent, "useCollapsibleContent");
|
|
150
|
+
var extractTextFromChildren = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((children) => {
|
|
151
|
+
if (typeof children === "string") {
|
|
152
|
+
return children;
|
|
153
|
+
}
|
|
154
|
+
if (typeof children === "number") {
|
|
155
|
+
return String(children);
|
|
156
|
+
}
|
|
157
|
+
if (React3__default.default.isValidElement(children)) {
|
|
158
|
+
const props = children.props;
|
|
159
|
+
return extractTextFromChildren(props.children);
|
|
160
|
+
}
|
|
161
|
+
if (Array.isArray(children)) {
|
|
162
|
+
return children.map(extractTextFromChildren).join("");
|
|
163
|
+
}
|
|
164
|
+
return "";
|
|
165
|
+
}, "extractTextFromChildren");
|
|
166
|
+
var CodeBlock = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ code, language, isUser, isCompact = false }) => {
|
|
167
|
+
const theme = hooks.useResolvedTheme();
|
|
168
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group my-3", children: [
|
|
169
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
170
|
+
components.CopyButton,
|
|
171
|
+
{
|
|
172
|
+
value: code,
|
|
173
|
+
variant: "ghost",
|
|
174
|
+
className: `
|
|
175
|
+
absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity
|
|
176
|
+
h-8 w-8
|
|
177
|
+
${isUser ? "hover:bg-white/20 text-white" : "hover:bg-muted-foreground/20 text-muted-foreground hover:text-foreground"}
|
|
178
|
+
`,
|
|
179
|
+
title: "Copy code"
|
|
180
|
+
}
|
|
181
|
+
),
|
|
182
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
183
|
+
PrettyCode_default,
|
|
184
|
+
{
|
|
185
|
+
data: code,
|
|
186
|
+
language,
|
|
187
|
+
className: isCompact ? "text-xs" : "text-sm",
|
|
188
|
+
customBg: isUser ? "bg-white/10" : "bg-muted dark:bg-muted",
|
|
189
|
+
mode: theme,
|
|
190
|
+
isCompact
|
|
191
|
+
}
|
|
192
|
+
)
|
|
193
|
+
] });
|
|
194
|
+
}, "CodeBlock");
|
|
195
|
+
var createMarkdownComponents = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((isUser = false, isCompact = false) => {
|
|
196
|
+
const textSize = isCompact ? "text-xs" : "text-sm";
|
|
197
|
+
const headingBase = isCompact ? "text-sm" : "text-base";
|
|
198
|
+
const headingSm = isCompact ? "text-xs" : "text-sm";
|
|
199
|
+
return {
|
|
200
|
+
// Headings - scaled for chat context
|
|
201
|
+
h1: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h1", { className: `${headingBase} font-bold mb-2 mt-3 first:mt-0`, children }), "h1"),
|
|
202
|
+
h2: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h2", { className: `${headingSm} font-bold mb-2 mt-3 first:mt-0`, children }), "h2"),
|
|
203
|
+
h3: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h3", { className: `${headingSm} font-semibold mb-1 mt-2 first:mt-0`, children }), "h3"),
|
|
204
|
+
h4: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h4", { className: `${headingSm} font-semibold mb-1 mt-2 first:mt-0`, children }), "h4"),
|
|
205
|
+
h5: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h5", { className: `${headingSm} font-medium mb-1 mt-2 first:mt-0`, children }), "h5"),
|
|
206
|
+
h6: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h6", { className: `${headingSm} font-medium mb-1 mt-2 first:mt-0`, children }), "h6"),
|
|
207
|
+
// Paragraphs - optimized for chat readability
|
|
208
|
+
p: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${textSize} mb-4 last:mb-0 leading-7 break-words font-light`, children }), "p"),
|
|
209
|
+
// Lists - compact
|
|
210
|
+
ul: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { className: `list-disc list-inside mb-2 space-y-1 ${textSize}`, children }), "ul"),
|
|
211
|
+
ol: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("ol", { className: `list-decimal list-inside mb-2 space-y-1 ${textSize}`, children }), "ol"),
|
|
212
|
+
li: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "break-words", children }), "li"),
|
|
213
|
+
// Links - appropriate for chat context
|
|
214
|
+
a: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ href, children }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
215
|
+
"a",
|
|
216
|
+
{
|
|
217
|
+
href,
|
|
218
|
+
className: `${textSize} ${isUser ? "text-white/90 underline hover:text-white" : "text-primary underline hover:text-primary/80"} transition-colors break-all`,
|
|
219
|
+
target: href?.startsWith("http") ? "_blank" : void 0,
|
|
220
|
+
rel: href?.startsWith("http") ? "noopener noreferrer" : void 0,
|
|
221
|
+
children
|
|
222
|
+
}
|
|
223
|
+
), "a"),
|
|
224
|
+
// Code blocks - using CodeBlock component with copy functionality
|
|
225
|
+
pre: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => {
|
|
226
|
+
let codeContent = "";
|
|
227
|
+
let language = "plaintext";
|
|
228
|
+
if (React3__default.default.isValidElement(children)) {
|
|
229
|
+
const child = children;
|
|
230
|
+
if (child.type === "code" || typeof child.type === "function" && child.type.name === "code") {
|
|
231
|
+
const codeProps = child.props;
|
|
232
|
+
const rawClassName = codeProps.className;
|
|
233
|
+
language = rawClassName?.replace(/language-/, "").trim() || "plaintext";
|
|
234
|
+
codeContent = extractTextFromChildren(codeProps.children).trim();
|
|
235
|
+
} else {
|
|
236
|
+
codeContent = extractTextFromChildren(children).trim();
|
|
237
|
+
}
|
|
238
|
+
} else {
|
|
239
|
+
codeContent = extractTextFromChildren(children).trim();
|
|
240
|
+
}
|
|
241
|
+
if (!codeContent) {
|
|
242
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-3 p-3 bg-muted rounded text-sm text-muted-foreground", children: "No content available" });
|
|
243
|
+
}
|
|
244
|
+
if (language === "mermaid") {
|
|
245
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "my-3 max-w-full overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsx(Mermaid_default, { chart: codeContent, className: "max-w-[600px] mx-auto", isCompact }) });
|
|
246
|
+
}
|
|
247
|
+
try {
|
|
248
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CodeBlock, { code: codeContent, language, isUser, isCompact });
|
|
249
|
+
} catch (error) {
|
|
250
|
+
console.warn("CodeBlock failed, using fallback:", error);
|
|
251
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group my-3", children: [
|
|
252
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
253
|
+
components.CopyButton,
|
|
254
|
+
{
|
|
255
|
+
value: codeContent,
|
|
256
|
+
variant: "ghost",
|
|
257
|
+
className: `
|
|
258
|
+
absolute top-2 right-2 z-10 opacity-0 group-hover:opacity-100 transition-opacity
|
|
259
|
+
h-8 w-8
|
|
260
|
+
${isUser ? "hover:bg-white/20 text-white" : "hover:bg-muted-foreground/20 text-muted-foreground hover:text-foreground"}
|
|
261
|
+
`,
|
|
262
|
+
title: "Copy code"
|
|
263
|
+
}
|
|
264
|
+
),
|
|
265
|
+
/* @__PURE__ */ jsxRuntime.jsx("pre", { className: `
|
|
266
|
+
p-3 rounded text-xs font-mono overflow-x-auto
|
|
267
|
+
${isUser ? "bg-white/10 text-white" : "bg-muted text-foreground"}
|
|
268
|
+
`, children: /* @__PURE__ */ jsxRuntime.jsx("code", { children: codeContent }) })
|
|
269
|
+
] });
|
|
270
|
+
}
|
|
271
|
+
}, "pre"),
|
|
272
|
+
// Inline code
|
|
273
|
+
code: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children, className }) => {
|
|
274
|
+
if (className?.includes("language-")) {
|
|
275
|
+
return /* @__PURE__ */ jsxRuntime.jsx("code", { className, children });
|
|
276
|
+
}
|
|
277
|
+
const codeContent = extractTextFromChildren(children);
|
|
278
|
+
return /* @__PURE__ */ jsxRuntime.jsx("code", { className: "px-1.5 py-0.5 rounded text-xs font-mono bg-muted text-foreground break-all", children: codeContent });
|
|
279
|
+
}, "code"),
|
|
280
|
+
// Blockquotes
|
|
281
|
+
blockquote: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("blockquote", { className: `${textSize} border-l-2 border-border pl-3 my-2 italic text-muted-foreground break-words`, children }), "blockquote"),
|
|
282
|
+
// Tables - compact for chat
|
|
283
|
+
table: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto my-3", children: /* @__PURE__ */ jsxRuntime.jsx("table", { className: `min-w-full ${textSize} border-collapse`, children }) }), "table"),
|
|
284
|
+
thead: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-muted/50", children }), "thead"),
|
|
285
|
+
tbody: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("tbody", { children }), "tbody"),
|
|
286
|
+
tr: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("tr", { className: "border-b border-border/50", children }), "tr"),
|
|
287
|
+
th: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-2 py-1 text-left font-medium break-words", children }), "th"),
|
|
288
|
+
td: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-2 py-1 break-words", children }), "td"),
|
|
289
|
+
// Horizontal rule
|
|
290
|
+
hr: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "my-3 border-0 h-px bg-border" }), "hr"),
|
|
291
|
+
// Strong and emphasis
|
|
292
|
+
strong: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("strong", { className: "font-semibold", children }), "strong"),
|
|
293
|
+
em: /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children }) => /* @__PURE__ */ jsxRuntime.jsx("em", { className: "italic", children }), "em")
|
|
294
|
+
};
|
|
295
|
+
}, "createMarkdownComponents");
|
|
296
|
+
var hasMarkdownSyntax = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((text) => {
|
|
297
|
+
if (text.trim().includes("\n")) {
|
|
298
|
+
return true;
|
|
299
|
+
}
|
|
300
|
+
const markdownPatterns = [
|
|
301
|
+
/^#{1,6}\s/m,
|
|
302
|
+
// Headers
|
|
303
|
+
/\*\*[^*]+\*\*/,
|
|
304
|
+
// Bold
|
|
305
|
+
/\*[^*]+\*/,
|
|
306
|
+
// Italic
|
|
307
|
+
/__[^_]+__/,
|
|
308
|
+
// Bold (underscore)
|
|
309
|
+
/_[^_]+_/,
|
|
310
|
+
// Italic (underscore)
|
|
311
|
+
/\[.+\]\(.+\)/,
|
|
312
|
+
// Links
|
|
313
|
+
/!\[.*\]\(.+\)/,
|
|
314
|
+
// Images
|
|
315
|
+
/```[\s\S]*```/,
|
|
316
|
+
// Code blocks
|
|
317
|
+
/`[^`]+`/,
|
|
318
|
+
// Inline code
|
|
319
|
+
/^\s*[-*+]\s/m,
|
|
320
|
+
// Unordered lists
|
|
321
|
+
/^\s*\d+\.\s/m,
|
|
322
|
+
// Ordered lists
|
|
323
|
+
/^\s*>/m,
|
|
324
|
+
// Blockquotes
|
|
325
|
+
/\|.+\|/,
|
|
326
|
+
// Tables
|
|
327
|
+
/^---+$/m,
|
|
328
|
+
// Horizontal rules
|
|
329
|
+
/~~[^~]+~~/
|
|
330
|
+
// Strikethrough
|
|
331
|
+
];
|
|
332
|
+
return markdownPatterns.some((pattern) => pattern.test(text));
|
|
333
|
+
}, "hasMarkdownSyntax");
|
|
334
|
+
var CollapseToggle = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({
|
|
335
|
+
isCollapsed,
|
|
336
|
+
onClick,
|
|
337
|
+
readMoreLabel,
|
|
338
|
+
showLessLabel,
|
|
339
|
+
isUser,
|
|
340
|
+
isCompact
|
|
341
|
+
}) => {
|
|
342
|
+
const textSize = isCompact ? "text-xs" : "text-sm";
|
|
343
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
344
|
+
"button",
|
|
345
|
+
{
|
|
346
|
+
type: "button",
|
|
347
|
+
onClick,
|
|
348
|
+
className: `
|
|
349
|
+
${textSize} font-medium cursor-pointer
|
|
350
|
+
transition-colors duration-200
|
|
351
|
+
${isUser ? "text-white/80 hover:text-white" : "text-primary hover:text-primary/80"}
|
|
352
|
+
inline-flex items-center gap-1
|
|
353
|
+
mt-1
|
|
354
|
+
`,
|
|
355
|
+
children: isCollapsed ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
356
|
+
readMoreLabel,
|
|
357
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
358
|
+
"svg",
|
|
359
|
+
{
|
|
360
|
+
className: "w-3 h-3",
|
|
361
|
+
fill: "none",
|
|
362
|
+
stroke: "currentColor",
|
|
363
|
+
viewBox: "0 0 24 24",
|
|
364
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
365
|
+
"path",
|
|
366
|
+
{
|
|
367
|
+
strokeLinecap: "round",
|
|
368
|
+
strokeLinejoin: "round",
|
|
369
|
+
strokeWidth: 2,
|
|
370
|
+
d: "M19 9l-7 7-7-7"
|
|
371
|
+
}
|
|
372
|
+
)
|
|
373
|
+
}
|
|
374
|
+
)
|
|
375
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
376
|
+
showLessLabel,
|
|
377
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
378
|
+
"svg",
|
|
379
|
+
{
|
|
380
|
+
className: "w-3 h-3",
|
|
381
|
+
fill: "none",
|
|
382
|
+
stroke: "currentColor",
|
|
383
|
+
viewBox: "0 0 24 24",
|
|
384
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
385
|
+
"path",
|
|
386
|
+
{
|
|
387
|
+
strokeLinecap: "round",
|
|
388
|
+
strokeLinejoin: "round",
|
|
389
|
+
strokeWidth: 2,
|
|
390
|
+
d: "M5 15l7-7 7 7"
|
|
391
|
+
}
|
|
392
|
+
)
|
|
393
|
+
}
|
|
394
|
+
)
|
|
395
|
+
] })
|
|
396
|
+
}
|
|
397
|
+
);
|
|
398
|
+
}, "CollapseToggle");
|
|
399
|
+
var MarkdownMessage = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({
|
|
400
|
+
content,
|
|
401
|
+
className = "",
|
|
402
|
+
isUser = false,
|
|
403
|
+
isCompact = false,
|
|
404
|
+
collapsible = false,
|
|
405
|
+
maxLength,
|
|
406
|
+
maxLines,
|
|
407
|
+
readMoreLabel = "Read more...",
|
|
408
|
+
showLessLabel = "Show less",
|
|
409
|
+
defaultExpanded = false,
|
|
410
|
+
onCollapseChange
|
|
411
|
+
}) => {
|
|
412
|
+
const trimmedContent = content.trim();
|
|
413
|
+
const collapsibleOptions = React3__default.default.useMemo(() => {
|
|
414
|
+
if (!collapsible) return {};
|
|
415
|
+
const effectiveMaxLength = maxLength ?? 1e3;
|
|
416
|
+
const effectiveMaxLines = maxLines ?? 10;
|
|
417
|
+
return { maxLength: effectiveMaxLength, maxLines: effectiveMaxLines, defaultExpanded };
|
|
418
|
+
}, [collapsible, maxLength, maxLines, defaultExpanded]);
|
|
419
|
+
const {
|
|
420
|
+
isCollapsed,
|
|
421
|
+
toggleCollapsed,
|
|
422
|
+
displayContent,
|
|
423
|
+
shouldCollapse
|
|
424
|
+
} = useCollapsibleContent(
|
|
425
|
+
trimmedContent,
|
|
426
|
+
collapsible ? collapsibleOptions : {}
|
|
427
|
+
);
|
|
428
|
+
React3__default.default.useEffect(() => {
|
|
429
|
+
if (collapsible && shouldCollapse && onCollapseChange) {
|
|
430
|
+
onCollapseChange(isCollapsed);
|
|
431
|
+
}
|
|
432
|
+
}, [isCollapsed, collapsible, shouldCollapse, onCollapseChange]);
|
|
433
|
+
const components = React3__default.default.useMemo(() => createMarkdownComponents(isUser, isCompact), [isUser, isCompact]);
|
|
434
|
+
const textSizeClass = isCompact ? "text-xs" : "text-sm";
|
|
435
|
+
const proseClass = isCompact ? "prose-xs" : "prose-sm";
|
|
436
|
+
const isPlainText = !hasMarkdownSyntax(displayContent);
|
|
437
|
+
if (isPlainText) {
|
|
438
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${textSizeClass} leading-7 break-words whitespace-pre-line font-light ${className}`, children: [
|
|
439
|
+
displayContent,
|
|
440
|
+
collapsible && shouldCollapse && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
441
|
+
isCollapsed && "... ",
|
|
442
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
443
|
+
CollapseToggle,
|
|
444
|
+
{
|
|
445
|
+
isCollapsed,
|
|
446
|
+
onClick: toggleCollapsed,
|
|
447
|
+
readMoreLabel,
|
|
448
|
+
showLessLabel,
|
|
449
|
+
isUser,
|
|
450
|
+
isCompact
|
|
451
|
+
}
|
|
452
|
+
)
|
|
453
|
+
] })
|
|
454
|
+
] });
|
|
455
|
+
}
|
|
456
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, children: [
|
|
457
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
458
|
+
"div",
|
|
459
|
+
{
|
|
460
|
+
className: `
|
|
461
|
+
prose ${proseClass} max-w-none break-words overflow-hidden ${textSizeClass}
|
|
462
|
+
${isUser ? "prose-invert" : "dark:prose-invert"}
|
|
463
|
+
[&>*]:leading-7
|
|
464
|
+
`,
|
|
465
|
+
style: {
|
|
466
|
+
// Inherit colors from parent - fixes issues with external CSS variables
|
|
467
|
+
"--tw-prose-body": "inherit",
|
|
468
|
+
"--tw-prose-headings": "inherit",
|
|
469
|
+
"--tw-prose-bold": "inherit",
|
|
470
|
+
"--tw-prose-links": "inherit",
|
|
471
|
+
color: "inherit"
|
|
472
|
+
},
|
|
473
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
474
|
+
ReactMarkdown__default.default,
|
|
475
|
+
{
|
|
476
|
+
remarkPlugins: [remarkGfm__default.default],
|
|
477
|
+
components,
|
|
478
|
+
children: displayContent
|
|
479
|
+
}
|
|
480
|
+
)
|
|
481
|
+
}
|
|
482
|
+
),
|
|
483
|
+
collapsible && shouldCollapse && /* @__PURE__ */ jsxRuntime.jsx(
|
|
484
|
+
CollapseToggle,
|
|
485
|
+
{
|
|
486
|
+
isCollapsed,
|
|
487
|
+
onClick: toggleCollapsed,
|
|
488
|
+
readMoreLabel,
|
|
489
|
+
showLessLabel,
|
|
490
|
+
isUser,
|
|
491
|
+
isCompact
|
|
492
|
+
}
|
|
493
|
+
)
|
|
494
|
+
] });
|
|
495
|
+
}, "MarkdownMessage");
|
|
496
|
+
|
|
497
|
+
// src/tools/OpenapiViewer/utils/apiKeyManager.ts
|
|
498
|
+
function findApiKeyById(apiKeys, keyId) {
|
|
499
|
+
return apiKeys.find((key) => key.id === keyId) || null;
|
|
500
|
+
}
|
|
501
|
+
chunkWGEGR3DF_cjs.__name(findApiKeyById, "findApiKeyById");
|
|
502
|
+
|
|
503
|
+
// src/tools/OpenapiViewer/utils/versionManager.ts
|
|
504
|
+
var API_VERSIONS = [
|
|
505
|
+
{
|
|
506
|
+
id: "v1",
|
|
507
|
+
name: "v1",
|
|
508
|
+
description: "Current stable version",
|
|
509
|
+
isDefault: true
|
|
510
|
+
}
|
|
511
|
+
];
|
|
512
|
+
var detectEndpointVersion = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((path) => {
|
|
513
|
+
const versionMatch = path.match(/\/api\/[^/]+\/(v\d+)\//);
|
|
514
|
+
if (versionMatch && versionMatch[1]) {
|
|
515
|
+
return versionMatch[1];
|
|
516
|
+
}
|
|
517
|
+
return "v1";
|
|
518
|
+
}, "detectEndpointVersion");
|
|
519
|
+
var isEndpointInVersion = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((endpoint, version) => {
|
|
520
|
+
const endpointVersion = detectEndpointVersion(endpoint.path);
|
|
521
|
+
return endpointVersion === version;
|
|
522
|
+
}, "isEndpointInVersion");
|
|
523
|
+
var deduplicateEndpoints = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((endpoints, preferredVersion) => {
|
|
524
|
+
const endpointMap = /* @__PURE__ */ new Map();
|
|
525
|
+
const groupedEndpoints = /* @__PURE__ */ new Map();
|
|
526
|
+
endpoints.forEach((endpoint) => {
|
|
527
|
+
const normalizedPath = normalizeEndpointPath(endpoint.path);
|
|
528
|
+
if (!groupedEndpoints.has(normalizedPath)) {
|
|
529
|
+
groupedEndpoints.set(normalizedPath, []);
|
|
530
|
+
}
|
|
531
|
+
groupedEndpoints.get(normalizedPath).push(endpoint);
|
|
532
|
+
});
|
|
533
|
+
groupedEndpoints.forEach((endpointGroup, normalizedPath) => {
|
|
534
|
+
let selectedEndpoint = null;
|
|
535
|
+
const versionEndpoint = endpointGroup.find((ep) => isEndpointInVersion(ep, preferredVersion));
|
|
536
|
+
if (versionEndpoint) {
|
|
537
|
+
selectedEndpoint = versionEndpoint;
|
|
538
|
+
} else if (endpointGroup.length > 0) {
|
|
539
|
+
selectedEndpoint = endpointGroup[0] || null;
|
|
540
|
+
}
|
|
541
|
+
if (selectedEndpoint) {
|
|
542
|
+
endpointMap.set(normalizedPath, selectedEndpoint);
|
|
543
|
+
}
|
|
544
|
+
});
|
|
545
|
+
return Array.from(endpointMap.values());
|
|
546
|
+
}, "deduplicateEndpoints");
|
|
547
|
+
var normalizeEndpointPath = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((path) => {
|
|
548
|
+
return path.replace(/\/v\d+\//, "/");
|
|
549
|
+
}, "normalizeEndpointPath");
|
|
550
|
+
var getDefaultVersion = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
|
|
551
|
+
const defaultVersion = API_VERSIONS.find((v) => v.isDefault);
|
|
552
|
+
if (defaultVersion) {
|
|
553
|
+
return defaultVersion;
|
|
554
|
+
}
|
|
555
|
+
if (API_VERSIONS.length > 0 && API_VERSIONS[0]) {
|
|
556
|
+
return API_VERSIONS[0];
|
|
557
|
+
}
|
|
558
|
+
throw new Error("No API versions defined");
|
|
559
|
+
}, "getDefaultVersion");
|
|
560
|
+
|
|
561
|
+
// src/tools/OpenapiViewer/utils/formatters.ts
|
|
562
|
+
var isValidJson = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((str) => {
|
|
563
|
+
if (!str || typeof str !== "string") return false;
|
|
564
|
+
try {
|
|
565
|
+
JSON.parse(str);
|
|
566
|
+
return true;
|
|
567
|
+
} catch {
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
}, "isValidJson");
|
|
571
|
+
var parseRequestHeaders = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name((headersString) => {
|
|
572
|
+
if (!headersString || typeof headersString !== "string") {
|
|
573
|
+
return { "Content-Type": "application/json" };
|
|
574
|
+
}
|
|
575
|
+
try {
|
|
576
|
+
const parsed = JSON.parse(headersString);
|
|
577
|
+
return typeof parsed === "object" && parsed !== null ? parsed : { "Content-Type": "application/json" };
|
|
578
|
+
} catch {
|
|
579
|
+
return { "Content-Type": "application/json" };
|
|
580
|
+
}
|
|
581
|
+
}, "parseRequestHeaders");
|
|
582
|
+
|
|
583
|
+
// src/tools/OpenapiViewer/utils/url.ts
|
|
584
|
+
var PATH_PARAM_RE = /\{([^{}]+)\}/g;
|
|
585
|
+
function extractPathPlaceholders(template) {
|
|
586
|
+
const seen = /* @__PURE__ */ new Set();
|
|
587
|
+
const out = [];
|
|
588
|
+
for (const match of template.matchAll(PATH_PARAM_RE)) {
|
|
589
|
+
const name = match[1];
|
|
590
|
+
if (!seen.has(name)) {
|
|
591
|
+
seen.add(name);
|
|
592
|
+
out.push(name);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return out;
|
|
596
|
+
}
|
|
597
|
+
chunkWGEGR3DF_cjs.__name(extractPathPlaceholders, "extractPathPlaceholders");
|
|
598
|
+
function substitutePath(template, values) {
|
|
599
|
+
return template.replace(PATH_PARAM_RE, (whole, name) => {
|
|
600
|
+
const v = values[name];
|
|
601
|
+
return v && v.trim() !== "" ? encodeURIComponent(v) : whole;
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
chunkWGEGR3DF_cjs.__name(substitutePath, "substitutePath");
|
|
605
|
+
function unfilledPlaceholders(template, values) {
|
|
606
|
+
return extractPathPlaceholders(template).filter(
|
|
607
|
+
(name) => !(values[name] ?? "").trim()
|
|
608
|
+
);
|
|
609
|
+
}
|
|
610
|
+
chunkWGEGR3DF_cjs.__name(unfilledPlaceholders, "unfilledPlaceholders");
|
|
611
|
+
function appendQuery(url, values, pathTemplate) {
|
|
612
|
+
const pathNames = new Set(extractPathPlaceholders(pathTemplate));
|
|
613
|
+
const queryEntries = Object.entries(values).filter(
|
|
614
|
+
([name, value]) => !pathNames.has(name) && value && value.trim() !== ""
|
|
615
|
+
);
|
|
616
|
+
if (queryEntries.length === 0) return url;
|
|
617
|
+
const [base, existingQuery = ""] = url.split("?", 2);
|
|
618
|
+
const params = new URLSearchParams(existingQuery);
|
|
619
|
+
for (const [k, v] of queryEntries) params.set(k, v);
|
|
620
|
+
const qs = params.toString();
|
|
621
|
+
return qs ? `${base}?${qs}` : base ?? url;
|
|
622
|
+
}
|
|
623
|
+
chunkWGEGR3DF_cjs.__name(appendQuery, "appendQuery");
|
|
624
|
+
function resolveAbsolute(url) {
|
|
625
|
+
if (!url) return url;
|
|
626
|
+
if (/^https?:\/\//i.test(url)) return url;
|
|
627
|
+
if (typeof window === "undefined") return url;
|
|
628
|
+
if (url.startsWith("//")) return `${window.location.protocol}${url}`;
|
|
629
|
+
if (url.startsWith("/")) return `${window.location.origin}${url}`;
|
|
630
|
+
return url;
|
|
631
|
+
}
|
|
632
|
+
chunkWGEGR3DF_cjs.__name(resolveAbsolute, "resolveAbsolute");
|
|
633
|
+
function relativePath(url) {
|
|
634
|
+
try {
|
|
635
|
+
return new URL(url).pathname;
|
|
636
|
+
} catch {
|
|
637
|
+
return url;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
chunkWGEGR3DF_cjs.__name(relativePath, "relativePath");
|
|
641
|
+
function joinUrl(...parts) {
|
|
642
|
+
return parts.filter((p) => p !== void 0 && p !== null && p !== "").map((p, i) => {
|
|
643
|
+
if (i === 0) return String(p).replace(/\/+$/, "");
|
|
644
|
+
return String(p).replace(/^\/+|\/+$/g, "");
|
|
645
|
+
}).filter((p) => p !== "").join("/");
|
|
646
|
+
}
|
|
647
|
+
chunkWGEGR3DF_cjs.__name(joinUrl, "joinUrl");
|
|
648
|
+
function resolveBaseUrl(sources) {
|
|
649
|
+
return sources.schemaSource || sources.config || sources.fromServers || "";
|
|
650
|
+
}
|
|
651
|
+
chunkWGEGR3DF_cjs.__name(resolveBaseUrl, "resolveBaseUrl");
|
|
652
|
+
var _UrlBuilder = class _UrlBuilder {
|
|
653
|
+
constructor(endpoint, parameters) {
|
|
654
|
+
this.endpoint = endpoint;
|
|
655
|
+
this.parameters = parameters;
|
|
656
|
+
}
|
|
657
|
+
/** What ``fetch()`` receives: substituted path + query string. Origin
|
|
658
|
+
* is whatever the endpoint template already had (relative paths
|
|
659
|
+
* stay relative so the browser resolves them against the page). */
|
|
660
|
+
build() {
|
|
661
|
+
const substituted = substitutePath(this.endpoint.path, this.parameters);
|
|
662
|
+
return appendQuery(substituted, this.parameters, this.endpoint.path);
|
|
663
|
+
}
|
|
664
|
+
/** Same as ``build()`` but guaranteed absolute — for curl snippets
|
|
665
|
+
* and anywhere the URL leaves the browser context. */
|
|
666
|
+
buildAbsolute() {
|
|
667
|
+
return resolveAbsolute(this.build());
|
|
668
|
+
}
|
|
669
|
+
/** Names of required path/query params still empty. */
|
|
670
|
+
missingRequired() {
|
|
671
|
+
if (!this.endpoint.parameters) return [];
|
|
672
|
+
return this.endpoint.parameters.filter((p) => p.required && !(this.parameters[p.name] ?? "").trim()).map((p) => p.name);
|
|
673
|
+
}
|
|
674
|
+
/** Placeholders in the template with no matching value. Usually a
|
|
675
|
+
* superset of ``missingRequired`` — catches schemas that forgot
|
|
676
|
+
* to flag a path param as required. */
|
|
677
|
+
unfilledPlaceholders() {
|
|
678
|
+
return unfilledPlaceholders(this.endpoint.path, this.parameters);
|
|
679
|
+
}
|
|
680
|
+
};
|
|
681
|
+
chunkWGEGR3DF_cjs.__name(_UrlBuilder, "UrlBuilder");
|
|
682
|
+
var UrlBuilder = _UrlBuilder;
|
|
683
|
+
|
|
684
|
+
// src/tools/OpenapiViewer/utils/schemaExport.ts
|
|
685
|
+
function dereferenceSchema(schema, maxDepth = 10) {
|
|
686
|
+
const root = schema;
|
|
687
|
+
function resolveRef(ref) {
|
|
688
|
+
if (!ref.startsWith("#/")) return null;
|
|
689
|
+
const parts = ref.slice(2).split("/");
|
|
690
|
+
let node = root;
|
|
691
|
+
for (const part of parts) {
|
|
692
|
+
if (node && typeof node === "object" && part in node) {
|
|
693
|
+
node = node[part];
|
|
694
|
+
} else {
|
|
695
|
+
return null;
|
|
696
|
+
}
|
|
697
|
+
}
|
|
698
|
+
return node;
|
|
699
|
+
}
|
|
700
|
+
chunkWGEGR3DF_cjs.__name(resolveRef, "resolveRef");
|
|
701
|
+
function walk(value, depth) {
|
|
702
|
+
if (depth > maxDepth) return value;
|
|
703
|
+
if (Array.isArray(value)) return value.map((v) => walk(v, depth + 1));
|
|
704
|
+
if (value && typeof value === "object") {
|
|
705
|
+
const obj = value;
|
|
706
|
+
if (typeof obj.$ref === "string") {
|
|
707
|
+
const resolved = resolveRef(obj.$ref);
|
|
708
|
+
if (resolved === null) return obj;
|
|
709
|
+
return walk(resolved, depth + 1);
|
|
710
|
+
}
|
|
711
|
+
const out = {};
|
|
712
|
+
for (const [k, v] of Object.entries(obj)) out[k] = walk(v, depth + 1);
|
|
713
|
+
return out;
|
|
714
|
+
}
|
|
715
|
+
return value;
|
|
716
|
+
}
|
|
717
|
+
chunkWGEGR3DF_cjs.__name(walk, "walk");
|
|
718
|
+
return walk(schema, 0);
|
|
719
|
+
}
|
|
720
|
+
chunkWGEGR3DF_cjs.__name(dereferenceSchema, "dereferenceSchema");
|
|
721
|
+
var NOISY_KEYS = /* @__PURE__ */ new Set(["xml", "example", "examples", "externalDocs"]);
|
|
722
|
+
var MAX_DESCRIPTION_LEN = 500;
|
|
723
|
+
function pruneForCompact(value) {
|
|
724
|
+
if (Array.isArray(value)) return value.map(pruneForCompact);
|
|
725
|
+
if (value && typeof value === "object") {
|
|
726
|
+
const out = {};
|
|
727
|
+
for (const [k, v] of Object.entries(value)) {
|
|
728
|
+
if (NOISY_KEYS.has(k)) continue;
|
|
729
|
+
if (k === "description" && typeof v === "string" && v.length > MAX_DESCRIPTION_LEN) {
|
|
730
|
+
out[k] = v.slice(0, MAX_DESCRIPTION_LEN).trimEnd() + "\u2026";
|
|
731
|
+
continue;
|
|
732
|
+
}
|
|
733
|
+
out[k] = pruneForCompact(v);
|
|
734
|
+
}
|
|
735
|
+
return out;
|
|
736
|
+
}
|
|
737
|
+
return value;
|
|
738
|
+
}
|
|
739
|
+
chunkWGEGR3DF_cjs.__name(pruneForCompact, "pruneForCompact");
|
|
740
|
+
function withResolvedBaseUrl(schema, baseUrl) {
|
|
741
|
+
if (!baseUrl) return schema;
|
|
742
|
+
return { ...schema, servers: [{ url: baseUrl }] };
|
|
743
|
+
}
|
|
744
|
+
chunkWGEGR3DF_cjs.__name(withResolvedBaseUrl, "withResolvedBaseUrl");
|
|
745
|
+
function toRawJson(schema, baseUrl) {
|
|
746
|
+
return JSON.stringify(withResolvedBaseUrl(schema, baseUrl), null, 2);
|
|
747
|
+
}
|
|
748
|
+
chunkWGEGR3DF_cjs.__name(toRawJson, "toRawJson");
|
|
749
|
+
function toCompactJson(schema, baseUrl) {
|
|
750
|
+
const resolved = dereferenceSchema(withResolvedBaseUrl(schema, baseUrl));
|
|
751
|
+
const pruned = pruneForCompact(resolved);
|
|
752
|
+
return JSON.stringify(pruned);
|
|
753
|
+
}
|
|
754
|
+
chunkWGEGR3DF_cjs.__name(toCompactJson, "toCompactJson");
|
|
755
|
+
function endpointToMarkdown(ep) {
|
|
756
|
+
const lines = [];
|
|
757
|
+
lines.push(`### ${ep.method} ${ep.path}`);
|
|
758
|
+
if (ep.description) lines.push(ep.description);
|
|
759
|
+
const pathParams = ep.parameters?.filter((p) => ep.path.includes(`{${p.name}}`)) ?? [];
|
|
760
|
+
const queryParams = ep.parameters?.filter((p) => !ep.path.includes(`{${p.name}}`)) ?? [];
|
|
761
|
+
if (pathParams.length > 0) {
|
|
762
|
+
lines.push("", "**Path parameters**");
|
|
763
|
+
for (const p of pathParams) {
|
|
764
|
+
const req = p.required ? " (required)" : "";
|
|
765
|
+
const desc = p.description ? ` \u2014 ${p.description}` : "";
|
|
766
|
+
lines.push(`- \`${p.name}\`: ${p.type}${req}${desc}`);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
if (queryParams.length > 0) {
|
|
770
|
+
lines.push("", "**Query parameters**");
|
|
771
|
+
for (const p of queryParams) {
|
|
772
|
+
const req = p.required ? " (required)" : "";
|
|
773
|
+
const desc = p.description ? ` \u2014 ${p.description}` : "";
|
|
774
|
+
lines.push(`- \`${p.name}\`: ${p.type}${req}${desc}`);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
if (ep.requestBody) {
|
|
778
|
+
const desc = ep.requestBody.description ? ` \u2014 ${ep.requestBody.description}` : "";
|
|
779
|
+
lines.push("", `**Request body:** ${ep.requestBody.type}${desc}`);
|
|
780
|
+
}
|
|
781
|
+
if (ep.responses && ep.responses.length > 0) {
|
|
782
|
+
lines.push("", "**Responses**");
|
|
783
|
+
for (const r of ep.responses) {
|
|
784
|
+
lines.push(`- \`${r.code}\` \u2014 ${r.description}`);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
return lines.join("\n");
|
|
788
|
+
}
|
|
789
|
+
chunkWGEGR3DF_cjs.__name(endpointToMarkdown, "endpointToMarkdown");
|
|
790
|
+
function toMarkdown(schema, endpoints, baseUrl) {
|
|
791
|
+
const lines = [];
|
|
792
|
+
const info = schema.info;
|
|
793
|
+
const resolvedBase = resolveBaseUrl({
|
|
794
|
+
config: baseUrl,
|
|
795
|
+
fromServers: schema.servers?.[0]?.url
|
|
796
|
+
});
|
|
797
|
+
lines.push(`# ${info?.title ?? "API"}${info?.version ? ` (v${info.version})` : ""}`);
|
|
798
|
+
if (resolvedBase) lines.push("", `**Base URL:** \`${resolvedBase}\``);
|
|
799
|
+
if (info?.description) lines.push("", info.description.trim());
|
|
800
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
801
|
+
for (const ep of endpoints) {
|
|
802
|
+
const arr = grouped.get(ep.category) ?? [];
|
|
803
|
+
arr.push(ep);
|
|
804
|
+
grouped.set(ep.category, arr);
|
|
805
|
+
}
|
|
806
|
+
const categories = Array.from(grouped.keys()).sort((a, b) => {
|
|
807
|
+
if (a === "Other") return 1;
|
|
808
|
+
if (b === "Other") return -1;
|
|
809
|
+
return a.localeCompare(b);
|
|
810
|
+
});
|
|
811
|
+
for (const category of categories) {
|
|
812
|
+
lines.push("", `## ${category}`);
|
|
813
|
+
const list = grouped.get(category);
|
|
814
|
+
for (const ep of list) {
|
|
815
|
+
const displayPath = relativePath(ep.path);
|
|
816
|
+
const sub = endpointToMarkdown({ ...ep, path: displayPath });
|
|
817
|
+
lines.push("", sub);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
return lines.join("\n");
|
|
821
|
+
}
|
|
822
|
+
chunkWGEGR3DF_cjs.__name(toMarkdown, "toMarkdown");
|
|
823
|
+
function formatBytes(s) {
|
|
824
|
+
const bytes = new Blob([s]).size;
|
|
825
|
+
if (bytes < 1024) return `${bytes} B`;
|
|
826
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
|
|
827
|
+
return `${(bytes / 1024 / 1024).toFixed(2)} MB`;
|
|
828
|
+
}
|
|
829
|
+
chunkWGEGR3DF_cjs.__name(formatBytes, "formatBytes");
|
|
830
|
+
var AUTH_KEY_STORAGE = "openapi-playground:auth:apiKeyId";
|
|
831
|
+
var AUTH_BEARER_STORAGE = "openapi-playground:auth:bearer";
|
|
832
|
+
var createInitialState = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => ({
|
|
833
|
+
currentStep: "endpoints",
|
|
834
|
+
steps: ["endpoints", "request", "response"],
|
|
835
|
+
selectedEndpoint: null,
|
|
836
|
+
selectedCategory: "All",
|
|
837
|
+
searchTerm: "",
|
|
838
|
+
selectedVersion: getDefaultVersion().id,
|
|
839
|
+
requestUrl: "",
|
|
840
|
+
requestMethod: "GET",
|
|
841
|
+
requestHeaders: '{\n "Content-Type": "application/json"\n}',
|
|
842
|
+
requestBody: "",
|
|
843
|
+
selectedApiKey: null,
|
|
844
|
+
manualApiToken: "",
|
|
845
|
+
parameters: {},
|
|
846
|
+
response: null,
|
|
847
|
+
loading: false,
|
|
848
|
+
sidebarOpen: false,
|
|
849
|
+
activeSchemaId: null
|
|
850
|
+
}), "createInitialState");
|
|
851
|
+
function reducer(state, action) {
|
|
852
|
+
switch (action.type) {
|
|
853
|
+
case "SET_STEP":
|
|
854
|
+
return { ...state, currentStep: action.step };
|
|
855
|
+
case "NEXT_STEP": {
|
|
856
|
+
const i = state.steps.indexOf(state.currentStep);
|
|
857
|
+
return i < state.steps.length - 1 ? { ...state, currentStep: state.steps[i + 1] } : state;
|
|
858
|
+
}
|
|
859
|
+
case "PREV_STEP": {
|
|
860
|
+
const i = state.steps.indexOf(state.currentStep);
|
|
861
|
+
return i > 0 ? { ...state, currentStep: state.steps[i - 1] } : state;
|
|
862
|
+
}
|
|
863
|
+
case "SELECT_ENDPOINT": {
|
|
864
|
+
if (!action.endpoint) return { ...state, selectedEndpoint: null };
|
|
865
|
+
const same = state.selectedEndpoint?.method === action.endpoint.method && state.selectedEndpoint?.path === action.endpoint.path;
|
|
866
|
+
const exampleBody = action.endpoint.requestBody?.example ?? "";
|
|
867
|
+
return {
|
|
868
|
+
...state,
|
|
869
|
+
selectedEndpoint: action.endpoint,
|
|
870
|
+
requestMethod: action.endpoint.method,
|
|
871
|
+
requestUrl: action.endpoint.path,
|
|
872
|
+
parameters: same ? state.parameters : {},
|
|
873
|
+
requestBody: same ? state.requestBody : exampleBody,
|
|
874
|
+
// Switching to a different endpoint: the previous response no
|
|
875
|
+
// longer belongs here. Clear it so the playground panel collapses
|
|
876
|
+
// back to single-column until the user sends a new request.
|
|
877
|
+
response: same ? state.response : null,
|
|
878
|
+
currentStep: "request"
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
case "SET_CATEGORY":
|
|
882
|
+
return { ...state, selectedCategory: action.category };
|
|
883
|
+
case "SET_SEARCH":
|
|
884
|
+
return { ...state, searchTerm: action.term };
|
|
885
|
+
case "SET_VERSION":
|
|
886
|
+
return { ...state, selectedVersion: action.version };
|
|
887
|
+
case "SET_REQUEST_URL":
|
|
888
|
+
return { ...state, requestUrl: action.url };
|
|
889
|
+
case "SET_REQUEST_METHOD":
|
|
890
|
+
return { ...state, requestMethod: action.method };
|
|
891
|
+
case "SET_REQUEST_HEADERS":
|
|
892
|
+
return { ...state, requestHeaders: action.headers };
|
|
893
|
+
case "SET_REQUEST_BODY":
|
|
894
|
+
return { ...state, requestBody: action.body };
|
|
895
|
+
case "SET_API_KEY":
|
|
896
|
+
return { ...state, selectedApiKey: action.apiKeyId };
|
|
897
|
+
case "SET_MANUAL_TOKEN":
|
|
898
|
+
return { ...state, manualApiToken: action.token };
|
|
899
|
+
case "SET_PARAMETERS":
|
|
900
|
+
return { ...state, parameters: action.parameters };
|
|
901
|
+
case "SET_RESPONSE":
|
|
902
|
+
return { ...state, response: action.response };
|
|
903
|
+
case "SET_LOADING":
|
|
904
|
+
return { ...state, loading: action.loading };
|
|
905
|
+
case "REQUEST_START":
|
|
906
|
+
return { ...state, loading: true, response: null };
|
|
907
|
+
case "REQUEST_SUCCESS":
|
|
908
|
+
return { ...state, loading: false, response: action.response, currentStep: "response" };
|
|
909
|
+
case "REQUEST_ERROR":
|
|
910
|
+
return { ...state, loading: false, response: action.response };
|
|
911
|
+
case "SET_SIDEBAR":
|
|
912
|
+
return { ...state, sidebarOpen: action.open };
|
|
913
|
+
case "SET_ACTIVE_SCHEMA_ID":
|
|
914
|
+
return { ...state, activeSchemaId: action.id };
|
|
915
|
+
case "SYNC_API_KEY_HEADER":
|
|
916
|
+
return { ...state, requestHeaders: action.headers };
|
|
917
|
+
case "CLEAR_API_KEY_SELECTION":
|
|
918
|
+
return { ...state, selectedApiKey: null };
|
|
919
|
+
case "SYNC_URL":
|
|
920
|
+
return { ...state, requestUrl: action.url };
|
|
921
|
+
case "RESET":
|
|
922
|
+
return createInitialState();
|
|
923
|
+
default:
|
|
924
|
+
return state;
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
chunkWGEGR3DF_cjs.__name(reducer, "reducer");
|
|
928
|
+
var PlaygroundContext = React3.createContext(void 0);
|
|
929
|
+
var usePlaygroundContext = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(() => {
|
|
930
|
+
const context = React3.useContext(PlaygroundContext);
|
|
931
|
+
if (!context) throw new Error("usePlaygroundContext must be used within a PlaygroundProvider");
|
|
932
|
+
return context;
|
|
933
|
+
}, "usePlaygroundContext");
|
|
934
|
+
var PlaygroundProvider = /* @__PURE__ */ chunkWGEGR3DF_cjs.__name(({ children, config }) => {
|
|
935
|
+
const [state, dispatch] = React3.useReducer(reducer, void 0, createInitialState);
|
|
936
|
+
const abortControllerRef = React3.useRef(null);
|
|
937
|
+
const apiKeys = React3__default.default.useMemo(
|
|
938
|
+
() => config.apiKeys ?? [],
|
|
939
|
+
[config.apiKeys]
|
|
940
|
+
);
|
|
941
|
+
const isLoadingApiKeys = config.apiKeysLoading ?? false;
|
|
942
|
+
const [storedApiKeyId, setStoredApiKeyId] = hooks.useSessionStorage(
|
|
943
|
+
AUTH_KEY_STORAGE,
|
|
944
|
+
null
|
|
945
|
+
);
|
|
946
|
+
const [storedBearer, setStoredBearer] = hooks.useSessionStorage(
|
|
947
|
+
AUTH_BEARER_STORAGE,
|
|
948
|
+
""
|
|
949
|
+
);
|
|
950
|
+
const hasHydratedAuthRef = React3.useRef(false);
|
|
951
|
+
React3.useEffect(() => {
|
|
952
|
+
if (hasHydratedAuthRef.current) return;
|
|
953
|
+
hasHydratedAuthRef.current = true;
|
|
954
|
+
if (storedApiKeyId) dispatch({ type: "SET_API_KEY", apiKeyId: storedApiKeyId });
|
|
955
|
+
if (storedBearer) dispatch({ type: "SET_MANUAL_TOKEN", token: storedBearer });
|
|
956
|
+
}, []);
|
|
957
|
+
React3.useEffect(() => {
|
|
958
|
+
if (!hasHydratedAuthRef.current) return;
|
|
959
|
+
setStoredApiKeyId(state.selectedApiKey);
|
|
960
|
+
}, [state.selectedApiKey, setStoredApiKeyId]);
|
|
961
|
+
React3.useEffect(() => {
|
|
962
|
+
if (!hasHydratedAuthRef.current) return;
|
|
963
|
+
setStoredBearer(state.manualApiToken);
|
|
964
|
+
}, [state.manualApiToken, setStoredBearer]);
|
|
965
|
+
React3.useEffect(() => {
|
|
966
|
+
if (!hasHydratedAuthRef.current) return;
|
|
967
|
+
if (!isLoadingApiKeys && apiKeys.length > 0 && !state.selectedApiKey && !storedApiKeyId) {
|
|
968
|
+
dispatch({ type: "SET_API_KEY", apiKeyId: apiKeys[0]?.id || null });
|
|
969
|
+
}
|
|
970
|
+
}, [apiKeys, isLoadingApiKeys, state.selectedApiKey, storedApiKeyId]);
|
|
971
|
+
React3.useEffect(() => {
|
|
972
|
+
try {
|
|
973
|
+
const headers = parseRequestHeaders(state.requestHeaders);
|
|
974
|
+
if (state.selectedApiKey) {
|
|
975
|
+
const apiKey = apiKeys.find((k) => k.id === state.selectedApiKey);
|
|
976
|
+
if (!apiKey) {
|
|
977
|
+
dispatch({ type: "CLEAR_API_KEY_SELECTION" });
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
const keyValue = apiKey.secret || apiKey.id;
|
|
981
|
+
if (headers["X-API-Key"] !== keyValue) {
|
|
982
|
+
headers["X-API-Key"] = keyValue;
|
|
983
|
+
dispatch({ type: "SYNC_API_KEY_HEADER", headers: JSON.stringify(headers, null, 2) });
|
|
984
|
+
}
|
|
985
|
+
} else if (headers["X-API-Key"]) {
|
|
986
|
+
delete headers["X-API-Key"];
|
|
987
|
+
dispatch({ type: "SYNC_API_KEY_HEADER", headers: JSON.stringify(headers, null, 2) });
|
|
988
|
+
}
|
|
989
|
+
} catch (error) {
|
|
990
|
+
consola__default.default.error("Error updating headers:", error);
|
|
991
|
+
}
|
|
992
|
+
}, [state.selectedApiKey, apiKeys]);
|
|
993
|
+
React3.useEffect(() => {
|
|
994
|
+
if (!state.selectedEndpoint) return;
|
|
995
|
+
const updated = new UrlBuilder(state.selectedEndpoint, state.parameters).build();
|
|
996
|
+
if (updated !== state.requestUrl) {
|
|
997
|
+
dispatch({ type: "SYNC_URL", url: updated });
|
|
998
|
+
}
|
|
999
|
+
}, [state.parameters, state.selectedEndpoint]);
|
|
1000
|
+
const setCurrentStep = React3.useCallback((step) => dispatch({ type: "SET_STEP", step }), []);
|
|
1001
|
+
const goToNextStep = React3.useCallback(() => dispatch({ type: "NEXT_STEP" }), []);
|
|
1002
|
+
const goToPreviousStep = React3.useCallback(() => dispatch({ type: "PREV_STEP" }), []);
|
|
1003
|
+
const setSelectedEndpoint = React3.useCallback((endpoint) => dispatch({ type: "SELECT_ENDPOINT", endpoint }), []);
|
|
1004
|
+
const setSelectedCategory = React3.useCallback((category) => dispatch({ type: "SET_CATEGORY", category }), []);
|
|
1005
|
+
const setSearchTerm = React3.useCallback((term) => dispatch({ type: "SET_SEARCH", term }), []);
|
|
1006
|
+
const setSelectedVersion = React3.useCallback((version) => dispatch({ type: "SET_VERSION", version }), []);
|
|
1007
|
+
const setRequestUrl = React3.useCallback((url) => dispatch({ type: "SET_REQUEST_URL", url }), []);
|
|
1008
|
+
const setRequestMethod = React3.useCallback((method) => dispatch({ type: "SET_REQUEST_METHOD", method }), []);
|
|
1009
|
+
const setRequestHeaders = React3.useCallback((headers) => dispatch({ type: "SET_REQUEST_HEADERS", headers }), []);
|
|
1010
|
+
const setRequestBody = React3.useCallback((body) => dispatch({ type: "SET_REQUEST_BODY", body }), []);
|
|
1011
|
+
const setSelectedApiKey = React3.useCallback((apiKeyId) => dispatch({ type: "SET_API_KEY", apiKeyId }), []);
|
|
1012
|
+
const setManualApiToken = React3.useCallback((token) => dispatch({ type: "SET_MANUAL_TOKEN", token }), []);
|
|
1013
|
+
const setParameters = React3.useCallback((parameters) => dispatch({ type: "SET_PARAMETERS", parameters }), []);
|
|
1014
|
+
const setResponse = React3.useCallback((response) => dispatch({ type: "SET_RESPONSE", response }), []);
|
|
1015
|
+
const setLoading = React3.useCallback((loading) => dispatch({ type: "SET_LOADING", loading }), []);
|
|
1016
|
+
const setSidebarOpen = React3.useCallback((open) => dispatch({ type: "SET_SIDEBAR", open }), []);
|
|
1017
|
+
const setActiveSchemaId = React3.useCallback((id) => dispatch({ type: "SET_ACTIVE_SCHEMA_ID", id }), []);
|
|
1018
|
+
const clearAll = React3.useCallback(() => dispatch({ type: "RESET" }), []);
|
|
1019
|
+
const sendRequest = React3.useCallback(async () => {
|
|
1020
|
+
if (!state.requestUrl) {
|
|
1021
|
+
consola__default.default.error("No URL provided");
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
abortControllerRef.current?.abort();
|
|
1025
|
+
const controller = new AbortController();
|
|
1026
|
+
abortControllerRef.current = controller;
|
|
1027
|
+
dispatch({ type: "REQUEST_START" });
|
|
1028
|
+
const startTime = Date.now();
|
|
1029
|
+
try {
|
|
1030
|
+
const headers = parseRequestHeaders(state.requestHeaders);
|
|
1031
|
+
let bearerToken = null;
|
|
1032
|
+
if (state.manualApiToken) {
|
|
1033
|
+
bearerToken = state.manualApiToken;
|
|
1034
|
+
} else if (typeof window !== "undefined") {
|
|
1035
|
+
bearerToken = window.localStorage.getItem("auth_token");
|
|
1036
|
+
}
|
|
1037
|
+
if (bearerToken) headers["Authorization"] = `Bearer ${bearerToken}`;
|
|
1038
|
+
const requestOptions = {
|
|
1039
|
+
method: state.requestMethod,
|
|
1040
|
+
headers,
|
|
1041
|
+
signal: controller.signal
|
|
1042
|
+
};
|
|
1043
|
+
if (state.requestBody && state.requestMethod !== "GET") {
|
|
1044
|
+
requestOptions.body = state.requestBody;
|
|
1045
|
+
}
|
|
1046
|
+
const response = await fetch(state.requestUrl, requestOptions);
|
|
1047
|
+
const duration = Date.now() - startTime;
|
|
1048
|
+
const responseText = await response.text();
|
|
1049
|
+
let responseData;
|
|
1050
|
+
try {
|
|
1051
|
+
responseData = JSON.parse(responseText);
|
|
1052
|
+
} catch {
|
|
1053
|
+
responseData = responseText;
|
|
1054
|
+
}
|
|
1055
|
+
dispatch({
|
|
1056
|
+
type: "REQUEST_SUCCESS",
|
|
1057
|
+
response: {
|
|
1058
|
+
status: response.status,
|
|
1059
|
+
statusText: response.statusText,
|
|
1060
|
+
headers: Object.fromEntries(response.headers.entries()),
|
|
1061
|
+
data: responseData,
|
|
1062
|
+
duration
|
|
1063
|
+
}
|
|
1064
|
+
});
|
|
1065
|
+
consola__default.default.success(`${state.requestMethod} ${state.requestUrl} \u2192 ${response.status} (${duration}ms)`);
|
|
1066
|
+
} catch (error) {
|
|
1067
|
+
if (error instanceof DOMException && error.name === "AbortError") return;
|
|
1068
|
+
consola__default.default.error("Request failed:", error);
|
|
1069
|
+
dispatch({
|
|
1070
|
+
type: "REQUEST_ERROR",
|
|
1071
|
+
response: {
|
|
1072
|
+
error: error instanceof Error ? error.message : "Request failed",
|
|
1073
|
+
duration: Date.now() - startTime
|
|
1074
|
+
}
|
|
1075
|
+
});
|
|
1076
|
+
}
|
|
1077
|
+
}, [state.requestUrl, state.requestHeaders, state.manualApiToken, state.requestMethod, state.requestBody]);
|
|
1078
|
+
const contextValue = {
|
|
1079
|
+
state,
|
|
1080
|
+
config,
|
|
1081
|
+
apiKeys,
|
|
1082
|
+
apiKeysLoading: isLoadingApiKeys,
|
|
1083
|
+
setCurrentStep,
|
|
1084
|
+
goToNextStep,
|
|
1085
|
+
goToPreviousStep,
|
|
1086
|
+
setSelectedEndpoint,
|
|
1087
|
+
setSelectedCategory,
|
|
1088
|
+
setSearchTerm,
|
|
1089
|
+
setSelectedVersion,
|
|
1090
|
+
setRequestUrl,
|
|
1091
|
+
setRequestMethod,
|
|
1092
|
+
setRequestHeaders,
|
|
1093
|
+
setRequestBody,
|
|
1094
|
+
setSelectedApiKey,
|
|
1095
|
+
setManualApiToken,
|
|
1096
|
+
setParameters,
|
|
1097
|
+
setResponse,
|
|
1098
|
+
setLoading,
|
|
1099
|
+
setSidebarOpen,
|
|
1100
|
+
setActiveSchemaId,
|
|
1101
|
+
clearAll,
|
|
1102
|
+
sendRequest
|
|
1103
|
+
};
|
|
1104
|
+
return /* @__PURE__ */ jsxRuntime.jsx(PlaygroundContext.Provider, { value: contextValue, children });
|
|
1105
|
+
}, "PlaygroundProvider");
|
|
1106
|
+
|
|
1107
|
+
exports.MarkdownMessage = MarkdownMessage;
|
|
1108
|
+
exports.Mermaid_default = Mermaid_default;
|
|
1109
|
+
exports.PlaygroundProvider = PlaygroundProvider;
|
|
1110
|
+
exports.PrettyCode_default = PrettyCode_default;
|
|
1111
|
+
exports.UrlBuilder = UrlBuilder;
|
|
1112
|
+
exports.deduplicateEndpoints = deduplicateEndpoints;
|
|
1113
|
+
exports.dereferenceSchema = dereferenceSchema;
|
|
1114
|
+
exports.endpointToMarkdown = endpointToMarkdown;
|
|
1115
|
+
exports.findApiKeyById = findApiKeyById;
|
|
1116
|
+
exports.formatBytes = formatBytes;
|
|
1117
|
+
exports.isValidJson = isValidJson;
|
|
1118
|
+
exports.joinUrl = joinUrl;
|
|
1119
|
+
exports.parseRequestHeaders = parseRequestHeaders;
|
|
1120
|
+
exports.relativePath = relativePath;
|
|
1121
|
+
exports.resolveAbsolute = resolveAbsolute;
|
|
1122
|
+
exports.resolveBaseUrl = resolveBaseUrl;
|
|
1123
|
+
exports.toCompactJson = toCompactJson;
|
|
1124
|
+
exports.toMarkdown = toMarkdown;
|
|
1125
|
+
exports.toRawJson = toRawJson;
|
|
1126
|
+
exports.useCollapsibleContent = useCollapsibleContent;
|
|
1127
|
+
exports.usePlaygroundContext = usePlaygroundContext;
|
|
1128
|
+
//# sourceMappingURL=chunk-IULI4XII.cjs.map
|
|
1129
|
+
//# sourceMappingURL=chunk-IULI4XII.cjs.map
|