@faapi/faapi 3.2.1 → 3.3.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/dist/testing.js CHANGED
@@ -266,7 +266,9 @@ function formatSetCookie(name, value, options) {
266
266
  return cookie;
267
267
  }
268
268
  function createContext(request, params, config = {}, ip = "") {
269
- const url = new URL(request.url);
269
+ return createContextFromUrl(request, new URL(request.url), params, config, ip);
270
+ }
271
+ function createContextFromUrl(request, url, params, config = {}, ip = "") {
270
272
  const meta = { headers: {}, setCookies: [] };
271
273
  const parsedCookies = parseCookies(request.headers.get("cookie") ?? "");
272
274
  const cookiesObj = {};
@@ -758,7 +760,7 @@ async function invokeHandler(handler, ctx, body, middlewares, injectors) {
758
760
  // src/testServer.ts
759
761
  import path11 from "path";
760
762
  import os from "os";
761
- import fs10 from "fs/promises";
763
+ import fs9 from "fs/promises";
762
764
 
763
765
  // src/router/scanRoutes.ts
764
766
  import fg from "fast-glob";
@@ -1105,6 +1107,45 @@ function createProgram(filePath) {
1105
1107
  if (cached) {
1106
1108
  return cached;
1107
1109
  }
1110
+ const program = buildProgram([filePath], findTsConfig(filePath));
1111
+ programCache.set(filePath, program);
1112
+ return program;
1113
+ }
1114
+ function createPrograms(filePaths) {
1115
+ const unique = [...new Set(filePaths)];
1116
+ const result = /* @__PURE__ */ new Map();
1117
+ const groups = /* @__PURE__ */ new Map();
1118
+ const noTsconfigFiles = [];
1119
+ for (const filePath of unique) {
1120
+ const tsconfigPath = findTsConfig(filePath);
1121
+ if (!tsconfigPath) {
1122
+ noTsconfigFiles.push(filePath);
1123
+ continue;
1124
+ }
1125
+ const group = groups.get(tsconfigPath);
1126
+ if (group) {
1127
+ group.files.push(filePath);
1128
+ } else {
1129
+ groups.set(tsconfigPath, { tsconfigPath, files: [filePath] });
1130
+ }
1131
+ }
1132
+ for (const { tsconfigPath, files } of groups.values()) {
1133
+ const cacheKey = `shared::${tsconfigPath}::${[...files].sort().join("|")}`;
1134
+ let program = programCache.get(cacheKey);
1135
+ if (!program) {
1136
+ program = buildProgram(files, tsconfigPath);
1137
+ programCache.set(cacheKey, program);
1138
+ }
1139
+ for (const filePath of files) {
1140
+ result.set(filePath, program);
1141
+ }
1142
+ }
1143
+ for (const filePath of noTsconfigFiles) {
1144
+ result.set(filePath, createProgram(filePath));
1145
+ }
1146
+ return result;
1147
+ }
1148
+ function buildProgram(entryFiles, tsconfigPath) {
1108
1149
  const options = {
1109
1150
  strict: true,
1110
1151
  target: ts2.ScriptTarget.ES2022,
@@ -1113,8 +1154,7 @@ function createProgram(filePath) {
1113
1154
  skipLibCheck: true,
1114
1155
  noEmit: true
1115
1156
  };
1116
- let rootNames = [filePath];
1117
- const tsconfigPath = findTsConfig(filePath);
1157
+ const rootNames = [...entryFiles];
1118
1158
  if (tsconfigPath) {
1119
1159
  const tsOptions = parseTsConfig(tsconfigPath);
1120
1160
  if (tsOptions.module !== void 0) {
@@ -1124,16 +1164,14 @@ function createProgram(filePath) {
1124
1164
  options.moduleResolution = tsOptions.moduleResolution;
1125
1165
  }
1126
1166
  if (tsOptions.fileNames.length > 0) {
1127
- if (!tsOptions.fileNames.includes(filePath)) {
1128
- rootNames = [filePath, ...tsOptions.fileNames];
1129
- } else {
1130
- rootNames = tsOptions.fileNames;
1167
+ for (const fileName of tsOptions.fileNames) {
1168
+ if (!rootNames.includes(fileName)) {
1169
+ rootNames.push(fileName);
1170
+ }
1131
1171
  }
1132
1172
  }
1133
1173
  }
1134
- const program = ts2.createProgram(rootNames, options);
1135
- programCache.set(filePath, program);
1136
- return program;
1174
+ return ts2.createProgram(rootNames, options);
1137
1175
  }
1138
1176
 
1139
1177
  // src/ast/extractHandlerTypes.ts
@@ -1912,12 +1950,11 @@ function collectRouteSchemaSources(routes, rootDir) {
1912
1950
  }
1913
1951
  entry.methods.add(route.method);
1914
1952
  }
1915
- const programByFile = /* @__PURE__ */ new Map();
1953
+ const programByFile = createPrograms([...methodsByFile.keys()]);
1916
1954
  const allTypesByFile = /* @__PURE__ */ new Map();
1917
1955
  const mergedAllTypes = /* @__PURE__ */ new Map();
1918
1956
  for (const filePath of methodsByFile.keys()) {
1919
- const program = createProgram(filePath);
1920
- programByFile.set(filePath, program);
1957
+ const program = programByFile.get(filePath);
1921
1958
  const allTypes = extractAllTypes(program, filePath);
1922
1959
  allTypesByFile.set(filePath, allTypes);
1923
1960
  for (const [name, info] of allTypes) {
@@ -2686,7 +2723,10 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
2686
2723
  state.inFlightSchemaGenerations.delete(schemaPath);
2687
2724
  }
2688
2725
  }
2726
+ var sourcePathCache = /* @__PURE__ */ new Map();
2689
2727
  function prodPathToSourcePath(prodAbsPath, rootDir, dist) {
2728
+ const cached = sourcePathCache.get(prodAbsPath);
2729
+ if (cached) return cached;
2690
2730
  const rel = path8.relative(rootDir, prodAbsPath).replace(/\\/g, "/");
2691
2731
  let relWithoutDist = rel;
2692
2732
  if (relWithoutDist.startsWith(`${dist}/`)) {
@@ -2695,8 +2735,14 @@ function prodPathToSourcePath(prodAbsPath, rootDir, dist) {
2695
2735
  const srcRel = `src/${relWithoutDist}`;
2696
2736
  const tsRel = srcRel.replace(/\.js$/, ".ts");
2697
2737
  const tsAbs = path8.resolve(rootDir, tsRel);
2698
- if (fs7.existsSync(tsAbs)) return tsAbs;
2699
- return path8.resolve(rootDir, srcRel);
2738
+ let result;
2739
+ if (fs7.existsSync(tsAbs)) {
2740
+ result = tsAbs;
2741
+ } else {
2742
+ result = path8.resolve(rootDir, srcRel);
2743
+ }
2744
+ sourcePathCache.set(prodAbsPath, result);
2745
+ return result;
2700
2746
  }
2701
2747
  function isDevOnDemandEnabled() {
2702
2748
  return state.enabled;
@@ -2802,15 +2848,50 @@ import { Readable as Readable2 } from "stream";
2802
2848
  import path10 from "path";
2803
2849
 
2804
2850
  // src/router/matchRoute.ts
2805
- function matchRoute(routes, method, path12) {
2851
+ var httpIndexCache = /* @__PURE__ */ new WeakMap();
2852
+ var wsIndexCache = /* @__PURE__ */ new WeakMap();
2853
+ function getHttpIndex(routes) {
2854
+ let index = httpIndexCache.get(routes);
2855
+ if (index) return index;
2856
+ index = { static: /* @__PURE__ */ new Map(), methodsByStaticPath: /* @__PURE__ */ new Map(), dynamics: [] };
2806
2857
  for (const route of routes) {
2807
- if (route.method !== method) {
2808
- continue;
2809
- }
2810
- if (!route.isDynamic) {
2811
- if (route.urlPath === path12) {
2812
- return { route, params: {} };
2858
+ if (route.isDynamic) {
2859
+ index.dynamics.push(route);
2860
+ } else {
2861
+ index.static.set(`${route.method}|${route.urlPath}`, route);
2862
+ let methods = index.methodsByStaticPath.get(route.urlPath);
2863
+ if (!methods) {
2864
+ methods = /* @__PURE__ */ new Set();
2865
+ index.methodsByStaticPath.set(route.urlPath, methods);
2813
2866
  }
2867
+ methods.add(route.method);
2868
+ }
2869
+ }
2870
+ httpIndexCache.set(routes, index);
2871
+ return index;
2872
+ }
2873
+ function getWsIndex(routes) {
2874
+ let index = wsIndexCache.get(routes);
2875
+ if (index) return index;
2876
+ index = { static: /* @__PURE__ */ new Map(), dynamics: [] };
2877
+ for (const route of routes) {
2878
+ if (route.isDynamic) {
2879
+ index.dynamics.push(route);
2880
+ } else {
2881
+ index.static.set(route.urlPath, route);
2882
+ }
2883
+ }
2884
+ wsIndexCache.set(routes, index);
2885
+ return index;
2886
+ }
2887
+ function matchRoute(routes, method, path12) {
2888
+ const index = getHttpIndex(routes);
2889
+ const staticHit = index.static.get(`${method}|${path12}`);
2890
+ if (staticHit) {
2891
+ return { route: staticHit, params: {} };
2892
+ }
2893
+ for (const route of index.dynamics) {
2894
+ if (route.method !== method) {
2814
2895
  continue;
2815
2896
  }
2816
2897
  const params = matchDynamicPath(route.urlPath, path12, route.paramNames, route.isCatchAll);
@@ -2821,13 +2902,12 @@ function matchRoute(routes, method, path12) {
2821
2902
  return null;
2822
2903
  }
2823
2904
  function matchWsRoute(wsRoutes, path12) {
2824
- for (const route of wsRoutes) {
2825
- if (!route.isDynamic) {
2826
- if (route.urlPath === path12) {
2827
- return { route, params: {} };
2828
- }
2829
- continue;
2830
- }
2905
+ const index = getWsIndex(wsRoutes);
2906
+ const staticHit = index.static.get(path12);
2907
+ if (staticHit) {
2908
+ return { route: staticHit, params: {} };
2909
+ }
2910
+ for (const route of index.dynamics) {
2831
2911
  const params = matchDynamicPath(route.urlPath, path12, route.paramNames, route.isCatchAll);
2832
2912
  if (params !== null) {
2833
2913
  return { route, params };
@@ -2835,6 +2915,23 @@ function matchWsRoute(wsRoutes, path12) {
2835
2915
  }
2836
2916
  return null;
2837
2917
  }
2918
+ function findAllowedMethods(routes, path12) {
2919
+ const index = getHttpIndex(routes);
2920
+ const methods = /* @__PURE__ */ new Set();
2921
+ const staticMethods = index.methodsByStaticPath.get(path12);
2922
+ if (staticMethods) {
2923
+ for (const method of staticMethods) {
2924
+ methods.add(method);
2925
+ }
2926
+ }
2927
+ for (const route of index.dynamics) {
2928
+ const params = matchDynamicPath(route.urlPath, path12, route.paramNames, route.isCatchAll);
2929
+ if (params !== null) {
2930
+ methods.add(route.method);
2931
+ }
2932
+ }
2933
+ return Array.from(methods);
2934
+ }
2838
2935
  function matchDynamicPath(pattern, path12, paramNames, isCatchAll) {
2839
2936
  const patternSegments = pattern.split("/").filter(Boolean);
2840
2937
  const pathSegments = path12.split("/").filter(Boolean);
@@ -2882,9 +2979,6 @@ function matchDynamicPath(pattern, path12, paramNames, isCatchAll) {
2882
2979
  return params;
2883
2980
  }
2884
2981
 
2885
- // src/loader/loadRouteModule.ts
2886
- import fs8 from "fs";
2887
-
2888
2982
  // src/loader/resolveExports.ts
2889
2983
  function resolveExport(module, exportName) {
2890
2984
  if (exportName in module && typeof module[exportName] !== "undefined") {
@@ -2915,7 +3009,7 @@ async function loadRouteModule(filePath, method, rootDir) {
2915
3009
  const dist = getDevDist();
2916
3010
  if (dist) {
2917
3011
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
2918
- if (sourcePath && fs8.existsSync(sourcePath)) {
3012
+ if (sourcePath) {
2919
3013
  try {
2920
3014
  await ensureCompiled(sourcePath, rootDir, dist);
2921
3015
  } catch (compileErr) {
@@ -2980,7 +3074,7 @@ async function parseMultipart(request) {
2980
3074
  }
2981
3075
 
2982
3076
  // src/runtime/resolveInput.ts
2983
- async function resolveInput(method, request) {
3077
+ async function resolveInputFromUrl(method, request, url) {
2984
3078
  const inputType = getInputTypeForMethod(method);
2985
3079
  if (inputType === "body") {
2986
3080
  const contentType = request.headers.get("content-type") ?? "";
@@ -3015,7 +3109,6 @@ async function resolveInput(method, request) {
3015
3109
  }
3016
3110
  return result.data;
3017
3111
  }
3018
- const url = new URL(request.url);
3019
3112
  return queryToObject(url.searchParams);
3020
3113
  }
3021
3114
 
@@ -3044,11 +3137,13 @@ async function sendNodeResponse(response, res) {
3044
3137
  }
3045
3138
 
3046
3139
  // src/utils/getClientIp.ts
3047
- function getClientIp(req) {
3048
- const xff = req.headers["x-forwarded-for"];
3049
- if (typeof xff === "string" && xff.length > 0) {
3050
- const first = xff.split(",")[0]?.trim();
3051
- if (first) return first;
3140
+ function getClientIp(req, trustedProxy = false) {
3141
+ if (trustedProxy) {
3142
+ const xff = req.headers["x-forwarded-for"];
3143
+ if (typeof xff === "string" && xff.length > 0) {
3144
+ const first = xff.split(",")[0]?.trim();
3145
+ if (first) return first;
3146
+ }
3052
3147
  }
3053
3148
  const remote = req.socket?.remoteAddress;
3054
3149
  if (remote) {
@@ -3221,7 +3316,7 @@ function logger(options = {}) {
3221
3316
  }
3222
3317
 
3223
3318
  // src/server/handleWsUpgrade.ts
3224
- import fs9 from "fs";
3319
+ import fs8 from "fs";
3225
3320
  import { WebSocketServer, WebSocket } from "ws";
3226
3321
  import path9 from "path";
3227
3322
 
@@ -3279,7 +3374,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
3279
3374
  const dist = getDevDist();
3280
3375
  if (dist) {
3281
3376
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
3282
- if (sourcePath && fs9.existsSync(sourcePath)) {
3377
+ if (sourcePath && fs8.existsSync(sourcePath)) {
3283
3378
  await ensureCompiled(sourcePath, rootDir, dist);
3284
3379
  }
3285
3380
  }
@@ -3337,7 +3432,7 @@ async function sendResponseToSocket(socket, response) {
3337
3432
  socket.destroy();
3338
3433
  }
3339
3434
  function attachWebSocket(options) {
3340
- const { server, routesRef, rootDir, config, globalMiddlewares } = options;
3435
+ const { server, routesRef, rootDir, config, globalMiddlewares, trustedProxy = false } = options;
3341
3436
  const wss = new WebSocketServer({ noServer: true });
3342
3437
  server.on("upgrade", async (req, socket, head) => {
3343
3438
  const currentWsRoutes = routesRef.wsCurrent;
@@ -3353,7 +3448,7 @@ function attachWebSocket(options) {
3353
3448
  const host = req.headers.host ?? "localhost";
3354
3449
  const url = `http://${host}${req.url ?? "/"}`;
3355
3450
  const request = new Request(url, { method: "GET", headers });
3356
- const ctx = createContext(request, params, config, getClientIp(req));
3451
+ const ctx = createContext(request, params, config, getClientIp(req, trustedProxy));
3357
3452
  const meta = ctx.meta;
3358
3453
  let upgraded = false;
3359
3454
  const finalHandler = async () => {
@@ -3422,16 +3517,26 @@ function toWebRequest(req, bodyLimit = DEFAULT_BODY_LIMIT) {
3422
3517
  const headers = nodeHttpToWebHeaders(req);
3423
3518
  const method = req.method ?? "GET";
3424
3519
  if (method === "GET" || method === "HEAD") {
3425
- return new Request(url.toString(), { method, headers });
3520
+ return { request: new Request(url.toString(), { method, headers }), url };
3521
+ }
3522
+ const contentLength = req.headers["content-length"];
3523
+ if (contentLength !== void 0) {
3524
+ const declared = Number(Array.isArray(contentLength) ? contentLength[0] : contentLength);
3525
+ if (Number.isFinite(declared) && declared > bodyLimit) {
3526
+ throw new PayloadTooLargeError(bodyLimit);
3527
+ }
3426
3528
  }
3427
3529
  const stream = Readable2.toWeb(req);
3428
3530
  const limitedStream = limitStreamSize(stream, bodyLimit);
3429
- return new Request(url.toString(), {
3430
- method,
3431
- headers,
3432
- body: limitedStream,
3433
- duplex: "half"
3434
- });
3531
+ return {
3532
+ request: new Request(url.toString(), {
3533
+ method,
3534
+ headers,
3535
+ body: limitedStream,
3536
+ duplex: "half"
3537
+ }),
3538
+ url
3539
+ };
3435
3540
  }
3436
3541
  function limitStreamSize(stream, maxSize) {
3437
3542
  let totalSize = 0;
@@ -3483,22 +3588,6 @@ function limitStreamSize(stream, maxSize) {
3483
3588
  }
3484
3589
  });
3485
3590
  }
3486
- function findAllowedMethods(routes, path12) {
3487
- const methods = /* @__PURE__ */ new Set();
3488
- for (const route of routes) {
3489
- if (route.urlPath === path12) {
3490
- methods.add(route.method);
3491
- continue;
3492
- }
3493
- if (route.isDynamic) {
3494
- const params = matchDynamicPath(route.urlPath, path12, route.paramNames, route.isCatchAll);
3495
- if (params !== null) {
3496
- methods.add(route.method);
3497
- }
3498
- }
3499
- }
3500
- return Array.from(methods);
3501
- }
3502
3591
  function createServer(options) {
3503
3592
  const {
3504
3593
  routes,
@@ -3513,7 +3602,8 @@ function createServer(options) {
3513
3602
  helmet: helmetOption,
3514
3603
  logger: loggerOption,
3515
3604
  bodyLimit = DEFAULT_BODY_LIMIT,
3516
- http2: http2Option
3605
+ http2: http2Option,
3606
+ trustedProxy = false
3517
3607
  } = options;
3518
3608
  const routesRef = { current: routes, wsCurrent: wsRoutes ?? [] };
3519
3609
  const configMiddlewares = [];
@@ -3525,6 +3615,10 @@ function createServer(options) {
3525
3615
  }
3526
3616
  const loggerMiddlewareInst = loggerOption === false ? null : loggerOption === true || loggerOption === void 0 ? logger() : logger(loggerOption);
3527
3617
  if (loggerMiddlewareInst) configMiddlewares.push(loggerMiddlewareInst);
3618
+ const outerMiddlewares = [...configMiddlewares];
3619
+ if (globalMiddlewares && globalMiddlewares.length > 0) {
3620
+ outerMiddlewares.push(...globalMiddlewares);
3621
+ }
3528
3622
  const server = (() => {
3529
3623
  if (http2Option) {
3530
3624
  const h2Opts = typeof http2Option === "object" ? http2Option : {};
@@ -3544,29 +3638,29 @@ function createServer(options) {
3544
3638
  dist,
3545
3639
  req,
3546
3640
  res,
3547
- configMiddlewares,
3641
+ outerMiddlewares,
3548
3642
  onError,
3549
3643
  config,
3550
- globalMiddlewares,
3551
3644
  globalInjectors,
3552
- bodyLimit
3645
+ bodyLimit,
3646
+ trustedProxy
3553
3647
  ).catch(() => {
3554
3648
  res.statusCode = 500;
3555
3649
  res.end();
3556
3650
  });
3557
3651
  });
3558
3652
  if (routesRef.wsCurrent.length > 0) {
3559
- attachWebSocket({ server, routesRef, rootDir, config, globalMiddlewares });
3653
+ attachWebSocket({ server, routesRef, rootDir, config, globalMiddlewares, trustedProxy });
3560
3654
  }
3561
3655
  return { server, routesRef };
3562
3656
  }
3563
- function prepareRequest(req, config, bodyLimit) {
3564
- const request = toWebRequest(req, bodyLimit);
3657
+ function prepareRequest(req, config, bodyLimit, trustedProxy) {
3658
+ const { request, url } = toWebRequest(req, bodyLimit);
3565
3659
  const method = request.method.toUpperCase();
3566
- const urlPath = new URL(request.url).pathname;
3567
- const ctx = createContext(request, {}, config, getClientIp(req));
3660
+ const urlPath = url.pathname;
3661
+ const ctx = createContextFromUrl(request, url, {}, config, getClientIp(req, trustedProxy));
3568
3662
  const meta = ctx.meta;
3569
- return { request, ctx, meta, method, urlPath };
3663
+ return { request, url, ctx, meta, method, urlPath };
3570
3664
  }
3571
3665
  function resolveRouteOrThrow(routes, method, urlPath) {
3572
3666
  const match = matchRoute(routes, method, urlPath);
@@ -3578,14 +3672,14 @@ function resolveRouteOrThrow(routes, method, urlPath) {
3578
3672
  throw new RouteNotFoundError(urlPath);
3579
3673
  }
3580
3674
  function createRoutePipeline(opts) {
3581
- const { routes, method, urlPath, ctx, request, rootDir, dist, globalInjectors } = opts;
3675
+ const { routes, method, urlPath, url, ctx, request, rootDir, dist, globalInjectors } = opts;
3582
3676
  return async () => {
3583
3677
  const match = resolveRouteOrThrow(routes, method, urlPath);
3584
3678
  ctx.params = match.params;
3585
3679
  const { route } = match;
3586
3680
  const absoluteFilePath = path10.resolve(rootDir, route.filePath);
3587
3681
  const routeModule = await loadRouteModule(absoluteFilePath, route.method, rootDir);
3588
- const input = await resolveInput(route.method, request);
3682
+ const input = await resolveInputFromUrl(route.method, request, url);
3589
3683
  const inputType = getInputTypeForMethod(route.method);
3590
3684
  const schemaPath = getRuntimeSchemaPath(route.filePath, dist, rootDir);
3591
3685
  if (isDevOnDemandEnabled()) {
@@ -3617,33 +3711,33 @@ async function sendSuccessResponse(response, res) {
3617
3711
  await sendNodeResponse(response, res);
3618
3712
  }
3619
3713
  async function sendErrorResponse(err, meta, res, onError, ctx) {
3620
- await sendNodeResponse(mergeMeta(buildErrorResponse(err, ctx.config), meta), res);
3621
- if (onError) {
3714
+ await sendNodeResponse(mergeMeta(buildErrorResponse(err, ctx?.config), meta), res);
3715
+ if (onError && ctx) {
3622
3716
  try {
3623
3717
  await onError(err, ctx);
3624
3718
  } catch {
3625
3719
  }
3626
3720
  }
3627
3721
  }
3628
- async function handleRequest(routes, rootDir, dist, req, res, configMiddlewares, onError, config, globalMiddlewares, globalInjectors, bodyLimit) {
3629
- const { request, ctx, meta, method, urlPath } = prepareRequest(req, config, bodyLimit);
3630
- const routePipeline = createRoutePipeline({
3631
- routes,
3632
- method,
3633
- urlPath,
3634
- ctx,
3635
- request,
3636
- rootDir,
3637
- dist,
3638
- globalMiddlewares,
3639
- globalInjectors
3640
- });
3641
- const outerMiddlewares = [];
3642
- if (configMiddlewares.length > 0) outerMiddlewares.push(...configMiddlewares);
3643
- if (globalMiddlewares && globalMiddlewares.length > 0) {
3644
- outerMiddlewares.push(...globalMiddlewares);
3645
- }
3722
+ async function handleRequest(routes, rootDir, dist, req, res, outerMiddlewares, onError, config, globalInjectors, bodyLimit, trustedProxy) {
3723
+ let meta = { headers: {}, setCookies: [] };
3724
+ let ctx;
3646
3725
  try {
3726
+ const prepared = prepareRequest(req, config, bodyLimit, trustedProxy);
3727
+ ctx = prepared.ctx;
3728
+ meta = prepared.meta;
3729
+ const { request, url, method, urlPath } = prepared;
3730
+ const routePipeline = createRoutePipeline({
3731
+ routes,
3732
+ method,
3733
+ urlPath,
3734
+ url,
3735
+ ctx,
3736
+ request,
3737
+ rootDir,
3738
+ dist,
3739
+ globalInjectors
3740
+ });
3647
3741
  const response = outerMiddlewares.length > 0 ? await compose(outerMiddlewares, ctx, routePipeline) : await routePipeline();
3648
3742
  await sendSuccessResponse(response, res);
3649
3743
  } catch (err) {
@@ -3670,7 +3764,7 @@ async function createTestServer(options) {
3670
3764
  } = options;
3671
3765
  const { routes, wsRoutes } = await scanRoutes(rootDir, patterns);
3672
3766
  const sorted = sortRoutes(routes);
3673
- const schemaDist = dist ? path11.isAbsolute(dist) ? dist : path11.resolve(rootDir, dist) : await fs10.mkdtemp(path11.join(os.tmpdir(), "faapi-test-schema-"));
3767
+ const schemaDist = dist ? path11.isAbsolute(dist) ? dist : path11.resolve(rootDir, dist) : await fs9.mkdtemp(path11.join(os.tmpdir(), "faapi-test-schema-"));
3674
3768
  await generateSchemaFiles(sorted, rootDir, schemaDist);
3675
3769
  const { server } = createServer({
3676
3770
  routes: sorted,
@@ -3703,7 +3797,7 @@ async function createTestServer(options) {
3703
3797
  await new Promise((resolve) => {
3704
3798
  server.close(() => resolve());
3705
3799
  });
3706
- await fs10.rm(schemaDist, { recursive: true, force: true }).catch(() => {
3800
+ await fs9.rm(schemaDist, { recursive: true, force: true }).catch(() => {
3707
3801
  });
3708
3802
  invalidateSchemaCache();
3709
3803
  }