@frontmcp/react 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +263 -0
- package/ai/createToolHandler.d.ts +10 -0
- package/ai/createToolHandler.d.ts.map +1 -0
- package/ai/index.d.ts +7 -0
- package/ai/index.d.ts.map +1 -0
- package/ai/index.js +416 -0
- package/ai/types.d.ts +52 -0
- package/ai/types.d.ts.map +1 -0
- package/ai/useAITools.d.ts +17 -0
- package/ai/useAITools.d.ts.map +1 -0
- package/ai/useTools.d.ts +19 -0
- package/ai/useTools.d.ts.map +1 -0
- package/api/api.types.d.ts +61 -0
- package/api/api.types.d.ts.map +1 -0
- package/api/createFetchClient.d.ts +9 -0
- package/api/createFetchClient.d.ts.map +1 -0
- package/api/index.d.ts +12 -0
- package/api/index.d.ts.map +1 -0
- package/api/index.js +402 -0
- package/api/parseOpenApiSpec.d.ts +9 -0
- package/api/parseOpenApiSpec.d.ts.map +1 -0
- package/api/useApiClient.d.ts +9 -0
- package/api/useApiClient.d.ts.map +1 -0
- package/components/AgentContent.d.ts +30 -0
- package/components/AgentContent.d.ts.map +1 -0
- package/components/AgentSearch.d.ts +35 -0
- package/components/AgentSearch.d.ts.map +1 -0
- package/components/ComponentRegistry.d.ts +36 -0
- package/components/ComponentRegistry.d.ts.map +1 -0
- package/components/DomResources.d.ts +16 -0
- package/components/DomResources.d.ts.map +1 -0
- package/components/DynamicRenderer.d.ts +19 -0
- package/components/DynamicRenderer.d.ts.map +1 -0
- package/components/OutputDisplay.d.ts +11 -0
- package/components/OutputDisplay.d.ts.map +1 -0
- package/components/PromptForm.d.ts +13 -0
- package/components/PromptForm.d.ts.map +1 -0
- package/components/ResourceViewer.d.ts +18 -0
- package/components/ResourceViewer.d.ts.map +1 -0
- package/components/ToolForm.d.ts +16 -0
- package/components/ToolForm.d.ts.map +1 -0
- package/components/index.d.ts +21 -0
- package/components/index.d.ts.map +1 -0
- package/components/mcpComponent.d.ts +48 -0
- package/components/mcpComponent.d.ts.map +1 -0
- package/esm/ai/index.mjs +393 -0
- package/esm/api/index.mjs +379 -0
- package/esm/index.mjs +1814 -0
- package/esm/package.json +111 -0
- package/esm/router/index.mjs +157 -0
- package/esm/state/index.mjs +450 -0
- package/hooks/index.d.ts +21 -0
- package/hooks/index.d.ts.map +1 -0
- package/hooks/useCallTool.d.ts +9 -0
- package/hooks/useCallTool.d.ts.map +1 -0
- package/hooks/useComponentTree.d.ts +21 -0
- package/hooks/useComponentTree.d.ts.map +1 -0
- package/hooks/useDynamicResource.d.ts +20 -0
- package/hooks/useDynamicResource.d.ts.map +1 -0
- package/hooks/useDynamicTool.d.ts +39 -0
- package/hooks/useDynamicTool.d.ts.map +1 -0
- package/hooks/useFrontMcp.d.ts +8 -0
- package/hooks/useFrontMcp.d.ts.map +1 -0
- package/hooks/useGetPrompt.d.ts +13 -0
- package/hooks/useGetPrompt.d.ts.map +1 -0
- package/hooks/useListPrompts.d.ts +10 -0
- package/hooks/useListPrompts.d.ts.map +1 -0
- package/hooks/useListResources.d.ts +14 -0
- package/hooks/useListResources.d.ts.map +1 -0
- package/hooks/useListTools.d.ts +10 -0
- package/hooks/useListTools.d.ts.map +1 -0
- package/hooks/useReadResource.d.ts +23 -0
- package/hooks/useReadResource.d.ts.map +1 -0
- package/hooks/useResolvedServer.d.ts +16 -0
- package/hooks/useResolvedServer.d.ts.map +1 -0
- package/hooks/useServer.d.ts +17 -0
- package/hooks/useServer.d.ts.map +1 -0
- package/hooks/useStoreResource.d.ts +22 -0
- package/hooks/useStoreResource.d.ts.map +1 -0
- package/index.d.ts +33 -0
- package/index.d.ts.map +1 -0
- package/index.js +1821 -0
- package/package.json +111 -0
- package/provider/FrontMcpContext.d.ts +6 -0
- package/provider/FrontMcpContext.d.ts.map +1 -0
- package/provider/FrontMcpProvider.d.ts +34 -0
- package/provider/FrontMcpProvider.d.ts.map +1 -0
- package/provider/index.d.ts +4 -0
- package/provider/index.d.ts.map +1 -0
- package/registry/DynamicRegistry.d.ts +55 -0
- package/registry/DynamicRegistry.d.ts.map +1 -0
- package/registry/ServerRegistry.d.ts +43 -0
- package/registry/ServerRegistry.d.ts.map +1 -0
- package/registry/createWrappedServer.d.ts +14 -0
- package/registry/createWrappedServer.d.ts.map +1 -0
- package/registry/index.d.ts +5 -0
- package/registry/index.d.ts.map +1 -0
- package/router/current-route.resource.d.ts +11 -0
- package/router/current-route.resource.d.ts.map +1 -0
- package/router/go-back.tool.d.ts +18 -0
- package/router/go-back.tool.d.ts.map +1 -0
- package/router/index.d.ts +9 -0
- package/router/index.d.ts.map +1 -0
- package/router/index.js +180 -0
- package/router/navigate.tool.d.ts +35 -0
- package/router/navigate.tool.d.ts.map +1 -0
- package/router/router-bridge.d.ts +20 -0
- package/router/router-bridge.d.ts.map +1 -0
- package/router/router.entries.d.ts +23 -0
- package/router/router.entries.d.ts.map +1 -0
- package/router/useRouterBridge.d.ts +7 -0
- package/router/useRouterBridge.d.ts.map +1 -0
- package/state/adapters/createStore.d.ts +15 -0
- package/state/adapters/createStore.d.ts.map +1 -0
- package/state/adapters/index.d.ts +7 -0
- package/state/adapters/index.d.ts.map +1 -0
- package/state/adapters/reduxAdapter.d.ts +21 -0
- package/state/adapters/reduxAdapter.d.ts.map +1 -0
- package/state/adapters/valtioAdapter.d.ts +19 -0
- package/state/adapters/valtioAdapter.d.ts.map +1 -0
- package/state/index.d.ts +15 -0
- package/state/index.d.ts.map +1 -0
- package/state/index.js +473 -0
- package/state/state.types.d.ts +48 -0
- package/state/state.types.d.ts.map +1 -0
- package/state/useReduxResource.d.ts +8 -0
- package/state/useReduxResource.d.ts.map +1 -0
- package/state/useStoreRegistration.d.ts +14 -0
- package/state/useStoreRegistration.d.ts.map +1 -0
- package/state/useStoreResource.d.ts +10 -0
- package/state/useStoreResource.d.ts.map +1 -0
- package/state/useValtioResource.d.ts +9 -0
- package/state/useValtioResource.d.ts.map +1 -0
- package/types.d.ts +127 -0
- package/types.d.ts.map +1 -0
- package/utils/index.d.ts +2 -0
- package/utils/index.d.ts.map +1 -0
- package/utils/zodToJsonSchema.d.ts +9 -0
- package/utils/zodToJsonSchema.d.ts.map +1 -0
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
// libs/react/src/api/useApiClient.ts
|
|
2
|
+
import { useContext, useEffect, useRef } from "react";
|
|
3
|
+
|
|
4
|
+
// libs/react/src/provider/FrontMcpContext.ts
|
|
5
|
+
import { createContext } from "react";
|
|
6
|
+
|
|
7
|
+
// libs/react/src/components/ComponentRegistry.ts
|
|
8
|
+
var ComponentRegistry = class {
|
|
9
|
+
entries = /* @__PURE__ */ new Map();
|
|
10
|
+
register(uri, component, meta) {
|
|
11
|
+
const name = extractName(uri);
|
|
12
|
+
this.entries.set(uri, { uri, name, component, description: meta?.description });
|
|
13
|
+
}
|
|
14
|
+
registerAll(map) {
|
|
15
|
+
for (const [uri, component] of Object.entries(map)) {
|
|
16
|
+
this.register(uri, component);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
get(uri) {
|
|
20
|
+
return this.entries.get(uri)?.component;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Resolve a shorthand name like `'UserCard'` by trying
|
|
24
|
+
* `component://UserCard`, `element://UserCard`, `page://UserCard`.
|
|
25
|
+
*/
|
|
26
|
+
resolve(type) {
|
|
27
|
+
const exact = this.entries.get(type);
|
|
28
|
+
if (exact) return exact.component;
|
|
29
|
+
for (const protocol of ["component://", "element://", "page://"]) {
|
|
30
|
+
const entry = this.entries.get(`${protocol}${type}`);
|
|
31
|
+
if (entry) return entry.component;
|
|
32
|
+
}
|
|
33
|
+
return void 0;
|
|
34
|
+
}
|
|
35
|
+
has(uri) {
|
|
36
|
+
return this.entries.has(uri);
|
|
37
|
+
}
|
|
38
|
+
list() {
|
|
39
|
+
return Array.from(this.entries.values()).map(({ uri, name, description }) => ({
|
|
40
|
+
uri,
|
|
41
|
+
name,
|
|
42
|
+
description
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
clear() {
|
|
46
|
+
this.entries.clear();
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
function extractName(uri) {
|
|
50
|
+
const idx = uri.indexOf("://");
|
|
51
|
+
return idx >= 0 ? uri.slice(idx + 3) : uri;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// libs/react/src/registry/DynamicRegistry.ts
|
|
55
|
+
var DynamicRegistry = class {
|
|
56
|
+
tools = /* @__PURE__ */ new Map();
|
|
57
|
+
resources = /* @__PURE__ */ new Map();
|
|
58
|
+
toolRefCounts = /* @__PURE__ */ new Map();
|
|
59
|
+
resourceRefCounts = /* @__PURE__ */ new Map();
|
|
60
|
+
listeners = /* @__PURE__ */ new Set();
|
|
61
|
+
version = 0;
|
|
62
|
+
/**
|
|
63
|
+
* Register a dynamic tool. Returns an unregister function
|
|
64
|
+
* suitable for useEffect cleanup.
|
|
65
|
+
*
|
|
66
|
+
* Multiple registrations of the same name are ref-counted:
|
|
67
|
+
* subsequent registrations update the definition but the tool
|
|
68
|
+
* is only removed when every registrant has unregistered.
|
|
69
|
+
*/
|
|
70
|
+
registerTool(def) {
|
|
71
|
+
const existing = this.toolRefCounts.get(def.name) ?? 0;
|
|
72
|
+
this.toolRefCounts.set(def.name, existing + 1);
|
|
73
|
+
this.tools.set(def.name, def);
|
|
74
|
+
if (existing === 0) {
|
|
75
|
+
this.notify();
|
|
76
|
+
}
|
|
77
|
+
let called = false;
|
|
78
|
+
return () => {
|
|
79
|
+
if (called) return;
|
|
80
|
+
called = true;
|
|
81
|
+
this.unregisterTool(def.name);
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
unregisterTool(name) {
|
|
85
|
+
const count = this.toolRefCounts.get(name);
|
|
86
|
+
if (count == null) return;
|
|
87
|
+
if (count <= 1) {
|
|
88
|
+
this.toolRefCounts.delete(name);
|
|
89
|
+
this.tools.delete(name);
|
|
90
|
+
this.notify();
|
|
91
|
+
} else {
|
|
92
|
+
this.toolRefCounts.set(name, count - 1);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Register a dynamic resource. Returns an unregister function
|
|
97
|
+
* suitable for useEffect cleanup.
|
|
98
|
+
*
|
|
99
|
+
* Multiple registrations of the same URI are ref-counted.
|
|
100
|
+
*/
|
|
101
|
+
registerResource(def) {
|
|
102
|
+
const existing = this.resourceRefCounts.get(def.uri) ?? 0;
|
|
103
|
+
this.resourceRefCounts.set(def.uri, existing + 1);
|
|
104
|
+
this.resources.set(def.uri, def);
|
|
105
|
+
if (existing === 0) {
|
|
106
|
+
this.notify();
|
|
107
|
+
}
|
|
108
|
+
let called = false;
|
|
109
|
+
return () => {
|
|
110
|
+
if (called) return;
|
|
111
|
+
called = true;
|
|
112
|
+
this.unregisterResource(def.uri);
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
unregisterResource(uri) {
|
|
116
|
+
const count = this.resourceRefCounts.get(uri);
|
|
117
|
+
if (count == null) return;
|
|
118
|
+
if (count <= 1) {
|
|
119
|
+
this.resourceRefCounts.delete(uri);
|
|
120
|
+
this.resources.delete(uri);
|
|
121
|
+
this.notify();
|
|
122
|
+
} else {
|
|
123
|
+
this.resourceRefCounts.set(uri, count - 1);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
/** Update the execute function for an existing tool (for stale closure prevention). */
|
|
127
|
+
updateToolExecute(name, execute) {
|
|
128
|
+
const existing = this.tools.get(name);
|
|
129
|
+
if (existing) {
|
|
130
|
+
existing.execute = execute;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
/** Update the read function for an existing resource and notify subscribers. */
|
|
134
|
+
updateResourceRead(uri, read) {
|
|
135
|
+
const existing = this.resources.get(uri);
|
|
136
|
+
if (existing) {
|
|
137
|
+
existing.read = read;
|
|
138
|
+
this.notify();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
getTools() {
|
|
142
|
+
return [...this.tools.values()];
|
|
143
|
+
}
|
|
144
|
+
getResources() {
|
|
145
|
+
return [...this.resources.values()];
|
|
146
|
+
}
|
|
147
|
+
findTool(name) {
|
|
148
|
+
return this.tools.get(name);
|
|
149
|
+
}
|
|
150
|
+
findResource(uri) {
|
|
151
|
+
return this.resources.get(uri);
|
|
152
|
+
}
|
|
153
|
+
hasTool(name) {
|
|
154
|
+
return this.tools.has(name);
|
|
155
|
+
}
|
|
156
|
+
hasResource(uri) {
|
|
157
|
+
return this.resources.has(uri);
|
|
158
|
+
}
|
|
159
|
+
subscribe(listener) {
|
|
160
|
+
this.listeners.add(listener);
|
|
161
|
+
return () => {
|
|
162
|
+
this.listeners.delete(listener);
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
getVersion() {
|
|
166
|
+
return this.version;
|
|
167
|
+
}
|
|
168
|
+
clear() {
|
|
169
|
+
if (this.tools.size === 0 && this.resources.size === 0) return;
|
|
170
|
+
this.tools.clear();
|
|
171
|
+
this.resources.clear();
|
|
172
|
+
this.toolRefCounts.clear();
|
|
173
|
+
this.resourceRefCounts.clear();
|
|
174
|
+
this.notify();
|
|
175
|
+
}
|
|
176
|
+
notify() {
|
|
177
|
+
this.version++;
|
|
178
|
+
this.listeners.forEach((l) => {
|
|
179
|
+
l();
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
// libs/react/src/provider/FrontMcpContext.ts
|
|
185
|
+
var defaultDynamicRegistry = new DynamicRegistry();
|
|
186
|
+
var FrontMcpContext = createContext({
|
|
187
|
+
name: "default",
|
|
188
|
+
registry: new ComponentRegistry(),
|
|
189
|
+
dynamicRegistry: defaultDynamicRegistry,
|
|
190
|
+
getDynamicRegistry: () => defaultDynamicRegistry,
|
|
191
|
+
connect: async () => {
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
// libs/react/src/api/createFetchClient.ts
|
|
196
|
+
function createFetchClient(fetchFn) {
|
|
197
|
+
const fn = fetchFn ?? globalThis.fetch.bind(globalThis);
|
|
198
|
+
return {
|
|
199
|
+
async request(config) {
|
|
200
|
+
const fetchOptions = {
|
|
201
|
+
method: config.method,
|
|
202
|
+
headers: config.headers
|
|
203
|
+
};
|
|
204
|
+
if (config.body !== void 0) {
|
|
205
|
+
fetchOptions.body = JSON.stringify(config.body);
|
|
206
|
+
const headers = fetchOptions.headers;
|
|
207
|
+
if (headers && !headers["Content-Type"] && !headers["content-type"]) {
|
|
208
|
+
headers["Content-Type"] = "application/json";
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
const response = await fn(config.url, fetchOptions);
|
|
212
|
+
const responseText = await response.text();
|
|
213
|
+
let data;
|
|
214
|
+
try {
|
|
215
|
+
data = JSON.parse(responseText);
|
|
216
|
+
} catch {
|
|
217
|
+
data = responseText;
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
status: response.status,
|
|
221
|
+
statusText: response.statusText,
|
|
222
|
+
data
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// libs/react/src/api/useApiClient.ts
|
|
229
|
+
function interpolatePath(path, params) {
|
|
230
|
+
return path.replace(/\{(\w+)\}/g, (_, key) => {
|
|
231
|
+
const value = params[key];
|
|
232
|
+
return value != null ? encodeURIComponent(String(value)) : `{${key}}`;
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
function useApiClient(options) {
|
|
236
|
+
const { baseUrl, operations, headers, prefix = "api", client, fetch: customFetch } = options;
|
|
237
|
+
const { getDynamicRegistry } = useContext(FrontMcpContext);
|
|
238
|
+
const dynamicRegistry = getDynamicRegistry(options.server);
|
|
239
|
+
const headersRef = useRef(headers);
|
|
240
|
+
headersRef.current = headers;
|
|
241
|
+
const clientRef = useRef(client ?? createFetchClient(customFetch));
|
|
242
|
+
clientRef.current = client ?? createFetchClient(customFetch);
|
|
243
|
+
useEffect(() => {
|
|
244
|
+
const cleanups = [];
|
|
245
|
+
for (const op of operations) {
|
|
246
|
+
const toolName = `${prefix}_${op.operationId}`;
|
|
247
|
+
const execute = async (args) => {
|
|
248
|
+
const resolvedHeaders = {
|
|
249
|
+
"Content-Type": "application/json",
|
|
250
|
+
...typeof headersRef.current === "function" ? headersRef.current() : headersRef.current ?? {}
|
|
251
|
+
};
|
|
252
|
+
const url = baseUrl + interpolatePath(op.path, args);
|
|
253
|
+
const body = args["body"];
|
|
254
|
+
const method = op.method;
|
|
255
|
+
const requestConfig = {
|
|
256
|
+
method,
|
|
257
|
+
url,
|
|
258
|
+
headers: resolvedHeaders
|
|
259
|
+
};
|
|
260
|
+
if (body !== void 0 && method !== "GET" && method !== "HEAD") {
|
|
261
|
+
requestConfig.body = body;
|
|
262
|
+
}
|
|
263
|
+
const response = await clientRef.current.request(requestConfig);
|
|
264
|
+
return {
|
|
265
|
+
content: [
|
|
266
|
+
{
|
|
267
|
+
type: "text",
|
|
268
|
+
text: JSON.stringify({
|
|
269
|
+
status: response.status,
|
|
270
|
+
statusText: response.statusText,
|
|
271
|
+
data: response.data
|
|
272
|
+
})
|
|
273
|
+
}
|
|
274
|
+
],
|
|
275
|
+
isError: response.status >= 400
|
|
276
|
+
};
|
|
277
|
+
};
|
|
278
|
+
cleanups.push(
|
|
279
|
+
dynamicRegistry.registerTool({
|
|
280
|
+
name: toolName,
|
|
281
|
+
description: op.description,
|
|
282
|
+
inputSchema: op.inputSchema,
|
|
283
|
+
execute
|
|
284
|
+
})
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
return () => {
|
|
288
|
+
cleanups.forEach((fn) => {
|
|
289
|
+
fn();
|
|
290
|
+
});
|
|
291
|
+
};
|
|
292
|
+
}, [dynamicRegistry, baseUrl, operations, prefix, client, customFetch]);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// libs/react/src/api/parseOpenApiSpec.ts
|
|
296
|
+
var HTTP_METHODS = ["get", "post", "put", "delete", "patch", "options", "head"];
|
|
297
|
+
function parseOpenApiSpec(spec) {
|
|
298
|
+
const paths = spec["paths"];
|
|
299
|
+
if (!paths) return [];
|
|
300
|
+
const operations = [];
|
|
301
|
+
const usedIds = /* @__PURE__ */ new Set();
|
|
302
|
+
for (const [path, pathItem] of Object.entries(paths)) {
|
|
303
|
+
if (!pathItem || typeof pathItem !== "object") continue;
|
|
304
|
+
for (const method of HTTP_METHODS) {
|
|
305
|
+
const operation = pathItem[method];
|
|
306
|
+
if (!operation || typeof operation !== "object") continue;
|
|
307
|
+
const rawOperationId = operation["operationId"];
|
|
308
|
+
let operationId = typeof rawOperationId === "string" ? rawOperationId : `${method}_${path.replace(/[^a-zA-Z0-9]/g, "_")}`;
|
|
309
|
+
if (usedIds.has(operationId)) {
|
|
310
|
+
let suffix = 1;
|
|
311
|
+
while (usedIds.has(`${operationId}_${suffix}`)) suffix++;
|
|
312
|
+
operationId = `${operationId}_${suffix}`;
|
|
313
|
+
}
|
|
314
|
+
usedIds.add(operationId);
|
|
315
|
+
const rawSummary = operation["summary"];
|
|
316
|
+
const rawDescription = operation["description"];
|
|
317
|
+
const description = (typeof rawSummary === "string" ? rawSummary : void 0) ?? (typeof rawDescription === "string" ? rawDescription : void 0) ?? `${method.toUpperCase()} ${path}`;
|
|
318
|
+
const properties = /* @__PURE__ */ Object.create(null);
|
|
319
|
+
const required = [];
|
|
320
|
+
const rawPathParams = pathItem["parameters"];
|
|
321
|
+
const rawOpParams = operation["parameters"];
|
|
322
|
+
const pathParams = Array.isArray(rawPathParams) ? rawPathParams.filter(Boolean) : [];
|
|
323
|
+
const opParams = Array.isArray(rawOpParams) ? rawOpParams.filter(Boolean) : [];
|
|
324
|
+
const paramMap = /* @__PURE__ */ new Map();
|
|
325
|
+
for (const param of pathParams) {
|
|
326
|
+
if (typeof param === "object" && param !== null && param.name) {
|
|
327
|
+
paramMap.set(`${param.in}:${param.name}`, param);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
for (const param of opParams) {
|
|
331
|
+
if (typeof param === "object" && param !== null && param.name) {
|
|
332
|
+
paramMap.set(`${param.in}:${param.name}`, param);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
const propertyLocations = /* @__PURE__ */ new Map();
|
|
336
|
+
for (const param of paramMap.values()) {
|
|
337
|
+
if (param.name === "__proto__" || param.name === "constructor" || param.name === "prototype") continue;
|
|
338
|
+
const existingIn = propertyLocations.get(param.name);
|
|
339
|
+
if (existingIn && existingIn !== param.in) {
|
|
340
|
+
throw new Error(
|
|
341
|
+
`Parameter "${param.name}" appears in both "${existingIn}" and "${param.in}" \u2014 ambiguous mapping`
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
propertyLocations.set(param.name, param.in);
|
|
345
|
+
properties[param.name] = {
|
|
346
|
+
...param.schema ?? { type: "string" },
|
|
347
|
+
description: param.description
|
|
348
|
+
};
|
|
349
|
+
if (param.required) required.push(param.name);
|
|
350
|
+
}
|
|
351
|
+
const requestBody = operation["requestBody"];
|
|
352
|
+
if (requestBody) {
|
|
353
|
+
const content = requestBody["content"];
|
|
354
|
+
const jsonContent = content?.["application/json"];
|
|
355
|
+
if (jsonContent?.["schema"]) {
|
|
356
|
+
properties["body"] = {
|
|
357
|
+
...jsonContent["schema"],
|
|
358
|
+
description: "Request body"
|
|
359
|
+
};
|
|
360
|
+
if (requestBody["required"]) required.push("body");
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
const inputSchema = {
|
|
364
|
+
type: "object",
|
|
365
|
+
properties
|
|
366
|
+
};
|
|
367
|
+
if (required.length > 0) {
|
|
368
|
+
inputSchema["required"] = required;
|
|
369
|
+
}
|
|
370
|
+
operations.push({ operationId, description, method: method.toUpperCase(), path, inputSchema });
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
return operations;
|
|
374
|
+
}
|
|
375
|
+
export {
|
|
376
|
+
createFetchClient,
|
|
377
|
+
parseOpenApiSpec,
|
|
378
|
+
useApiClient
|
|
379
|
+
};
|