@faapi/faapi 3.2.0 → 3.2.1

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
@@ -129,14 +129,14 @@ var ValidationError = class extends FaapiError {
129
129
  issues;
130
130
  };
131
131
  var RouteNotFoundError = class extends FaapiError {
132
- constructor(path11) {
133
- super("ROUTE_NOT_FOUND", `Route not found: ${path11}`, 404);
132
+ constructor(path12) {
133
+ super("ROUTE_NOT_FOUND", `Route not found: ${path12}`, 404);
134
134
  this.name = "RouteNotFoundError";
135
135
  }
136
136
  };
137
137
  var MethodNotAllowedError = class extends FaapiError {
138
- constructor(method, path11, allowedMethods) {
139
- super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path11}`, 405);
138
+ constructor(method, path12, allowedMethods) {
139
+ super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path12}`, 405);
140
140
  this.allowedMethods = allowedMethods;
141
141
  this.name = "MethodNotAllowedError";
142
142
  }
@@ -370,8 +370,8 @@ function createContext(request, params, config = {}, ip = "") {
370
370
  return ctx;
371
371
  }
372
372
  function createTestContext(options) {
373
- const { method = "GET", path: path11, query, headers, params = {}, config = {}, ip = "" } = options;
374
- const url = new URL(`http://localhost${path11}`);
373
+ const { method = "GET", path: path12, query, headers, params = {}, config = {}, ip = "" } = options;
374
+ const url = new URL(`http://localhost${path12}`);
375
375
  if (query) {
376
376
  for (const [key, value] of Object.entries(query)) {
377
377
  if (Array.isArray(value)) {
@@ -756,9 +756,9 @@ async function invokeHandler(handler, ctx, body, middlewares, injectors) {
756
756
  }
757
757
 
758
758
  // src/testServer.ts
759
- import path10 from "path";
759
+ import path11 from "path";
760
760
  import os from "os";
761
- import fs9 from "fs/promises";
761
+ import fs10 from "fs/promises";
762
762
 
763
763
  // src/router/scanRoutes.ts
764
764
  import fg from "fast-glob";
@@ -770,9 +770,9 @@ var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
770
770
  var HTTP_METHOD_SET = new Set(HTTP_METHODS);
771
771
 
772
772
  // src/utils/normalizePath.ts
773
- function normalizePath(path11) {
774
- if (!path11) return "";
775
- let result = path11.replace(/\\/g, "/");
773
+ function normalizePath(path12) {
774
+ if (!path12) return "";
775
+ let result = path12.replace(/\\/g, "/");
776
776
  result = result.replace(/\/+/g, "/");
777
777
  result = result.replace(/\/+$/, "");
778
778
  if (result && !result.startsWith("/")) {
@@ -1045,25 +1045,93 @@ function sortRoutes(routes) {
1045
1045
  }
1046
1046
 
1047
1047
  // src/cli/generateSchemaFiles.ts
1048
- import path3 from "path";
1049
- import fs2 from "fs/promises";
1048
+ import path4 from "path";
1049
+ import fs3 from "fs/promises";
1050
1050
 
1051
1051
  // src/ast/createProgram.ts
1052
1052
  import ts2 from "typescript";
1053
+ import fs2 from "fs";
1054
+ import path2 from "path";
1053
1055
  var programCache = /* @__PURE__ */ new Map();
1056
+ var tsConfigCache = /* @__PURE__ */ new Map();
1057
+ function findTsConfig(filePath) {
1058
+ let dir = path2.dirname(filePath);
1059
+ const root = path2.parse(dir).root;
1060
+ while (true) {
1061
+ const candidate = path2.join(dir, "tsconfig.json");
1062
+ if (fs2.existsSync(candidate)) {
1063
+ return candidate;
1064
+ }
1065
+ if (dir === root) return null;
1066
+ const parent = path2.dirname(dir);
1067
+ if (parent === dir) return null;
1068
+ dir = parent;
1069
+ }
1070
+ }
1071
+ function parseTsConfig(tsconfigPath) {
1072
+ const cached = tsConfigCache.get(tsconfigPath);
1073
+ if (cached) return cached;
1074
+ const result = { fileNames: [] };
1075
+ try {
1076
+ const configFile = ts2.readConfigFile(tsconfigPath, (p) => fs2.readFileSync(p, "utf-8"));
1077
+ if (configFile.error) {
1078
+ tsConfigCache.set(tsconfigPath, result);
1079
+ return result;
1080
+ }
1081
+ const config = configFile.config ?? {};
1082
+ const basePath = path2.dirname(tsconfigPath);
1083
+ const parsed = ts2.parseJsonConfigFileContent(
1084
+ config,
1085
+ ts2.sys,
1086
+ basePath,
1087
+ /* existingOptions */
1088
+ void 0,
1089
+ tsconfigPath
1090
+ );
1091
+ result.fileNames = parsed.fileNames;
1092
+ if (parsed.options.module !== void 0) {
1093
+ result.module = parsed.options.module;
1094
+ }
1095
+ if (parsed.options.moduleResolution !== void 0) {
1096
+ result.moduleResolution = parsed.options.moduleResolution;
1097
+ }
1098
+ } catch {
1099
+ }
1100
+ tsConfigCache.set(tsconfigPath, result);
1101
+ return result;
1102
+ }
1054
1103
  function createProgram(filePath) {
1055
1104
  const cached = programCache.get(filePath);
1056
1105
  if (cached) {
1057
1106
  return cached;
1058
1107
  }
1059
- const program = ts2.createProgram([filePath], {
1108
+ const options = {
1060
1109
  strict: true,
1061
1110
  target: ts2.ScriptTarget.ES2022,
1062
1111
  module: ts2.ModuleKind.NodeNext,
1063
1112
  moduleResolution: ts2.ModuleResolutionKind.NodeNext,
1064
1113
  skipLibCheck: true,
1065
1114
  noEmit: true
1066
- });
1115
+ };
1116
+ let rootNames = [filePath];
1117
+ const tsconfigPath = findTsConfig(filePath);
1118
+ if (tsconfigPath) {
1119
+ const tsOptions = parseTsConfig(tsconfigPath);
1120
+ if (tsOptions.module !== void 0) {
1121
+ options.module = tsOptions.module;
1122
+ }
1123
+ if (tsOptions.moduleResolution !== void 0) {
1124
+ options.moduleResolution = tsOptions.moduleResolution;
1125
+ }
1126
+ if (tsOptions.fileNames.length > 0) {
1127
+ if (!tsOptions.fileNames.includes(filePath)) {
1128
+ rootNames = [filePath, ...tsOptions.fileNames];
1129
+ } else {
1130
+ rootNames = tsOptions.fileNames;
1131
+ }
1132
+ }
1133
+ }
1134
+ const program = ts2.createProgram(rootNames, options);
1067
1135
  programCache.set(filePath, program);
1068
1136
  return program;
1069
1137
  }
@@ -1073,6 +1141,10 @@ import ts4 from "typescript";
1073
1141
 
1074
1142
  // src/ast/resolveTypeNode.ts
1075
1143
  import ts3 from "typescript";
1144
+ var currentProgram = null;
1145
+ function setProgramContext(program) {
1146
+ currentProgram = program;
1147
+ }
1076
1148
  var SchemaExtractionError = class extends Error {
1077
1149
  constructor(typeText, reason, options) {
1078
1150
  super(`\u65E0\u6CD5\u89E3\u6790\u7C7B\u578B "${typeText}": ${reason}`, options);
@@ -1395,11 +1467,69 @@ function resolveTypeReference(typeNode, checker, visited = /* @__PURE__ */ new S
1395
1467
  if (ts3.isEnumDeclaration(declaration)) {
1396
1468
  return resolveEnumDeclaration(declaration);
1397
1469
  }
1470
+ if (ts3.isImportSpecifier(declaration) || ts3.isImportClause(declaration)) {
1471
+ const resolved = resolveImportAlias(typeNode, symbol, checker, visited);
1472
+ if (resolved) return resolved;
1473
+ }
1398
1474
  }
1399
1475
  }
1400
1476
  }
1401
1477
  throw new SchemaExtractionError(typeNode.getText(), `\u65E0\u6CD5\u89E3\u6790\u7684\u5F15\u7528\u7C7B\u578B "${typeName}"`);
1402
1478
  }
1479
+ function resolveImportAlias(typeNode, symbol, checker, visited) {
1480
+ const typeName = typeNode.typeName.getText();
1481
+ try {
1482
+ const aliased = checker.getAliasedSymbol(symbol);
1483
+ if (aliased && aliased.declarations && aliased.declarations.length > 0) {
1484
+ const decl = aliased.declarations[0];
1485
+ if (ts3.isInterfaceDeclaration(decl)) {
1486
+ return resolveInterfaceDeclaration(decl, checker, visited);
1487
+ }
1488
+ if (ts3.isTypeAliasDeclaration(decl)) {
1489
+ return resolveTypeNode(decl.type, checker, visited);
1490
+ }
1491
+ if (ts3.isEnumDeclaration(decl)) {
1492
+ return resolveEnumDeclaration(decl);
1493
+ }
1494
+ }
1495
+ } catch {
1496
+ }
1497
+ const program = currentProgram;
1498
+ if (!program) return null;
1499
+ const allSFs = program.getSourceFiles();
1500
+ for (const sourceFile of allSFs) {
1501
+ if (sourceFile.fileName.includes("/node_modules/") || sourceFile.fileName.includes("typescript/lib/")) {
1502
+ continue;
1503
+ }
1504
+ const found = findTopLevelDecl(sourceFile, typeName);
1505
+ if (found) {
1506
+ if (found.kind === "interface") {
1507
+ return resolveInterfaceDeclaration(found.node, checker, visited);
1508
+ }
1509
+ if (found.kind === "typeAlias") {
1510
+ return resolveTypeNode(found.node.type, checker, visited);
1511
+ }
1512
+ if (found.kind === "enum") {
1513
+ return resolveEnumDeclaration(found.node);
1514
+ }
1515
+ }
1516
+ }
1517
+ return null;
1518
+ }
1519
+ function findTopLevelDecl(sourceFile, typeName) {
1520
+ let found = null;
1521
+ ts3.forEachChild(sourceFile, (node) => {
1522
+ if (found) return;
1523
+ if (ts3.isInterfaceDeclaration(node) && node.name.text === typeName) {
1524
+ found = { kind: "interface", node };
1525
+ } else if (ts3.isTypeAliasDeclaration(node) && node.name.text === typeName) {
1526
+ found = { kind: "typeAlias", node };
1527
+ } else if (ts3.isEnumDeclaration(node) && node.name.text === typeName) {
1528
+ found = { kind: "enum", node };
1529
+ }
1530
+ });
1531
+ return found;
1532
+ }
1403
1533
  function resolveEnumDeclaration(node) {
1404
1534
  const members = [];
1405
1535
  let nextNumericValue = 0;
@@ -1604,80 +1734,90 @@ function extractTypeInfo(program, filePath, typeName) {
1604
1734
  const sourceFile = program.getSourceFile(filePath);
1605
1735
  if (!sourceFile) return null;
1606
1736
  const checker = program.getTypeChecker();
1607
- let result = null;
1608
- ts4.forEachChild(sourceFile, (node) => {
1609
- if (result) return;
1610
- if (ts4.isInterfaceDeclaration(node) && node.name.text === typeName) {
1611
- const visited = /* @__PURE__ */ new Set();
1612
- visited.add(typeName);
1613
- const runtimeType = withFileContext(
1614
- filePath,
1615
- typeName,
1616
- () => resolveInterfaceDeclaration(node, checker, visited)
1617
- );
1618
- result = {
1619
- name: typeName,
1620
- properties: runtimeType.kind === "object" ? runtimeType.properties : [],
1621
- runtimeType
1622
- };
1623
- return;
1624
- }
1625
- if (ts4.isTypeAliasDeclaration(node) && node.name.text === typeName) {
1626
- const visited = /* @__PURE__ */ new Set();
1627
- visited.add(typeName);
1628
- const runtimeType = withFileContext(
1629
- filePath,
1630
- typeName,
1631
- () => resolveTypeNode(node.type, checker, visited)
1632
- );
1633
- result = {
1634
- name: typeName,
1635
- properties: runtimeType.kind === "object" ? runtimeType.properties : [],
1636
- runtimeType
1637
- };
1638
- return;
1639
- }
1640
- });
1641
- return result;
1737
+ setProgramContext(program);
1738
+ try {
1739
+ let result = null;
1740
+ ts4.forEachChild(sourceFile, (node) => {
1741
+ if (result) return;
1742
+ if (ts4.isInterfaceDeclaration(node) && node.name.text === typeName) {
1743
+ const visited = /* @__PURE__ */ new Set();
1744
+ visited.add(typeName);
1745
+ const runtimeType = withFileContext(
1746
+ filePath,
1747
+ typeName,
1748
+ () => resolveInterfaceDeclaration(node, checker, visited)
1749
+ );
1750
+ result = {
1751
+ name: typeName,
1752
+ properties: runtimeType.kind === "object" ? runtimeType.properties : [],
1753
+ runtimeType
1754
+ };
1755
+ return;
1756
+ }
1757
+ if (ts4.isTypeAliasDeclaration(node) && node.name.text === typeName) {
1758
+ const visited = /* @__PURE__ */ new Set();
1759
+ visited.add(typeName);
1760
+ const runtimeType = withFileContext(
1761
+ filePath,
1762
+ typeName,
1763
+ () => resolveTypeNode(node.type, checker, visited)
1764
+ );
1765
+ result = {
1766
+ name: typeName,
1767
+ properties: runtimeType.kind === "object" ? runtimeType.properties : [],
1768
+ runtimeType
1769
+ };
1770
+ return;
1771
+ }
1772
+ });
1773
+ return result;
1774
+ } finally {
1775
+ setProgramContext(null);
1776
+ }
1642
1777
  }
1643
1778
  function extractAllTypes(program, filePath) {
1644
1779
  const sourceFile = program.getSourceFile(filePath);
1645
1780
  if (!sourceFile) return /* @__PURE__ */ new Map();
1646
1781
  const checker = program.getTypeChecker();
1647
- const result = /* @__PURE__ */ new Map();
1648
- ts4.forEachChild(sourceFile, (node) => {
1649
- if (ts4.isInterfaceDeclaration(node)) {
1650
- const visited = /* @__PURE__ */ new Set();
1651
- visited.add(node.name.text);
1652
- const runtimeType = withFileContext(
1653
- filePath,
1654
- node.name.text,
1655
- () => resolveInterfaceDeclaration(node, checker, visited)
1656
- );
1657
- result.set(node.name.text, {
1658
- name: node.name.text,
1659
- properties: runtimeType.kind === "object" ? runtimeType.properties : [],
1660
- runtimeType
1661
- });
1662
- return;
1663
- }
1664
- if (ts4.isTypeAliasDeclaration(node)) {
1665
- const visited = /* @__PURE__ */ new Set();
1666
- visited.add(node.name.text);
1667
- const runtimeType = withFileContext(
1668
- filePath,
1669
- node.name.text,
1670
- () => resolveTypeNode(node.type, checker, visited)
1671
- );
1672
- result.set(node.name.text, {
1673
- name: node.name.text,
1674
- properties: runtimeType.kind === "object" ? runtimeType.properties : [],
1675
- runtimeType
1676
- });
1677
- return;
1678
- }
1679
- });
1680
- return result;
1782
+ setProgramContext(program);
1783
+ try {
1784
+ const result = /* @__PURE__ */ new Map();
1785
+ ts4.forEachChild(sourceFile, (node) => {
1786
+ if (ts4.isInterfaceDeclaration(node)) {
1787
+ const visited = /* @__PURE__ */ new Set();
1788
+ visited.add(node.name.text);
1789
+ const runtimeType = withFileContext(
1790
+ filePath,
1791
+ node.name.text,
1792
+ () => resolveInterfaceDeclaration(node, checker, visited)
1793
+ );
1794
+ result.set(node.name.text, {
1795
+ name: node.name.text,
1796
+ properties: runtimeType.kind === "object" ? runtimeType.properties : [],
1797
+ runtimeType
1798
+ });
1799
+ return;
1800
+ }
1801
+ if (ts4.isTypeAliasDeclaration(node)) {
1802
+ const visited = /* @__PURE__ */ new Set();
1803
+ visited.add(node.name.text);
1804
+ const runtimeType = withFileContext(
1805
+ filePath,
1806
+ node.name.text,
1807
+ () => resolveTypeNode(node.type, checker, visited)
1808
+ );
1809
+ result.set(node.name.text, {
1810
+ name: node.name.text,
1811
+ properties: runtimeType.kind === "object" ? runtimeType.properties : [],
1812
+ runtimeType
1813
+ });
1814
+ return;
1815
+ }
1816
+ });
1817
+ return result;
1818
+ } finally {
1819
+ setProgramContext(null);
1820
+ }
1681
1821
  }
1682
1822
  function withFileContext(filePath, typeName, fn) {
1683
1823
  try {
@@ -1760,11 +1900,11 @@ function extractSchema(typeNode, sourceFile) {
1760
1900
  }
1761
1901
 
1762
1902
  // src/cli/collectRouteSchemaSources.ts
1763
- import path2 from "path";
1903
+ import path3 from "path";
1764
1904
  function collectRouteSchemaSources(routes, rootDir) {
1765
1905
  const methodsByFile = /* @__PURE__ */ new Map();
1766
1906
  for (const route of routes) {
1767
- const filePath = rootDir ? path2.resolve(rootDir, route.filePath) : route.filePath;
1907
+ const filePath = rootDir ? path3.resolve(rootDir, route.filePath) : route.filePath;
1768
1908
  let entry = methodsByFile.get(filePath);
1769
1909
  if (!entry) {
1770
1910
  entry = { urlPath: route.urlPath, methods: /* @__PURE__ */ new Set() };
@@ -2115,7 +2255,7 @@ function getSchemaOutputPath(sourceFile, dist, rootDir) {
2115
2255
  }
2116
2256
  const idx = rel.lastIndexOf("/");
2117
2257
  const relDir = idx >= 0 ? rel.slice(0, idx) : "";
2118
- return path3.resolve(rootDir, dist, relDir, "zod.js");
2258
+ return path4.resolve(rootDir, dist, relDir, "zod.js");
2119
2259
  }
2120
2260
  function getRuntimeSchemaPath(filePath, dist, rootDir) {
2121
2261
  let rel = filePath.replace(/\\/g, "/");
@@ -2126,7 +2266,7 @@ function getRuntimeSchemaPath(filePath, dist, rootDir) {
2126
2266
  }
2127
2267
  const idx = rel.lastIndexOf("/");
2128
2268
  const relDir = idx >= 0 ? rel.slice(0, idx) : "";
2129
- return path3.resolve(rootDir, dist, relDir, "zod.js");
2269
+ return path4.resolve(rootDir, dist, relDir, "zod.js");
2130
2270
  }
2131
2271
  function getHelpersImportPath(relDir) {
2132
2272
  if (!relDir) return `./${HELPERS_FILENAME}`;
@@ -2176,7 +2316,7 @@ async function generateSchemaFiles(routes, rootDir, dist) {
2176
2316
  }
2177
2317
  const fileEntries = [];
2178
2318
  for (const [filePath, fileSources] of sourcesByFile) {
2179
- const relFile = path3.relative(rootDir, filePath).replace(/\\/g, "/");
2319
+ const relFile = path4.relative(rootDir, filePath).replace(/\\/g, "/");
2180
2320
  const outputPath = getSchemaOutputPath(relFile, dist, rootDir);
2181
2321
  const allTypes = allTypesByFile.get(filePath) ?? /* @__PURE__ */ new Map();
2182
2322
  let relForDir = relFile;
@@ -2191,7 +2331,7 @@ async function generateSchemaFiles(routes, rootDir, dist) {
2191
2331
  }
2192
2332
  const allSourceCode = fileEntries.map((e) => e.source).join("\n");
2193
2333
  if (usesCoerceHelpers(allSourceCode)) {
2194
- const helpersPath = path3.resolve(rootDir, dist, HELPERS_FILENAME);
2334
+ const helpersPath = path4.resolve(rootDir, dist, HELPERS_FILENAME);
2195
2335
  await writeSchemaFile(helpersPath, generateHelpersFileSource());
2196
2336
  }
2197
2337
  await Promise.all(
@@ -2199,22 +2339,22 @@ async function generateSchemaFiles(routes, rootDir, dist) {
2199
2339
  );
2200
2340
  }
2201
2341
  async function writeSchemaFile(outputPath, source) {
2202
- await fs2.mkdir(path3.dirname(outputPath), { recursive: true });
2203
- await fs2.writeFile(outputPath, source, "utf-8");
2342
+ await fs3.mkdir(path4.dirname(outputPath), { recursive: true });
2343
+ await fs3.writeFile(outputPath, source, "utf-8");
2204
2344
  }
2205
2345
 
2206
2346
  // src/cli/compileOnDemand.ts
2207
- import path7 from "path";
2208
- import fs6 from "fs";
2347
+ import path8 from "path";
2348
+ import fs7 from "fs";
2209
2349
 
2210
2350
  // src/cli/compileDevRoutes.ts
2211
- import path6 from "path";
2212
- import fs5 from "fs";
2351
+ import path7 from "path";
2352
+ import fs6 from "fs";
2213
2353
  import fg2 from "fast-glob";
2214
2354
 
2215
2355
  // src/cli/aliasPlugin.ts
2216
- import path5 from "path";
2217
- import fs4 from "fs";
2356
+ import path6 from "path";
2357
+ import fs5 from "fs";
2218
2358
 
2219
2359
  // src/utils/resolveAlias.ts
2220
2360
  function resolveAlias(specifier, config) {
@@ -2241,11 +2381,11 @@ function resolveAlias(specifier, config) {
2241
2381
 
2242
2382
  // src/utils/readTsconfig.ts
2243
2383
  import ts6 from "typescript";
2244
- import path4 from "path";
2245
- import fs3 from "fs";
2384
+ import path5 from "path";
2385
+ import fs4 from "fs";
2246
2386
  function readTsconfig(rootDir) {
2247
- const tsconfigPath = path4.resolve(rootDir, "tsconfig.json");
2248
- if (!fs3.existsSync(tsconfigPath)) return null;
2387
+ const tsconfigPath = path5.resolve(rootDir, "tsconfig.json");
2388
+ if (!fs4.existsSync(tsconfigPath)) return null;
2249
2389
  const configFile = ts6.readConfigFile(tsconfigPath, ts6.sys.readFile);
2250
2390
  if (configFile.error || !configFile.config) return null;
2251
2391
  const parsed = ts6.parseJsonConfigFileContent(configFile.config, ts6.sys, rootDir);
@@ -2254,7 +2394,7 @@ function readTsconfig(rootDir) {
2254
2394
  if (!rawPaths) return null;
2255
2395
  const paths = {};
2256
2396
  for (const [pattern, targets] of Object.entries(rawPaths)) {
2257
- paths[pattern] = targets.map((t) => path4.resolve(baseUrl, t));
2397
+ paths[pattern] = targets.map((t) => path5.resolve(baseUrl, t));
2258
2398
  }
2259
2399
  return { baseUrl, paths };
2260
2400
  }
@@ -2267,29 +2407,29 @@ function toProdExtension(filePath) {
2267
2407
  return filePath;
2268
2408
  }
2269
2409
  function toProdImportPath(sourceFile, importer) {
2270
- const importerDir = path5.dirname(importer);
2271
- let rel = path5.relative(importerDir, sourceFile);
2272
- rel = rel.split(path5.sep).join("/");
2410
+ const importerDir = path6.dirname(importer);
2411
+ let rel = path6.relative(importerDir, sourceFile);
2412
+ rel = rel.split(path6.sep).join("/");
2273
2413
  if (!rel.startsWith(".")) rel = "./" + rel;
2274
2414
  return toProdExtension(rel);
2275
2415
  }
2276
2416
  function toRealPath(p) {
2277
2417
  try {
2278
- return fs4.realpathSync(p);
2418
+ return fs5.realpathSync(p);
2279
2419
  } catch {
2280
2420
  return p;
2281
2421
  }
2282
2422
  }
2283
2423
  function isInsideDir(filePath, dir) {
2284
- const rel = path5.relative(dir, filePath);
2285
- return rel !== "" && !rel.startsWith("..") && !path5.isAbsolute(rel);
2424
+ const rel = path6.relative(dir, filePath);
2425
+ return rel !== "" && !rel.startsWith("..") && !path6.isAbsolute(rel);
2286
2426
  }
2287
2427
  var APP_DIR = "src";
2288
2428
  function toStrippedProdImportPath(sourceFile, rootDir) {
2289
- const appDirAbs = toRealPath(path5.resolve(rootDir, APP_DIR));
2429
+ const appDirAbs = toRealPath(path6.resolve(rootDir, APP_DIR));
2290
2430
  const sourceReal = toRealPath(sourceFile);
2291
- let rel = path5.relative(appDirAbs, sourceReal);
2292
- rel = rel.split(path5.sep).join("/");
2431
+ let rel = path6.relative(appDirAbs, sourceReal);
2432
+ rel = rel.split(path6.sep).join("/");
2293
2433
  if (!rel.startsWith(".")) rel = "./" + rel;
2294
2434
  return toProdExtension(rel);
2295
2435
  }
@@ -2304,34 +2444,34 @@ var INDEX_EXTS = [
2304
2444
  "/index.cjs"
2305
2445
  ];
2306
2446
  function resolveRelativeSpecifier(importer, specifier) {
2307
- const importerDir = path5.dirname(importer);
2308
- const base = path5.resolve(importerDir, specifier);
2447
+ const importerDir = path6.dirname(importer);
2448
+ const base = path6.resolve(importerDir, specifier);
2309
2449
  if (PROD_EXTS.some((ext) => specifier.endsWith(ext))) {
2310
- return fs4.existsSync(base) ? base : null;
2450
+ return fs5.existsSync(base) ? base : null;
2311
2451
  }
2312
2452
  if (/\.(ts|tsx|jsx)$/.test(specifier)) {
2313
- return fs4.existsSync(base) ? base : null;
2453
+ return fs5.existsSync(base) ? base : null;
2314
2454
  }
2315
2455
  for (const ext of SOURCE_EXTS) {
2316
2456
  const file = base + ext;
2317
- if (fs4.existsSync(file)) return file;
2457
+ if (fs5.existsSync(file)) return file;
2318
2458
  }
2319
2459
  for (const indexExt of INDEX_EXTS) {
2320
2460
  const file = base + indexExt;
2321
- if (fs4.existsSync(file)) return file;
2461
+ if (fs5.existsSync(file)) return file;
2322
2462
  }
2323
2463
  return null;
2324
2464
  }
2325
2465
  function createAliasPlugin(config, options) {
2326
2466
  const SPEC_RE = /(\bfrom\s*|import\s*\(\s*)(['"])([^'"]+)\2/g;
2327
- const appDirAbs = options?.rootDir ? toRealPath(path5.resolve(options.rootDir, APP_DIR)) : null;
2467
+ const appDirAbs = options?.rootDir ? toRealPath(path6.resolve(options.rootDir, APP_DIR)) : null;
2328
2468
  return {
2329
2469
  name: "faapi-alias",
2330
2470
  setup(build) {
2331
2471
  build.onLoad({ filter: /\.(ts|tsx|js|jsx|mjs|cjs)$/ }, (args) => {
2332
2472
  let source;
2333
2473
  try {
2334
- source = fs4.readFileSync(args.path, "utf8");
2474
+ source = fs5.readFileSync(args.path, "utf8");
2335
2475
  } catch {
2336
2476
  return void 0;
2337
2477
  }
@@ -2364,7 +2504,7 @@ function createAliasPlugin(config, options) {
2364
2504
  for (const candidate of candidates) {
2365
2505
  for (const ext of SOURCE_EXTS) {
2366
2506
  const file = candidate + ext;
2367
- if (fs4.existsSync(file)) {
2507
+ if (fs5.existsSync(file)) {
2368
2508
  modified = true;
2369
2509
  if (appDirAbs && importerOutsideAppDir && isInsideDir(file, appDirAbs)) {
2370
2510
  return `${prefix}${quote}${toStrippedProdImportPath(
@@ -2377,7 +2517,7 @@ function createAliasPlugin(config, options) {
2377
2517
  }
2378
2518
  for (const indexExt of INDEX_EXTS) {
2379
2519
  const file = candidate + indexExt;
2380
- if (fs4.existsSync(file)) {
2520
+ if (fs5.existsSync(file)) {
2381
2521
  modified = true;
2382
2522
  if (appDirAbs && importerOutsideAppDir && isInsideDir(file, appDirAbs)) {
2383
2523
  return `${prefix}${quote}${toStrippedProdImportPath(
@@ -2415,11 +2555,11 @@ async function compileDevRoutes(options) {
2415
2555
  if (entryPoints.length === 0) {
2416
2556
  return { compiledFiles: [] };
2417
2557
  }
2418
- const absDist = path6.resolve(rootDir, dist);
2419
- await fs5.promises.mkdir(absDist, { recursive: true });
2558
+ const absDist = path7.resolve(rootDir, dist);
2559
+ await fs6.promises.mkdir(absDist, { recursive: true });
2420
2560
  const plugins = buildAliasPlugins(rootDir);
2421
2561
  const esbuild = await import("esbuild");
2422
- const outbase = path6.resolve(rootDir, APP_DIR2);
2562
+ const outbase = path7.resolve(rootDir, APP_DIR2);
2423
2563
  const result = await esbuild.build({
2424
2564
  entryPoints,
2425
2565
  outdir: absDist,
@@ -2436,10 +2576,10 @@ async function compileDevRoutes(options) {
2436
2576
  if (result.outputFiles) {
2437
2577
  await Promise.all(
2438
2578
  result.outputFiles.map(async (file) => {
2439
- await fs5.promises.mkdir(path6.dirname(file.path), { recursive: true });
2579
+ await fs6.promises.mkdir(path7.dirname(file.path), { recursive: true });
2440
2580
  const tmp = `${file.path}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
2441
- await fs5.promises.writeFile(tmp, file.contents);
2442
- await fs5.promises.rename(tmp, file.path);
2581
+ await fs6.promises.writeFile(tmp, file.contents);
2582
+ await fs6.promises.rename(tmp, file.path);
2443
2583
  })
2444
2584
  );
2445
2585
  }
@@ -2449,8 +2589,8 @@ async function compileDevRoutes(options) {
2449
2589
  // src/cli/compileOnDemand.ts
2450
2590
  function isProductFresh(sourceAbsPath, productAbsPath) {
2451
2591
  try {
2452
- const srcStat = fs6.statSync(sourceAbsPath);
2453
- const prodStat = fs6.statSync(productAbsPath);
2592
+ const srcStat = fs7.statSync(sourceAbsPath);
2593
+ const prodStat = fs7.statSync(productAbsPath);
2454
2594
  return prodStat.mtimeMs >= srcStat.mtimeMs;
2455
2595
  } catch {
2456
2596
  return false;
@@ -2477,7 +2617,7 @@ async function ensureCompiled(sourceAbsPath, rootDir, dist) {
2477
2617
  if (state.compiledFiles.has(sourceAbsPath)) {
2478
2618
  return false;
2479
2619
  }
2480
- if (!fs6.existsSync(sourceAbsPath)) {
2620
+ if (!fs7.existsSync(sourceAbsPath)) {
2481
2621
  return false;
2482
2622
  }
2483
2623
  const productPath = prodSourcePathToProductPath(sourceAbsPath, rootDir, dist);
@@ -2503,11 +2643,11 @@ async function ensureCompiled(sourceAbsPath, rootDir, dist) {
2503
2643
  }
2504
2644
  }
2505
2645
  function prodSourcePathToProductPath(sourceAbsPath, rootDir, dist) {
2506
- const rel = path7.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
2646
+ const rel = path8.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
2507
2647
  if (!rel.startsWith("src/")) return null;
2508
2648
  const relWithoutSrc = rel.slice(4);
2509
2649
  const jsRel = relWithoutSrc.replace(/\.ts$/, ".js");
2510
- return path7.resolve(rootDir, dist, jsRel);
2650
+ return path8.resolve(rootDir, dist, jsRel);
2511
2651
  }
2512
2652
  async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir, dist) {
2513
2653
  const inFlight = state.inFlightSchemaGenerations.get(schemaPath);
@@ -2519,9 +2659,9 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
2519
2659
  if (state.generatedSchemas.has(schemaPath)) {
2520
2660
  return false;
2521
2661
  }
2522
- const prodAbsPath = path7.resolve(rootDir, routeFilePath);
2662
+ const prodAbsPath = path8.resolve(rootDir, routeFilePath);
2523
2663
  const sourceAbsPath = prodPathToSourcePath(prodAbsPath, rootDir, dist);
2524
- if (!fs6.existsSync(sourceAbsPath)) {
2664
+ if (!fs7.existsSync(sourceAbsPath)) {
2525
2665
  return false;
2526
2666
  }
2527
2667
  if (isProductFresh(sourceAbsPath, schemaPath)) {
@@ -2532,7 +2672,7 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
2532
2672
  if (fileRoutes.length === 0) {
2533
2673
  return false;
2534
2674
  }
2535
- const sourceRelPath = path7.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
2675
+ const sourceRelPath = path8.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
2536
2676
  const sourceRoutes = fileRoutes.map((r) => ({ ...r, filePath: sourceRelPath }));
2537
2677
  const generatePromise = (async () => {
2538
2678
  await generateSchemaFiles(sourceRoutes, rootDir, dist);
@@ -2547,16 +2687,16 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
2547
2687
  }
2548
2688
  }
2549
2689
  function prodPathToSourcePath(prodAbsPath, rootDir, dist) {
2550
- const rel = path7.relative(rootDir, prodAbsPath).replace(/\\/g, "/");
2690
+ const rel = path8.relative(rootDir, prodAbsPath).replace(/\\/g, "/");
2551
2691
  let relWithoutDist = rel;
2552
2692
  if (relWithoutDist.startsWith(`${dist}/`)) {
2553
2693
  relWithoutDist = relWithoutDist.slice(dist.length + 1);
2554
2694
  }
2555
2695
  const srcRel = `src/${relWithoutDist}`;
2556
2696
  const tsRel = srcRel.replace(/\.js$/, ".ts");
2557
- const tsAbs = path7.resolve(rootDir, tsRel);
2558
- if (fs6.existsSync(tsAbs)) return tsAbs;
2559
- return path7.resolve(rootDir, srcRel);
2697
+ const tsAbs = path8.resolve(rootDir, tsRel);
2698
+ if (fs7.existsSync(tsAbs)) return tsAbs;
2699
+ return path8.resolve(rootDir, srcRel);
2560
2700
  }
2561
2701
  function isDevOnDemandEnabled() {
2562
2702
  return state.enabled;
@@ -2609,9 +2749,9 @@ async function validateInput(schemaPath, method, inputType, input) {
2609
2749
  function mapZodIssues(error) {
2610
2750
  return error.issues.map((issue) => {
2611
2751
  const code = mapZodCode(issue.code, issue.message);
2612
- const path11 = issue.path.map(String).join(".") || "";
2752
+ const path12 = issue.path.map(String).join(".") || "";
2613
2753
  return {
2614
- path: path11,
2754
+ path: path12,
2615
2755
  code,
2616
2756
  expected: issue.expected ?? mapExpectedFromMessage(issue.message),
2617
2757
  received: issue.received ?? mapReceivedFromMessage(issue.message),
@@ -2659,45 +2799,45 @@ import {
2659
2799
  import { createSecureServer as createHttp2SecureServer } from "http2";
2660
2800
  import { readFileSync } from "fs";
2661
2801
  import { Readable as Readable2 } from "stream";
2662
- import path9 from "path";
2802
+ import path10 from "path";
2663
2803
 
2664
2804
  // src/router/matchRoute.ts
2665
- function matchRoute(routes, method, path11) {
2805
+ function matchRoute(routes, method, path12) {
2666
2806
  for (const route of routes) {
2667
2807
  if (route.method !== method) {
2668
2808
  continue;
2669
2809
  }
2670
2810
  if (!route.isDynamic) {
2671
- if (route.urlPath === path11) {
2811
+ if (route.urlPath === path12) {
2672
2812
  return { route, params: {} };
2673
2813
  }
2674
2814
  continue;
2675
2815
  }
2676
- const params = matchDynamicPath(route.urlPath, path11, route.paramNames, route.isCatchAll);
2816
+ const params = matchDynamicPath(route.urlPath, path12, route.paramNames, route.isCatchAll);
2677
2817
  if (params !== null) {
2678
2818
  return { route, params };
2679
2819
  }
2680
2820
  }
2681
2821
  return null;
2682
2822
  }
2683
- function matchWsRoute(wsRoutes, path11) {
2823
+ function matchWsRoute(wsRoutes, path12) {
2684
2824
  for (const route of wsRoutes) {
2685
2825
  if (!route.isDynamic) {
2686
- if (route.urlPath === path11) {
2826
+ if (route.urlPath === path12) {
2687
2827
  return { route, params: {} };
2688
2828
  }
2689
2829
  continue;
2690
2830
  }
2691
- const params = matchDynamicPath(route.urlPath, path11, route.paramNames, route.isCatchAll);
2831
+ const params = matchDynamicPath(route.urlPath, path12, route.paramNames, route.isCatchAll);
2692
2832
  if (params !== null) {
2693
2833
  return { route, params };
2694
2834
  }
2695
2835
  }
2696
2836
  return null;
2697
2837
  }
2698
- function matchDynamicPath(pattern, path11, paramNames, isCatchAll) {
2838
+ function matchDynamicPath(pattern, path12, paramNames, isCatchAll) {
2699
2839
  const patternSegments = pattern.split("/").filter(Boolean);
2700
- const pathSegments = path11.split("/").filter(Boolean);
2840
+ const pathSegments = path12.split("/").filter(Boolean);
2701
2841
  if (isCatchAll) {
2702
2842
  const nonCatchAllCount = patternSegments.length - 1;
2703
2843
  if (pathSegments.length <= nonCatchAllCount) {
@@ -2743,7 +2883,7 @@ function matchDynamicPath(pattern, path11, paramNames, isCatchAll) {
2743
2883
  }
2744
2884
 
2745
2885
  // src/loader/loadRouteModule.ts
2746
- import fs7 from "fs";
2886
+ import fs8 from "fs";
2747
2887
 
2748
2888
  // src/loader/resolveExports.ts
2749
2889
  function resolveExport(module, exportName) {
@@ -2775,7 +2915,7 @@ async function loadRouteModule(filePath, method, rootDir) {
2775
2915
  const dist = getDevDist();
2776
2916
  if (dist) {
2777
2917
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
2778
- if (sourcePath && fs7.existsSync(sourcePath)) {
2918
+ if (sourcePath && fs8.existsSync(sourcePath)) {
2779
2919
  try {
2780
2920
  await ensureCompiled(sourcePath, rootDir, dist);
2781
2921
  } catch (compileErr) {
@@ -3081,9 +3221,9 @@ function logger(options = {}) {
3081
3221
  }
3082
3222
 
3083
3223
  // src/server/handleWsUpgrade.ts
3084
- import fs8 from "fs";
3224
+ import fs9 from "fs";
3085
3225
  import { WebSocketServer, WebSocket } from "ws";
3086
- import path8 from "path";
3226
+ import path9 from "path";
3087
3227
 
3088
3228
  // src/server/serverUtils.ts
3089
3229
  function nodeHttpToWebHeaders(req) {
@@ -3139,7 +3279,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
3139
3279
  const dist = getDevDist();
3140
3280
  if (dist) {
3141
3281
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
3142
- if (sourcePath && fs8.existsSync(sourcePath)) {
3282
+ if (sourcePath && fs9.existsSync(sourcePath)) {
3143
3283
  await ensureCompiled(sourcePath, rootDir, dist);
3144
3284
  }
3145
3285
  }
@@ -3219,7 +3359,7 @@ function attachWebSocket(options) {
3219
3359
  const finalHandler = async () => {
3220
3360
  let handlers;
3221
3361
  try {
3222
- const absoluteFilePath = path8.resolve(rootDir, route.filePath);
3362
+ const absoluteFilePath = path9.resolve(rootDir, route.filePath);
3223
3363
  handlers = await loadWsHandler(absoluteFilePath, ctx, rootDir);
3224
3364
  } catch (err) {
3225
3365
  const reason = err instanceof Error ? err.message : String(err);
@@ -3343,15 +3483,15 @@ function limitStreamSize(stream, maxSize) {
3343
3483
  }
3344
3484
  });
3345
3485
  }
3346
- function findAllowedMethods(routes, path11) {
3486
+ function findAllowedMethods(routes, path12) {
3347
3487
  const methods = /* @__PURE__ */ new Set();
3348
3488
  for (const route of routes) {
3349
- if (route.urlPath === path11) {
3489
+ if (route.urlPath === path12) {
3350
3490
  methods.add(route.method);
3351
3491
  continue;
3352
3492
  }
3353
3493
  if (route.isDynamic) {
3354
- const params = matchDynamicPath(route.urlPath, path11, route.paramNames, route.isCatchAll);
3494
+ const params = matchDynamicPath(route.urlPath, path12, route.paramNames, route.isCatchAll);
3355
3495
  if (params !== null) {
3356
3496
  methods.add(route.method);
3357
3497
  }
@@ -3443,7 +3583,7 @@ function createRoutePipeline(opts) {
3443
3583
  const match = resolveRouteOrThrow(routes, method, urlPath);
3444
3584
  ctx.params = match.params;
3445
3585
  const { route } = match;
3446
- const absoluteFilePath = path9.resolve(rootDir, route.filePath);
3586
+ const absoluteFilePath = path10.resolve(rootDir, route.filePath);
3447
3587
  const routeModule = await loadRouteModule(absoluteFilePath, route.method, rootDir);
3448
3588
  const input = await resolveInput(route.method, request);
3449
3589
  const inputType = getInputTypeForMethod(route.method);
@@ -3530,7 +3670,7 @@ async function createTestServer(options) {
3530
3670
  } = options;
3531
3671
  const { routes, wsRoutes } = await scanRoutes(rootDir, patterns);
3532
3672
  const sorted = sortRoutes(routes);
3533
- const schemaDist = dist ? path10.isAbsolute(dist) ? dist : path10.resolve(rootDir, dist) : await fs9.mkdtemp(path10.join(os.tmpdir(), "faapi-test-schema-"));
3673
+ const schemaDist = dist ? path11.isAbsolute(dist) ? dist : path11.resolve(rootDir, dist) : await fs10.mkdtemp(path11.join(os.tmpdir(), "faapi-test-schema-"));
3534
3674
  await generateSchemaFiles(sorted, rootDir, schemaDist);
3535
3675
  const { server } = createServer({
3536
3676
  routes: sorted,
@@ -3563,7 +3703,7 @@ async function createTestServer(options) {
3563
3703
  await new Promise((resolve) => {
3564
3704
  server.close(() => resolve());
3565
3705
  });
3566
- await fs9.rm(schemaDist, { recursive: true, force: true }).catch(() => {
3706
+ await fs10.rm(schemaDist, { recursive: true, force: true }).catch(() => {
3567
3707
  });
3568
3708
  invalidateSchemaCache();
3569
3709
  }