@faapi/faapi 3.1.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)) {
@@ -590,18 +590,11 @@ function queryToObject(params) {
590
590
  return result;
591
591
  }
592
592
 
593
- // src/injection/skillRegistry.ts
594
- var registry = /* @__PURE__ */ new Map();
595
- function listSkills() {
596
- return Array.from(registry.values());
597
- }
598
-
599
593
  // src/injection/agentRegistry.ts
600
- var registry2 = /* @__PURE__ */ new Map();
594
+ var registry = /* @__PURE__ */ new Map();
601
595
  function listAgents() {
602
596
  const merged = /* @__PURE__ */ new Map();
603
- for (const agent of registry2.values()) merged.set(agent.name, agent);
604
- for (const skill of listSkills()) merged.set(skill.name, skill);
597
+ for (const agent of registry.values()) merged.set(agent.name, agent);
605
598
  return Array.from(merged.values());
606
599
  }
607
600
 
@@ -763,9 +756,9 @@ async function invokeHandler(handler, ctx, body, middlewares, injectors) {
763
756
  }
764
757
 
765
758
  // src/testServer.ts
766
- import path10 from "path";
759
+ import path11 from "path";
767
760
  import os from "os";
768
- import fs9 from "fs/promises";
761
+ import fs10 from "fs/promises";
769
762
 
770
763
  // src/router/scanRoutes.ts
771
764
  import fg from "fast-glob";
@@ -777,9 +770,9 @@ var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
777
770
  var HTTP_METHOD_SET = new Set(HTTP_METHODS);
778
771
 
779
772
  // src/utils/normalizePath.ts
780
- function normalizePath(path11) {
781
- if (!path11) return "";
782
- let result = path11.replace(/\\/g, "/");
773
+ function normalizePath(path12) {
774
+ if (!path12) return "";
775
+ let result = path12.replace(/\\/g, "/");
783
776
  result = result.replace(/\/+/g, "/");
784
777
  result = result.replace(/\/+$/, "");
785
778
  if (result && !result.startsWith("/")) {
@@ -1052,25 +1045,93 @@ function sortRoutes(routes) {
1052
1045
  }
1053
1046
 
1054
1047
  // src/cli/generateSchemaFiles.ts
1055
- import path3 from "path";
1056
- import fs2 from "fs/promises";
1048
+ import path4 from "path";
1049
+ import fs3 from "fs/promises";
1057
1050
 
1058
1051
  // src/ast/createProgram.ts
1059
1052
  import ts2 from "typescript";
1053
+ import fs2 from "fs";
1054
+ import path2 from "path";
1060
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
+ }
1061
1103
  function createProgram(filePath) {
1062
1104
  const cached = programCache.get(filePath);
1063
1105
  if (cached) {
1064
1106
  return cached;
1065
1107
  }
1066
- const program = ts2.createProgram([filePath], {
1108
+ const options = {
1067
1109
  strict: true,
1068
1110
  target: ts2.ScriptTarget.ES2022,
1069
1111
  module: ts2.ModuleKind.NodeNext,
1070
1112
  moduleResolution: ts2.ModuleResolutionKind.NodeNext,
1071
1113
  skipLibCheck: true,
1072
1114
  noEmit: true
1073
- });
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);
1074
1135
  programCache.set(filePath, program);
1075
1136
  return program;
1076
1137
  }
@@ -1080,6 +1141,10 @@ import ts4 from "typescript";
1080
1141
 
1081
1142
  // src/ast/resolveTypeNode.ts
1082
1143
  import ts3 from "typescript";
1144
+ var currentProgram = null;
1145
+ function setProgramContext(program) {
1146
+ currentProgram = program;
1147
+ }
1083
1148
  var SchemaExtractionError = class extends Error {
1084
1149
  constructor(typeText, reason, options) {
1085
1150
  super(`\u65E0\u6CD5\u89E3\u6790\u7C7B\u578B "${typeText}": ${reason}`, options);
@@ -1402,11 +1467,69 @@ function resolveTypeReference(typeNode, checker, visited = /* @__PURE__ */ new S
1402
1467
  if (ts3.isEnumDeclaration(declaration)) {
1403
1468
  return resolveEnumDeclaration(declaration);
1404
1469
  }
1470
+ if (ts3.isImportSpecifier(declaration) || ts3.isImportClause(declaration)) {
1471
+ const resolved = resolveImportAlias(typeNode, symbol, checker, visited);
1472
+ if (resolved) return resolved;
1473
+ }
1405
1474
  }
1406
1475
  }
1407
1476
  }
1408
1477
  throw new SchemaExtractionError(typeNode.getText(), `\u65E0\u6CD5\u89E3\u6790\u7684\u5F15\u7528\u7C7B\u578B "${typeName}"`);
1409
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
+ }
1410
1533
  function resolveEnumDeclaration(node) {
1411
1534
  const members = [];
1412
1535
  let nextNumericValue = 0;
@@ -1611,80 +1734,90 @@ function extractTypeInfo(program, filePath, typeName) {
1611
1734
  const sourceFile = program.getSourceFile(filePath);
1612
1735
  if (!sourceFile) return null;
1613
1736
  const checker = program.getTypeChecker();
1614
- let result = null;
1615
- ts4.forEachChild(sourceFile, (node) => {
1616
- if (result) return;
1617
- if (ts4.isInterfaceDeclaration(node) && node.name.text === typeName) {
1618
- const visited = /* @__PURE__ */ new Set();
1619
- visited.add(typeName);
1620
- const runtimeType = withFileContext(
1621
- filePath,
1622
- typeName,
1623
- () => resolveInterfaceDeclaration(node, checker, visited)
1624
- );
1625
- result = {
1626
- name: typeName,
1627
- properties: runtimeType.kind === "object" ? runtimeType.properties : [],
1628
- runtimeType
1629
- };
1630
- return;
1631
- }
1632
- if (ts4.isTypeAliasDeclaration(node) && node.name.text === typeName) {
1633
- const visited = /* @__PURE__ */ new Set();
1634
- visited.add(typeName);
1635
- const runtimeType = withFileContext(
1636
- filePath,
1637
- typeName,
1638
- () => resolveTypeNode(node.type, checker, visited)
1639
- );
1640
- result = {
1641
- name: typeName,
1642
- properties: runtimeType.kind === "object" ? runtimeType.properties : [],
1643
- runtimeType
1644
- };
1645
- return;
1646
- }
1647
- });
1648
- 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
+ }
1649
1777
  }
1650
1778
  function extractAllTypes(program, filePath) {
1651
1779
  const sourceFile = program.getSourceFile(filePath);
1652
1780
  if (!sourceFile) return /* @__PURE__ */ new Map();
1653
1781
  const checker = program.getTypeChecker();
1654
- const result = /* @__PURE__ */ new Map();
1655
- ts4.forEachChild(sourceFile, (node) => {
1656
- if (ts4.isInterfaceDeclaration(node)) {
1657
- const visited = /* @__PURE__ */ new Set();
1658
- visited.add(node.name.text);
1659
- const runtimeType = withFileContext(
1660
- filePath,
1661
- node.name.text,
1662
- () => resolveInterfaceDeclaration(node, checker, visited)
1663
- );
1664
- result.set(node.name.text, {
1665
- name: node.name.text,
1666
- properties: runtimeType.kind === "object" ? runtimeType.properties : [],
1667
- runtimeType
1668
- });
1669
- return;
1670
- }
1671
- if (ts4.isTypeAliasDeclaration(node)) {
1672
- const visited = /* @__PURE__ */ new Set();
1673
- visited.add(node.name.text);
1674
- const runtimeType = withFileContext(
1675
- filePath,
1676
- node.name.text,
1677
- () => resolveTypeNode(node.type, checker, visited)
1678
- );
1679
- result.set(node.name.text, {
1680
- name: node.name.text,
1681
- properties: runtimeType.kind === "object" ? runtimeType.properties : [],
1682
- runtimeType
1683
- });
1684
- return;
1685
- }
1686
- });
1687
- 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
+ }
1688
1821
  }
1689
1822
  function withFileContext(filePath, typeName, fn) {
1690
1823
  try {
@@ -1767,11 +1900,11 @@ function extractSchema(typeNode, sourceFile) {
1767
1900
  }
1768
1901
 
1769
1902
  // src/cli/collectRouteSchemaSources.ts
1770
- import path2 from "path";
1903
+ import path3 from "path";
1771
1904
  function collectRouteSchemaSources(routes, rootDir) {
1772
1905
  const methodsByFile = /* @__PURE__ */ new Map();
1773
1906
  for (const route of routes) {
1774
- const filePath = rootDir ? path2.resolve(rootDir, route.filePath) : route.filePath;
1907
+ const filePath = rootDir ? path3.resolve(rootDir, route.filePath) : route.filePath;
1775
1908
  let entry = methodsByFile.get(filePath);
1776
1909
  if (!entry) {
1777
1910
  entry = { urlPath: route.urlPath, methods: /* @__PURE__ */ new Set() };
@@ -2122,7 +2255,7 @@ function getSchemaOutputPath(sourceFile, dist, rootDir) {
2122
2255
  }
2123
2256
  const idx = rel.lastIndexOf("/");
2124
2257
  const relDir = idx >= 0 ? rel.slice(0, idx) : "";
2125
- return path3.resolve(rootDir, dist, relDir, "zod.js");
2258
+ return path4.resolve(rootDir, dist, relDir, "zod.js");
2126
2259
  }
2127
2260
  function getRuntimeSchemaPath(filePath, dist, rootDir) {
2128
2261
  let rel = filePath.replace(/\\/g, "/");
@@ -2133,7 +2266,7 @@ function getRuntimeSchemaPath(filePath, dist, rootDir) {
2133
2266
  }
2134
2267
  const idx = rel.lastIndexOf("/");
2135
2268
  const relDir = idx >= 0 ? rel.slice(0, idx) : "";
2136
- return path3.resolve(rootDir, dist, relDir, "zod.js");
2269
+ return path4.resolve(rootDir, dist, relDir, "zod.js");
2137
2270
  }
2138
2271
  function getHelpersImportPath(relDir) {
2139
2272
  if (!relDir) return `./${HELPERS_FILENAME}`;
@@ -2183,7 +2316,7 @@ async function generateSchemaFiles(routes, rootDir, dist) {
2183
2316
  }
2184
2317
  const fileEntries = [];
2185
2318
  for (const [filePath, fileSources] of sourcesByFile) {
2186
- const relFile = path3.relative(rootDir, filePath).replace(/\\/g, "/");
2319
+ const relFile = path4.relative(rootDir, filePath).replace(/\\/g, "/");
2187
2320
  const outputPath = getSchemaOutputPath(relFile, dist, rootDir);
2188
2321
  const allTypes = allTypesByFile.get(filePath) ?? /* @__PURE__ */ new Map();
2189
2322
  let relForDir = relFile;
@@ -2198,7 +2331,7 @@ async function generateSchemaFiles(routes, rootDir, dist) {
2198
2331
  }
2199
2332
  const allSourceCode = fileEntries.map((e) => e.source).join("\n");
2200
2333
  if (usesCoerceHelpers(allSourceCode)) {
2201
- const helpersPath = path3.resolve(rootDir, dist, HELPERS_FILENAME);
2334
+ const helpersPath = path4.resolve(rootDir, dist, HELPERS_FILENAME);
2202
2335
  await writeSchemaFile(helpersPath, generateHelpersFileSource());
2203
2336
  }
2204
2337
  await Promise.all(
@@ -2206,22 +2339,22 @@ async function generateSchemaFiles(routes, rootDir, dist) {
2206
2339
  );
2207
2340
  }
2208
2341
  async function writeSchemaFile(outputPath, source) {
2209
- await fs2.mkdir(path3.dirname(outputPath), { recursive: true });
2210
- await fs2.writeFile(outputPath, source, "utf-8");
2342
+ await fs3.mkdir(path4.dirname(outputPath), { recursive: true });
2343
+ await fs3.writeFile(outputPath, source, "utf-8");
2211
2344
  }
2212
2345
 
2213
2346
  // src/cli/compileOnDemand.ts
2214
- import path7 from "path";
2215
- import fs6 from "fs";
2347
+ import path8 from "path";
2348
+ import fs7 from "fs";
2216
2349
 
2217
2350
  // src/cli/compileDevRoutes.ts
2218
- import path6 from "path";
2219
- import fs5 from "fs";
2351
+ import path7 from "path";
2352
+ import fs6 from "fs";
2220
2353
  import fg2 from "fast-glob";
2221
2354
 
2222
2355
  // src/cli/aliasPlugin.ts
2223
- import path5 from "path";
2224
- import fs4 from "fs";
2356
+ import path6 from "path";
2357
+ import fs5 from "fs";
2225
2358
 
2226
2359
  // src/utils/resolveAlias.ts
2227
2360
  function resolveAlias(specifier, config) {
@@ -2248,11 +2381,11 @@ function resolveAlias(specifier, config) {
2248
2381
 
2249
2382
  // src/utils/readTsconfig.ts
2250
2383
  import ts6 from "typescript";
2251
- import path4 from "path";
2252
- import fs3 from "fs";
2384
+ import path5 from "path";
2385
+ import fs4 from "fs";
2253
2386
  function readTsconfig(rootDir) {
2254
- const tsconfigPath = path4.resolve(rootDir, "tsconfig.json");
2255
- if (!fs3.existsSync(tsconfigPath)) return null;
2387
+ const tsconfigPath = path5.resolve(rootDir, "tsconfig.json");
2388
+ if (!fs4.existsSync(tsconfigPath)) return null;
2256
2389
  const configFile = ts6.readConfigFile(tsconfigPath, ts6.sys.readFile);
2257
2390
  if (configFile.error || !configFile.config) return null;
2258
2391
  const parsed = ts6.parseJsonConfigFileContent(configFile.config, ts6.sys, rootDir);
@@ -2261,7 +2394,7 @@ function readTsconfig(rootDir) {
2261
2394
  if (!rawPaths) return null;
2262
2395
  const paths = {};
2263
2396
  for (const [pattern, targets] of Object.entries(rawPaths)) {
2264
- paths[pattern] = targets.map((t) => path4.resolve(baseUrl, t));
2397
+ paths[pattern] = targets.map((t) => path5.resolve(baseUrl, t));
2265
2398
  }
2266
2399
  return { baseUrl, paths };
2267
2400
  }
@@ -2274,29 +2407,29 @@ function toProdExtension(filePath) {
2274
2407
  return filePath;
2275
2408
  }
2276
2409
  function toProdImportPath(sourceFile, importer) {
2277
- const importerDir = path5.dirname(importer);
2278
- let rel = path5.relative(importerDir, sourceFile);
2279
- 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("/");
2280
2413
  if (!rel.startsWith(".")) rel = "./" + rel;
2281
2414
  return toProdExtension(rel);
2282
2415
  }
2283
2416
  function toRealPath(p) {
2284
2417
  try {
2285
- return fs4.realpathSync(p);
2418
+ return fs5.realpathSync(p);
2286
2419
  } catch {
2287
2420
  return p;
2288
2421
  }
2289
2422
  }
2290
2423
  function isInsideDir(filePath, dir) {
2291
- const rel = path5.relative(dir, filePath);
2292
- return rel !== "" && !rel.startsWith("..") && !path5.isAbsolute(rel);
2424
+ const rel = path6.relative(dir, filePath);
2425
+ return rel !== "" && !rel.startsWith("..") && !path6.isAbsolute(rel);
2293
2426
  }
2294
2427
  var APP_DIR = "src";
2295
2428
  function toStrippedProdImportPath(sourceFile, rootDir) {
2296
- const appDirAbs = toRealPath(path5.resolve(rootDir, APP_DIR));
2429
+ const appDirAbs = toRealPath(path6.resolve(rootDir, APP_DIR));
2297
2430
  const sourceReal = toRealPath(sourceFile);
2298
- let rel = path5.relative(appDirAbs, sourceReal);
2299
- rel = rel.split(path5.sep).join("/");
2431
+ let rel = path6.relative(appDirAbs, sourceReal);
2432
+ rel = rel.split(path6.sep).join("/");
2300
2433
  if (!rel.startsWith(".")) rel = "./" + rel;
2301
2434
  return toProdExtension(rel);
2302
2435
  }
@@ -2311,34 +2444,34 @@ var INDEX_EXTS = [
2311
2444
  "/index.cjs"
2312
2445
  ];
2313
2446
  function resolveRelativeSpecifier(importer, specifier) {
2314
- const importerDir = path5.dirname(importer);
2315
- const base = path5.resolve(importerDir, specifier);
2447
+ const importerDir = path6.dirname(importer);
2448
+ const base = path6.resolve(importerDir, specifier);
2316
2449
  if (PROD_EXTS.some((ext) => specifier.endsWith(ext))) {
2317
- return fs4.existsSync(base) ? base : null;
2450
+ return fs5.existsSync(base) ? base : null;
2318
2451
  }
2319
2452
  if (/\.(ts|tsx|jsx)$/.test(specifier)) {
2320
- return fs4.existsSync(base) ? base : null;
2453
+ return fs5.existsSync(base) ? base : null;
2321
2454
  }
2322
2455
  for (const ext of SOURCE_EXTS) {
2323
2456
  const file = base + ext;
2324
- if (fs4.existsSync(file)) return file;
2457
+ if (fs5.existsSync(file)) return file;
2325
2458
  }
2326
2459
  for (const indexExt of INDEX_EXTS) {
2327
2460
  const file = base + indexExt;
2328
- if (fs4.existsSync(file)) return file;
2461
+ if (fs5.existsSync(file)) return file;
2329
2462
  }
2330
2463
  return null;
2331
2464
  }
2332
2465
  function createAliasPlugin(config, options) {
2333
2466
  const SPEC_RE = /(\bfrom\s*|import\s*\(\s*)(['"])([^'"]+)\2/g;
2334
- 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;
2335
2468
  return {
2336
2469
  name: "faapi-alias",
2337
2470
  setup(build) {
2338
2471
  build.onLoad({ filter: /\.(ts|tsx|js|jsx|mjs|cjs)$/ }, (args) => {
2339
2472
  let source;
2340
2473
  try {
2341
- source = fs4.readFileSync(args.path, "utf8");
2474
+ source = fs5.readFileSync(args.path, "utf8");
2342
2475
  } catch {
2343
2476
  return void 0;
2344
2477
  }
@@ -2371,7 +2504,7 @@ function createAliasPlugin(config, options) {
2371
2504
  for (const candidate of candidates) {
2372
2505
  for (const ext of SOURCE_EXTS) {
2373
2506
  const file = candidate + ext;
2374
- if (fs4.existsSync(file)) {
2507
+ if (fs5.existsSync(file)) {
2375
2508
  modified = true;
2376
2509
  if (appDirAbs && importerOutsideAppDir && isInsideDir(file, appDirAbs)) {
2377
2510
  return `${prefix}${quote}${toStrippedProdImportPath(
@@ -2384,7 +2517,7 @@ function createAliasPlugin(config, options) {
2384
2517
  }
2385
2518
  for (const indexExt of INDEX_EXTS) {
2386
2519
  const file = candidate + indexExt;
2387
- if (fs4.existsSync(file)) {
2520
+ if (fs5.existsSync(file)) {
2388
2521
  modified = true;
2389
2522
  if (appDirAbs && importerOutsideAppDir && isInsideDir(file, appDirAbs)) {
2390
2523
  return `${prefix}${quote}${toStrippedProdImportPath(
@@ -2422,11 +2555,11 @@ async function compileDevRoutes(options) {
2422
2555
  if (entryPoints.length === 0) {
2423
2556
  return { compiledFiles: [] };
2424
2557
  }
2425
- const absDist = path6.resolve(rootDir, dist);
2426
- await fs5.promises.mkdir(absDist, { recursive: true });
2558
+ const absDist = path7.resolve(rootDir, dist);
2559
+ await fs6.promises.mkdir(absDist, { recursive: true });
2427
2560
  const plugins = buildAliasPlugins(rootDir);
2428
2561
  const esbuild = await import("esbuild");
2429
- const outbase = path6.resolve(rootDir, APP_DIR2);
2562
+ const outbase = path7.resolve(rootDir, APP_DIR2);
2430
2563
  const result = await esbuild.build({
2431
2564
  entryPoints,
2432
2565
  outdir: absDist,
@@ -2443,10 +2576,10 @@ async function compileDevRoutes(options) {
2443
2576
  if (result.outputFiles) {
2444
2577
  await Promise.all(
2445
2578
  result.outputFiles.map(async (file) => {
2446
- await fs5.promises.mkdir(path6.dirname(file.path), { recursive: true });
2579
+ await fs6.promises.mkdir(path7.dirname(file.path), { recursive: true });
2447
2580
  const tmp = `${file.path}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
2448
- await fs5.promises.writeFile(tmp, file.contents);
2449
- await fs5.promises.rename(tmp, file.path);
2581
+ await fs6.promises.writeFile(tmp, file.contents);
2582
+ await fs6.promises.rename(tmp, file.path);
2450
2583
  })
2451
2584
  );
2452
2585
  }
@@ -2456,8 +2589,8 @@ async function compileDevRoutes(options) {
2456
2589
  // src/cli/compileOnDemand.ts
2457
2590
  function isProductFresh(sourceAbsPath, productAbsPath) {
2458
2591
  try {
2459
- const srcStat = fs6.statSync(sourceAbsPath);
2460
- const prodStat = fs6.statSync(productAbsPath);
2592
+ const srcStat = fs7.statSync(sourceAbsPath);
2593
+ const prodStat = fs7.statSync(productAbsPath);
2461
2594
  return prodStat.mtimeMs >= srcStat.mtimeMs;
2462
2595
  } catch {
2463
2596
  return false;
@@ -2484,7 +2617,7 @@ async function ensureCompiled(sourceAbsPath, rootDir, dist) {
2484
2617
  if (state.compiledFiles.has(sourceAbsPath)) {
2485
2618
  return false;
2486
2619
  }
2487
- if (!fs6.existsSync(sourceAbsPath)) {
2620
+ if (!fs7.existsSync(sourceAbsPath)) {
2488
2621
  return false;
2489
2622
  }
2490
2623
  const productPath = prodSourcePathToProductPath(sourceAbsPath, rootDir, dist);
@@ -2510,11 +2643,11 @@ async function ensureCompiled(sourceAbsPath, rootDir, dist) {
2510
2643
  }
2511
2644
  }
2512
2645
  function prodSourcePathToProductPath(sourceAbsPath, rootDir, dist) {
2513
- const rel = path7.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
2646
+ const rel = path8.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
2514
2647
  if (!rel.startsWith("src/")) return null;
2515
2648
  const relWithoutSrc = rel.slice(4);
2516
2649
  const jsRel = relWithoutSrc.replace(/\.ts$/, ".js");
2517
- return path7.resolve(rootDir, dist, jsRel);
2650
+ return path8.resolve(rootDir, dist, jsRel);
2518
2651
  }
2519
2652
  async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir, dist) {
2520
2653
  const inFlight = state.inFlightSchemaGenerations.get(schemaPath);
@@ -2526,9 +2659,9 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
2526
2659
  if (state.generatedSchemas.has(schemaPath)) {
2527
2660
  return false;
2528
2661
  }
2529
- const prodAbsPath = path7.resolve(rootDir, routeFilePath);
2662
+ const prodAbsPath = path8.resolve(rootDir, routeFilePath);
2530
2663
  const sourceAbsPath = prodPathToSourcePath(prodAbsPath, rootDir, dist);
2531
- if (!fs6.existsSync(sourceAbsPath)) {
2664
+ if (!fs7.existsSync(sourceAbsPath)) {
2532
2665
  return false;
2533
2666
  }
2534
2667
  if (isProductFresh(sourceAbsPath, schemaPath)) {
@@ -2539,7 +2672,7 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
2539
2672
  if (fileRoutes.length === 0) {
2540
2673
  return false;
2541
2674
  }
2542
- const sourceRelPath = path7.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
2675
+ const sourceRelPath = path8.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
2543
2676
  const sourceRoutes = fileRoutes.map((r) => ({ ...r, filePath: sourceRelPath }));
2544
2677
  const generatePromise = (async () => {
2545
2678
  await generateSchemaFiles(sourceRoutes, rootDir, dist);
@@ -2554,16 +2687,16 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
2554
2687
  }
2555
2688
  }
2556
2689
  function prodPathToSourcePath(prodAbsPath, rootDir, dist) {
2557
- const rel = path7.relative(rootDir, prodAbsPath).replace(/\\/g, "/");
2690
+ const rel = path8.relative(rootDir, prodAbsPath).replace(/\\/g, "/");
2558
2691
  let relWithoutDist = rel;
2559
2692
  if (relWithoutDist.startsWith(`${dist}/`)) {
2560
2693
  relWithoutDist = relWithoutDist.slice(dist.length + 1);
2561
2694
  }
2562
2695
  const srcRel = `src/${relWithoutDist}`;
2563
2696
  const tsRel = srcRel.replace(/\.js$/, ".ts");
2564
- const tsAbs = path7.resolve(rootDir, tsRel);
2565
- if (fs6.existsSync(tsAbs)) return tsAbs;
2566
- 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);
2567
2700
  }
2568
2701
  function isDevOnDemandEnabled() {
2569
2702
  return state.enabled;
@@ -2616,9 +2749,9 @@ async function validateInput(schemaPath, method, inputType, input) {
2616
2749
  function mapZodIssues(error) {
2617
2750
  return error.issues.map((issue) => {
2618
2751
  const code = mapZodCode(issue.code, issue.message);
2619
- const path11 = issue.path.map(String).join(".") || "";
2752
+ const path12 = issue.path.map(String).join(".") || "";
2620
2753
  return {
2621
- path: path11,
2754
+ path: path12,
2622
2755
  code,
2623
2756
  expected: issue.expected ?? mapExpectedFromMessage(issue.message),
2624
2757
  received: issue.received ?? mapReceivedFromMessage(issue.message),
@@ -2666,45 +2799,45 @@ import {
2666
2799
  import { createSecureServer as createHttp2SecureServer } from "http2";
2667
2800
  import { readFileSync } from "fs";
2668
2801
  import { Readable as Readable2 } from "stream";
2669
- import path9 from "path";
2802
+ import path10 from "path";
2670
2803
 
2671
2804
  // src/router/matchRoute.ts
2672
- function matchRoute(routes, method, path11) {
2805
+ function matchRoute(routes, method, path12) {
2673
2806
  for (const route of routes) {
2674
2807
  if (route.method !== method) {
2675
2808
  continue;
2676
2809
  }
2677
2810
  if (!route.isDynamic) {
2678
- if (route.urlPath === path11) {
2811
+ if (route.urlPath === path12) {
2679
2812
  return { route, params: {} };
2680
2813
  }
2681
2814
  continue;
2682
2815
  }
2683
- const params = matchDynamicPath(route.urlPath, path11, route.paramNames, route.isCatchAll);
2816
+ const params = matchDynamicPath(route.urlPath, path12, route.paramNames, route.isCatchAll);
2684
2817
  if (params !== null) {
2685
2818
  return { route, params };
2686
2819
  }
2687
2820
  }
2688
2821
  return null;
2689
2822
  }
2690
- function matchWsRoute(wsRoutes, path11) {
2823
+ function matchWsRoute(wsRoutes, path12) {
2691
2824
  for (const route of wsRoutes) {
2692
2825
  if (!route.isDynamic) {
2693
- if (route.urlPath === path11) {
2826
+ if (route.urlPath === path12) {
2694
2827
  return { route, params: {} };
2695
2828
  }
2696
2829
  continue;
2697
2830
  }
2698
- const params = matchDynamicPath(route.urlPath, path11, route.paramNames, route.isCatchAll);
2831
+ const params = matchDynamicPath(route.urlPath, path12, route.paramNames, route.isCatchAll);
2699
2832
  if (params !== null) {
2700
2833
  return { route, params };
2701
2834
  }
2702
2835
  }
2703
2836
  return null;
2704
2837
  }
2705
- function matchDynamicPath(pattern, path11, paramNames, isCatchAll) {
2838
+ function matchDynamicPath(pattern, path12, paramNames, isCatchAll) {
2706
2839
  const patternSegments = pattern.split("/").filter(Boolean);
2707
- const pathSegments = path11.split("/").filter(Boolean);
2840
+ const pathSegments = path12.split("/").filter(Boolean);
2708
2841
  if (isCatchAll) {
2709
2842
  const nonCatchAllCount = patternSegments.length - 1;
2710
2843
  if (pathSegments.length <= nonCatchAllCount) {
@@ -2750,7 +2883,7 @@ function matchDynamicPath(pattern, path11, paramNames, isCatchAll) {
2750
2883
  }
2751
2884
 
2752
2885
  // src/loader/loadRouteModule.ts
2753
- import fs7 from "fs";
2886
+ import fs8 from "fs";
2754
2887
 
2755
2888
  // src/loader/resolveExports.ts
2756
2889
  function resolveExport(module, exportName) {
@@ -2782,7 +2915,7 @@ async function loadRouteModule(filePath, method, rootDir) {
2782
2915
  const dist = getDevDist();
2783
2916
  if (dist) {
2784
2917
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
2785
- if (sourcePath && fs7.existsSync(sourcePath)) {
2918
+ if (sourcePath && fs8.existsSync(sourcePath)) {
2786
2919
  try {
2787
2920
  await ensureCompiled(sourcePath, rootDir, dist);
2788
2921
  } catch (compileErr) {
@@ -3088,9 +3221,9 @@ function logger(options = {}) {
3088
3221
  }
3089
3222
 
3090
3223
  // src/server/handleWsUpgrade.ts
3091
- import fs8 from "fs";
3224
+ import fs9 from "fs";
3092
3225
  import { WebSocketServer, WebSocket } from "ws";
3093
- import path8 from "path";
3226
+ import path9 from "path";
3094
3227
 
3095
3228
  // src/server/serverUtils.ts
3096
3229
  function nodeHttpToWebHeaders(req) {
@@ -3146,7 +3279,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
3146
3279
  const dist = getDevDist();
3147
3280
  if (dist) {
3148
3281
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
3149
- if (sourcePath && fs8.existsSync(sourcePath)) {
3282
+ if (sourcePath && fs9.existsSync(sourcePath)) {
3150
3283
  await ensureCompiled(sourcePath, rootDir, dist);
3151
3284
  }
3152
3285
  }
@@ -3226,7 +3359,7 @@ function attachWebSocket(options) {
3226
3359
  const finalHandler = async () => {
3227
3360
  let handlers;
3228
3361
  try {
3229
- const absoluteFilePath = path8.resolve(rootDir, route.filePath);
3362
+ const absoluteFilePath = path9.resolve(rootDir, route.filePath);
3230
3363
  handlers = await loadWsHandler(absoluteFilePath, ctx, rootDir);
3231
3364
  } catch (err) {
3232
3365
  const reason = err instanceof Error ? err.message : String(err);
@@ -3350,15 +3483,15 @@ function limitStreamSize(stream, maxSize) {
3350
3483
  }
3351
3484
  });
3352
3485
  }
3353
- function findAllowedMethods(routes, path11) {
3486
+ function findAllowedMethods(routes, path12) {
3354
3487
  const methods = /* @__PURE__ */ new Set();
3355
3488
  for (const route of routes) {
3356
- if (route.urlPath === path11) {
3489
+ if (route.urlPath === path12) {
3357
3490
  methods.add(route.method);
3358
3491
  continue;
3359
3492
  }
3360
3493
  if (route.isDynamic) {
3361
- const params = matchDynamicPath(route.urlPath, path11, route.paramNames, route.isCatchAll);
3494
+ const params = matchDynamicPath(route.urlPath, path12, route.paramNames, route.isCatchAll);
3362
3495
  if (params !== null) {
3363
3496
  methods.add(route.method);
3364
3497
  }
@@ -3450,7 +3583,7 @@ function createRoutePipeline(opts) {
3450
3583
  const match = resolveRouteOrThrow(routes, method, urlPath);
3451
3584
  ctx.params = match.params;
3452
3585
  const { route } = match;
3453
- const absoluteFilePath = path9.resolve(rootDir, route.filePath);
3586
+ const absoluteFilePath = path10.resolve(rootDir, route.filePath);
3454
3587
  const routeModule = await loadRouteModule(absoluteFilePath, route.method, rootDir);
3455
3588
  const input = await resolveInput(route.method, request);
3456
3589
  const inputType = getInputTypeForMethod(route.method);
@@ -3537,7 +3670,7 @@ async function createTestServer(options) {
3537
3670
  } = options;
3538
3671
  const { routes, wsRoutes } = await scanRoutes(rootDir, patterns);
3539
3672
  const sorted = sortRoutes(routes);
3540
- 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-"));
3541
3674
  await generateSchemaFiles(sorted, rootDir, schemaDist);
3542
3675
  const { server } = createServer({
3543
3676
  routes: sorted,
@@ -3570,7 +3703,7 @@ async function createTestServer(options) {
3570
3703
  await new Promise((resolve) => {
3571
3704
  server.close(() => resolve());
3572
3705
  });
3573
- await fs9.rm(schemaDist, { recursive: true, force: true }).catch(() => {
3706
+ await fs10.rm(schemaDist, { recursive: true, force: true }).catch(() => {
3574
3707
  });
3575
3708
  invalidateSchemaCache();
3576
3709
  }