@forklaunch/core 0.10.4 → 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.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 import_common5 = require("@forklaunch/common");
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
- switch (authorizationMethod.method) {
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 (!authorizationMethod.login(username, password)) {
234
+ if (!auth.login(username, password)) {
204
235
  return invalidAuthorizationLogin;
205
236
  }
206
237
  resourceId = username;
207
238
  break;
208
239
  }
209
- case "other":
210
- if (tokenPrefix !== authorizationMethod.tokenPrefix) {
211
- return invalidAuthorizationTokenFormat;
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.allowedPermissions || authorizationMethod.forbiddenPermissions) {
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[(auth.method === "other" ? auth.headerName : void 0) ?? "Authorization"],
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
- next?.(new Error(message));
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 import_common4 = require("@forklaunch/common");
331
+ var import_common5 = require("@forklaunch/common");
304
332
 
305
333
  // src/http/telemetry/openTelemetryCollector.ts
306
- var import_common3 = require("@forklaunch/common");
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 import_common2 = require("@forklaunch/common");
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, import_common2.isNever)(level);
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(import_common2.safeStringify);
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, import_common3.getEnvVar)("DOTENV_FILE_PATH") });
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, import_common3.getEnvVar)("OTEL_SERVICE_NAME")
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, import_common3.getEnvVar)("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/traces`
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, import_common3.getEnvVar)("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/metrics`
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, import_common3.getEnvVar)("OTEL_EXPORTER_OTLP_ENDPOINT") ?? "http://localhost:4318"}/v1/logs`
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, import_common3.getEnvVar)("OTEL_SERVICE_NAME") ?? "unknown"
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, import_common3.getEnvVar)("OTEL_SERVICE_NAME") || "unknown").createCounter("http_requests_total", {
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, import_common3.getEnvVar)("OTEL_SERVICE_NAME") || "unknown").createHistogram("http_server_duration", {
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, import_common4.getEnvVar)("OTEL_SERVICE_NAME") || "unknown",
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, 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);
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, import_common5.toRecord)(this.fetchMap)[(0, import_common5.sanitizePathSlashes)(`${this.basePath}${key}`)] = value
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, import_common5.toPrettyCamelCase)(router.basePath)];
1146
- (0, import_common5.toRecord)(this.sdk)[router.sdkName ?? (0, import_common5.toPrettyCamelCase)(router.basePath)] = {
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 import_common7 = require("@forklaunch/common");
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 import_common6 = require("@forklaunch/common");
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, import_common6.toPrettyCamelCase)(router.sdkName ?? router.basePath)
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, import_common6.toPrettyCamelCase)(router.sdkName ?? router.basePath)
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, import_common7.safeStringify)(body);
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, import_common7.isRecord)(body)) {
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, import_common7.isRecord)(body)) {
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, import_common7.safeStringify)(value)
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, import_common7.isNever)(discriminatedBody.parserType);
2633
- parsedBody = (0, import_common7.safeStringify)(body);
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, import_common7.safeStringify)(value)
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, import_common7.safeStringify)(await response.json())
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 import_common9 = require("@forklaunch/common");
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 import_common8 = require("@forklaunch/common");
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, import_common8.getEnvVar)("OTEL_SERVICE_NAME"),
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, import_common9.isNodeJsWriteableStream)(res)) {
2828
- import_stream.Readable.from((0, import_common9.readableStreamToAsyncIterable)(data.stream())).pipe(
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, import_common9.isAsyncGenerator)(data)) {
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, import_common9.safeStringify)(value)}
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, import_common9.isNodeJsWriteableStream)(res)) {
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, import_common9.isRecord)(data)) {
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, import_common9.isNever)(parserType);
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 import_common10 = require("@forklaunch/common");
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, import_common10.openApiCompliantPath)(
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, import_common10.toPrettyCamelCase)(name)}`
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.method === "jwt") {
3122
+ if ("basic" in route.contractDetails.auth) {
3094
3123
  operationObject.security = [
3095
3124
  {
3096
- bearer: Array.from(
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