@kubb/plugin-mcp 5.0.0-alpha.9 → 5.0.0-beta.4
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 +17 -10
- package/README.md +1 -4
- package/dist/index.cjs +957 -92
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +207 -4
- package/dist/index.js +923 -90
- package/dist/index.js.map +1 -1
- package/extension.yaml +470 -0
- package/package.json +42 -64
- package/src/components/McpHandler.tsx +173 -0
- package/src/components/Server.tsx +89 -109
- package/src/generators/mcpGenerator.tsx +65 -84
- package/src/generators/serverGenerator.tsx +95 -58
- package/src/index.ts +11 -2
- package/src/plugin.ts +87 -135
- package/src/resolvers/resolverMcp.ts +25 -0
- package/src/types.ts +46 -28
- package/src/utils.ts +113 -0
- package/dist/Server-DV9zFrUP.cjs +0 -221
- package/dist/Server-DV9zFrUP.cjs.map +0 -1
- package/dist/Server-KWLMg0Lm.js +0 -173
- package/dist/Server-KWLMg0Lm.js.map +0 -1
- package/dist/components.cjs +0 -3
- package/dist/components.d.ts +0 -41
- package/dist/components.js +0 -2
- package/dist/generators-CWAFnA94.cjs +0 -285
- package/dist/generators-CWAFnA94.cjs.map +0 -1
- package/dist/generators-TtEOkDB1.js +0 -274
- package/dist/generators-TtEOkDB1.js.map +0 -1
- package/dist/generators.cjs +0 -4
- package/dist/generators.d.ts +0 -508
- package/dist/generators.js +0 -2
- package/dist/types-DXZDZ3vf.d.ts +0 -64
- package/src/components/index.ts +0 -1
- package/src/generators/index.ts +0 -2
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { camelCase } from '@internals/utils'
|
|
2
|
+
import { defineResolver } from '@kubb/core'
|
|
3
|
+
import type { PluginMcp } from '../types.ts'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Naming convention resolver for MCP plugin.
|
|
7
|
+
*
|
|
8
|
+
* Provides default naming helpers using camelCase with a `handler` suffix for functions.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* `resolverMcp.default('addPet', 'function') // → 'addPetHandler'`
|
|
12
|
+
*/
|
|
13
|
+
export const resolverMcp = defineResolver<PluginMcp>((ctx) => ({
|
|
14
|
+
name: 'default',
|
|
15
|
+
pluginName: 'plugin-mcp',
|
|
16
|
+
default(name, type) {
|
|
17
|
+
if (type === 'file') {
|
|
18
|
+
return camelCase(name, { isFile: true })
|
|
19
|
+
}
|
|
20
|
+
return camelCase(name, { suffix: 'handler' })
|
|
21
|
+
},
|
|
22
|
+
resolveName(name) {
|
|
23
|
+
return ctx.default(name, 'function')
|
|
24
|
+
},
|
|
25
|
+
}))
|
package/src/types.ts
CHANGED
|
@@ -1,62 +1,80 @@
|
|
|
1
|
-
import type { Group, Output, PluginFactoryOptions,
|
|
2
|
-
|
|
3
|
-
import type { contentType, Oas } from '@kubb/oas'
|
|
1
|
+
import type { ast, Exclude, Generator, Group, Include, Output, Override, PluginFactoryOptions, Resolver } from '@kubb/core'
|
|
4
2
|
import type { ClientImportPath, PluginClient } from '@kubb/plugin-client'
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Resolver for MCP that provides naming methods for handler functions.
|
|
6
|
+
*/
|
|
7
|
+
export type ResolverMcp = Resolver & {
|
|
8
|
+
/**
|
|
9
|
+
* Resolves the handler function name for an operation.
|
|
10
|
+
*
|
|
11
|
+
* @example Resolving handler function names
|
|
12
|
+
* `resolver.resolveName('show pet by id') // -> 'showPetByIdHandler'`
|
|
13
|
+
*/
|
|
14
|
+
resolveName(this: ResolverMcp, name: string): string
|
|
15
|
+
}
|
|
7
16
|
|
|
8
17
|
export type Options = {
|
|
9
18
|
/**
|
|
10
|
-
* Specify the export location for the files and define the behavior of the output
|
|
19
|
+
* Specify the export location for the files and define the behavior of the output.
|
|
11
20
|
* @default { path: 'mcp', barrelType: 'named' }
|
|
12
21
|
*/
|
|
13
|
-
output?: Output
|
|
22
|
+
output?: Output
|
|
14
23
|
/**
|
|
15
|
-
*
|
|
16
|
-
* By default, the first JSON valid mediaType is used
|
|
24
|
+
* Client configuration for HTTP request generation.
|
|
17
25
|
*/
|
|
18
|
-
contentType?: contentType
|
|
19
26
|
client?: ClientImportPath & Pick<PluginClient['options'], 'clientType' | 'dataReturnType' | 'baseURL' | 'bundle' | 'paramsCasing'>
|
|
20
27
|
/**
|
|
21
|
-
*
|
|
22
|
-
* When set to 'camelcase', parameter names in path, query, and header params will be transformed to camelCase.
|
|
23
|
-
* This should match the paramsCasing setting used in @kubb/plugin-ts.
|
|
24
|
-
* @default undefined
|
|
28
|
+
* Apply casing to parameter names to match your configuration.
|
|
25
29
|
*/
|
|
26
30
|
paramsCasing?: 'camelcase'
|
|
27
31
|
/**
|
|
28
|
-
* Group the
|
|
32
|
+
* Group the MCP requests based on the provided name.
|
|
29
33
|
*/
|
|
30
34
|
group?: Group
|
|
31
35
|
/**
|
|
32
|
-
*
|
|
36
|
+
* Tags, operations, or paths to exclude from generation.
|
|
33
37
|
*/
|
|
34
38
|
exclude?: Array<Exclude>
|
|
35
39
|
/**
|
|
36
|
-
*
|
|
40
|
+
* Tags, operations, or paths to include in generation.
|
|
37
41
|
*/
|
|
38
42
|
include?: Array<Include>
|
|
39
43
|
/**
|
|
40
|
-
*
|
|
44
|
+
* Override options for specific tags, operations, or paths.
|
|
41
45
|
*/
|
|
42
46
|
override?: Array<Override<ResolvedOptions>>
|
|
43
|
-
transformers?: {
|
|
44
|
-
/**
|
|
45
|
-
* Customize the names based on the type that is provided by the plugin.
|
|
46
|
-
*/
|
|
47
|
-
name?: (name: ResolveNameParams['name'], type?: ResolveNameParams['type']) => string
|
|
48
|
-
}
|
|
49
47
|
/**
|
|
50
|
-
*
|
|
48
|
+
* Override naming conventions for function names and types.
|
|
49
|
+
*/
|
|
50
|
+
resolver?: Partial<ResolverMcp> & ThisType<ResolverMcp>
|
|
51
|
+
/**
|
|
52
|
+
* AST visitor to transform generated nodes.
|
|
53
|
+
*/
|
|
54
|
+
transformer?: ast.Visitor
|
|
55
|
+
/**
|
|
56
|
+
* Additional generators alongside the default generators.
|
|
51
57
|
*/
|
|
52
58
|
generators?: Array<Generator<PluginMcp>>
|
|
53
59
|
}
|
|
54
60
|
|
|
55
61
|
type ResolvedOptions = {
|
|
56
|
-
output: Output
|
|
57
|
-
|
|
62
|
+
output: Output
|
|
63
|
+
exclude: Array<Exclude>
|
|
64
|
+
include: Array<Include> | undefined
|
|
65
|
+
override: Array<Override<ResolvedOptions>>
|
|
66
|
+
group: Group | undefined
|
|
58
67
|
client: Pick<PluginClient['options'], 'client' | 'clientType' | 'dataReturnType' | 'importPath' | 'baseURL' | 'bundle' | 'paramsCasing'>
|
|
59
68
|
paramsCasing: Options['paramsCasing']
|
|
69
|
+
resolver: ResolverMcp
|
|
60
70
|
}
|
|
61
71
|
|
|
62
|
-
export type PluginMcp = PluginFactoryOptions<'plugin-mcp', Options, ResolvedOptions,
|
|
72
|
+
export type PluginMcp = PluginFactoryOptions<'plugin-mcp', Options, ResolvedOptions, ResolverMcp>
|
|
73
|
+
|
|
74
|
+
declare global {
|
|
75
|
+
namespace Kubb {
|
|
76
|
+
interface PluginRegistry {
|
|
77
|
+
'plugin-mcp': PluginMcp
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { camelCase } from '@internals/utils'
|
|
2
|
+
import type { ast } from '@kubb/core'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Find the first 2xx response status code from an operation's responses.
|
|
6
|
+
*/
|
|
7
|
+
export function findSuccessStatusCode(responses: Array<{ statusCode: number | string }>): ast.StatusCode | undefined {
|
|
8
|
+
for (const res of responses) {
|
|
9
|
+
const code = Number(res.statusCode)
|
|
10
|
+
if (code >= 200 && code < 300) {
|
|
11
|
+
return res.statusCode as ast.StatusCode
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
return undefined
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type ZodParam = {
|
|
18
|
+
name: string
|
|
19
|
+
schemaName: string
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Render a group param value — compose individual schemas into `z.object({ ... })`,
|
|
24
|
+
* or use a schema name string directly.
|
|
25
|
+
*/
|
|
26
|
+
export function zodGroupExpr(entry: string | Array<ZodParam>): string {
|
|
27
|
+
if (typeof entry === 'string') {
|
|
28
|
+
return entry
|
|
29
|
+
}
|
|
30
|
+
const entries = entry.map((p) => `${JSON.stringify(p.name)}: ${p.schemaName}`)
|
|
31
|
+
return `z.object({ ${entries.join(', ')} })`
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Build JSDoc comment lines from an OperationNode.
|
|
36
|
+
*/
|
|
37
|
+
export function getComments(node: ast.OperationNode): Array<string> {
|
|
38
|
+
return [
|
|
39
|
+
node.description && `@description ${node.description}`,
|
|
40
|
+
node.summary && `@summary ${node.summary}`,
|
|
41
|
+
node.deprecated && '@deprecated',
|
|
42
|
+
`{@link ${node.path.replaceAll('{', ':').replaceAll('}', '')}}`,
|
|
43
|
+
].filter((x): x is string => Boolean(x))
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Build a mapping of original param names → camelCase names.
|
|
48
|
+
* Returns `undefined` when no names actually change (no remapping needed).
|
|
49
|
+
*/
|
|
50
|
+
export function getParamsMapping(params: Array<{ name: string }>): Record<string, string> | undefined {
|
|
51
|
+
if (!params.length) {
|
|
52
|
+
return undefined
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const mapping: Record<string, string> = {}
|
|
56
|
+
let hasDifference = false
|
|
57
|
+
|
|
58
|
+
for (const p of params) {
|
|
59
|
+
const camelName = camelCase(p.name)
|
|
60
|
+
mapping[p.name] = camelName
|
|
61
|
+
if (p.name !== camelName) {
|
|
62
|
+
hasDifference = true
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return hasDifference ? mapping : undefined
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Convert a SchemaNode type to an inline Zod expression string.
|
|
71
|
+
* Used as fallback when no named zod schema is available for a path parameter.
|
|
72
|
+
*/
|
|
73
|
+
export function zodExprFromSchemaNode(schema: ast.SchemaNode): string {
|
|
74
|
+
let expr: string
|
|
75
|
+
switch (schema.type) {
|
|
76
|
+
case 'enum': {
|
|
77
|
+
// namedEnumValues takes priority over enumValues
|
|
78
|
+
const rawValues: Array<string | number | boolean> = schema.namedEnumValues?.length
|
|
79
|
+
? schema.namedEnumValues.map((v) => v.value)
|
|
80
|
+
: (schema.enumValues ?? []).filter((v): v is string | number | boolean => v !== null)
|
|
81
|
+
|
|
82
|
+
if (rawValues.length > 0 && rawValues.every((v) => typeof v === 'string')) {
|
|
83
|
+
expr = `z.enum([${rawValues.map((v) => JSON.stringify(v)).join(', ')}])`
|
|
84
|
+
} else if (rawValues.length > 0) {
|
|
85
|
+
const literals = rawValues.map((v) => `z.literal(${JSON.stringify(v)})`)
|
|
86
|
+
expr = literals.length === 1 ? literals[0]! : `z.union([${literals.join(', ')}])`
|
|
87
|
+
} else {
|
|
88
|
+
expr = 'z.string()'
|
|
89
|
+
}
|
|
90
|
+
break
|
|
91
|
+
}
|
|
92
|
+
case 'integer':
|
|
93
|
+
expr = 'z.coerce.number()'
|
|
94
|
+
break
|
|
95
|
+
case 'number':
|
|
96
|
+
expr = 'z.number()'
|
|
97
|
+
break
|
|
98
|
+
case 'boolean':
|
|
99
|
+
expr = 'z.boolean()'
|
|
100
|
+
break
|
|
101
|
+
case 'array':
|
|
102
|
+
expr = 'z.array(z.unknown())'
|
|
103
|
+
break
|
|
104
|
+
default:
|
|
105
|
+
expr = 'z.string()'
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (schema.nullable) {
|
|
109
|
+
expr = `${expr}.nullable()`
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return expr
|
|
113
|
+
}
|
package/dist/Server-DV9zFrUP.cjs
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
//#region \0rolldown/runtime.js
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __name = (target, value) => __defProp(target, "name", {
|
|
5
|
-
value,
|
|
6
|
-
configurable: true
|
|
7
|
-
});
|
|
8
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
9
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
10
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
11
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
14
|
-
key = keys[i];
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
16
|
-
get: ((k) => from[k]).bind(null, key),
|
|
17
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
return to;
|
|
21
|
-
};
|
|
22
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
23
|
-
value: mod,
|
|
24
|
-
enumerable: true
|
|
25
|
-
}) : target, mod));
|
|
26
|
-
//#endregion
|
|
27
|
-
let _kubb_plugin_oas_utils = require("@kubb/plugin-oas/utils");
|
|
28
|
-
let _kubb_react_fabric = require("@kubb/react-fabric");
|
|
29
|
-
let _kubb_react_fabric_jsx_runtime = require("@kubb/react-fabric/jsx-runtime");
|
|
30
|
-
//#region ../../internals/utils/src/casing.ts
|
|
31
|
-
/**
|
|
32
|
-
* Shared implementation for camelCase and PascalCase conversion.
|
|
33
|
-
* Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
|
|
34
|
-
* and capitalizes each word according to `pascal`.
|
|
35
|
-
*
|
|
36
|
-
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
37
|
-
*/
|
|
38
|
-
function toCamelOrPascal(text, pascal) {
|
|
39
|
-
return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
|
|
40
|
-
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
41
|
-
if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
|
|
42
|
-
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
43
|
-
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
44
|
-
}
|
|
45
|
-
/**
|
|
46
|
-
* Splits `text` on `.` and applies `transformPart` to each segment.
|
|
47
|
-
* The last segment receives `isLast = true`, all earlier segments receive `false`.
|
|
48
|
-
* Segments are joined with `/` to form a file path.
|
|
49
|
-
*/
|
|
50
|
-
function applyToFileParts(text, transformPart) {
|
|
51
|
-
const parts = text.split(".");
|
|
52
|
-
return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
|
|
53
|
-
}
|
|
54
|
-
/**
|
|
55
|
-
* Converts `text` to camelCase.
|
|
56
|
-
* When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
|
|
57
|
-
*
|
|
58
|
-
* @example
|
|
59
|
-
* camelCase('hello-world') // 'helloWorld'
|
|
60
|
-
* camelCase('pet.petId', { isFile: true }) // 'pet/petId'
|
|
61
|
-
*/
|
|
62
|
-
function camelCase(text, { isFile, prefix = "", suffix = "" } = {}) {
|
|
63
|
-
if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
|
|
64
|
-
prefix,
|
|
65
|
-
suffix
|
|
66
|
-
} : {}));
|
|
67
|
-
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
68
|
-
}
|
|
69
|
-
//#endregion
|
|
70
|
-
//#region ../../internals/utils/src/reserved.ts
|
|
71
|
-
/**
|
|
72
|
-
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
73
|
-
*/
|
|
74
|
-
function isValidVarName(name) {
|
|
75
|
-
try {
|
|
76
|
-
new Function(`var ${name}`);
|
|
77
|
-
} catch {
|
|
78
|
-
return false;
|
|
79
|
-
}
|
|
80
|
-
return true;
|
|
81
|
-
}
|
|
82
|
-
//#endregion
|
|
83
|
-
//#region src/components/Server.tsx
|
|
84
|
-
function zodExprFromOasSchema(schema) {
|
|
85
|
-
const types = Array.isArray(schema.type) ? schema.type : [schema.type];
|
|
86
|
-
const baseType = types.find((t) => t && t !== "null");
|
|
87
|
-
const isNullableType = types.includes("null");
|
|
88
|
-
let expr;
|
|
89
|
-
switch (baseType) {
|
|
90
|
-
case "integer":
|
|
91
|
-
expr = "z.coerce.number()";
|
|
92
|
-
break;
|
|
93
|
-
case "number":
|
|
94
|
-
expr = "z.number()";
|
|
95
|
-
break;
|
|
96
|
-
case "boolean":
|
|
97
|
-
expr = "z.boolean()";
|
|
98
|
-
break;
|
|
99
|
-
case "array":
|
|
100
|
-
expr = "z.array(z.unknown())";
|
|
101
|
-
break;
|
|
102
|
-
default: expr = "z.string()";
|
|
103
|
-
}
|
|
104
|
-
if (isNullableType) expr = `${expr}.nullable()`;
|
|
105
|
-
return expr;
|
|
106
|
-
}
|
|
107
|
-
function getParams({ schemas, paramsCasing }) {
|
|
108
|
-
const pathParamProperties = schemas.pathParams?.schema?.properties ?? {};
|
|
109
|
-
const requiredFields = Array.isArray(schemas.pathParams?.schema?.required) ? schemas.pathParams.schema.required : [];
|
|
110
|
-
const pathParamEntries = Object.entries(pathParamProperties).reduce((acc, [originalKey, propSchema]) => {
|
|
111
|
-
const key = paramsCasing === "camelcase" || !isValidVarName(originalKey) ? camelCase(originalKey) : originalKey;
|
|
112
|
-
acc[key] = {
|
|
113
|
-
value: zodExprFromOasSchema(propSchema),
|
|
114
|
-
optional: !requiredFields.includes(originalKey)
|
|
115
|
-
};
|
|
116
|
-
return acc;
|
|
117
|
-
}, {});
|
|
118
|
-
return _kubb_react_fabric.FunctionParams.factory({ data: {
|
|
119
|
-
mode: "object",
|
|
120
|
-
children: {
|
|
121
|
-
...pathParamEntries,
|
|
122
|
-
data: schemas.request?.name ? {
|
|
123
|
-
value: schemas.request?.name,
|
|
124
|
-
optional: (0, _kubb_plugin_oas_utils.isOptional)(schemas.request?.schema)
|
|
125
|
-
} : void 0,
|
|
126
|
-
params: schemas.queryParams?.name ? {
|
|
127
|
-
value: schemas.queryParams?.name,
|
|
128
|
-
optional: (0, _kubb_plugin_oas_utils.isOptional)(schemas.queryParams?.schema)
|
|
129
|
-
} : void 0,
|
|
130
|
-
headers: schemas.headerParams?.name ? {
|
|
131
|
-
value: schemas.headerParams?.name,
|
|
132
|
-
optional: (0, _kubb_plugin_oas_utils.isOptional)(schemas.headerParams?.schema)
|
|
133
|
-
} : void 0
|
|
134
|
-
}
|
|
135
|
-
} });
|
|
136
|
-
}
|
|
137
|
-
function Server({ name, serverName, serverVersion, paramsCasing, operations }) {
|
|
138
|
-
return /* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsxs)(_kubb_react_fabric.File.Source, {
|
|
139
|
-
name,
|
|
140
|
-
isExportable: true,
|
|
141
|
-
isIndexable: true,
|
|
142
|
-
children: [
|
|
143
|
-
/* @__PURE__ */ (0, _kubb_react_fabric_jsx_runtime.jsx)(_kubb_react_fabric.Const, {
|
|
144
|
-
name: "server",
|
|
145
|
-
export: true,
|
|
146
|
-
children: `
|
|
147
|
-
new McpServer({
|
|
148
|
-
name: '${serverName}',
|
|
149
|
-
version: '${serverVersion}',
|
|
150
|
-
})
|
|
151
|
-
`
|
|
152
|
-
}),
|
|
153
|
-
operations.map(({ tool, mcp, zod }) => {
|
|
154
|
-
const paramsClient = getParams({
|
|
155
|
-
schemas: zod.schemas,
|
|
156
|
-
paramsCasing
|
|
157
|
-
});
|
|
158
|
-
const outputSchema = zod.schemas.response?.name;
|
|
159
|
-
const config = [
|
|
160
|
-
tool.title ? `title: ${JSON.stringify(tool.title)}` : null,
|
|
161
|
-
`description: ${JSON.stringify(tool.description)}`,
|
|
162
|
-
outputSchema ? `outputSchema: { data: ${outputSchema} }` : null
|
|
163
|
-
].filter(Boolean).join(",\n ");
|
|
164
|
-
if (zod.schemas.request?.name || zod.schemas.headerParams?.name || zod.schemas.queryParams?.name || zod.schemas.pathParams?.name) return `
|
|
165
|
-
server.registerTool(${JSON.stringify(tool.name)}, {
|
|
166
|
-
${config},
|
|
167
|
-
inputSchema: ${paramsClient.toObjectValue()},
|
|
168
|
-
}, async (${paramsClient.toObject()}) => {
|
|
169
|
-
return ${mcp.name}(${paramsClient.toObject()})
|
|
170
|
-
})
|
|
171
|
-
`;
|
|
172
|
-
return `
|
|
173
|
-
server.registerTool(${JSON.stringify(tool.name)}, {
|
|
174
|
-
${config},
|
|
175
|
-
}, async () => {
|
|
176
|
-
return ${mcp.name}(${paramsClient.toObject()})
|
|
177
|
-
})
|
|
178
|
-
`;
|
|
179
|
-
}).filter(Boolean),
|
|
180
|
-
`
|
|
181
|
-
export async function startServer() {
|
|
182
|
-
try {
|
|
183
|
-
const transport = new StdioServerTransport()
|
|
184
|
-
await server.connect(transport)
|
|
185
|
-
|
|
186
|
-
} catch (error) {
|
|
187
|
-
console.error('Failed to start server:', error)
|
|
188
|
-
process.exit(1)
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
`
|
|
192
|
-
]
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
//#endregion
|
|
196
|
-
Object.defineProperty(exports, "Server", {
|
|
197
|
-
enumerable: true,
|
|
198
|
-
get: function() {
|
|
199
|
-
return Server;
|
|
200
|
-
}
|
|
201
|
-
});
|
|
202
|
-
Object.defineProperty(exports, "__name", {
|
|
203
|
-
enumerable: true,
|
|
204
|
-
get: function() {
|
|
205
|
-
return __name;
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
Object.defineProperty(exports, "__toESM", {
|
|
209
|
-
enumerable: true,
|
|
210
|
-
get: function() {
|
|
211
|
-
return __toESM;
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
Object.defineProperty(exports, "camelCase", {
|
|
215
|
-
enumerable: true,
|
|
216
|
-
get: function() {
|
|
217
|
-
return camelCase;
|
|
218
|
-
}
|
|
219
|
-
});
|
|
220
|
-
|
|
221
|
-
//# sourceMappingURL=Server-DV9zFrUP.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Server-DV9zFrUP.cjs","names":["FunctionParams","File","Const"],"sources":["../../../internals/utils/src/casing.ts","../../../internals/utils/src/reserved.ts","../src/components/Server.tsx"],"sourcesContent":["type Options = {\n /** When `true`, dot-separated segments are split on `.` and joined with `/` after casing. */\n isFile?: boolean\n /** Text prepended before casing is applied. */\n prefix?: string\n /** Text appended before casing is applied. */\n suffix?: string\n}\n\n/**\n * Shared implementation for camelCase and PascalCase conversion.\n * Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)\n * and capitalizes each word according to `pascal`.\n *\n * When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.\n */\nfunction toCamelOrPascal(text: string, pascal: boolean): string {\n const normalized = text\n .trim()\n .replace(/([a-z\\d])([A-Z])/g, '$1 $2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')\n .replace(/(\\d)([a-z])/g, '$1 $2')\n\n const words = normalized.split(/[\\s\\-_./\\\\:]+/).filter(Boolean)\n\n return words\n .map((word, i) => {\n const allUpper = word.length > 1 && word === word.toUpperCase()\n if (allUpper) return word\n if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1)\n return word.charAt(0).toUpperCase() + word.slice(1)\n })\n .join('')\n .replace(/[^a-zA-Z0-9]/g, '')\n}\n\n/**\n * Splits `text` on `.` and applies `transformPart` to each segment.\n * The last segment receives `isLast = true`, all earlier segments receive `false`.\n * Segments are joined with `/` to form a file path.\n */\nfunction applyToFileParts(text: string, transformPart: (part: string, isLast: boolean) => string): string {\n const parts = text.split('.')\n return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join('/')\n}\n\n/**\n * Converts `text` to camelCase.\n * When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.\n *\n * @example\n * camelCase('hello-world') // 'helloWorld'\n * camelCase('pet.petId', { isFile: true }) // 'pet/petId'\n */\nexport function camelCase(text: string, { isFile, prefix = '', suffix = '' }: Options = {}): string {\n if (isFile) {\n return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? { prefix, suffix } : {}))\n }\n\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false)\n}\n\n/**\n * Converts `text` to PascalCase.\n * When `isFile` is `true`, the last dot-separated segment is PascalCased and earlier segments are camelCased.\n *\n * @example\n * pascalCase('hello-world') // 'HelloWorld'\n * pascalCase('pet.petId', { isFile: true }) // 'pet/PetId'\n */\nexport function pascalCase(text: string, { isFile, prefix = '', suffix = '' }: Options = {}): string {\n if (isFile) {\n return applyToFileParts(text, (part, isLast) => (isLast ? pascalCase(part, { prefix, suffix }) : camelCase(part)))\n }\n\n return toCamelOrPascal(`${prefix} ${text} ${suffix}`, true)\n}\n\n/**\n * Converts `text` to snake_case.\n *\n * @example\n * snakeCase('helloWorld') // 'hello_world'\n * snakeCase('Hello-World') // 'hello_world'\n */\nexport function snakeCase(text: string, { prefix = '', suffix = '' }: Omit<Options, 'isFile'> = {}): string {\n const processed = `${prefix} ${text} ${suffix}`.trim()\n return processed\n .replace(/([a-z])([A-Z])/g, '$1_$2')\n .replace(/[\\s\\-.]+/g, '_')\n .replace(/[^a-zA-Z0-9_]/g, '')\n .toLowerCase()\n .split('_')\n .filter(Boolean)\n .join('_')\n}\n\n/**\n * Converts `text` to SCREAMING_SNAKE_CASE.\n *\n * @example\n * screamingSnakeCase('helloWorld') // 'HELLO_WORLD'\n */\nexport function screamingSnakeCase(text: string, { prefix = '', suffix = '' }: Omit<Options, 'isFile'> = {}): string {\n return snakeCase(text, { prefix, suffix }).toUpperCase()\n}\n","/**\n * JavaScript and Java reserved words.\n * @link https://github.com/jonschlinkert/reserved/blob/master/index.js\n */\nconst reservedWords = new Set([\n 'abstract',\n 'arguments',\n 'boolean',\n 'break',\n 'byte',\n 'case',\n 'catch',\n 'char',\n 'class',\n 'const',\n 'continue',\n 'debugger',\n 'default',\n 'delete',\n 'do',\n 'double',\n 'else',\n 'enum',\n 'eval',\n 'export',\n 'extends',\n 'false',\n 'final',\n 'finally',\n 'float',\n 'for',\n 'function',\n 'goto',\n 'if',\n 'implements',\n 'import',\n 'in',\n 'instanceof',\n 'int',\n 'interface',\n 'let',\n 'long',\n 'native',\n 'new',\n 'null',\n 'package',\n 'private',\n 'protected',\n 'public',\n 'return',\n 'short',\n 'static',\n 'super',\n 'switch',\n 'synchronized',\n 'this',\n 'throw',\n 'throws',\n 'transient',\n 'true',\n 'try',\n 'typeof',\n 'var',\n 'void',\n 'volatile',\n 'while',\n 'with',\n 'yield',\n 'Array',\n 'Date',\n 'hasOwnProperty',\n 'Infinity',\n 'isFinite',\n 'isNaN',\n 'isPrototypeOf',\n 'length',\n 'Math',\n 'name',\n 'NaN',\n 'Number',\n 'Object',\n 'prototype',\n 'String',\n 'toString',\n 'undefined',\n 'valueOf',\n] as const)\n\n/**\n * Prefixes a word with `_` when it is a reserved JavaScript/Java identifier\n * or starts with a digit.\n */\nexport function transformReservedWord(word: string): string {\n const firstChar = word.charCodeAt(0)\n if (word && (reservedWords.has(word as 'valueOf') || (firstChar >= 48 && firstChar <= 57))) {\n return `_${word}`\n }\n return word\n}\n\n/**\n * Returns `true` when `name` is a syntactically valid JavaScript variable name.\n */\nexport function isValidVarName(name: string): boolean {\n try {\n new Function(`var ${name}`)\n } catch {\n return false\n }\n return true\n}\n","import { camelCase, isValidVarName } from '@internals/utils'\nimport type { KubbFile } from '@kubb/fabric-core/types'\nimport type { SchemaObject } from '@kubb/oas'\nimport type { OperationSchemas } from '@kubb/plugin-oas'\nimport { isOptional } from '@kubb/plugin-oas/utils'\nimport { Const, File, FunctionParams } from '@kubb/react-fabric'\nimport type { FabricReactNode } from '@kubb/react-fabric/types'\n\ntype Props = {\n name: string\n serverName: string\n serverVersion: string\n paramsCasing?: 'camelcase'\n operations: Array<{\n tool: {\n name: string\n title?: string\n description: string\n }\n mcp: {\n name: string\n file: KubbFile.File\n }\n zod: {\n name: string\n file: KubbFile.File\n schemas: OperationSchemas\n }\n type: {\n schemas: OperationSchemas\n }\n }>\n}\n\ntype GetParamsProps = {\n schemas: OperationSchemas\n paramsCasing?: 'camelcase'\n}\n\nfunction zodExprFromOasSchema(schema: SchemaObject): string {\n const types = Array.isArray(schema.type) ? schema.type : [schema.type]\n const baseType = types.find((t) => t && t !== 'null')\n const isNullableType = types.includes('null')\n\n let expr: string\n switch (baseType) {\n case 'integer':\n expr = 'z.coerce.number()'\n break\n case 'number':\n expr = 'z.number()'\n break\n case 'boolean':\n expr = 'z.boolean()'\n break\n case 'array':\n expr = 'z.array(z.unknown())'\n break\n default:\n expr = 'z.string()'\n }\n\n if (isNullableType) {\n expr = `${expr}.nullable()`\n }\n\n return expr\n}\n\nfunction getParams({ schemas, paramsCasing }: GetParamsProps) {\n const pathParamProperties = schemas.pathParams?.schema?.properties ?? {}\n const requiredFields = Array.isArray(schemas.pathParams?.schema?.required) ? schemas.pathParams.schema.required : []\n\n const pathParamEntries = Object.entries(pathParamProperties).reduce<Record<string, { value: string; optional: boolean }>>(\n (acc, [originalKey, propSchema]) => {\n const key = paramsCasing === 'camelcase' || !isValidVarName(originalKey) ? camelCase(originalKey) : originalKey\n acc[key] = {\n value: zodExprFromOasSchema(propSchema as SchemaObject),\n optional: !requiredFields.includes(originalKey),\n }\n return acc\n },\n {},\n )\n\n return FunctionParams.factory({\n data: {\n mode: 'object',\n children: {\n ...pathParamEntries,\n data: schemas.request?.name\n ? {\n value: schemas.request?.name,\n optional: isOptional(schemas.request?.schema),\n }\n : undefined,\n params: schemas.queryParams?.name\n ? {\n value: schemas.queryParams?.name,\n optional: isOptional(schemas.queryParams?.schema),\n }\n : undefined,\n headers: schemas.headerParams?.name\n ? {\n value: schemas.headerParams?.name,\n optional: isOptional(schemas.headerParams?.schema),\n }\n : undefined,\n },\n },\n })\n}\n\nexport function Server({ name, serverName, serverVersion, paramsCasing, operations }: Props): FabricReactNode {\n return (\n <File.Source name={name} isExportable isIndexable>\n <Const name={'server'} export>\n {`\n new McpServer({\n name: '${serverName}',\n version: '${serverVersion}',\n})\n `}\n </Const>\n\n {operations\n .map(({ tool, mcp, zod }) => {\n const paramsClient = getParams({ schemas: zod.schemas, paramsCasing })\n const outputSchema = zod.schemas.response?.name\n\n const config = [\n tool.title ? `title: ${JSON.stringify(tool.title)}` : null,\n `description: ${JSON.stringify(tool.description)}`,\n outputSchema ? `outputSchema: { data: ${outputSchema} }` : null,\n ]\n .filter(Boolean)\n .join(',\\n ')\n\n if (zod.schemas.request?.name || zod.schemas.headerParams?.name || zod.schemas.queryParams?.name || zod.schemas.pathParams?.name) {\n return `\nserver.registerTool(${JSON.stringify(tool.name)}, {\n ${config},\n inputSchema: ${paramsClient.toObjectValue()},\n}, async (${paramsClient.toObject()}) => {\n return ${mcp.name}(${paramsClient.toObject()})\n})\n `\n }\n\n return `\nserver.registerTool(${JSON.stringify(tool.name)}, {\n ${config},\n}, async () => {\n return ${mcp.name}(${paramsClient.toObject()})\n})\n `\n })\n .filter(Boolean)}\n\n {`\nexport async function startServer() {\n try {\n const transport = new StdioServerTransport()\n await server.connect(transport)\n\n } catch (error) {\n console.error('Failed to start server:', error)\n process.exit(1)\n }\n}\n`}\n </File.Source>\n )\n}\n"],"mappings":"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"}
|
package/dist/Server-KWLMg0Lm.js
DELETED
|
@@ -1,173 +0,0 @@
|
|
|
1
|
-
import "./chunk--u3MIqq1.js";
|
|
2
|
-
import { isOptional } from "@kubb/plugin-oas/utils";
|
|
3
|
-
import { Const, File, FunctionParams } from "@kubb/react-fabric";
|
|
4
|
-
import { jsx, jsxs } from "@kubb/react-fabric/jsx-runtime";
|
|
5
|
-
//#region ../../internals/utils/src/casing.ts
|
|
6
|
-
/**
|
|
7
|
-
* Shared implementation for camelCase and PascalCase conversion.
|
|
8
|
-
* Splits on common word boundaries (spaces, hyphens, underscores, dots, slashes, colons)
|
|
9
|
-
* and capitalizes each word according to `pascal`.
|
|
10
|
-
*
|
|
11
|
-
* When `pascal` is `true` the first word is also capitalized (PascalCase), otherwise only subsequent words are.
|
|
12
|
-
*/
|
|
13
|
-
function toCamelOrPascal(text, pascal) {
|
|
14
|
-
return text.trim().replace(/([a-z\d])([A-Z])/g, "$1 $2").replace(/([A-Z]+)([A-Z][a-z])/g, "$1 $2").replace(/(\d)([a-z])/g, "$1 $2").split(/[\s\-_./\\:]+/).filter(Boolean).map((word, i) => {
|
|
15
|
-
if (word.length > 1 && word === word.toUpperCase()) return word;
|
|
16
|
-
if (i === 0 && !pascal) return word.charAt(0).toLowerCase() + word.slice(1);
|
|
17
|
-
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
18
|
-
}).join("").replace(/[^a-zA-Z0-9]/g, "");
|
|
19
|
-
}
|
|
20
|
-
/**
|
|
21
|
-
* Splits `text` on `.` and applies `transformPart` to each segment.
|
|
22
|
-
* The last segment receives `isLast = true`, all earlier segments receive `false`.
|
|
23
|
-
* Segments are joined with `/` to form a file path.
|
|
24
|
-
*/
|
|
25
|
-
function applyToFileParts(text, transformPart) {
|
|
26
|
-
const parts = text.split(".");
|
|
27
|
-
return parts.map((part, i) => transformPart(part, i === parts.length - 1)).join("/");
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Converts `text` to camelCase.
|
|
31
|
-
* When `isFile` is `true`, dot-separated segments are each cased independently and joined with `/`.
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* camelCase('hello-world') // 'helloWorld'
|
|
35
|
-
* camelCase('pet.petId', { isFile: true }) // 'pet/petId'
|
|
36
|
-
*/
|
|
37
|
-
function camelCase(text, { isFile, prefix = "", suffix = "" } = {}) {
|
|
38
|
-
if (isFile) return applyToFileParts(text, (part, isLast) => camelCase(part, isLast ? {
|
|
39
|
-
prefix,
|
|
40
|
-
suffix
|
|
41
|
-
} : {}));
|
|
42
|
-
return toCamelOrPascal(`${prefix} ${text} ${suffix}`, false);
|
|
43
|
-
}
|
|
44
|
-
//#endregion
|
|
45
|
-
//#region ../../internals/utils/src/reserved.ts
|
|
46
|
-
/**
|
|
47
|
-
* Returns `true` when `name` is a syntactically valid JavaScript variable name.
|
|
48
|
-
*/
|
|
49
|
-
function isValidVarName(name) {
|
|
50
|
-
try {
|
|
51
|
-
new Function(`var ${name}`);
|
|
52
|
-
} catch {
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
return true;
|
|
56
|
-
}
|
|
57
|
-
//#endregion
|
|
58
|
-
//#region src/components/Server.tsx
|
|
59
|
-
function zodExprFromOasSchema(schema) {
|
|
60
|
-
const types = Array.isArray(schema.type) ? schema.type : [schema.type];
|
|
61
|
-
const baseType = types.find((t) => t && t !== "null");
|
|
62
|
-
const isNullableType = types.includes("null");
|
|
63
|
-
let expr;
|
|
64
|
-
switch (baseType) {
|
|
65
|
-
case "integer":
|
|
66
|
-
expr = "z.coerce.number()";
|
|
67
|
-
break;
|
|
68
|
-
case "number":
|
|
69
|
-
expr = "z.number()";
|
|
70
|
-
break;
|
|
71
|
-
case "boolean":
|
|
72
|
-
expr = "z.boolean()";
|
|
73
|
-
break;
|
|
74
|
-
case "array":
|
|
75
|
-
expr = "z.array(z.unknown())";
|
|
76
|
-
break;
|
|
77
|
-
default: expr = "z.string()";
|
|
78
|
-
}
|
|
79
|
-
if (isNullableType) expr = `${expr}.nullable()`;
|
|
80
|
-
return expr;
|
|
81
|
-
}
|
|
82
|
-
function getParams({ schemas, paramsCasing }) {
|
|
83
|
-
const pathParamProperties = schemas.pathParams?.schema?.properties ?? {};
|
|
84
|
-
const requiredFields = Array.isArray(schemas.pathParams?.schema?.required) ? schemas.pathParams.schema.required : [];
|
|
85
|
-
const pathParamEntries = Object.entries(pathParamProperties).reduce((acc, [originalKey, propSchema]) => {
|
|
86
|
-
const key = paramsCasing === "camelcase" || !isValidVarName(originalKey) ? camelCase(originalKey) : originalKey;
|
|
87
|
-
acc[key] = {
|
|
88
|
-
value: zodExprFromOasSchema(propSchema),
|
|
89
|
-
optional: !requiredFields.includes(originalKey)
|
|
90
|
-
};
|
|
91
|
-
return acc;
|
|
92
|
-
}, {});
|
|
93
|
-
return FunctionParams.factory({ data: {
|
|
94
|
-
mode: "object",
|
|
95
|
-
children: {
|
|
96
|
-
...pathParamEntries,
|
|
97
|
-
data: schemas.request?.name ? {
|
|
98
|
-
value: schemas.request?.name,
|
|
99
|
-
optional: isOptional(schemas.request?.schema)
|
|
100
|
-
} : void 0,
|
|
101
|
-
params: schemas.queryParams?.name ? {
|
|
102
|
-
value: schemas.queryParams?.name,
|
|
103
|
-
optional: isOptional(schemas.queryParams?.schema)
|
|
104
|
-
} : void 0,
|
|
105
|
-
headers: schemas.headerParams?.name ? {
|
|
106
|
-
value: schemas.headerParams?.name,
|
|
107
|
-
optional: isOptional(schemas.headerParams?.schema)
|
|
108
|
-
} : void 0
|
|
109
|
-
}
|
|
110
|
-
} });
|
|
111
|
-
}
|
|
112
|
-
function Server({ name, serverName, serverVersion, paramsCasing, operations }) {
|
|
113
|
-
return /* @__PURE__ */ jsxs(File.Source, {
|
|
114
|
-
name,
|
|
115
|
-
isExportable: true,
|
|
116
|
-
isIndexable: true,
|
|
117
|
-
children: [
|
|
118
|
-
/* @__PURE__ */ jsx(Const, {
|
|
119
|
-
name: "server",
|
|
120
|
-
export: true,
|
|
121
|
-
children: `
|
|
122
|
-
new McpServer({
|
|
123
|
-
name: '${serverName}',
|
|
124
|
-
version: '${serverVersion}',
|
|
125
|
-
})
|
|
126
|
-
`
|
|
127
|
-
}),
|
|
128
|
-
operations.map(({ tool, mcp, zod }) => {
|
|
129
|
-
const paramsClient = getParams({
|
|
130
|
-
schemas: zod.schemas,
|
|
131
|
-
paramsCasing
|
|
132
|
-
});
|
|
133
|
-
const outputSchema = zod.schemas.response?.name;
|
|
134
|
-
const config = [
|
|
135
|
-
tool.title ? `title: ${JSON.stringify(tool.title)}` : null,
|
|
136
|
-
`description: ${JSON.stringify(tool.description)}`,
|
|
137
|
-
outputSchema ? `outputSchema: { data: ${outputSchema} }` : null
|
|
138
|
-
].filter(Boolean).join(",\n ");
|
|
139
|
-
if (zod.schemas.request?.name || zod.schemas.headerParams?.name || zod.schemas.queryParams?.name || zod.schemas.pathParams?.name) return `
|
|
140
|
-
server.registerTool(${JSON.stringify(tool.name)}, {
|
|
141
|
-
${config},
|
|
142
|
-
inputSchema: ${paramsClient.toObjectValue()},
|
|
143
|
-
}, async (${paramsClient.toObject()}) => {
|
|
144
|
-
return ${mcp.name}(${paramsClient.toObject()})
|
|
145
|
-
})
|
|
146
|
-
`;
|
|
147
|
-
return `
|
|
148
|
-
server.registerTool(${JSON.stringify(tool.name)}, {
|
|
149
|
-
${config},
|
|
150
|
-
}, async () => {
|
|
151
|
-
return ${mcp.name}(${paramsClient.toObject()})
|
|
152
|
-
})
|
|
153
|
-
`;
|
|
154
|
-
}).filter(Boolean),
|
|
155
|
-
`
|
|
156
|
-
export async function startServer() {
|
|
157
|
-
try {
|
|
158
|
-
const transport = new StdioServerTransport()
|
|
159
|
-
await server.connect(transport)
|
|
160
|
-
|
|
161
|
-
} catch (error) {
|
|
162
|
-
console.error('Failed to start server:', error)
|
|
163
|
-
process.exit(1)
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
`
|
|
167
|
-
]
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
//#endregion
|
|
171
|
-
export { camelCase as n, Server as t };
|
|
172
|
-
|
|
173
|
-
//# sourceMappingURL=Server-KWLMg0Lm.js.map
|