@faapi/faapi 0.0.0-canary.f08a14e → 1.0.0-canary.3a00f3e

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/index.d.ts CHANGED
@@ -561,17 +561,19 @@ interface LifecycleContext {
561
561
  * } satisfies FaapiConfig;
562
562
  * ```
563
563
  *
564
- * 多环境配置:
564
+ * 自定义业务配置(任意 key):
565
565
  * ```ts
566
566
  * import type { FaapiConfig } from '@faapi/faapi';
567
567
  * export default {
568
568
  * cors: { origin: '*' },
569
- * // 自定义业务配置(任意 key)
570
- * db: { host: 'localhost', port: 5432 },
569
+ * // 通过 process.env.XXX 读取 .env 文件加载的环境变量
570
+ * db: { host: process.env.DB_HOST ?? 'localhost', port: 5432 },
571
571
  * } satisfies FaapiConfig;
572
572
  * ```
573
573
  *
574
- * 环境覆盖通过 faapi.config.{NODE_ENV}.ts 实现(如 faapi.config.production.ts)
574
+ * 多环境差异通过 `.env` 系列文件实现(见 `loadEnv`):
575
+ * - `.env` / `.env.local` / `.env.{env}` / `.env.{env}.local`
576
+ * - 环境由 `NODE_ENV > 'development'` 决定
575
577
  *
576
578
  * 框架元信息通过环境变量配置(不放在 config 内):
577
579
  * - `PORT`:服务端口,默认 3000
@@ -1009,7 +1011,8 @@ declare function collectRouteSchemaSources(routes: RouteManifest, rootDir?: stri
1009
1011
  * - dev 模式:`faapi dev` 启动时由 `compileConfig` 生成 `.faapi/faapi-config.js`
1010
1012
  * - prod 模式:`faapi build` 时由 `compileConfig` 生成 `dist/faapi-config.js`
1011
1013
  *
1012
- * 产物由 `compileConfig` 在构建阶段合并 env 后固化,运行时不读源码、不现场编译、不按 env 合并。
1014
+ * 产物由 `compileConfig` 在构建阶段编译,运行时不读源码、不现场编译。
1015
+ * 环境变量由 `loadEnv` 从 `.env` 系列文件加载到 `process.env`,配置文件中通过 `process.env.XXX` 读取。
1013
1016
  *
1014
1017
  * - 产物存在 → import 并返回 default
1015
1018
  * - 产物不存在但源码有配置文件 → 抛错(强制 rebuild)
@@ -1021,6 +1024,26 @@ declare function collectRouteSchemaSources(routes: RouteManifest, rootDir?: stri
1021
1024
  */
1022
1025
  declare function loadConfig(rootDir: string, dist: string): Promise<Partial<FaapiConfig> | null>;
1023
1026
 
1027
+ /**
1028
+ * 加载 `.env` 系列文件到 `process.env`
1029
+ *
1030
+ * 按 Next.js 约定加载四级文件(从低到高):
1031
+ * 1. `.env` — 所有环境共享
1032
+ * 2. `.env.local` — 本地覆盖
1033
+ * 3. `.env.{env}` — 按环境覆盖
1034
+ * 4. `.env.{env}.local` — 按环境本地覆盖
1035
+ *
1036
+ * env 由 `NODE_ENV || 'development'` 决定。调用方应在调 loadEnv 之前自行兜底 NODE_ENV
1037
+ * (dev 设 'development',prod 设 'production')。
1038
+ *
1039
+ * 合并规则:
1040
+ * - 后加载的文件覆盖先加载的同名变量
1041
+ * - **shell 已设置的变量不被覆盖**(`process.env` 已有的值优先)
1042
+ *
1043
+ * @param rootDir 项目根目录(`.env` 文件所在目录)
1044
+ */
1045
+ declare function loadEnv(rootDir: string): void;
1046
+
1024
1047
  declare const VALIDATION_ERROR = "VALIDATION_ERROR";
1025
1048
  declare const ROUTE_NOT_FOUND = "ROUTE_NOT_FOUND";
1026
1049
  declare const METHOD_NOT_ALLOWED = "METHOD_NOT_ALLOWED";
@@ -1192,4 +1215,4 @@ type ProdApp = AppBase;
1192
1215
  */
1193
1216
  declare function createProdApp(options?: CreateAppOptions): Promise<ProdApp>;
1194
1217
 
1195
- export { type ProdApp as App, type CorsOptions, type CreateAppOptions, type DevApp, type FaapiConfig, type FaapiContext, type FaapiContextConfig, FaapiError, type FaapiMiddleware, type FaapiPlugin, type HandlerTypeInfo, type HelmetOptions, type InjectOptions, type InjectResponse, type Injector, type InjectorMap, InternalError, type LifecycleContext, type LifecycleHooks, type LoggerOptions, MethodNotAllowedError, ModuleLoadError, type PluginContext, type PluginDeclaration, type ProdApp, type PropertyType, type RequestHandler, type RouteInfo, type RouteInputSchema, type RouteManifest, RouteNotFoundError, type RouteOutputSchema, type RouteParamSchema, type RouteSchemaSource, type RuntimeType, SchemaExtractionError, type SseEvent, type SseWriter, type TypeConstraint, type UpgradeHandler, ValidationError, type ValidationErrorCode, type ValidationIssue, type WsContext, type WsEventHandlers, type WsHandler, type WsSocket, collectRouteSchemaSources, cors, createProdApp as createApp, createContext, createDevApp, createProdApp, createProgram, extractTypeInfo, getInputTypeForMethod, helmet, invalidateProgramCache, invokeHandler, loadConfig, logger, resolveTypeNode };
1218
+ export { type ProdApp as App, type CorsOptions, type CreateAppOptions, type DevApp, type FaapiConfig, type FaapiContext, type FaapiContextConfig, FaapiError, type FaapiMiddleware, type FaapiPlugin, type HandlerTypeInfo, type HelmetOptions, type InjectOptions, type InjectResponse, type Injector, type InjectorMap, InternalError, type LifecycleContext, type LifecycleHooks, type LoggerOptions, MethodNotAllowedError, ModuleLoadError, type PluginContext, type PluginDeclaration, type ProdApp, type PropertyType, type RequestHandler, type RouteInfo, type RouteInputSchema, type RouteManifest, RouteNotFoundError, type RouteOutputSchema, type RouteParamSchema, type RouteSchemaSource, type RuntimeType, SchemaExtractionError, type SseEvent, type SseWriter, type TypeConstraint, type UpgradeHandler, ValidationError, type ValidationErrorCode, type ValidationIssue, type WsContext, type WsEventHandlers, type WsHandler, type WsSocket, collectRouteSchemaSources, cors, createProdApp as createApp, createContext, createDevApp, createProdApp, createProgram, extractTypeInfo, getInputTypeForMethod, helmet, invalidateProgramCache, invokeHandler, loadConfig, loadEnv, logger, resolveTypeNode };
package/dist/index.js CHANGED
@@ -1043,6 +1043,87 @@ async function loadConfig(rootDir, dist) {
1043
1043
  return null;
1044
1044
  }
1045
1045
 
1046
+ // src/cli/loadEnv.ts
1047
+ import fs2 from "fs";
1048
+ import path3 from "path";
1049
+ function resolveEnv() {
1050
+ return process.env.NODE_ENV || "development";
1051
+ }
1052
+ function getEnvFiles(env) {
1053
+ return [".env", ".env.local", `.env.${env}`, `.env.${env}.local`];
1054
+ }
1055
+ function parseEnvFile(content, fileVars) {
1056
+ const result = {};
1057
+ const lines = content.replace(/\r\n/g, "\n").split("\n");
1058
+ for (const line of lines) {
1059
+ const trimmed = line.trim();
1060
+ if (!trimmed || trimmed.startsWith("#")) continue;
1061
+ const match = /^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(trimmed);
1062
+ if (!match) continue;
1063
+ const [, key, rawValue] = match;
1064
+ const value = parseValue(rawValue, { ...fileVars, ...result });
1065
+ result[key] = value;
1066
+ }
1067
+ return result;
1068
+ }
1069
+ function parseValue(raw, env) {
1070
+ if (raw === "") return "";
1071
+ if (raw[0] === "'") {
1072
+ const end = raw.indexOf("'", 1);
1073
+ return end === -1 ? raw.slice(1) : raw.slice(1, end);
1074
+ }
1075
+ if (raw[0] === '"') {
1076
+ const match = /^"((?:\\.|[^"\\])*)"/.exec(raw);
1077
+ const inner = match ? match[1] : raw.slice(1);
1078
+ return expandEscapesAndVars(inner, env);
1079
+ }
1080
+ const commentMatch = /^(.*?)(\s+#.*)$/.exec(raw);
1081
+ const value = commentMatch ? commentMatch[1] : raw;
1082
+ return value.trim();
1083
+ }
1084
+ function expandEscapesAndVars(str, env) {
1085
+ const escaped = str.replace(/\\(.)/g, (_, ch) => {
1086
+ switch (ch) {
1087
+ case "n":
1088
+ return "\n";
1089
+ case "r":
1090
+ return "\r";
1091
+ case "t":
1092
+ return " ";
1093
+ case "\\":
1094
+ return "\\";
1095
+ case '"':
1096
+ return '"';
1097
+ default:
1098
+ return ch;
1099
+ }
1100
+ });
1101
+ return escaped.replace(
1102
+ /\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Za-z_][A-Za-z0-9_]*)/g,
1103
+ (_, braced, plain) => {
1104
+ const varName = braced || plain;
1105
+ return env[varName] ?? process.env[varName] ?? "";
1106
+ }
1107
+ );
1108
+ }
1109
+ function loadEnv(rootDir) {
1110
+ const env = resolveEnv();
1111
+ const files = getEnvFiles(env);
1112
+ const merged = {};
1113
+ for (const file of files) {
1114
+ const filePath = path3.join(rootDir, file);
1115
+ if (!fs2.existsSync(filePath)) continue;
1116
+ const content = fs2.readFileSync(filePath, "utf-8");
1117
+ const parsed = parseEnvFile(content, merged);
1118
+ Object.assign(merged, parsed);
1119
+ }
1120
+ for (const [key, value] of Object.entries(merged)) {
1121
+ if (process.env[key] === void 0) {
1122
+ process.env[key] = value;
1123
+ }
1124
+ }
1125
+ }
1126
+
1046
1127
  // src/errors/FaapiError.ts
1047
1128
  var FaapiError = class extends Error {
1048
1129
  constructor(code, message, statusCode) {
@@ -1069,14 +1150,14 @@ var ValidationError = class extends FaapiError {
1069
1150
  issues;
1070
1151
  };
1071
1152
  var RouteNotFoundError = class extends FaapiError {
1072
- constructor(path9) {
1073
- super("ROUTE_NOT_FOUND", `Route not found: ${path9}`, 404);
1153
+ constructor(path10) {
1154
+ super("ROUTE_NOT_FOUND", `Route not found: ${path10}`, 404);
1074
1155
  this.name = "RouteNotFoundError";
1075
1156
  }
1076
1157
  };
1077
1158
  var MethodNotAllowedError = class extends FaapiError {
1078
- constructor(method, path9, allowedMethods) {
1079
- super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path9}`, 405);
1159
+ constructor(method, path10, allowedMethods) {
1160
+ super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path10}`, 405);
1080
1161
  this.allowedMethods = allowedMethods;
1081
1162
  this.name = "MethodNotAllowedError";
1082
1163
  }
@@ -1554,8 +1635,8 @@ async function invokeHandler(handler, ctx, body, middlewares, injectors) {
1554
1635
  }
1555
1636
 
1556
1637
  // src/cli/createAppCore.ts
1557
- import fs4 from "fs";
1558
- import path7 from "path";
1638
+ import fs5 from "fs";
1639
+ import path8 from "path";
1559
1640
  import { PassThrough } from "stream";
1560
1641
 
1561
1642
  // src/router/sortRoutes.ts
@@ -1608,45 +1689,45 @@ import {
1608
1689
  import { createSecureServer as createHttp2SecureServer } from "http2";
1609
1690
  import { readFileSync } from "fs";
1610
1691
  import { Readable as Readable2 } from "stream";
1611
- import path5 from "path";
1692
+ import path6 from "path";
1612
1693
 
1613
1694
  // src/router/matchRoute.ts
1614
- function matchRoute(routes, method, path9) {
1695
+ function matchRoute(routes, method, path10) {
1615
1696
  for (const route of routes) {
1616
1697
  if (route.method !== method) {
1617
1698
  continue;
1618
1699
  }
1619
1700
  if (!route.isDynamic) {
1620
- if (route.urlPath === path9) {
1701
+ if (route.urlPath === path10) {
1621
1702
  return { route, params: {} };
1622
1703
  }
1623
1704
  continue;
1624
1705
  }
1625
- const params = matchDynamicPath(route.urlPath, path9, route.paramNames, route.isCatchAll);
1706
+ const params = matchDynamicPath(route.urlPath, path10, route.paramNames, route.isCatchAll);
1626
1707
  if (params !== null) {
1627
1708
  return { route, params };
1628
1709
  }
1629
1710
  }
1630
1711
  return null;
1631
1712
  }
1632
- function matchWsRoute(wsRoutes, path9) {
1713
+ function matchWsRoute(wsRoutes, path10) {
1633
1714
  for (const route of wsRoutes) {
1634
1715
  if (!route.isDynamic) {
1635
- if (route.urlPath === path9) {
1716
+ if (route.urlPath === path10) {
1636
1717
  return { route, params: {} };
1637
1718
  }
1638
1719
  continue;
1639
1720
  }
1640
- const params = matchDynamicPath(route.urlPath, path9, route.paramNames, route.isCatchAll);
1721
+ const params = matchDynamicPath(route.urlPath, path10, route.paramNames, route.isCatchAll);
1641
1722
  if (params !== null) {
1642
1723
  return { route, params };
1643
1724
  }
1644
1725
  }
1645
1726
  return null;
1646
1727
  }
1647
- function matchDynamicPath(pattern, path9, paramNames, isCatchAll) {
1728
+ function matchDynamicPath(pattern, path10, paramNames, isCatchAll) {
1648
1729
  const patternSegments = pattern.split("/").filter(Boolean);
1649
- const pathSegments = path9.split("/").filter(Boolean);
1730
+ const pathSegments = path10.split("/").filter(Boolean);
1650
1731
  if (isCatchAll) {
1651
1732
  const nonCatchAllCount = patternSegments.length - 1;
1652
1733
  if (pathSegments.length <= nonCatchAllCount) {
@@ -1877,9 +1958,9 @@ async function validateInput(schemaPath, method, inputType, input) {
1877
1958
  function mapZodIssues(error) {
1878
1959
  return error.issues.map((issue) => {
1879
1960
  const code = mapZodCode(issue.code, issue.message);
1880
- const path9 = issue.path.map(String).join(".") || "";
1961
+ const path10 = issue.path.map(String).join(".") || "";
1881
1962
  return {
1882
- path: path9,
1963
+ path: path10,
1883
1964
  code,
1884
1965
  expected: issue.expected ?? mapExpectedFromMessage(issue.message),
1885
1966
  received: issue.received ?? mapReceivedFromMessage(issue.message),
@@ -1939,7 +2020,7 @@ function getClientIp(req) {
1939
2020
 
1940
2021
  // src/server/handleWsUpgrade.ts
1941
2022
  import { WebSocketServer, WebSocket } from "ws";
1942
- import path3 from "path";
2023
+ import path4 from "path";
1943
2024
 
1944
2025
  // src/errors/formatErrorResponse.ts
1945
2026
  function formatErrorResponse(error) {
@@ -2112,7 +2193,7 @@ function attachWebSocket(options) {
2112
2193
  const finalHandler = async () => {
2113
2194
  let handlers;
2114
2195
  try {
2115
- const absoluteFilePath = path3.resolve(rootDir, route.filePath);
2196
+ const absoluteFilePath = path4.resolve(rootDir, route.filePath);
2116
2197
  handlers = await loadWsHandler(absoluteFilePath, ctx);
2117
2198
  } catch (err) {
2118
2199
  const reason = err instanceof Error ? err.message : String(err);
@@ -2158,8 +2239,8 @@ function attachWebSocket(options) {
2158
2239
  }
2159
2240
 
2160
2241
  // src/cli/generateSchemaFiles.ts
2161
- import path4 from "path";
2162
- import fs2 from "fs/promises";
2242
+ import path5 from "path";
2243
+ import fs3 from "fs/promises";
2163
2244
 
2164
2245
  // src/ast/generateZodSchema.ts
2165
2246
  var CodeGenContext = class {
@@ -2468,7 +2549,7 @@ function getSchemaOutputPath(sourceFile, dist, rootDir) {
2468
2549
  }
2469
2550
  const idx = rel.lastIndexOf("/");
2470
2551
  const relDir = idx >= 0 ? rel.slice(0, idx) : "";
2471
- return path4.resolve(rootDir, dist, relDir, "zod.js");
2552
+ return path5.resolve(rootDir, dist, relDir, "zod.js");
2472
2553
  }
2473
2554
  function getRuntimeSchemaPath(filePath, dist, rootDir) {
2474
2555
  let rel = filePath.replace(/\\/g, "/");
@@ -2479,7 +2560,7 @@ function getRuntimeSchemaPath(filePath, dist, rootDir) {
2479
2560
  }
2480
2561
  const idx = rel.lastIndexOf("/");
2481
2562
  const relDir = idx >= 0 ? rel.slice(0, idx) : "";
2482
- return path4.resolve(rootDir, dist, relDir, "zod.js");
2563
+ return path5.resolve(rootDir, dist, relDir, "zod.js");
2483
2564
  }
2484
2565
  function getHelpersImportPath(relDir) {
2485
2566
  if (!relDir) return `./${HELPERS_FILENAME}`;
@@ -2529,7 +2610,7 @@ async function generateSchemaFiles(routes, rootDir, dist) {
2529
2610
  }
2530
2611
  const fileEntries = [];
2531
2612
  for (const [filePath, fileSources] of sourcesByFile) {
2532
- const relFile = path4.relative(rootDir, filePath).replace(/\\/g, "/");
2613
+ const relFile = path5.relative(rootDir, filePath).replace(/\\/g, "/");
2533
2614
  const outputPath = getSchemaOutputPath(relFile, dist, rootDir);
2534
2615
  const allTypes = allTypesByFile.get(filePath) ?? /* @__PURE__ */ new Map();
2535
2616
  let relForDir = relFile;
@@ -2544,7 +2625,7 @@ async function generateSchemaFiles(routes, rootDir, dist) {
2544
2625
  }
2545
2626
  const allSourceCode = fileEntries.map((e) => e.source).join("\n");
2546
2627
  if (usesCoerceHelpers(allSourceCode)) {
2547
- const helpersPath = path4.resolve(rootDir, dist, HELPERS_FILENAME);
2628
+ const helpersPath = path5.resolve(rootDir, dist, HELPERS_FILENAME);
2548
2629
  await writeSchemaFile(helpersPath, generateHelpersFileSource());
2549
2630
  }
2550
2631
  await Promise.all(
@@ -2552,8 +2633,8 @@ async function generateSchemaFiles(routes, rootDir, dist) {
2552
2633
  );
2553
2634
  }
2554
2635
  async function writeSchemaFile(outputPath, source) {
2555
- await fs2.mkdir(path4.dirname(outputPath), { recursive: true });
2556
- await fs2.writeFile(outputPath, source, "utf-8");
2636
+ await fs3.mkdir(path5.dirname(outputPath), { recursive: true });
2637
+ await fs3.writeFile(outputPath, source, "utf-8");
2557
2638
  }
2558
2639
 
2559
2640
  // src/server/createServer.ts
@@ -2601,15 +2682,15 @@ function limitStreamSize(stream, maxSize) {
2601
2682
  }
2602
2683
  });
2603
2684
  }
2604
- function findAllowedMethods(routes, path9) {
2685
+ function findAllowedMethods(routes, path10) {
2605
2686
  const methods = /* @__PURE__ */ new Set();
2606
2687
  for (const route of routes) {
2607
- if (route.urlPath === path9) {
2688
+ if (route.urlPath === path10) {
2608
2689
  methods.add(route.method);
2609
2690
  continue;
2610
2691
  }
2611
2692
  if (route.isDynamic) {
2612
- const params = matchDynamicPath(route.urlPath, path9, route.paramNames, route.isCatchAll);
2693
+ const params = matchDynamicPath(route.urlPath, path10, route.paramNames, route.isCatchAll);
2613
2694
  if (params !== null) {
2614
2695
  methods.add(route.method);
2615
2696
  }
@@ -2695,7 +2776,7 @@ async function handleRequest(routes, rootDir, dist, req, res, configMiddlewares,
2695
2776
  }
2696
2777
  ctx.params = match.params;
2697
2778
  const { route } = match;
2698
- const absoluteFilePath = path5.resolve(rootDir, route.filePath);
2779
+ const absoluteFilePath = path6.resolve(rootDir, route.filePath);
2699
2780
  const routeModule = await loadRouteModule(absoluteFilePath, route.method);
2700
2781
  const input = await resolveInput(route.method, request);
2701
2782
  const inputType = getInputTypeForMethod(route.method);
@@ -2769,8 +2850,8 @@ function applyPluginWrappers(server, handlerWrappers, upgradeWrappers) {
2769
2850
  }
2770
2851
 
2771
2852
  // src/cli/generateRoutes.ts
2772
- import fs3 from "fs";
2773
- import path6 from "path";
2853
+ import fs4 from "fs";
2854
+ import path7 from "path";
2774
2855
 
2775
2856
  // src/middleware/loadMiddlewares.ts
2776
2857
  var middlewareCache = /* @__PURE__ */ new Map();
@@ -2948,8 +3029,8 @@ function isFaapiConfigKey(key) {
2948
3029
  async function createAppBase(options) {
2949
3030
  const rootDir = options?.rootDir ?? process.cwd();
2950
3031
  const dist = options?.dist ?? process.env.FAAPI_DIST ?? DEFAULT_DIST;
2951
- const routesPath = path7.resolve(rootDir, dist, ROUTES_FILE);
2952
- if (!fs4.existsSync(routesPath)) {
3032
+ const routesPath = path8.resolve(rootDir, dist, ROUTES_FILE);
3033
+ if (!fs5.existsSync(routesPath)) {
2953
3034
  throw new Error(
2954
3035
  `[faapi] ${dist}/${ROUTES_FILE} \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6267\u884C \`faapi build\`\uFF08\u6216 \`faapi dev\`\uFF09\u751F\u6210\u4EA7\u7269\u3002`
2955
3036
  );
@@ -3152,8 +3233,8 @@ async function createAppBase(options) {
3152
3233
 
3153
3234
  // src/router/scanRoutes.ts
3154
3235
  import fg from "fast-glob";
3155
- import path8 from "path";
3156
- import fs5 from "fs";
3236
+ import path9 from "path";
3237
+ import fs6 from "fs";
3157
3238
 
3158
3239
  // src/router/constants.ts
3159
3240
  var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
@@ -3163,9 +3244,9 @@ function isHttpMethod(value) {
3163
3244
  }
3164
3245
 
3165
3246
  // src/utils/normalizePath.ts
3166
- function normalizePath(path9) {
3167
- if (!path9) return "";
3168
- let result = path9.replace(/\\/g, "/");
3247
+ function normalizePath(path10) {
3248
+ if (!path10) return "";
3249
+ let result = path10.replace(/\\/g, "/");
3169
3250
  result = result.replace(/\/+/g, "/");
3170
3251
  result = result.replace(/\/+$/, "");
3171
3252
  if (result && !result.startsWith("/")) {
@@ -3214,38 +3295,38 @@ function filePathToUrlPath(filePath) {
3214
3295
  // src/router/scanRoutes.ts
3215
3296
  var APP_DIR = "src";
3216
3297
  function toProdAbsPath(sourceAbsPath, rootDir, dist) {
3217
- let rel = path8.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
3298
+ let rel = path9.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
3218
3299
  if (rel.startsWith(`${APP_DIR}/`)) {
3219
3300
  rel = rel.slice(APP_DIR.length + 1);
3220
3301
  }
3221
3302
  const prodRel = `${dist}/${rel.replace(/\.ts$/, ".js")}`;
3222
- return path8.resolve(rootDir, prodRel);
3303
+ return path9.resolve(rootDir, prodRel);
3223
3304
  }
3224
3305
  async function findMergedMiddlewares(routeFilePath, rootDir, dist) {
3225
- const routeDir = path8.dirname(routeFilePath);
3226
- const resolvedRoot = path8.resolve(rootDir);
3306
+ const routeDir = path9.dirname(routeFilePath);
3307
+ const resolvedRoot = path9.resolve(rootDir);
3227
3308
  const mwPaths = [];
3228
- let currentDir = path8.resolve(rootDir, routeDir);
3309
+ let currentDir = path9.resolve(rootDir, routeDir);
3229
3310
  while (true) {
3230
3311
  if (dist) {
3231
- const mwPath = path8.join(currentDir, "middlewares.js");
3232
- const absMwPath = path8.resolve(rootDir, mwPath);
3312
+ const mwPath = path9.join(currentDir, "middlewares.js");
3313
+ const absMwPath = path9.resolve(rootDir, mwPath);
3233
3314
  const prodAbsMwPath = toProdAbsPath(absMwPath, rootDir, dist);
3234
- if (fs5.existsSync(prodAbsMwPath)) {
3315
+ if (fs6.existsSync(prodAbsMwPath)) {
3235
3316
  mwPaths.push(prodAbsMwPath);
3236
3317
  }
3237
3318
  } else {
3238
3319
  for (const ext of [".ts", ".js"]) {
3239
- const mwPath = path8.join(currentDir, `middlewares${ext}`);
3240
- const absMwPath = path8.resolve(rootDir, mwPath);
3241
- if (fs5.existsSync(absMwPath)) {
3320
+ const mwPath = path9.join(currentDir, `middlewares${ext}`);
3321
+ const absMwPath = path9.resolve(rootDir, mwPath);
3322
+ if (fs6.existsSync(absMwPath)) {
3242
3323
  mwPaths.push(absMwPath);
3243
3324
  break;
3244
3325
  }
3245
3326
  }
3246
3327
  }
3247
3328
  if (currentDir === resolvedRoot) break;
3248
- const parentDir = path8.dirname(currentDir);
3329
+ const parentDir = path9.dirname(currentDir);
3249
3330
  if (parentDir === currentDir) break;
3250
3331
  currentDir = parentDir;
3251
3332
  }
@@ -3307,7 +3388,7 @@ async function scanRoutes(rootDir, patterns, dist) {
3307
3388
  const normalizedFile = file.replace(/\\/g, "/");
3308
3389
  const fileName = normalizedFile.split("/").pop();
3309
3390
  if (fileName === "handler.ts" || fileName === "handler.js") {
3310
- const absPath = path8.resolve(rootDir, normalizedFile);
3391
+ const absPath = path9.resolve(rootDir, normalizedFile);
3311
3392
  const importPath = dist ? toProdAbsPath(absPath, rootDir, dist) : absPath;
3312
3393
  const urlPath = filePathToUrlPath(normalizedFile);
3313
3394
  const paramNames = extractParamNames(urlPath);
@@ -3388,6 +3469,7 @@ export {
3388
3469
  invalidateProgramCache,
3389
3470
  invokeHandler,
3390
3471
  loadConfig,
3472
+ loadEnv,
3391
3473
  logger,
3392
3474
  resolveTypeNode
3393
3475
  };