@forklaunch/core 0.9.21 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/http/index.d.mts +296 -102
- package/lib/http/index.d.ts +296 -102
- package/lib/http/index.js +452 -191
- package/lib/http/index.js.map +1 -1
- package/lib/http/index.mjs +455 -191
- package/lib/http/index.mjs.map +1 -1
- package/package.json +13 -12
package/lib/http/index.js
CHANGED
@@ -45,6 +45,7 @@ __export(http_exports, {
|
|
45
45
|
discriminateResponseBodies: () => discriminateResponseBodies,
|
46
46
|
enrichExpressLikeSend: () => enrichExpressLikeSend,
|
47
47
|
evaluateTelemetryOptions: () => evaluateTelemetryOptions,
|
48
|
+
generateMcpServer: () => generateMcpServer,
|
48
49
|
generateSwaggerDocument: () => generateSwaggerDocument,
|
49
50
|
get: () => get,
|
50
51
|
getCodeForStatus: () => getCodeForStatus,
|
@@ -90,35 +91,8 @@ function cors(corsOptions) {
|
|
90
91
|
};
|
91
92
|
}
|
92
93
|
|
93
|
-
// src/http/
|
94
|
-
var
|
95
|
-
var import_uuid = require("uuid");
|
96
|
-
|
97
|
-
// src/http/telemetry/constants.ts
|
98
|
-
var import_semantic_conventions = require("@opentelemetry/semantic-conventions");
|
99
|
-
var ATTR_API_NAME = "api.name";
|
100
|
-
var ATTR_CORRELATION_ID = "correlation.id";
|
101
|
-
|
102
|
-
// src/http/middleware/request/createContext.middleware.ts
|
103
|
-
function createContext(schemaValidator) {
|
104
|
-
return function setContext(req, res, next) {
|
105
|
-
req.schemaValidator = schemaValidator;
|
106
|
-
let correlationId = (0, import_uuid.v4)();
|
107
|
-
if (req.headers["x-correlation-id"]) {
|
108
|
-
correlationId = req.headers["x-correlation-id"];
|
109
|
-
}
|
110
|
-
res.setHeader("x-correlation-id", correlationId);
|
111
|
-
req.context = {
|
112
|
-
correlationId
|
113
|
-
};
|
114
|
-
const span = import_api.trace.getActiveSpan();
|
115
|
-
if (span != null) {
|
116
|
-
req.context.span = span;
|
117
|
-
req.context.span?.setAttribute(ATTR_CORRELATION_ID, correlationId);
|
118
|
-
}
|
119
|
-
next?.();
|
120
|
-
};
|
121
|
-
}
|
94
|
+
// src/http/router/expressLikeRouter.ts
|
95
|
+
var import_common5 = require("@forklaunch/common");
|
122
96
|
|
123
97
|
// src/http/guards/isForklaunchRouter.ts
|
124
98
|
function isForklaunchRouter(maybeForklaunchRouter) {
|
@@ -138,7 +112,7 @@ function isExpressLikeSchemaHandler(middleware2) {
|
|
138
112
|
(argumentName) => argumentName.toLowerCase()
|
139
113
|
)
|
140
114
|
);
|
141
|
-
return extractedArgumentNames && extractedArgumentNames.size <=
|
115
|
+
return extractedArgumentNames && extractedArgumentNames.size <= 4;
|
142
116
|
}
|
143
117
|
|
144
118
|
// src/http/guards/isForklaunchExpressLikeRouter.ts
|
@@ -295,6 +269,36 @@ async function parseRequestAuth(req, res, next) {
|
|
295
269
|
next?.();
|
296
270
|
}
|
297
271
|
|
272
|
+
// src/http/middleware/request/createContext.middleware.ts
|
273
|
+
var import_api = require("@opentelemetry/api");
|
274
|
+
var import_uuid = require("uuid");
|
275
|
+
|
276
|
+
// src/http/telemetry/constants.ts
|
277
|
+
var import_semantic_conventions = require("@opentelemetry/semantic-conventions");
|
278
|
+
var ATTR_API_NAME = "api.name";
|
279
|
+
var ATTR_CORRELATION_ID = "correlation.id";
|
280
|
+
|
281
|
+
// src/http/middleware/request/createContext.middleware.ts
|
282
|
+
function createContext(schemaValidator) {
|
283
|
+
return function setContext(req, res, next) {
|
284
|
+
req.schemaValidator = schemaValidator;
|
285
|
+
let correlationId = (0, import_uuid.v4)();
|
286
|
+
if (req.headers["x-correlation-id"]) {
|
287
|
+
correlationId = req.headers["x-correlation-id"];
|
288
|
+
}
|
289
|
+
res.setHeader("x-correlation-id", correlationId);
|
290
|
+
req.context = {
|
291
|
+
correlationId
|
292
|
+
};
|
293
|
+
const span = import_api.trace.getActiveSpan();
|
294
|
+
if (span != null) {
|
295
|
+
req.context.span = span;
|
296
|
+
req.context.span?.setAttribute(ATTR_CORRELATION_ID, correlationId);
|
297
|
+
}
|
298
|
+
next?.();
|
299
|
+
};
|
300
|
+
}
|
301
|
+
|
298
302
|
// src/http/middleware/request/enrichDetails.middleware.ts
|
299
303
|
var import_common4 = require("@forklaunch/common");
|
300
304
|
|
@@ -546,7 +550,7 @@ function enrichDetails(path, contractDetails, requestSchema, responseSchemas, op
|
|
546
550
|
req.requestSchema = requestSchema;
|
547
551
|
res.responseSchemas = responseSchemas;
|
548
552
|
req.openTelemetryCollector = openTelemetryCollector;
|
549
|
-
req.context
|
553
|
+
req.context?.span?.setAttribute(ATTR_API_NAME, req.contractDetails?.name);
|
550
554
|
const startTime = process.hrtime();
|
551
555
|
res.on("finish", () => {
|
552
556
|
const [seconds, nanoseconds] = process.hrtime(startTime);
|
@@ -681,6 +685,12 @@ function discriminateBody(schemaValidator, body) {
|
|
681
685
|
parserType: "text",
|
682
686
|
schema: maybeTypedBody
|
683
687
|
};
|
688
|
+
} else if (schemaValidator.openapi(maybeTypedBody).format === "binary") {
|
689
|
+
return {
|
690
|
+
contentType: "application/octet-stream",
|
691
|
+
parserType: "file",
|
692
|
+
schema: maybeTypedBody
|
693
|
+
};
|
684
694
|
} else {
|
685
695
|
return {
|
686
696
|
contentType: "application/json",
|
@@ -732,6 +742,12 @@ function discriminateResponseBodies(schemaValidator, responses) {
|
|
732
742
|
parserType: "text",
|
733
743
|
schema: response
|
734
744
|
};
|
745
|
+
} else if (schemaValidator.openapi(response).format === "binary") {
|
746
|
+
discriminatedResponses[Number(statusCode)] = {
|
747
|
+
contentType: "application/octet-stream",
|
748
|
+
parserType: "file",
|
749
|
+
schema: response
|
750
|
+
};
|
735
751
|
} else {
|
736
752
|
discriminatedResponses[Number(statusCode)] = {
|
737
753
|
contentType: "application/json",
|
@@ -751,18 +767,38 @@ function discriminateResponseBodies(schemaValidator, responses) {
|
|
751
767
|
}
|
752
768
|
|
753
769
|
// src/http/router/expressLikeRouter.ts
|
754
|
-
var ForklaunchExpressLikeRouter = class {
|
755
|
-
constructor(basePath, schemaValidator, internal, postEnrichMiddleware, openTelemetryCollector) {
|
770
|
+
var ForklaunchExpressLikeRouter = class _ForklaunchExpressLikeRouter {
|
771
|
+
constructor(basePath, schemaValidator, internal, postEnrichMiddleware, openTelemetryCollector, sdkName) {
|
772
|
+
this.basePath = basePath;
|
756
773
|
this.schemaValidator = schemaValidator;
|
757
774
|
this.internal = internal;
|
758
775
|
this.postEnrichMiddleware = postEnrichMiddleware;
|
759
776
|
this.openTelemetryCollector = openTelemetryCollector;
|
760
|
-
this.
|
777
|
+
this.sdkName = sdkName;
|
778
|
+
if (process.env.NODE_ENV !== "test" && !process.env.VITEST) {
|
779
|
+
process.on("uncaughtException", (err) => {
|
780
|
+
this.openTelemetryCollector.error(`Uncaught exception: ${err}`);
|
781
|
+
process.exit(1);
|
782
|
+
});
|
783
|
+
process.on("unhandledRejection", (reason) => {
|
784
|
+
this.openTelemetryCollector.error(`Unhandled rejection: ${reason}`);
|
785
|
+
process.exit(1);
|
786
|
+
});
|
787
|
+
process.on("exit", () => {
|
788
|
+
this.openTelemetryCollector.info("Shutting down application");
|
789
|
+
});
|
790
|
+
process.on("SIGINT", () => {
|
791
|
+
this.openTelemetryCollector.info("Shutting down application");
|
792
|
+
process.exit(0);
|
793
|
+
});
|
794
|
+
}
|
795
|
+
this.internal.use(createContext(this.schemaValidator));
|
761
796
|
}
|
762
797
|
requestHandler;
|
763
798
|
routers = [];
|
764
799
|
routes = [];
|
765
|
-
|
800
|
+
fetchMap = {};
|
801
|
+
sdk = {};
|
766
802
|
/**
|
767
803
|
* Resolves middlewares based on the contract details.
|
768
804
|
*
|
@@ -881,6 +917,20 @@ var ForklaunchExpressLikeRouter = class {
|
|
881
917
|
responseSchemas
|
882
918
|
};
|
883
919
|
}
|
920
|
+
/**
|
921
|
+
* Fetches a route from the route map and executes it with the given parameters.
|
922
|
+
*
|
923
|
+
* @template Path - The path type that extends keyof fetchMap and string.
|
924
|
+
* @param {Path} path - The route path
|
925
|
+
* @param {Parameters<fetchMap[Path]>[1]} [requestInit] - Optional request initialization parameters.
|
926
|
+
* @returns {Promise<ReturnType<fetchMap[Path]>>} - The result of executing the route handler.
|
927
|
+
*/
|
928
|
+
fetch = async (path, ...reqInit) => {
|
929
|
+
return this.fetchMap[path](
|
930
|
+
path,
|
931
|
+
reqInit[0]
|
932
|
+
);
|
933
|
+
};
|
884
934
|
/**
|
885
935
|
* Executes request locally, applying parameters
|
886
936
|
*
|
@@ -900,24 +950,6 @@ var ForklaunchExpressLikeRouter = class {
|
|
900
950
|
body: discriminateBody(this.schemaValidator, request?.body)?.schema ?? {},
|
901
951
|
path: route
|
902
952
|
};
|
903
|
-
function remapFileBody(body) {
|
904
|
-
if (body instanceof File) {
|
905
|
-
return (name, contentType) => {
|
906
|
-
return new File([body], name, { type: contentType });
|
907
|
-
};
|
908
|
-
}
|
909
|
-
Object.entries(body).forEach(([key, value]) => {
|
910
|
-
if (value instanceof File) {
|
911
|
-
body[key] = (name, contentType) => {
|
912
|
-
return new File([value], name, { type: contentType });
|
913
|
-
};
|
914
|
-
} else if (typeof value === "object") {
|
915
|
-
body[key] = remapFileBody(value);
|
916
|
-
}
|
917
|
-
});
|
918
|
-
return body;
|
919
|
-
}
|
920
|
-
req.body = remapFileBody(req.body);
|
921
953
|
const res = {
|
922
954
|
status: (code) => {
|
923
955
|
statusCode = code;
|
@@ -971,24 +1003,20 @@ var ForklaunchExpressLikeRouter = class {
|
|
971
1003
|
registerRoute(method, path, registrationMethod, contractDetailsOrMiddlewareOrTypedHandler, ...middlewareOrMiddlewareAndTypedHandler) {
|
972
1004
|
if (isTypedHandler(contractDetailsOrMiddlewareOrTypedHandler)) {
|
973
1005
|
const { contractDetails, handlers } = contractDetailsOrMiddlewareOrTypedHandler;
|
974
|
-
|
975
|
-
|
976
|
-
path,
|
977
|
-
registrationMethod,
|
978
|
-
contractDetails,
|
979
|
-
...handlers
|
980
|
-
);
|
1006
|
+
this.registerRoute(method, path, registrationMethod, contractDetails, ...handlers);
|
1007
|
+
return this;
|
981
1008
|
} else {
|
982
1009
|
const maybeTypedHandler = middlewareOrMiddlewareAndTypedHandler[middlewareOrMiddlewareAndTypedHandler.length - 1];
|
983
1010
|
if (isTypedHandler(maybeTypedHandler)) {
|
984
1011
|
const { contractDetails, handlers } = maybeTypedHandler;
|
985
|
-
|
1012
|
+
this.registerRoute(
|
986
1013
|
method,
|
987
1014
|
path,
|
988
1015
|
registrationMethod,
|
989
1016
|
contractDetails,
|
990
1017
|
...middlewareOrMiddlewareAndTypedHandler.concat(handlers)
|
991
1018
|
);
|
1019
|
+
return this;
|
992
1020
|
} else {
|
993
1021
|
if (isExpressLikeSchemaHandler(contractDetailsOrMiddlewareOrTypedHandler) || isTypedHandler(contractDetailsOrMiddlewareOrTypedHandler)) {
|
994
1022
|
throw new Error("Contract details are not defined");
|
@@ -1020,10 +1048,13 @@ var ForklaunchExpressLikeRouter = class {
|
|
1020
1048
|
).concat(handlers),
|
1021
1049
|
this.#parseAndRunControllerHandler(controllerHandler)
|
1022
1050
|
);
|
1023
|
-
|
1051
|
+
const localParamRequest = this.#localParamRequest(
|
1024
1052
|
handlers,
|
1025
1053
|
controllerHandler
|
1026
1054
|
);
|
1055
|
+
(0, import_common5.toRecord)(this.fetchMap)[(0, import_common5.sanitizePathSlashes)(`${this.basePath}${path}`)] = localParamRequest;
|
1056
|
+
(0, import_common5.toRecord)(this.sdk)[(0, import_common5.toPrettyCamelCase)(contractDetails.name ?? this.basePath)] = (req) => localParamRequest(`${this.basePath}${path}`, req);
|
1057
|
+
return this;
|
1027
1058
|
}
|
1028
1059
|
}
|
1029
1060
|
}
|
@@ -1047,10 +1078,13 @@ var ForklaunchExpressLikeRouter = class {
|
|
1047
1078
|
return this.#extractHandlers(handlers);
|
1048
1079
|
}
|
1049
1080
|
#extractNestableMiddlewareFromEnrichedTypedHandlerArray(handlers) {
|
1050
|
-
return this.#extractHandlers(
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1081
|
+
return this.#extractHandlers(handlers, (handler) => {
|
1082
|
+
if (isForklaunchExpressLikeRouter(handler)) {
|
1083
|
+
this.addRouterToSdk(handler);
|
1084
|
+
return handler.internal;
|
1085
|
+
}
|
1086
|
+
return handler;
|
1087
|
+
});
|
1054
1088
|
}
|
1055
1089
|
#processTypedHandlerOrMiddleware(handler, middleware2) {
|
1056
1090
|
if (isTypedHandler(handler)) {
|
@@ -1074,6 +1108,7 @@ var ForklaunchExpressLikeRouter = class {
|
|
1074
1108
|
middleware2
|
1075
1109
|
);
|
1076
1110
|
if (isForklaunchExpressLikeRouter(contractDetailsOrMiddlewareOrTypedHandler)) {
|
1111
|
+
this.addRouterToSdk(contractDetailsOrMiddlewareOrTypedHandler);
|
1077
1112
|
middleware2.push(contractDetailsOrMiddlewareOrTypedHandler.internal);
|
1078
1113
|
}
|
1079
1114
|
middleware2.push(
|
@@ -1103,6 +1138,16 @@ var ForklaunchExpressLikeRouter = class {
|
|
1103
1138
|
}
|
1104
1139
|
return this;
|
1105
1140
|
}
|
1141
|
+
addRouterToSdk(router) {
|
1142
|
+
Object.entries(router.fetchMap).map(
|
1143
|
+
([key, value]) => (0, import_common5.toRecord)(this.fetchMap)[(0, import_common5.sanitizePathSlashes)(`${this.basePath}${key}`)] = value
|
1144
|
+
);
|
1145
|
+
const existingSdk = this.sdk[router.sdkName ?? (0, import_common5.toPrettyCamelCase)(router.basePath)];
|
1146
|
+
(0, import_common5.toRecord)(this.sdk)[router.sdkName ?? (0, import_common5.toPrettyCamelCase)(router.basePath)] = {
|
1147
|
+
...typeof existingSdk === "object" ? existingSdk : {},
|
1148
|
+
...router.sdk
|
1149
|
+
};
|
1150
|
+
}
|
1106
1151
|
registerNestableMiddlewareHandler(registrationMethod, pathOrContractDetailsOrMiddlewareOrTypedHandler, contractDetailsOrMiddlewareOrTypedHandler, ...middlewareOrMiddlewareWithTypedHandler) {
|
1107
1152
|
const middleware2 = [];
|
1108
1153
|
let path;
|
@@ -1118,7 +1163,9 @@ var ForklaunchExpressLikeRouter = class {
|
|
1118
1163
|
if (isConstrainedForklaunchRouter(
|
1119
1164
|
pathOrContractDetailsOrMiddlewareOrTypedHandler
|
1120
1165
|
)) {
|
1121
|
-
|
1166
|
+
const router = pathOrContractDetailsOrMiddlewareOrTypedHandler;
|
1167
|
+
this.addRouterToSdk(router);
|
1168
|
+
path = router.basePath;
|
1122
1169
|
}
|
1123
1170
|
middleware2.push(
|
1124
1171
|
...this.#extractNestableMiddlewareAsRouterHandlers(
|
@@ -1129,6 +1176,11 @@ var ForklaunchExpressLikeRouter = class {
|
|
1129
1176
|
)
|
1130
1177
|
);
|
1131
1178
|
}
|
1179
|
+
if (!path) {
|
1180
|
+
path = middleware2.filter(
|
1181
|
+
(m) => isForklaunchExpressLikeRouter(m)
|
1182
|
+
)[0]?.basePath;
|
1183
|
+
}
|
1132
1184
|
if (path) {
|
1133
1185
|
registrationMethod.bind(this.internal)(path, ...middleware2);
|
1134
1186
|
} else {
|
@@ -1183,15 +1235,13 @@ var ForklaunchExpressLikeRouter = class {
|
|
1183
1235
|
* @returns {ExpressRouter} - The Express router.
|
1184
1236
|
*/
|
1185
1237
|
get = (path, contractDetailsOrMiddlewareOrTypedHandler, ...middlewareOrMiddlewareWithTypedHandler) => {
|
1186
|
-
return
|
1187
|
-
get
|
1188
|
-
|
1189
|
-
|
1190
|
-
|
1191
|
-
|
1192
|
-
|
1193
|
-
)
|
1194
|
-
};
|
1238
|
+
return this.registerRoute(
|
1239
|
+
"get",
|
1240
|
+
path,
|
1241
|
+
this.internal.get,
|
1242
|
+
contractDetailsOrMiddlewareOrTypedHandler,
|
1243
|
+
...middlewareOrMiddlewareWithTypedHandler
|
1244
|
+
);
|
1195
1245
|
};
|
1196
1246
|
/**
|
1197
1247
|
* Registers a POST route with the specified contract details and handler handlers.
|
@@ -1207,15 +1257,13 @@ var ForklaunchExpressLikeRouter = class {
|
|
1207
1257
|
* @returns {ExpressRouter} - The Expxwress router.
|
1208
1258
|
*/
|
1209
1259
|
post = (path, contractDetailsOrMiddlewareOrTypedHandler, ...middlewareOrMiddlewareWithTypedHandler) => {
|
1210
|
-
return
|
1211
|
-
post
|
1212
|
-
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1216
|
-
|
1217
|
-
)
|
1218
|
-
};
|
1260
|
+
return this.registerRoute(
|
1261
|
+
"post",
|
1262
|
+
path,
|
1263
|
+
this.internal.post,
|
1264
|
+
contractDetailsOrMiddlewareOrTypedHandler,
|
1265
|
+
...middlewareOrMiddlewareWithTypedHandler
|
1266
|
+
);
|
1219
1267
|
};
|
1220
1268
|
/**
|
1221
1269
|
* Registers a PUT route with the specified contract details and handler handlers.
|
@@ -1231,15 +1279,13 @@ var ForklaunchExpressLikeRouter = class {
|
|
1231
1279
|
* @returns {ExpressRouter} - The Express router.
|
1232
1280
|
*/
|
1233
1281
|
put = (path, contractDetailsOrMiddlewareOrTypedHandler, ...middlewareOrMiddlewareWithTypedHandler) => {
|
1234
|
-
return
|
1235
|
-
put
|
1236
|
-
|
1237
|
-
|
1238
|
-
|
1239
|
-
|
1240
|
-
|
1241
|
-
)
|
1242
|
-
};
|
1282
|
+
return this.registerRoute(
|
1283
|
+
"put",
|
1284
|
+
path,
|
1285
|
+
this.internal.put,
|
1286
|
+
contractDetailsOrMiddlewareOrTypedHandler,
|
1287
|
+
...middlewareOrMiddlewareWithTypedHandler
|
1288
|
+
);
|
1243
1289
|
};
|
1244
1290
|
/**
|
1245
1291
|
* Registers a PATCH route with the specified contract details and handler handlers.
|
@@ -1255,15 +1301,13 @@ var ForklaunchExpressLikeRouter = class {
|
|
1255
1301
|
* @returns {ExpressRouter} - The Express router.
|
1256
1302
|
*/
|
1257
1303
|
patch = (path, contractDetailsOrMiddlewareOrTypedHandler, ...middlewareOrMiddlewareWithTypedHandler) => {
|
1258
|
-
return
|
1259
|
-
patch
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1265
|
-
)
|
1266
|
-
};
|
1304
|
+
return this.registerRoute(
|
1305
|
+
"patch",
|
1306
|
+
path,
|
1307
|
+
this.internal.patch,
|
1308
|
+
contractDetailsOrMiddlewareOrTypedHandler,
|
1309
|
+
...middlewareOrMiddlewareWithTypedHandler
|
1310
|
+
);
|
1267
1311
|
};
|
1268
1312
|
/**
|
1269
1313
|
* Registers a DELETE route with the specified contract details and handler handlers.
|
@@ -1279,15 +1323,13 @@ var ForklaunchExpressLikeRouter = class {
|
|
1279
1323
|
* @returns {ExpressRouter} - The Express router.
|
1280
1324
|
*/
|
1281
1325
|
delete = (path, contractDetailsOrMiddlewareOrTypedHandler, ...middlewareOrMiddlewareWithTypedHandler) => {
|
1282
|
-
return
|
1283
|
-
delete
|
1284
|
-
|
1285
|
-
|
1286
|
-
|
1287
|
-
|
1288
|
-
|
1289
|
-
)
|
1290
|
-
};
|
1326
|
+
return this.registerRoute(
|
1327
|
+
"delete",
|
1328
|
+
path,
|
1329
|
+
this.internal.delete,
|
1330
|
+
contractDetailsOrMiddlewareOrTypedHandler,
|
1331
|
+
...middlewareOrMiddlewareWithTypedHandler
|
1332
|
+
);
|
1291
1333
|
};
|
1292
1334
|
/**
|
1293
1335
|
* Registers a OPTIONS route with the specified contract details and handler handlers.
|
@@ -1303,15 +1345,13 @@ var ForklaunchExpressLikeRouter = class {
|
|
1303
1345
|
* @returns {ExpressRouter} - The Express router.
|
1304
1346
|
*/
|
1305
1347
|
options = (path, contractDetailsOrMiddlewareOrTypedHandler, ...middlewareOrMiddlewareWithTypedHandler) => {
|
1306
|
-
return
|
1307
|
-
options
|
1308
|
-
|
1309
|
-
|
1310
|
-
|
1311
|
-
|
1312
|
-
|
1313
|
-
)
|
1314
|
-
};
|
1348
|
+
return this.registerRoute(
|
1349
|
+
"options",
|
1350
|
+
path,
|
1351
|
+
this.internal.options,
|
1352
|
+
contractDetailsOrMiddlewareOrTypedHandler,
|
1353
|
+
...middlewareOrMiddlewareWithTypedHandler
|
1354
|
+
);
|
1315
1355
|
};
|
1316
1356
|
/**
|
1317
1357
|
* Registers a HEAD route with the specified contract details and handler handlers.
|
@@ -1327,15 +1367,13 @@ var ForklaunchExpressLikeRouter = class {
|
|
1327
1367
|
* @returns {ExpressRouter} - The Express router.
|
1328
1368
|
*/
|
1329
1369
|
head = (path, contractDetailsOrMiddlewareOrTypedHandler, ...middlewareOrMiddlewareWithTypedHandler) => {
|
1330
|
-
return
|
1331
|
-
head
|
1332
|
-
|
1333
|
-
|
1334
|
-
|
1335
|
-
|
1336
|
-
|
1337
|
-
)
|
1338
|
-
};
|
1370
|
+
return this.registerRoute(
|
1371
|
+
"head",
|
1372
|
+
path,
|
1373
|
+
this.internal.head,
|
1374
|
+
contractDetailsOrMiddlewareOrTypedHandler,
|
1375
|
+
...middlewareOrMiddlewareWithTypedHandler
|
1376
|
+
);
|
1339
1377
|
};
|
1340
1378
|
/**
|
1341
1379
|
* Registers a TRACE route with the specified contract details and handler handlers.
|
@@ -1351,16 +1389,32 @@ var ForklaunchExpressLikeRouter = class {
|
|
1351
1389
|
* @returns {ExpressRouter} - The Express router.
|
1352
1390
|
*/
|
1353
1391
|
trace = (path, contractDetailsOrMiddlewareOrTypedHandler, ...middlewareOrMiddlewareWithTypedHandler) => {
|
1354
|
-
return
|
1355
|
-
trace
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
)
|
1362
|
-
};
|
1392
|
+
return this.registerRoute(
|
1393
|
+
"trace",
|
1394
|
+
path,
|
1395
|
+
this.internal.trace,
|
1396
|
+
contractDetailsOrMiddlewareOrTypedHandler,
|
1397
|
+
...middlewareOrMiddlewareWithTypedHandler
|
1398
|
+
);
|
1363
1399
|
};
|
1400
|
+
cloneInternals(clone) {
|
1401
|
+
clone.routers = [...this.routers];
|
1402
|
+
clone.routes = [...this.routes];
|
1403
|
+
clone.fetchMap = { ...this.fetchMap };
|
1404
|
+
clone.sdk = { ...this.sdk };
|
1405
|
+
}
|
1406
|
+
clone() {
|
1407
|
+
const clone = new _ForklaunchExpressLikeRouter(
|
1408
|
+
this.basePath,
|
1409
|
+
this.schemaValidator,
|
1410
|
+
this.internal,
|
1411
|
+
this.postEnrichMiddleware,
|
1412
|
+
this.openTelemetryCollector,
|
1413
|
+
this.sdkName
|
1414
|
+
);
|
1415
|
+
this.cloneInternals(clone);
|
1416
|
+
return clone;
|
1417
|
+
}
|
1364
1418
|
};
|
1365
1419
|
|
1366
1420
|
// src/http/application/expressLikeApplication.ts
|
@@ -1383,25 +1437,6 @@ var ForklaunchExpressLikeApplication = class extends ForklaunchExpressLikeRouter
|
|
1383
1437
|
this.postEnrichMiddleware = postEnrichMiddleware;
|
1384
1438
|
this.openTelemetryCollector = openTelemetryCollector;
|
1385
1439
|
this.appOptions = appOptions;
|
1386
|
-
process.on("uncaughtException", (err) => {
|
1387
|
-
this.openTelemetryCollector.log("error", `Uncaught exception: ${err}`);
|
1388
|
-
process.exit(1);
|
1389
|
-
});
|
1390
|
-
process.on("unhandledRejection", (reason) => {
|
1391
|
-
this.openTelemetryCollector.log(
|
1392
|
-
"error",
|
1393
|
-
`Unhandled rejection: ${reason}`
|
1394
|
-
);
|
1395
|
-
process.exit(1);
|
1396
|
-
});
|
1397
|
-
process.on("exit", () => {
|
1398
|
-
this.openTelemetryCollector.log("info", "Shutting down application");
|
1399
|
-
});
|
1400
|
-
process.on("SIGINT", () => {
|
1401
|
-
this.openTelemetryCollector.log("info", "Shutting down application");
|
1402
|
-
process.exit(0);
|
1403
|
-
});
|
1404
|
-
this.internal.use(createContext(this.schemaValidator));
|
1405
1440
|
this.internal.use(cors(this.appOptions?.cors ?? {}));
|
1406
1441
|
}
|
1407
1442
|
};
|
@@ -2466,6 +2501,218 @@ var getCodeForStatus = (status) => {
|
|
2466
2501
|
};
|
2467
2502
|
var httpStatusCodes_default = HTTPStatuses;
|
2468
2503
|
|
2504
|
+
// src/http/mcpGenerator/mcpGenerator.ts
|
2505
|
+
var import_common7 = require("@forklaunch/common");
|
2506
|
+
var import_zod = require("@forklaunch/validator/zod");
|
2507
|
+
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
2508
|
+
|
2509
|
+
// src/http/router/unpackRouters.ts
|
2510
|
+
var import_common6 = require("@forklaunch/common");
|
2511
|
+
function unpackRouters(routers, recursiveBasePath = [], recursiveSdkPath = []) {
|
2512
|
+
return routers.reduce((acc, router) => {
|
2513
|
+
acc.push({
|
2514
|
+
fullPath: [...recursiveBasePath, router.basePath].join(""),
|
2515
|
+
sdkPath: [
|
2516
|
+
...recursiveSdkPath,
|
2517
|
+
(0, import_common6.toPrettyCamelCase)(router.sdkName ?? router.basePath)
|
2518
|
+
].join("."),
|
2519
|
+
router
|
2520
|
+
});
|
2521
|
+
acc.push(
|
2522
|
+
...unpackRouters(
|
2523
|
+
router.routers,
|
2524
|
+
[...recursiveBasePath, router.basePath],
|
2525
|
+
[
|
2526
|
+
...recursiveSdkPath,
|
2527
|
+
(0, import_common6.toPrettyCamelCase)(router.sdkName ?? router.basePath)
|
2528
|
+
]
|
2529
|
+
)
|
2530
|
+
);
|
2531
|
+
return acc;
|
2532
|
+
}, []);
|
2533
|
+
}
|
2534
|
+
|
2535
|
+
// src/http/mcpGenerator/mcpGenerator.ts
|
2536
|
+
function generateMcpServer(schemaValidator, protocol, host, port, version, routers, contentTypeMap) {
|
2537
|
+
if (!(schemaValidator instanceof import_zod.ZodSchemaValidator)) {
|
2538
|
+
throw new Error(
|
2539
|
+
"Schema validator must be an instance of ZodSchemaValidator"
|
2540
|
+
);
|
2541
|
+
}
|
2542
|
+
const mcpServer = new import_mcp.McpServer({
|
2543
|
+
name: "example-server",
|
2544
|
+
version
|
2545
|
+
});
|
2546
|
+
unpackRouters(routers).forEach(({ fullPath, router }) => {
|
2547
|
+
router.routes.forEach((route) => {
|
2548
|
+
let discriminatedBody;
|
2549
|
+
if ("body" in route.contractDetails) {
|
2550
|
+
discriminatedBody = discriminateBody(
|
2551
|
+
schemaValidator,
|
2552
|
+
route.contractDetails.body
|
2553
|
+
);
|
2554
|
+
}
|
2555
|
+
const inputSchema = {
|
2556
|
+
...discriminatedBody && "body" in route.contractDetails ? {
|
2557
|
+
..."contentType" in route.contractDetails.body ? { contentType: route.contractDetails.body.contentType } : {},
|
2558
|
+
body: schemaValidator.schemify(discriminatedBody.schema)
|
2559
|
+
} : {},
|
2560
|
+
...route.contractDetails.params ? { params: schemaValidator.schemify(route.contractDetails.params) } : {},
|
2561
|
+
...route.contractDetails.query ? { query: schemaValidator.schemify(route.contractDetails.query) } : {},
|
2562
|
+
...route.contractDetails.requestHeaders ? {
|
2563
|
+
headers: schemaValidator.schemify(
|
2564
|
+
route.contractDetails.requestHeaders
|
2565
|
+
)
|
2566
|
+
} : {}
|
2567
|
+
// TODO: support auth
|
2568
|
+
// ...(route.contractDetails.auth
|
2569
|
+
// ? { auth: route.contractDetails.auth }
|
2570
|
+
// : {})
|
2571
|
+
};
|
2572
|
+
mcpServer.tool(
|
2573
|
+
route.contractDetails.name,
|
2574
|
+
route.contractDetails.summary,
|
2575
|
+
inputSchema,
|
2576
|
+
async (args) => {
|
2577
|
+
const { contentType, body, params, query, headers } = args;
|
2578
|
+
let url = `${protocol}://${host}:${port}${fullPath}${route.path}`;
|
2579
|
+
if (params) {
|
2580
|
+
for (const key in params) {
|
2581
|
+
url = url.replace(
|
2582
|
+
`:${key}`,
|
2583
|
+
encodeURIComponent(params[key])
|
2584
|
+
);
|
2585
|
+
}
|
2586
|
+
}
|
2587
|
+
let parsedBody;
|
2588
|
+
if (discriminatedBody) {
|
2589
|
+
switch (discriminatedBody.parserType) {
|
2590
|
+
case "json": {
|
2591
|
+
parsedBody = (0, import_common7.safeStringify)(body);
|
2592
|
+
break;
|
2593
|
+
}
|
2594
|
+
case "text": {
|
2595
|
+
parsedBody = body;
|
2596
|
+
break;
|
2597
|
+
}
|
2598
|
+
case "file": {
|
2599
|
+
parsedBody = body;
|
2600
|
+
break;
|
2601
|
+
}
|
2602
|
+
case "multipart": {
|
2603
|
+
const formData = new FormData();
|
2604
|
+
if ((0, import_common7.isRecord)(body)) {
|
2605
|
+
for (const key in body) {
|
2606
|
+
if (typeof body[key] === "string" || body[key] instanceof Blob) {
|
2607
|
+
formData.append(key, body[key]);
|
2608
|
+
} else {
|
2609
|
+
throw new Error("Body is not a valid multipart object");
|
2610
|
+
}
|
2611
|
+
}
|
2612
|
+
} else {
|
2613
|
+
throw new Error("Body is not a valid multipart object");
|
2614
|
+
}
|
2615
|
+
parsedBody = formData;
|
2616
|
+
break;
|
2617
|
+
}
|
2618
|
+
case "urlEncoded": {
|
2619
|
+
if ((0, import_common7.isRecord)(body)) {
|
2620
|
+
parsedBody = new URLSearchParams(
|
2621
|
+
Object.entries(body).map(([key, value]) => [
|
2622
|
+
key,
|
2623
|
+
(0, import_common7.safeStringify)(value)
|
2624
|
+
])
|
2625
|
+
);
|
2626
|
+
} else {
|
2627
|
+
throw new Error("Body is not a valid url encoded object");
|
2628
|
+
}
|
2629
|
+
break;
|
2630
|
+
}
|
2631
|
+
default: {
|
2632
|
+
(0, import_common7.isNever)(discriminatedBody.parserType);
|
2633
|
+
parsedBody = (0, import_common7.safeStringify)(body);
|
2634
|
+
break;
|
2635
|
+
}
|
2636
|
+
}
|
2637
|
+
}
|
2638
|
+
if (query) {
|
2639
|
+
const queryString = new URLSearchParams(
|
2640
|
+
Object.entries(query).map(([key, value]) => [
|
2641
|
+
key,
|
2642
|
+
(0, import_common7.safeStringify)(value)
|
2643
|
+
])
|
2644
|
+
).toString();
|
2645
|
+
url += queryString ? `?${queryString}` : "";
|
2646
|
+
}
|
2647
|
+
const response = await fetch(encodeURI(url), {
|
2648
|
+
method: route.method.toUpperCase(),
|
2649
|
+
headers: {
|
2650
|
+
...headers,
|
2651
|
+
...discriminatedBody?.contentType != "multipart/form-data" ? {
|
2652
|
+
"Content-Type": contentType ?? discriminatedBody?.contentType
|
2653
|
+
} : {}
|
2654
|
+
},
|
2655
|
+
body: parsedBody
|
2656
|
+
});
|
2657
|
+
if (response.status >= 300) {
|
2658
|
+
throw new Error(
|
2659
|
+
`Error received while proxying request to ${url}: ${await response.text()}`
|
2660
|
+
);
|
2661
|
+
}
|
2662
|
+
const contractContentType = discriminateResponseBodies(
|
2663
|
+
schemaValidator,
|
2664
|
+
route.contractDetails.responses
|
2665
|
+
)[response.status].contentType;
|
2666
|
+
switch (contentTypeMap && contentTypeMap[contractContentType] ? contentTypeMap[contractContentType] : contractContentType) {
|
2667
|
+
case "application/json":
|
2668
|
+
return {
|
2669
|
+
content: [
|
2670
|
+
{
|
2671
|
+
type: "text",
|
2672
|
+
text: (0, import_common7.safeStringify)(await response.json())
|
2673
|
+
}
|
2674
|
+
]
|
2675
|
+
};
|
2676
|
+
case "text/plain":
|
2677
|
+
return {
|
2678
|
+
content: [
|
2679
|
+
{ type: "text", text: await response.text() }
|
2680
|
+
]
|
2681
|
+
};
|
2682
|
+
case "application/octet-stream":
|
2683
|
+
return {
|
2684
|
+
content: [
|
2685
|
+
{
|
2686
|
+
type: "resource",
|
2687
|
+
resource: {
|
2688
|
+
uri: response.url,
|
2689
|
+
blob: Buffer.from(
|
2690
|
+
await (await response.blob()).arrayBuffer()
|
2691
|
+
).toString("base64")
|
2692
|
+
}
|
2693
|
+
}
|
2694
|
+
]
|
2695
|
+
};
|
2696
|
+
case "text/event-stream":
|
2697
|
+
return {
|
2698
|
+
content: [
|
2699
|
+
{ type: "text", text: await response.text() }
|
2700
|
+
]
|
2701
|
+
};
|
2702
|
+
default:
|
2703
|
+
return {
|
2704
|
+
content: [
|
2705
|
+
{ type: "text", text: await response.text() }
|
2706
|
+
]
|
2707
|
+
};
|
2708
|
+
}
|
2709
|
+
}
|
2710
|
+
);
|
2711
|
+
});
|
2712
|
+
});
|
2713
|
+
return mcpServer;
|
2714
|
+
}
|
2715
|
+
|
2469
2716
|
// src/http/middleware/response/parse.middleware.ts
|
2470
2717
|
var import_validator2 = require("@forklaunch/validator");
|
2471
2718
|
function parse2(req, res, next) {
|
@@ -2528,18 +2775,18 @@ ${parseErrors.join("\n\n")}`
|
|
2528
2775
|
}
|
2529
2776
|
|
2530
2777
|
// src/http/middleware/response/enrichExpressLikeSend.middleware.ts
|
2531
|
-
var
|
2778
|
+
var import_common9 = require("@forklaunch/common");
|
2532
2779
|
var import_stream = require("stream");
|
2533
2780
|
|
2534
2781
|
// src/http/telemetry/recordMetric.ts
|
2535
|
-
var
|
2782
|
+
var import_common8 = require("@forklaunch/common");
|
2536
2783
|
var import_semantic_conventions3 = require("@opentelemetry/semantic-conventions");
|
2537
2784
|
function recordMetric(req, res) {
|
2538
2785
|
if (res.metricRecorded) {
|
2539
2786
|
return;
|
2540
2787
|
}
|
2541
2788
|
httpRequestsTotalCounter.add(1, {
|
2542
|
-
[import_semantic_conventions3.ATTR_SERVICE_NAME]: (0,
|
2789
|
+
[import_semantic_conventions3.ATTR_SERVICE_NAME]: (0, import_common8.getEnvVar)("OTEL_SERVICE_NAME"),
|
2543
2790
|
[ATTR_API_NAME]: req.contractDetails?.name,
|
2544
2791
|
[ATTR_CORRELATION_ID]: req.context.correlationId,
|
2545
2792
|
[import_semantic_conventions3.ATTR_HTTP_REQUEST_METHOD]: req.method,
|
@@ -2559,7 +2806,7 @@ function enrichExpressLikeSend(instance, req, res, originalOperation, originalSe
|
|
2559
2806
|
if (res.statusCode === 404) {
|
2560
2807
|
res.type("text/plain");
|
2561
2808
|
res.status(404);
|
2562
|
-
|
2809
|
+
req.openTelemetryCollector.error("Not Found");
|
2563
2810
|
originalSend.call(instance, "Not Found");
|
2564
2811
|
errorSent = true;
|
2565
2812
|
}
|
@@ -2577,8 +2824,8 @@ function enrichExpressLikeSend(instance, req, res, originalOperation, originalSe
|
|
2577
2824
|
`attachment; filename="${data.name}"`
|
2578
2825
|
);
|
2579
2826
|
}
|
2580
|
-
if ((0,
|
2581
|
-
import_stream.Readable.from((0,
|
2827
|
+
if ((0, import_common9.isNodeJsWriteableStream)(res)) {
|
2828
|
+
import_stream.Readable.from((0, import_common9.readableStreamToAsyncIterable)(data.stream())).pipe(
|
2582
2829
|
res
|
2583
2830
|
);
|
2584
2831
|
} else {
|
@@ -2587,7 +2834,7 @@ function enrichExpressLikeSend(instance, req, res, originalOperation, originalSe
|
|
2587
2834
|
originalSend.call(instance, "Not a NodeJS WritableStream");
|
2588
2835
|
errorSent = true;
|
2589
2836
|
}
|
2590
|
-
} else if ((0,
|
2837
|
+
} else if ((0, import_common9.isAsyncGenerator)(data)) {
|
2591
2838
|
let firstPass = true;
|
2592
2839
|
const transformer = new import_stream.Transform({
|
2593
2840
|
objectMode: true,
|
@@ -2602,7 +2849,7 @@ function enrichExpressLikeSend(instance, req, res, originalOperation, originalSe
|
|
2602
2849
|
------------------
|
2603
2850
|
${res.locals.errorMessage}`;
|
2604
2851
|
}
|
2605
|
-
|
2852
|
+
req.openTelemetryCollector.error(errorString);
|
2606
2853
|
res.type("text/plain");
|
2607
2854
|
res.status(500);
|
2608
2855
|
originalSend.call(instance, errorString);
|
@@ -2615,7 +2862,7 @@ ${res.locals.errorMessage}`;
|
|
2615
2862
|
if (!errorSent) {
|
2616
2863
|
let data2 = "";
|
2617
2864
|
for (const [key, value] of Object.entries(chunk)) {
|
2618
|
-
data2 += `${key}: ${typeof value === "string" ? value : (0,
|
2865
|
+
data2 += `${key}: ${typeof value === "string" ? value : (0, import_common9.safeStringify)(value)}
|
2619
2866
|
`;
|
2620
2867
|
}
|
2621
2868
|
data2 += "\n";
|
@@ -2623,7 +2870,7 @@ ${res.locals.errorMessage}`;
|
|
2623
2870
|
}
|
2624
2871
|
}
|
2625
2872
|
});
|
2626
|
-
if ((0,
|
2873
|
+
if ((0, import_common9.isNodeJsWriteableStream)(res)) {
|
2627
2874
|
import_stream.Readable.from(data).pipe(transformer).pipe(res);
|
2628
2875
|
} else {
|
2629
2876
|
res.type("text/plain");
|
@@ -2634,7 +2881,7 @@ ${res.locals.errorMessage}`;
|
|
2634
2881
|
} else {
|
2635
2882
|
const parserType = responseBodies?.[Number(res.statusCode)]?.parserType;
|
2636
2883
|
res.bodyData = data;
|
2637
|
-
if ((0,
|
2884
|
+
if ((0, import_common9.isRecord)(data)) {
|
2638
2885
|
switch (parserType) {
|
2639
2886
|
case "json":
|
2640
2887
|
res.bodyData = "json" in data ? data.json : data;
|
@@ -2655,7 +2902,7 @@ ${res.locals.errorMessage}`;
|
|
2655
2902
|
res.bodyData = data;
|
2656
2903
|
break;
|
2657
2904
|
default:
|
2658
|
-
(0,
|
2905
|
+
(0, import_common9.isNever)(parserType);
|
2659
2906
|
res.bodyData = data;
|
2660
2907
|
break;
|
2661
2908
|
}
|
@@ -2668,7 +2915,7 @@ ${res.locals.errorMessage}`;
|
|
2668
2915
|
------------------
|
2669
2916
|
${res.locals.errorMessage}`;
|
2670
2917
|
}
|
2671
|
-
|
2918
|
+
req.openTelemetryCollector.error(errorString);
|
2672
2919
|
res.type("text/plain");
|
2673
2920
|
res.status(500);
|
2674
2921
|
originalSend.call(instance, errorString);
|
@@ -2691,16 +2938,17 @@ ${res.locals.errorMessage}`;
|
|
2691
2938
|
}
|
2692
2939
|
|
2693
2940
|
// src/http/openApiV3Generator/openApiV3Generator.ts
|
2941
|
+
var import_common10 = require("@forklaunch/common");
|
2694
2942
|
function toUpperCase(str) {
|
2695
2943
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
2696
2944
|
}
|
2697
2945
|
function transformBasePath(basePath) {
|
2698
2946
|
if (basePath.startsWith("/")) {
|
2699
|
-
return
|
2947
|
+
return basePath.slice(1);
|
2700
2948
|
}
|
2701
2949
|
return `/${basePath}`;
|
2702
2950
|
}
|
2703
|
-
function generateOpenApiDocument(port, tags, paths) {
|
2951
|
+
function generateOpenApiDocument(protocol, host, port, tags, paths, otherServers) {
|
2704
2952
|
return {
|
2705
2953
|
openapi: "3.1.0",
|
2706
2954
|
info: {
|
@@ -2719,8 +2967,10 @@ function generateOpenApiDocument(port, tags, paths) {
|
|
2719
2967
|
tags,
|
2720
2968
|
servers: [
|
2721
2969
|
{
|
2722
|
-
url:
|
2723
|
-
|
2970
|
+
url: `${protocol}://${host}:${port}`,
|
2971
|
+
description: "Main Server"
|
2972
|
+
},
|
2973
|
+
...otherServers || []
|
2724
2974
|
],
|
2725
2975
|
paths
|
2726
2976
|
};
|
@@ -2741,19 +2991,21 @@ function contentResolver(schemaValidator, body, contentType) {
|
|
2741
2991
|
}
|
2742
2992
|
};
|
2743
2993
|
}
|
2744
|
-
function generateSwaggerDocument(schemaValidator, port, routers) {
|
2994
|
+
function generateSwaggerDocument(schemaValidator, protocol, host, port, routers, otherServers) {
|
2745
2995
|
const tags = [];
|
2746
2996
|
const paths = {};
|
2747
|
-
routers
|
2748
|
-
const controllerName = transformBasePath(
|
2997
|
+
unpackRouters(routers).forEach(({ fullPath, router, sdkPath }) => {
|
2998
|
+
const controllerName = transformBasePath(fullPath);
|
2749
2999
|
tags.push({
|
2750
3000
|
name: controllerName,
|
2751
|
-
description: `${controllerName} Operations`
|
3001
|
+
description: `${toUpperCase(controllerName)} Operations`
|
2752
3002
|
});
|
2753
3003
|
router.routes.forEach((route) => {
|
2754
|
-
const
|
2755
|
-
|
2756
|
-
|
3004
|
+
const openApiPath = (0, import_common10.openApiCompliantPath)(
|
3005
|
+
`${fullPath}${route.path === "/" ? "" : route.path}`
|
3006
|
+
);
|
3007
|
+
if (!paths[openApiPath]) {
|
3008
|
+
paths[openApiPath] = {};
|
2757
3009
|
}
|
2758
3010
|
const { name, summary, query, requestHeaders } = route.contractDetails;
|
2759
3011
|
const responses = {};
|
@@ -2780,15 +3032,16 @@ function generateSwaggerDocument(schemaValidator, port, routers) {
|
|
2780
3032
|
};
|
2781
3033
|
}
|
2782
3034
|
}
|
2783
|
-
const
|
3035
|
+
const operationObject = {
|
2784
3036
|
tags: [controllerName],
|
2785
3037
|
summary: `${name}: ${summary}`,
|
2786
3038
|
parameters: [],
|
2787
|
-
responses
|
3039
|
+
responses,
|
3040
|
+
operationId: `${sdkPath}.${(0, import_common10.toPrettyCamelCase)(name)}`
|
2788
3041
|
};
|
2789
3042
|
if (route.contractDetails.params) {
|
2790
3043
|
for (const key in route.contractDetails.params) {
|
2791
|
-
|
3044
|
+
operationObject.parameters?.push({
|
2792
3045
|
name: key,
|
2793
3046
|
in: "path",
|
2794
3047
|
schema: schemaValidator.openapi(
|
@@ -2799,7 +3052,7 @@ function generateSwaggerDocument(schemaValidator, port, routers) {
|
|
2799
3052
|
}
|
2800
3053
|
const discriminatedBodyResult = "body" in route.contractDetails ? discriminateBody(schemaValidator, route.contractDetails.body) : null;
|
2801
3054
|
if (discriminatedBodyResult) {
|
2802
|
-
|
3055
|
+
operationObject.requestBody = {
|
2803
3056
|
required: true,
|
2804
3057
|
content: contentResolver(
|
2805
3058
|
schemaValidator,
|
@@ -2810,7 +3063,7 @@ function generateSwaggerDocument(schemaValidator, port, routers) {
|
|
2810
3063
|
}
|
2811
3064
|
if (requestHeaders) {
|
2812
3065
|
for (const key in requestHeaders) {
|
2813
|
-
|
3066
|
+
operationObject.parameters?.push({
|
2814
3067
|
name: key,
|
2815
3068
|
in: "header",
|
2816
3069
|
schema: schemaValidator.openapi(
|
@@ -2821,7 +3074,7 @@ function generateSwaggerDocument(schemaValidator, port, routers) {
|
|
2821
3074
|
}
|
2822
3075
|
if (query) {
|
2823
3076
|
for (const key in query) {
|
2824
|
-
|
3077
|
+
operationObject.parameters?.push({
|
2825
3078
|
name: key,
|
2826
3079
|
in: "query",
|
2827
3080
|
schema: schemaValidator.openapi(query[key])
|
@@ -2838,7 +3091,7 @@ function generateSwaggerDocument(schemaValidator, port, routers) {
|
|
2838
3091
|
content: contentResolver(schemaValidator, schemaValidator.string)
|
2839
3092
|
};
|
2840
3093
|
if (route.contractDetails.auth.method === "jwt") {
|
2841
|
-
|
3094
|
+
operationObject.security = [
|
2842
3095
|
{
|
2843
3096
|
bearer: Array.from(
|
2844
3097
|
route.contractDetails.auth.allowedPermissions?.values() || []
|
@@ -2848,11 +3101,18 @@ function generateSwaggerDocument(schemaValidator, port, routers) {
|
|
2848
3101
|
}
|
2849
3102
|
}
|
2850
3103
|
if (route.method !== "middleware") {
|
2851
|
-
paths[
|
3104
|
+
paths[openApiPath][route.method] = operationObject;
|
2852
3105
|
}
|
2853
3106
|
});
|
2854
3107
|
});
|
2855
|
-
return generateOpenApiDocument(
|
3108
|
+
return generateOpenApiDocument(
|
3109
|
+
protocol,
|
3110
|
+
host,
|
3111
|
+
port,
|
3112
|
+
tags,
|
3113
|
+
paths,
|
3114
|
+
otherServers
|
3115
|
+
);
|
2856
3116
|
}
|
2857
3117
|
|
2858
3118
|
// src/http/telemetry/evaluateTelemetryOptions.ts
|
@@ -2892,6 +3152,7 @@ function metricsDefinitions(metrics2) {
|
|
2892
3152
|
discriminateResponseBodies,
|
2893
3153
|
enrichExpressLikeSend,
|
2894
3154
|
evaluateTelemetryOptions,
|
3155
|
+
generateMcpServer,
|
2895
3156
|
generateSwaggerDocument,
|
2896
3157
|
get,
|
2897
3158
|
getCodeForStatus,
|