@forklaunch/core 0.15.2 → 0.15.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/lib/environment/index.d.mts +24 -0
- package/lib/environment/index.d.ts +24 -0
- package/lib/environment/index.js +151 -0
- package/lib/environment/index.js.map +1 -0
- package/lib/environment/index.mjs +113 -0
- package/lib/environment/index.mjs.map +1 -0
- package/lib/http/index.js +162 -154
- package/lib/http/index.js.map +1 -1
- package/lib/http/index.mjs +162 -154
- package/lib/http/index.mjs.map +1 -1
- package/lib/persistence/index.js +1 -1
- package/lib/persistence/index.js.map +1 -1
- package/lib/persistence/index.mjs +1 -1
- package/lib/persistence/index.mjs.map +1 -1
- package/lib/services/index.d.mts +10 -0
- package/lib/services/index.d.ts +10 -0
- package/lib/services/index.js +125 -2
- package/lib/services/index.js.map +1 -1
- package/lib/services/index.mjs +112 -1
- package/lib/services/index.mjs.map +1 -1
- package/package.json +24 -17
package/lib/http/index.mjs
CHANGED
@@ -3038,11 +3038,6 @@ import { isNever as isNever3, isRecord as isRecord3, safeStringify as safeString
|
|
3038
3038
|
import { FastMCP } from "@forklaunch/fastmcp-fork";
|
3039
3039
|
import { string, ZodSchemaValidator } from "@forklaunch/validator/zod";
|
3040
3040
|
|
3041
|
-
// src/http/guards/isVersionedInputSchema.ts
|
3042
|
-
function isUnionable(schema) {
|
3043
|
-
return schema.length > 1;
|
3044
|
-
}
|
3045
|
-
|
3046
3041
|
// src/http/router/unpackRouters.ts
|
3047
3042
|
function unpackRouters(routers, recursiveBasePath = []) {
|
3048
3043
|
return routers.reduce((acc, router) => {
|
@@ -3072,8 +3067,12 @@ function generateInputSchema(schemaValidator, body, params, query, requestHeader
|
|
3072
3067
|
..."contentType" in body ? { contentType: body.contentType } : {},
|
3073
3068
|
body: schemaValidator.schemify(discriminatedBody.schema)
|
3074
3069
|
} : {},
|
3075
|
-
...params ? {
|
3076
|
-
|
3070
|
+
...params ? {
|
3071
|
+
params: schemaValidator.schemify(params)
|
3072
|
+
} : {},
|
3073
|
+
...query ? {
|
3074
|
+
query: schemaValidator.schemify(query)
|
3075
|
+
} : {},
|
3077
3076
|
...requestHeaders ? {
|
3078
3077
|
headers: schemaValidator.schemify({
|
3079
3078
|
...requestHeaders,
|
@@ -3136,163 +3135,172 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, appli
|
|
3136
3135
|
)
|
3137
3136
|
);
|
3138
3137
|
}
|
3139
|
-
|
3140
|
-
|
3141
|
-
|
3142
|
-
|
3143
|
-
|
3144
|
-
|
3145
|
-
|
3146
|
-
|
3147
|
-
|
3148
|
-
|
3149
|
-
|
3150
|
-
|
3151
|
-
|
3152
|
-
|
3153
|
-
}
|
3154
|
-
let bodySchema;
|
3155
|
-
let responsesSchemas;
|
3156
|
-
if (route.contractDetails.versions) {
|
3157
|
-
Object.values(route.contractDetails.versions).forEach(
|
3158
|
-
(version2, index) => {
|
3159
|
-
if (version2.body && schemaValidator.parse(inputSchemas[index], args).ok) {
|
3160
|
-
bodySchema = version2.body;
|
3161
|
-
responsesSchemas = version2.responses;
|
3162
|
-
}
|
3163
|
-
}
|
3164
|
-
);
|
3165
|
-
} else {
|
3166
|
-
bodySchema = route.contractDetails.body;
|
3167
|
-
responsesSchemas = route.contractDetails.responses;
|
3168
|
-
}
|
3169
|
-
const discriminatedBody = bodySchema ? discriminateBody(schemaValidator, bodySchema) : void 0;
|
3170
|
-
let parsedBody;
|
3171
|
-
if (discriminatedBody) {
|
3172
|
-
switch (discriminatedBody.parserType) {
|
3173
|
-
case "json": {
|
3174
|
-
parsedBody = safeStringify3(body);
|
3175
|
-
break;
|
3138
|
+
inputSchemas.forEach((inputSchema, index) => {
|
3139
|
+
mcpServer.addTool({
|
3140
|
+
name: route.contractDetails.name + (Object.keys(route.contractDetails.versions ?? {}).length > 1 ? ` [v${Object.keys(route.contractDetails.versions ?? {})[index]}]` : ""),
|
3141
|
+
description: route.contractDetails.summary,
|
3142
|
+
parameters: inputSchema,
|
3143
|
+
execute: async (args) => {
|
3144
|
+
const { contentType, body, params, query, headers } = args;
|
3145
|
+
let url = `${protocol}://${host}:${port}${fullPath}${route.path}`;
|
3146
|
+
if (params) {
|
3147
|
+
for (const key in params) {
|
3148
|
+
url = url.replace(
|
3149
|
+
`:${key}`,
|
3150
|
+
encodeURIComponent(params[key])
|
3151
|
+
);
|
3176
3152
|
}
|
3177
|
-
|
3178
|
-
|
3179
|
-
|
3180
|
-
|
3181
|
-
|
3182
|
-
|
3183
|
-
|
3153
|
+
}
|
3154
|
+
let bodySchema;
|
3155
|
+
let responsesSchemas;
|
3156
|
+
if (route.contractDetails.versions) {
|
3157
|
+
const version2 = route.contractDetails.versions[index];
|
3158
|
+
if (version2.body && schemaValidator.parse(inputSchema, args).ok) {
|
3159
|
+
bodySchema = version2.body;
|
3160
|
+
responsesSchemas = version2.responses;
|
3184
3161
|
}
|
3185
|
-
|
3186
|
-
|
3187
|
-
|
3188
|
-
|
3189
|
-
|
3190
|
-
|
3191
|
-
|
3192
|
-
|
3162
|
+
} else {
|
3163
|
+
bodySchema = route.contractDetails.body;
|
3164
|
+
responsesSchemas = route.contractDetails.responses;
|
3165
|
+
}
|
3166
|
+
const discriminatedBody = bodySchema ? discriminateBody(schemaValidator, bodySchema) : void 0;
|
3167
|
+
let parsedBody;
|
3168
|
+
if (discriminatedBody) {
|
3169
|
+
switch (discriminatedBody.parserType) {
|
3170
|
+
case "json": {
|
3171
|
+
parsedBody = safeStringify3(body);
|
3172
|
+
break;
|
3173
|
+
}
|
3174
|
+
case "text": {
|
3175
|
+
parsedBody = body;
|
3176
|
+
break;
|
3177
|
+
}
|
3178
|
+
case "file": {
|
3179
|
+
parsedBody = Buffer.from(safeStringify3(body));
|
3180
|
+
break;
|
3181
|
+
}
|
3182
|
+
case "multipart": {
|
3183
|
+
const formData = new FormData();
|
3184
|
+
if (isRecord3(body)) {
|
3185
|
+
for (const key in body) {
|
3186
|
+
if (typeof body[key] === "string") {
|
3187
|
+
if (schemaValidator.isInstanceOf(
|
3188
|
+
body[key],
|
3189
|
+
schemaValidator.file
|
3190
|
+
)) {
|
3191
|
+
formData.append(
|
3192
|
+
key,
|
3193
|
+
new Blob([Buffer.from(body[key])])
|
3194
|
+
);
|
3195
|
+
} else {
|
3196
|
+
formData.append(key, body[key]);
|
3197
|
+
}
|
3198
|
+
} else {
|
3199
|
+
throw new Error("Body is not a valid multipart object");
|
3200
|
+
}
|
3193
3201
|
}
|
3202
|
+
} else {
|
3203
|
+
throw new Error("Body is not a valid multipart object");
|
3194
3204
|
}
|
3195
|
-
|
3196
|
-
|
3205
|
+
parsedBody = formData;
|
3206
|
+
break;
|
3197
3207
|
}
|
3198
|
-
|
3199
|
-
|
3200
|
-
|
3201
|
-
|
3202
|
-
|
3203
|
-
|
3204
|
-
|
3205
|
-
|
3206
|
-
|
3207
|
-
|
3208
|
-
|
3209
|
-
|
3210
|
-
|
3208
|
+
case "urlEncoded": {
|
3209
|
+
if (isRecord3(body)) {
|
3210
|
+
parsedBody = new URLSearchParams(
|
3211
|
+
Object.entries(body).map(([key, value]) => [
|
3212
|
+
key,
|
3213
|
+
safeStringify3(value)
|
3214
|
+
])
|
3215
|
+
);
|
3216
|
+
} else {
|
3217
|
+
throw new Error("Body is not a valid url encoded object");
|
3218
|
+
}
|
3219
|
+
break;
|
3220
|
+
}
|
3221
|
+
default: {
|
3222
|
+
isNever3(discriminatedBody.parserType);
|
3223
|
+
parsedBody = safeStringify3(body);
|
3224
|
+
break;
|
3211
3225
|
}
|
3212
|
-
break;
|
3213
|
-
}
|
3214
|
-
default: {
|
3215
|
-
isNever3(discriminatedBody.parserType);
|
3216
|
-
parsedBody = safeStringify3(body);
|
3217
|
-
break;
|
3218
3226
|
}
|
3219
3227
|
}
|
3220
|
-
|
3221
|
-
|
3222
|
-
|
3223
|
-
|
3224
|
-
|
3225
|
-
|
3226
|
-
|
3227
|
-
|
3228
|
-
|
3229
|
-
|
3230
|
-
|
3231
|
-
|
3232
|
-
|
3233
|
-
|
3234
|
-
|
3235
|
-
|
3236
|
-
}
|
3237
|
-
|
3238
|
-
|
3239
|
-
|
3240
|
-
|
3241
|
-
|
3242
|
-
|
3243
|
-
|
3244
|
-
|
3245
|
-
|
3246
|
-
|
3247
|
-
|
3248
|
-
|
3249
|
-
|
3250
|
-
|
3251
|
-
|
3252
|
-
|
3253
|
-
|
3254
|
-
|
3255
|
-
|
3256
|
-
|
3257
|
-
|
3258
|
-
text: safeStringify3(await response.json())
|
3259
|
-
}
|
3260
|
-
]
|
3261
|
-
};
|
3262
|
-
case "text/plain":
|
3263
|
-
return {
|
3264
|
-
content: [
|
3265
|
-
{ type: "text", text: await response.text() }
|
3266
|
-
]
|
3267
|
-
};
|
3268
|
-
case "application/octet-stream":
|
3269
|
-
return {
|
3270
|
-
content: [
|
3271
|
-
{
|
3272
|
-
type: "resource",
|
3273
|
-
resource: {
|
3274
|
-
uri: response.url,
|
3275
|
-
blob: Buffer.from(
|
3276
|
-
await (await response.blob()).arrayBuffer()
|
3277
|
-
).toString("base64")
|
3228
|
+
if (query) {
|
3229
|
+
const queryString = new URLSearchParams(
|
3230
|
+
Object.entries(query).map(([key, value]) => [
|
3231
|
+
key,
|
3232
|
+
safeStringify3(value)
|
3233
|
+
])
|
3234
|
+
).toString();
|
3235
|
+
url += queryString ? `?${queryString}` : "";
|
3236
|
+
}
|
3237
|
+
const response = await fetch(encodeURI(url), {
|
3238
|
+
method: route.method.toUpperCase(),
|
3239
|
+
headers: {
|
3240
|
+
...headers,
|
3241
|
+
...discriminatedBody?.contentType != "multipart/form-data" ? {
|
3242
|
+
"Content-Type": contentType ?? discriminatedBody?.contentType
|
3243
|
+
} : {}
|
3244
|
+
},
|
3245
|
+
body: parsedBody
|
3246
|
+
});
|
3247
|
+
if (response.status >= 300) {
|
3248
|
+
throw new Error(
|
3249
|
+
`Error received while proxying request to ${url}: ${await response.text()}`
|
3250
|
+
);
|
3251
|
+
}
|
3252
|
+
if (!responsesSchemas) {
|
3253
|
+
throw new Error("No responses schemas found");
|
3254
|
+
}
|
3255
|
+
const contractContentType = discriminateResponseBodies(
|
3256
|
+
schemaValidator,
|
3257
|
+
responsesSchemas
|
3258
|
+
)[response.status].contentType;
|
3259
|
+
switch (contentTypeMap && contentTypeMap[contractContentType] ? contentTypeMap[contractContentType] : contractContentType) {
|
3260
|
+
case "application/json":
|
3261
|
+
return {
|
3262
|
+
content: [
|
3263
|
+
{
|
3264
|
+
type: "text",
|
3265
|
+
text: safeStringify3(await response.json())
|
3278
3266
|
}
|
3279
|
-
|
3280
|
-
|
3281
|
-
|
3282
|
-
|
3283
|
-
|
3284
|
-
|
3285
|
-
|
3286
|
-
|
3287
|
-
|
3288
|
-
|
3289
|
-
|
3290
|
-
|
3291
|
-
|
3292
|
-
|
3293
|
-
|
3267
|
+
]
|
3268
|
+
};
|
3269
|
+
case "text/plain":
|
3270
|
+
return {
|
3271
|
+
content: [
|
3272
|
+
{ type: "text", text: await response.text() }
|
3273
|
+
]
|
3274
|
+
};
|
3275
|
+
case "application/octet-stream":
|
3276
|
+
return {
|
3277
|
+
content: [
|
3278
|
+
{
|
3279
|
+
type: "resource",
|
3280
|
+
resource: {
|
3281
|
+
uri: response.url,
|
3282
|
+
blob: Buffer.from(
|
3283
|
+
await (await response.blob()).arrayBuffer()
|
3284
|
+
).toString("base64")
|
3285
|
+
}
|
3286
|
+
}
|
3287
|
+
]
|
3288
|
+
};
|
3289
|
+
case "text/event-stream":
|
3290
|
+
return {
|
3291
|
+
content: [
|
3292
|
+
{ type: "text", text: await response.text() }
|
3293
|
+
]
|
3294
|
+
};
|
3295
|
+
default:
|
3296
|
+
return {
|
3297
|
+
content: [
|
3298
|
+
{ type: "text", text: await response.text() }
|
3299
|
+
]
|
3300
|
+
};
|
3301
|
+
}
|
3294
3302
|
}
|
3295
|
-
}
|
3303
|
+
});
|
3296
3304
|
});
|
3297
3305
|
});
|
3298
3306
|
});
|