@forklaunch/core 0.10.3 → 0.11.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 +115 -120
- package/lib/http/index.d.ts +115 -120
- package/lib/http/index.js +143 -87
- package/lib/http/index.js.map +1 -1
- package/lib/http/index.mjs +104 -49
- package/lib/http/index.mjs.map +1 -1
- package/lib/services/index.d.mts +9 -8
- package/lib/services/index.d.ts +9 -8
- package/lib/services/index.js +14 -15
- package/lib/services/index.js.map +1 -1
- package/lib/services/index.mjs +14 -15
- package/lib/services/index.mjs.map +1 -1
- package/package.json +19 -19
package/lib/http/index.js
CHANGED
@@ -70,6 +70,7 @@ __export(http_exports, {
|
|
70
70
|
put: () => put,
|
71
71
|
recordMetric: () => recordMetric,
|
72
72
|
trace: () => trace3,
|
73
|
+
typedAuthHandler: () => typedAuthHandler,
|
73
74
|
typedHandler: () => typedHandler
|
74
75
|
});
|
75
76
|
module.exports = __toCommonJS(http_exports);
|
@@ -92,7 +93,7 @@ function cors(corsOptions) {
|
|
92
93
|
}
|
93
94
|
|
94
95
|
// src/http/router/expressLikeRouter.ts
|
95
|
-
var
|
96
|
+
var import_common6 = require("@forklaunch/common");
|
96
97
|
|
97
98
|
// src/http/guards/isForklaunchRouter.ts
|
98
99
|
function isForklaunchRouter(maybeForklaunchRouter) {
|
@@ -138,7 +139,39 @@ function isTypedHandler(maybeTypedHandler) {
|
|
138
139
|
}
|
139
140
|
|
140
141
|
// src/http/middleware/request/auth.middleware.ts
|
142
|
+
var import_common2 = require("@forklaunch/common");
|
141
143
|
var import_jose = require("jose");
|
144
|
+
|
145
|
+
// src/http/discriminateAuthMethod.ts
|
146
|
+
function discriminateAuthMethod(auth) {
|
147
|
+
if ("basic" in auth) {
|
148
|
+
return {
|
149
|
+
type: "basic",
|
150
|
+
auth: auth.basic
|
151
|
+
};
|
152
|
+
} else if ("jwt" in auth) {
|
153
|
+
return {
|
154
|
+
type: "jwt",
|
155
|
+
auth: auth.jwt
|
156
|
+
};
|
157
|
+
} else {
|
158
|
+
return {
|
159
|
+
type: "jwt"
|
160
|
+
};
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
// src/http/guards/hasPermissionChecks.ts
|
165
|
+
function hasPermissionChecks(maybePermissionedAuth) {
|
166
|
+
return typeof maybePermissionedAuth === "object" && maybePermissionedAuth !== null && "mapPermissions" in maybePermissionedAuth && ("allowedPermissions" in maybePermissionedAuth || "forbiddenPermissions" in maybePermissionedAuth);
|
167
|
+
}
|
168
|
+
|
169
|
+
// src/http/guards/hasRoleChecks.ts
|
170
|
+
function hasRoleChecks(maybeRoledAuth) {
|
171
|
+
return typeof maybeRoledAuth === "object" && maybeRoledAuth !== null && "mapRoles" in maybeRoledAuth && ("allowedRoles" in maybeRoledAuth || "forbiddenRoles" in maybeRoledAuth);
|
172
|
+
}
|
173
|
+
|
174
|
+
// src/http/middleware/request/auth.middleware.ts
|
142
175
|
var invalidAuthorizationTokenFormat = [
|
143
176
|
401,
|
144
177
|
"Invalid Authorization token format."
|
@@ -169,18 +202,16 @@ async function checkAuthorizationToken(authorizationMethod, authorizationToken,
|
|
169
202
|
}
|
170
203
|
const [tokenPrefix, token] = authorizationToken.split(" ");
|
171
204
|
let resourceId;
|
172
|
-
|
205
|
+
const { type, auth } = discriminateAuthMethod(authorizationMethod);
|
206
|
+
switch (type) {
|
173
207
|
case "jwt": {
|
174
|
-
if (tokenPrefix !== "Bearer") {
|
208
|
+
if (tokenPrefix !== (authorizationMethod.tokenPrefix ?? "Bearer")) {
|
175
209
|
return invalidAuthorizationTokenFormat;
|
176
210
|
}
|
177
211
|
try {
|
178
212
|
const decodedJwt = await (0, import_jose.jwtVerify)(
|
179
213
|
token,
|
180
|
-
new TextEncoder().encode(
|
181
|
-
// TODO: Check this at application startup if there is any route with jwt checking
|
182
|
-
process.env.JWT_SECRET
|
183
|
-
)
|
214
|
+
new TextEncoder().encode(process.env.JWT_SECRET)
|
184
215
|
);
|
185
216
|
if (!decodedJwt.payload.sub) {
|
186
217
|
return invalidAuthorizationSubject;
|
@@ -193,27 +224,24 @@ async function checkAuthorizationToken(authorizationMethod, authorizationToken,
|
|
193
224
|
break;
|
194
225
|
}
|
195
226
|
case "basic": {
|
196
|
-
if (authorizationToken !== "Basic") {
|
227
|
+
if (authorizationToken !== (authorizationMethod.tokenPrefix ?? "Basic")) {
|
197
228
|
return invalidAuthorizationTokenFormat;
|
198
229
|
}
|
199
230
|
const [username, password] = Buffer.from(token, "base64").toString("utf-8").split(":");
|
200
231
|
if (!username || !password) {
|
201
232
|
return invalidAuthorizationTokenFormat;
|
202
233
|
}
|
203
|
-
if (!
|
234
|
+
if (!auth.login(username, password)) {
|
204
235
|
return invalidAuthorizationLogin;
|
205
236
|
}
|
206
237
|
resourceId = username;
|
207
238
|
break;
|
208
239
|
}
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
}
|
213
|
-
resourceId = authorizationMethod.decodeResource(token);
|
214
|
-
break;
|
240
|
+
default:
|
241
|
+
(0, import_common2.isNever)(type);
|
242
|
+
return [401, "Invalid Authorization method."];
|
215
243
|
}
|
216
|
-
if (authorizationMethod
|
244
|
+
if (hasPermissionChecks(authorizationMethod)) {
|
217
245
|
if (!authorizationMethod.mapPermissions) {
|
218
246
|
return [500, "No permission mapping function provided."];
|
219
247
|
}
|
@@ -221,49 +249,49 @@ async function checkAuthorizationToken(authorizationMethod, authorizationToken,
|
|
221
249
|
resourceId,
|
222
250
|
req
|
223
251
|
);
|
224
|
-
if (authorizationMethod.allowedPermissions) {
|
252
|
+
if ("allowedPermissions" in authorizationMethod && authorizationMethod.allowedPermissions) {
|
225
253
|
if (resourcePermissions.intersection(authorizationMethod.allowedPermissions).size === 0) {
|
226
254
|
return invalidAuthorizationTokenPermissions;
|
227
255
|
}
|
228
256
|
}
|
229
|
-
if (authorizationMethod.forbiddenPermissions) {
|
257
|
+
if ("forbiddenPermissions" in authorizationMethod && authorizationMethod.forbiddenPermissions) {
|
230
258
|
if (resourcePermissions.intersection(
|
231
259
|
authorizationMethod.forbiddenPermissions
|
232
260
|
).size !== 0) {
|
233
261
|
return invalidAuthorizationTokenPermissions;
|
234
262
|
}
|
235
263
|
}
|
236
|
-
}
|
237
|
-
if (authorizationMethod.allowedRoles || authorizationMethod.forbiddenRoles) {
|
264
|
+
} else if (hasRoleChecks(authorizationMethod)) {
|
238
265
|
if (!authorizationMethod.mapRoles) {
|
239
266
|
return [500, "No role mapping function provided."];
|
240
267
|
}
|
241
268
|
const resourceRoles = await authorizationMethod.mapRoles(resourceId, req);
|
242
|
-
if (authorizationMethod.allowedRoles) {
|
269
|
+
if ("allowedRoles" in authorizationMethod && authorizationMethod.allowedRoles) {
|
243
270
|
if (resourceRoles.intersection(authorizationMethod.allowedRoles).size === 0) {
|
244
271
|
return invalidAuthorizationTokenRoles;
|
245
272
|
}
|
246
273
|
}
|
247
|
-
if (authorizationMethod.forbiddenRoles) {
|
274
|
+
if ("forbiddenRoles" in authorizationMethod && authorizationMethod.forbiddenRoles) {
|
248
275
|
if (resourceRoles.intersection(authorizationMethod.forbiddenRoles).size !== 0) {
|
249
276
|
return invalidAuthorizationTokenRoles;
|
250
277
|
}
|
251
278
|
}
|
279
|
+
} else {
|
280
|
+
return [401, "Invalid Authorization method."];
|
252
281
|
}
|
253
|
-
return [401, "Invalid Authorization method."];
|
254
282
|
}
|
255
283
|
async function parseRequestAuth(req, res, next) {
|
256
284
|
const auth = req.contractDetails.auth;
|
257
285
|
if (auth) {
|
258
286
|
const [error, message] = await checkAuthorizationToken(
|
259
287
|
auth,
|
260
|
-
req.headers[
|
288
|
+
req.headers[auth.headerName ?? "Authorization"] || req.headers[auth.headerName ?? "authorization"],
|
261
289
|
req
|
262
290
|
) ?? [];
|
263
291
|
if (error != null) {
|
264
292
|
res.type("text/plain");
|
265
293
|
res.status(error).send(message);
|
266
|
-
|
294
|
+
return;
|
267
295
|
}
|
268
296
|
}
|
269
297
|
next?.();
|
@@ -300,10 +328,10 @@ function createContext(schemaValidator) {
|
|
300
328
|
}
|
301
329
|
|
302
330
|
// src/http/middleware/request/enrichDetails.middleware.ts
|
303
|
-
var
|
331
|
+
var import_common5 = require("@forklaunch/common");
|
304
332
|
|
305
333
|
// src/http/telemetry/openTelemetryCollector.ts
|
306
|
-
var
|
334
|
+
var import_common4 = require("@forklaunch/common");
|
307
335
|
var import_opentelemetry_instrumentation_hyper_express = require("@forklaunch/opentelemetry-instrumentation-hyper-express");
|
308
336
|
var import_api3 = require("@opentelemetry/api");
|
309
337
|
var import_exporter_logs_otlp_http = require("@opentelemetry/exporter-logs-otlp-http");
|
@@ -325,7 +353,7 @@ function isForklaunchRequest(request) {
|
|
325
353
|
}
|
326
354
|
|
327
355
|
// src/http/telemetry/pinoLogger.ts
|
328
|
-
var
|
356
|
+
var import_common3 = require("@forklaunch/common");
|
329
357
|
var import_api2 = require("@opentelemetry/api");
|
330
358
|
var import_api_logs = require("@opentelemetry/api-logs");
|
331
359
|
var import_pino = __toESM(require("pino"));
|
@@ -357,7 +385,7 @@ function mapSeverity(level) {
|
|
357
385
|
case "fatal":
|
358
386
|
return 21;
|
359
387
|
default:
|
360
|
-
(0,
|
388
|
+
(0, import_common3.isNever)(level);
|
361
389
|
return 0;
|
362
390
|
}
|
363
391
|
}
|
@@ -391,7 +419,7 @@ var PinoLogger = class _PinoLogger {
|
|
391
419
|
return false;
|
392
420
|
}
|
393
421
|
return true;
|
394
|
-
}).map(
|
422
|
+
}).map(import_common3.safeStringify);
|
395
423
|
const activeSpan = import_api2.trace.getActiveSpan();
|
396
424
|
if (activeSpan) {
|
397
425
|
const activeSpanContext = activeSpan.spanContext();
|
@@ -497,24 +525,24 @@ var OpenTelemetryCollector = class {
|
|
497
525
|
return this.metrics[metricId];
|
498
526
|
}
|
499
527
|
};
|
500
|
-
import_dotenv.default.config({ path: (0,
|
528
|
+
import_dotenv.default.config({ path: (0, import_common4.getEnvVar)("DOTENV_FILE_PATH") });
|
501
529
|
new import_sdk_node.NodeSDK({
|
502
530
|
resource: (0, import_resources.resourceFromAttributes)({
|
503
|
-
[import_semantic_conventions2.ATTR_SERVICE_NAME]: (0,
|
531
|
+
[import_semantic_conventions2.ATTR_SERVICE_NAME]: (0, import_common4.getEnvVar)("OTEL_SERVICE_NAME")
|
504
532
|
}),
|
505
533
|
traceExporter: new import_exporter_trace_otlp_http.OTLPTraceExporter({
|
506
|
-
url: `${(0,
|
534
|
+
url: `${(0, import_common4.getEnvVar)("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/traces`
|
507
535
|
}),
|
508
536
|
metricReader: new import_sdk_metrics.PeriodicExportingMetricReader({
|
509
537
|
exporter: new import_exporter_metrics_otlp_http.OTLPMetricExporter({
|
510
|
-
url: `${(0,
|
538
|
+
url: `${(0, import_common4.getEnvVar)("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/metrics`
|
511
539
|
}),
|
512
540
|
exportIntervalMillis: 5e3
|
513
541
|
}),
|
514
542
|
logRecordProcessors: [
|
515
543
|
new import_sdk_logs.BatchLogRecordProcessor(
|
516
544
|
new import_exporter_logs_otlp_http.OTLPLogExporter({
|
517
|
-
url: `${(0,
|
545
|
+
url: `${(0, import_common4.getEnvVar)("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/logs`
|
518
546
|
})
|
519
547
|
)
|
520
548
|
],
|
@@ -523,7 +551,7 @@ new import_sdk_node.NodeSDK({
|
|
523
551
|
applyCustomAttributesOnSpan: (span, request) => {
|
524
552
|
span.setAttribute(
|
525
553
|
"service.name",
|
526
|
-
(0,
|
554
|
+
(0, import_common4.getEnvVar)("OTEL_SERVICE_NAME") ?? "unknown"
|
527
555
|
);
|
528
556
|
if (isForklaunchRequest(request)) {
|
529
557
|
span.setAttribute("api.name", request.contractDetails?.name);
|
@@ -534,10 +562,10 @@ new import_sdk_node.NodeSDK({
|
|
534
562
|
new import_opentelemetry_instrumentation_hyper_express.HyperExpressInstrumentation()
|
535
563
|
]
|
536
564
|
}).start();
|
537
|
-
var httpRequestsTotalCounter = import_api3.metrics.getMeter((0,
|
565
|
+
var httpRequestsTotalCounter = import_api3.metrics.getMeter((0, import_common4.getEnvVar)("OTEL_SERVICE_NAME") || "unknown").createCounter("http_requests_total", {
|
538
566
|
description: "Number of HTTP requests"
|
539
567
|
});
|
540
|
-
var httpServerDurationHistogram = import_api3.metrics.getMeter((0,
|
568
|
+
var httpServerDurationHistogram = import_api3.metrics.getMeter((0, import_common4.getEnvVar)("OTEL_SERVICE_NAME") || "unknown").createHistogram("http_server_duration", {
|
541
569
|
description: "Duration of HTTP server requests",
|
542
570
|
unit: "s"
|
543
571
|
});
|
@@ -556,7 +584,7 @@ function enrichDetails(path, contractDetails, requestSchema, responseSchemas, op
|
|
556
584
|
const [seconds, nanoseconds] = process.hrtime(startTime);
|
557
585
|
const durationMs = seconds + nanoseconds / 1e9;
|
558
586
|
httpServerDurationHistogram.record(durationMs, {
|
559
|
-
[import_semantic_conventions.ATTR_SERVICE_NAME]: (0,
|
587
|
+
[import_semantic_conventions.ATTR_SERVICE_NAME]: (0, import_common5.getEnvVar)("OTEL_SERVICE_NAME") || "unknown",
|
560
588
|
[ATTR_API_NAME]: req.contractDetails?.name || "unknown",
|
561
589
|
[import_semantic_conventions.ATTR_HTTP_REQUEST_METHOD]: req.method,
|
562
590
|
[import_semantic_conventions.ATTR_HTTP_ROUTE]: req.originalPath || "unknown",
|
@@ -1052,8 +1080,8 @@ var ForklaunchExpressLikeRouter = class _ForklaunchExpressLikeRouter {
|
|
1052
1080
|
handlers,
|
1053
1081
|
controllerHandler
|
1054
1082
|
);
|
1055
|
-
(0,
|
1056
|
-
(0,
|
1083
|
+
(0, import_common6.toRecord)(this.fetchMap)[(0, import_common6.sanitizePathSlashes)(`${this.basePath}${path}`)] = localParamRequest;
|
1084
|
+
(0, import_common6.toRecord)(this.sdk)[(0, import_common6.toPrettyCamelCase)(contractDetails.name ?? this.basePath)] = (req) => localParamRequest(`${this.basePath}${path}`, req);
|
1057
1085
|
return this;
|
1058
1086
|
}
|
1059
1087
|
}
|
@@ -1140,10 +1168,10 @@ var ForklaunchExpressLikeRouter = class _ForklaunchExpressLikeRouter {
|
|
1140
1168
|
}
|
1141
1169
|
addRouterToSdk(router) {
|
1142
1170
|
Object.entries(router.fetchMap).map(
|
1143
|
-
([key, value]) => (0,
|
1171
|
+
([key, value]) => (0, import_common6.toRecord)(this.fetchMap)[(0, import_common6.sanitizePathSlashes)(`${this.basePath}${key}`)] = value
|
1144
1172
|
);
|
1145
|
-
const existingSdk = this.sdk[router.sdkName ?? (0,
|
1146
|
-
(0,
|
1173
|
+
const existingSdk = this.sdk[router.sdkName ?? (0, import_common6.toPrettyCamelCase)(router.basePath)];
|
1174
|
+
(0, import_common6.toRecord)(this.sdk)[router.sdkName ?? (0, import_common6.toPrettyCamelCase)(router.basePath)] = {
|
1147
1175
|
...typeof existingSdk === "object" ? existingSdk : {},
|
1148
1176
|
...router.sdk
|
1149
1177
|
};
|
@@ -1518,6 +1546,11 @@ var trace3 = (_schemaValidator, path, contractDetails, ...handlers) => {
|
|
1518
1546
|
return typedHandler(_schemaValidator, path, "trace", contractDetails, ...handlers);
|
1519
1547
|
};
|
1520
1548
|
|
1549
|
+
// src/http/handlers/typedAuthHandler.ts
|
1550
|
+
function typedAuthHandler(_schemaValidator, _contractDetails, authHandler) {
|
1551
|
+
return authHandler;
|
1552
|
+
}
|
1553
|
+
|
1521
1554
|
// src/http/httpStatusCodes.ts
|
1522
1555
|
var HTTPStatuses = {
|
1523
1556
|
/**
|
@@ -2502,19 +2535,19 @@ var getCodeForStatus = (status) => {
|
|
2502
2535
|
var httpStatusCodes_default = HTTPStatuses;
|
2503
2536
|
|
2504
2537
|
// src/http/mcpGenerator/mcpGenerator.ts
|
2505
|
-
var
|
2538
|
+
var import_common8 = require("@forklaunch/common");
|
2506
2539
|
var import_zod = require("@forklaunch/validator/zod");
|
2507
2540
|
var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
2508
2541
|
|
2509
2542
|
// src/http/router/unpackRouters.ts
|
2510
|
-
var
|
2543
|
+
var import_common7 = require("@forklaunch/common");
|
2511
2544
|
function unpackRouters(routers, recursiveBasePath = [], recursiveSdkPath = []) {
|
2512
2545
|
return routers.reduce((acc, router) => {
|
2513
2546
|
acc.push({
|
2514
2547
|
fullPath: [...recursiveBasePath, router.basePath].join(""),
|
2515
2548
|
sdkPath: [
|
2516
2549
|
...recursiveSdkPath,
|
2517
|
-
(0,
|
2550
|
+
(0, import_common7.toPrettyCamelCase)(router.sdkName ?? router.basePath)
|
2518
2551
|
].join("."),
|
2519
2552
|
router
|
2520
2553
|
});
|
@@ -2524,7 +2557,7 @@ function unpackRouters(routers, recursiveBasePath = [], recursiveSdkPath = []) {
|
|
2524
2557
|
[...recursiveBasePath, router.basePath],
|
2525
2558
|
[
|
2526
2559
|
...recursiveSdkPath,
|
2527
|
-
(0,
|
2560
|
+
(0, import_common7.toPrettyCamelCase)(router.sdkName ?? router.basePath)
|
2528
2561
|
]
|
2529
2562
|
)
|
2530
2563
|
);
|
@@ -2560,14 +2593,15 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, route
|
|
2560
2593
|
...route.contractDetails.params ? { params: schemaValidator.schemify(route.contractDetails.params) } : {},
|
2561
2594
|
...route.contractDetails.query ? { query: schemaValidator.schemify(route.contractDetails.query) } : {},
|
2562
2595
|
...route.contractDetails.requestHeaders ? {
|
2563
|
-
headers: schemaValidator.schemify(
|
2564
|
-
route.contractDetails.requestHeaders
|
2565
|
-
|
2596
|
+
headers: schemaValidator.schemify({
|
2597
|
+
...route.contractDetails.requestHeaders,
|
2598
|
+
...route.contractDetails.auth ? {
|
2599
|
+
[route.contractDetails.auth.headerName ?? "authorization"]: import_zod.string.startsWith(
|
2600
|
+
route.contractDetails.auth.tokenPrefix ?? ("basic" in route.contractDetails.auth ? "Basic " : "Bearer ")
|
2601
|
+
)
|
2602
|
+
} : {}
|
2603
|
+
})
|
2566
2604
|
} : {}
|
2567
|
-
// TODO: support auth
|
2568
|
-
// ...(route.contractDetails.auth
|
2569
|
-
// ? { auth: route.contractDetails.auth }
|
2570
|
-
// : {})
|
2571
2605
|
};
|
2572
2606
|
mcpServer.tool(
|
2573
2607
|
route.contractDetails.name,
|
@@ -2588,7 +2622,7 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, route
|
|
2588
2622
|
if (discriminatedBody) {
|
2589
2623
|
switch (discriminatedBody.parserType) {
|
2590
2624
|
case "json": {
|
2591
|
-
parsedBody = (0,
|
2625
|
+
parsedBody = (0, import_common8.safeStringify)(body);
|
2592
2626
|
break;
|
2593
2627
|
}
|
2594
2628
|
case "text": {
|
@@ -2601,7 +2635,7 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, route
|
|
2601
2635
|
}
|
2602
2636
|
case "multipart": {
|
2603
2637
|
const formData = new FormData();
|
2604
|
-
if ((0,
|
2638
|
+
if ((0, import_common8.isRecord)(body)) {
|
2605
2639
|
for (const key in body) {
|
2606
2640
|
if (typeof body[key] === "string" || body[key] instanceof Blob) {
|
2607
2641
|
formData.append(key, body[key]);
|
@@ -2616,11 +2650,11 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, route
|
|
2616
2650
|
break;
|
2617
2651
|
}
|
2618
2652
|
case "urlEncoded": {
|
2619
|
-
if ((0,
|
2653
|
+
if ((0, import_common8.isRecord)(body)) {
|
2620
2654
|
parsedBody = new URLSearchParams(
|
2621
2655
|
Object.entries(body).map(([key, value]) => [
|
2622
2656
|
key,
|
2623
|
-
(0,
|
2657
|
+
(0, import_common8.safeStringify)(value)
|
2624
2658
|
])
|
2625
2659
|
);
|
2626
2660
|
} else {
|
@@ -2629,8 +2663,8 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, route
|
|
2629
2663
|
break;
|
2630
2664
|
}
|
2631
2665
|
default: {
|
2632
|
-
(0,
|
2633
|
-
parsedBody = (0,
|
2666
|
+
(0, import_common8.isNever)(discriminatedBody.parserType);
|
2667
|
+
parsedBody = (0, import_common8.safeStringify)(body);
|
2634
2668
|
break;
|
2635
2669
|
}
|
2636
2670
|
}
|
@@ -2639,7 +2673,7 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, route
|
|
2639
2673
|
const queryString = new URLSearchParams(
|
2640
2674
|
Object.entries(query).map(([key, value]) => [
|
2641
2675
|
key,
|
2642
|
-
(0,
|
2676
|
+
(0, import_common8.safeStringify)(value)
|
2643
2677
|
])
|
2644
2678
|
).toString();
|
2645
2679
|
url += queryString ? `?${queryString}` : "";
|
@@ -2669,7 +2703,7 @@ function generateMcpServer(schemaValidator, protocol, host, port, version, route
|
|
2669
2703
|
content: [
|
2670
2704
|
{
|
2671
2705
|
type: "text",
|
2672
|
-
text: (0,
|
2706
|
+
text: (0, import_common8.safeStringify)(await response.json())
|
2673
2707
|
}
|
2674
2708
|
]
|
2675
2709
|
};
|
@@ -2775,18 +2809,18 @@ ${parseErrors.join("\n\n")}`
|
|
2775
2809
|
}
|
2776
2810
|
|
2777
2811
|
// src/http/middleware/response/enrichExpressLikeSend.middleware.ts
|
2778
|
-
var
|
2812
|
+
var import_common10 = require("@forklaunch/common");
|
2779
2813
|
var import_stream = require("stream");
|
2780
2814
|
|
2781
2815
|
// src/http/telemetry/recordMetric.ts
|
2782
|
-
var
|
2816
|
+
var import_common9 = require("@forklaunch/common");
|
2783
2817
|
var import_semantic_conventions3 = require("@opentelemetry/semantic-conventions");
|
2784
2818
|
function recordMetric(req, res) {
|
2785
2819
|
if (res.metricRecorded) {
|
2786
2820
|
return;
|
2787
2821
|
}
|
2788
2822
|
httpRequestsTotalCounter.add(1, {
|
2789
|
-
[import_semantic_conventions3.ATTR_SERVICE_NAME]: (0,
|
2823
|
+
[import_semantic_conventions3.ATTR_SERVICE_NAME]: (0, import_common9.getEnvVar)("OTEL_SERVICE_NAME"),
|
2790
2824
|
[ATTR_API_NAME]: req.contractDetails?.name,
|
2791
2825
|
[ATTR_CORRELATION_ID]: req.context.correlationId,
|
2792
2826
|
[import_semantic_conventions3.ATTR_HTTP_REQUEST_METHOD]: req.method,
|
@@ -2824,8 +2858,8 @@ function enrichExpressLikeSend(instance, req, res, originalOperation, originalSe
|
|
2824
2858
|
`attachment; filename="${data.name}"`
|
2825
2859
|
);
|
2826
2860
|
}
|
2827
|
-
if ((0,
|
2828
|
-
import_stream.Readable.from((0,
|
2861
|
+
if ((0, import_common10.isNodeJsWriteableStream)(res)) {
|
2862
|
+
import_stream.Readable.from((0, import_common10.readableStreamToAsyncIterable)(data.stream())).pipe(
|
2829
2863
|
res
|
2830
2864
|
);
|
2831
2865
|
} else {
|
@@ -2834,7 +2868,7 @@ function enrichExpressLikeSend(instance, req, res, originalOperation, originalSe
|
|
2834
2868
|
originalSend.call(instance, "Not a NodeJS WritableStream");
|
2835
2869
|
errorSent = true;
|
2836
2870
|
}
|
2837
|
-
} else if ((0,
|
2871
|
+
} else if ((0, import_common10.isAsyncGenerator)(data)) {
|
2838
2872
|
let firstPass = true;
|
2839
2873
|
const transformer = new import_stream.Transform({
|
2840
2874
|
objectMode: true,
|
@@ -2862,7 +2896,7 @@ ${res.locals.errorMessage}`;
|
|
2862
2896
|
if (!errorSent) {
|
2863
2897
|
let data2 = "";
|
2864
2898
|
for (const [key, value] of Object.entries(chunk)) {
|
2865
|
-
data2 += `${key}: ${typeof value === "string" ? value : (0,
|
2899
|
+
data2 += `${key}: ${typeof value === "string" ? value : (0, import_common10.safeStringify)(value)}
|
2866
2900
|
`;
|
2867
2901
|
}
|
2868
2902
|
data2 += "\n";
|
@@ -2870,7 +2904,7 @@ ${res.locals.errorMessage}`;
|
|
2870
2904
|
}
|
2871
2905
|
}
|
2872
2906
|
});
|
2873
|
-
if ((0,
|
2907
|
+
if ((0, import_common10.isNodeJsWriteableStream)(res)) {
|
2874
2908
|
import_stream.Readable.from(data).pipe(transformer).pipe(res);
|
2875
2909
|
} else {
|
2876
2910
|
res.type("text/plain");
|
@@ -2881,7 +2915,7 @@ ${res.locals.errorMessage}`;
|
|
2881
2915
|
} else {
|
2882
2916
|
const parserType = responseBodies?.[Number(res.statusCode)]?.parserType;
|
2883
2917
|
res.bodyData = data;
|
2884
|
-
if ((0,
|
2918
|
+
if ((0, import_common10.isRecord)(data)) {
|
2885
2919
|
switch (parserType) {
|
2886
2920
|
case "json":
|
2887
2921
|
res.bodyData = "json" in data ? data.json : data;
|
@@ -2902,7 +2936,7 @@ ${res.locals.errorMessage}`;
|
|
2902
2936
|
res.bodyData = data;
|
2903
2937
|
break;
|
2904
2938
|
default:
|
2905
|
-
(0,
|
2939
|
+
(0, import_common10.isNever)(parserType);
|
2906
2940
|
res.bodyData = data;
|
2907
2941
|
break;
|
2908
2942
|
}
|
@@ -2938,7 +2972,7 @@ ${res.locals.errorMessage}`;
|
|
2938
2972
|
}
|
2939
2973
|
|
2940
2974
|
// src/http/openApiV3Generator/openApiV3Generator.ts
|
2941
|
-
var
|
2975
|
+
var import_common11 = require("@forklaunch/common");
|
2942
2976
|
function toUpperCase(str) {
|
2943
2977
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
2944
2978
|
}
|
@@ -2948,7 +2982,7 @@ function transformBasePath(basePath) {
|
|
2948
2982
|
}
|
2949
2983
|
return `/${basePath}`;
|
2950
2984
|
}
|
2951
|
-
function generateOpenApiDocument(protocol, host, port, tags, paths, otherServers) {
|
2985
|
+
function generateOpenApiDocument(protocol, host, port, tags, paths, securitySchemes, otherServers) {
|
2952
2986
|
return {
|
2953
2987
|
openapi: "3.1.0",
|
2954
2988
|
info: {
|
@@ -2956,13 +2990,7 @@ function generateOpenApiDocument(protocol, host, port, tags, paths, otherServers
|
|
2956
2990
|
version: process.env.VERSION || "1.0.0"
|
2957
2991
|
},
|
2958
2992
|
components: {
|
2959
|
-
securitySchemes
|
2960
|
-
bearer: {
|
2961
|
-
type: "http",
|
2962
|
-
scheme: "bearer",
|
2963
|
-
bearerFormat: "JWT"
|
2964
|
-
}
|
2965
|
-
}
|
2993
|
+
securitySchemes
|
2966
2994
|
},
|
2967
2995
|
tags,
|
2968
2996
|
servers: [
|
@@ -2994,6 +3022,7 @@ function contentResolver(schemaValidator, body, contentType) {
|
|
2994
3022
|
function generateSwaggerDocument(schemaValidator, protocol, host, port, routers, otherServers) {
|
2995
3023
|
const tags = [];
|
2996
3024
|
const paths = {};
|
3025
|
+
const securitySchemes = {};
|
2997
3026
|
unpackRouters(routers).forEach(({ fullPath, router, sdkPath }) => {
|
2998
3027
|
const controllerName = transformBasePath(fullPath);
|
2999
3028
|
tags.push({
|
@@ -3001,7 +3030,7 @@ function generateSwaggerDocument(schemaValidator, protocol, host, port, routers,
|
|
3001
3030
|
description: `${toUpperCase(controllerName)} Operations`
|
3002
3031
|
});
|
3003
3032
|
router.routes.forEach((route) => {
|
3004
|
-
const openApiPath = (0,
|
3033
|
+
const openApiPath = (0, import_common11.openApiCompliantPath)(
|
3005
3034
|
`${fullPath}${route.path === "/" ? "" : route.path}`
|
3006
3035
|
);
|
3007
3036
|
if (!paths[openApiPath]) {
|
@@ -3037,7 +3066,7 @@ function generateSwaggerDocument(schemaValidator, protocol, host, port, routers,
|
|
3037
3066
|
summary: `${name}: ${summary}`,
|
3038
3067
|
parameters: [],
|
3039
3068
|
responses,
|
3040
|
-
operationId: `${sdkPath}.${(0,
|
3069
|
+
operationId: `${sdkPath}.${(0, import_common11.toPrettyCamelCase)(name)}`
|
3041
3070
|
};
|
3042
3071
|
if (route.contractDetails.params) {
|
3043
3072
|
for (const key in route.contractDetails.params) {
|
@@ -3090,14 +3119,39 @@ function generateSwaggerDocument(schemaValidator, protocol, host, port, routers,
|
|
3090
3119
|
description: httpStatusCodes_default[403],
|
3091
3120
|
content: contentResolver(schemaValidator, schemaValidator.string)
|
3092
3121
|
};
|
3093
|
-
if (route.contractDetails.auth
|
3122
|
+
if ("basic" in route.contractDetails.auth) {
|
3094
3123
|
operationObject.security = [
|
3095
3124
|
{
|
3096
|
-
|
3097
|
-
route.contractDetails.auth.allowedPermissions?.values() || []
|
3125
|
+
basic: Array.from(
|
3126
|
+
"allowedPermissions" in route.contractDetails.auth ? route.contractDetails.auth.allowedPermissions?.values() || [] : []
|
3098
3127
|
)
|
3099
3128
|
}
|
3100
3129
|
];
|
3130
|
+
securitySchemes["basic"] = {
|
3131
|
+
type: "http",
|
3132
|
+
scheme: "basic"
|
3133
|
+
};
|
3134
|
+
} else if (route.contractDetails.auth) {
|
3135
|
+
operationObject.security = [
|
3136
|
+
{
|
3137
|
+
[route.contractDetails.auth.headerName !== "Authorization" ? "bearer" : "apiKey"]: Array.from(
|
3138
|
+
"allowedPermissions" in route.contractDetails.auth ? route.contractDetails.auth.allowedPermissions?.values() || [] : []
|
3139
|
+
)
|
3140
|
+
}
|
3141
|
+
];
|
3142
|
+
if (route.contractDetails.auth.headerName && route.contractDetails.auth.headerName !== "Authorization") {
|
3143
|
+
securitySchemes[route.contractDetails.auth.headerName] = {
|
3144
|
+
type: "apiKey",
|
3145
|
+
in: "header",
|
3146
|
+
name: route.contractDetails.auth.headerName
|
3147
|
+
};
|
3148
|
+
} else {
|
3149
|
+
securitySchemes["Authorization"] = {
|
3150
|
+
type: "http",
|
3151
|
+
scheme: "bearer",
|
3152
|
+
bearerFormat: "JWT"
|
3153
|
+
};
|
3154
|
+
}
|
3101
3155
|
}
|
3102
3156
|
}
|
3103
3157
|
if (route.method !== "middleware") {
|
@@ -3111,6 +3165,7 @@ function generateSwaggerDocument(schemaValidator, protocol, host, port, routers,
|
|
3111
3165
|
port,
|
3112
3166
|
tags,
|
3113
3167
|
paths,
|
3168
|
+
securitySchemes,
|
3114
3169
|
otherServers
|
3115
3170
|
);
|
3116
3171
|
}
|
@@ -3177,6 +3232,7 @@ function metricsDefinitions(metrics2) {
|
|
3177
3232
|
put,
|
3178
3233
|
recordMetric,
|
3179
3234
|
trace,
|
3235
|
+
typedAuthHandler,
|
3180
3236
|
typedHandler
|
3181
3237
|
});
|
3182
3238
|
//# sourceMappingURL=index.js.map
|