@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/index.js CHANGED
@@ -10,35 +10,107 @@ var __export = (target, all) => {
10
10
 
11
11
  // src/ast/createProgram.ts
12
12
  import ts from "typescript";
13
+ import fs from "fs";
14
+ import path from "path";
13
15
  function invalidateProgramCache() {
14
16
  programCache.clear();
17
+ tsConfigCache.clear();
18
+ }
19
+ function findTsConfig(filePath) {
20
+ let dir = path.dirname(filePath);
21
+ const root = path.parse(dir).root;
22
+ while (true) {
23
+ const candidate = path.join(dir, "tsconfig.json");
24
+ if (fs.existsSync(candidate)) {
25
+ return candidate;
26
+ }
27
+ if (dir === root) return null;
28
+ const parent = path.dirname(dir);
29
+ if (parent === dir) return null;
30
+ dir = parent;
31
+ }
32
+ }
33
+ function parseTsConfig(tsconfigPath) {
34
+ const cached = tsConfigCache.get(tsconfigPath);
35
+ if (cached) return cached;
36
+ const result = { fileNames: [] };
37
+ try {
38
+ const configFile = ts.readConfigFile(tsconfigPath, (p) => fs.readFileSync(p, "utf-8"));
39
+ if (configFile.error) {
40
+ tsConfigCache.set(tsconfigPath, result);
41
+ return result;
42
+ }
43
+ const config = configFile.config ?? {};
44
+ const basePath = path.dirname(tsconfigPath);
45
+ const parsed = ts.parseJsonConfigFileContent(
46
+ config,
47
+ ts.sys,
48
+ basePath,
49
+ /* existingOptions */
50
+ void 0,
51
+ tsconfigPath
52
+ );
53
+ result.fileNames = parsed.fileNames;
54
+ if (parsed.options.module !== void 0) {
55
+ result.module = parsed.options.module;
56
+ }
57
+ if (parsed.options.moduleResolution !== void 0) {
58
+ result.moduleResolution = parsed.options.moduleResolution;
59
+ }
60
+ } catch {
61
+ }
62
+ tsConfigCache.set(tsconfigPath, result);
63
+ return result;
15
64
  }
16
65
  function createProgram(filePath) {
17
66
  const cached = programCache.get(filePath);
18
67
  if (cached) {
19
68
  return cached;
20
69
  }
21
- const program = ts.createProgram([filePath], {
70
+ const options = {
22
71
  strict: true,
23
72
  target: ts.ScriptTarget.ES2022,
24
73
  module: ts.ModuleKind.NodeNext,
25
74
  moduleResolution: ts.ModuleResolutionKind.NodeNext,
26
75
  skipLibCheck: true,
27
76
  noEmit: true
28
- });
77
+ };
78
+ let rootNames = [filePath];
79
+ const tsconfigPath = findTsConfig(filePath);
80
+ if (tsconfigPath) {
81
+ const tsOptions = parseTsConfig(tsconfigPath);
82
+ if (tsOptions.module !== void 0) {
83
+ options.module = tsOptions.module;
84
+ }
85
+ if (tsOptions.moduleResolution !== void 0) {
86
+ options.moduleResolution = tsOptions.moduleResolution;
87
+ }
88
+ if (tsOptions.fileNames.length > 0) {
89
+ if (!tsOptions.fileNames.includes(filePath)) {
90
+ rootNames = [filePath, ...tsOptions.fileNames];
91
+ } else {
92
+ rootNames = tsOptions.fileNames;
93
+ }
94
+ }
95
+ }
96
+ const program = ts.createProgram(rootNames, options);
29
97
  programCache.set(filePath, program);
30
98
  return program;
31
99
  }
32
- var programCache;
100
+ var programCache, tsConfigCache;
33
101
  var init_createProgram = __esm({
34
102
  "src/ast/createProgram.ts"() {
35
103
  "use strict";
36
104
  programCache = /* @__PURE__ */ new Map();
105
+ tsConfigCache = /* @__PURE__ */ new Map();
37
106
  }
38
107
  });
39
108
 
40
109
  // src/ast/resolveTypeNode.ts
41
110
  import ts2 from "typescript";
111
+ function setProgramContext(program) {
112
+ currentProgram = program;
113
+ }
42
114
  function resolveTypeNode(typeNode, checker, visited = /* @__PURE__ */ new Set()) {
43
115
  const kind = typeNode.kind;
44
116
  switch (kind) {
@@ -351,11 +423,69 @@ function resolveTypeReference(typeNode, checker, visited = /* @__PURE__ */ new S
351
423
  if (ts2.isEnumDeclaration(declaration)) {
352
424
  return resolveEnumDeclaration(declaration);
353
425
  }
426
+ if (ts2.isImportSpecifier(declaration) || ts2.isImportClause(declaration)) {
427
+ const resolved = resolveImportAlias(typeNode, symbol, checker, visited);
428
+ if (resolved) return resolved;
429
+ }
354
430
  }
355
431
  }
356
432
  }
357
433
  throw new SchemaExtractionError(typeNode.getText(), `\u65E0\u6CD5\u89E3\u6790\u7684\u5F15\u7528\u7C7B\u578B "${typeName}"`);
358
434
  }
435
+ function resolveImportAlias(typeNode, symbol, checker, visited) {
436
+ const typeName = typeNode.typeName.getText();
437
+ try {
438
+ const aliased = checker.getAliasedSymbol(symbol);
439
+ if (aliased && aliased.declarations && aliased.declarations.length > 0) {
440
+ const decl = aliased.declarations[0];
441
+ if (ts2.isInterfaceDeclaration(decl)) {
442
+ return resolveInterfaceDeclaration(decl, checker, visited);
443
+ }
444
+ if (ts2.isTypeAliasDeclaration(decl)) {
445
+ return resolveTypeNode(decl.type, checker, visited);
446
+ }
447
+ if (ts2.isEnumDeclaration(decl)) {
448
+ return resolveEnumDeclaration(decl);
449
+ }
450
+ }
451
+ } catch {
452
+ }
453
+ const program = currentProgram;
454
+ if (!program) return null;
455
+ const allSFs = program.getSourceFiles();
456
+ for (const sourceFile of allSFs) {
457
+ if (sourceFile.fileName.includes("/node_modules/") || sourceFile.fileName.includes("typescript/lib/")) {
458
+ continue;
459
+ }
460
+ const found = findTopLevelDecl(sourceFile, typeName);
461
+ if (found) {
462
+ if (found.kind === "interface") {
463
+ return resolveInterfaceDeclaration(found.node, checker, visited);
464
+ }
465
+ if (found.kind === "typeAlias") {
466
+ return resolveTypeNode(found.node.type, checker, visited);
467
+ }
468
+ if (found.kind === "enum") {
469
+ return resolveEnumDeclaration(found.node);
470
+ }
471
+ }
472
+ }
473
+ return null;
474
+ }
475
+ function findTopLevelDecl(sourceFile, typeName) {
476
+ let found = null;
477
+ ts2.forEachChild(sourceFile, (node) => {
478
+ if (found) return;
479
+ if (ts2.isInterfaceDeclaration(node) && node.name.text === typeName) {
480
+ found = { kind: "interface", node };
481
+ } else if (ts2.isTypeAliasDeclaration(node) && node.name.text === typeName) {
482
+ found = { kind: "typeAlias", node };
483
+ } else if (ts2.isEnumDeclaration(node) && node.name.text === typeName) {
484
+ found = { kind: "enum", node };
485
+ }
486
+ });
487
+ return found;
488
+ }
359
489
  function resolveEnumDeclaration(node) {
360
490
  const members = [];
361
491
  let nextNumericValue = 0;
@@ -534,10 +664,11 @@ function validateConstraints(constraints, type, fieldName) {
534
664
  }
535
665
  }
536
666
  }
537
- var SchemaExtractionError, NUMBER_CONSTRAINT_KINDS, LENGTH_CONSTRAINT_KINDS, STRING_FORMAT_CONSTRAINT_KINDS;
667
+ var currentProgram, SchemaExtractionError, NUMBER_CONSTRAINT_KINDS, LENGTH_CONSTRAINT_KINDS, STRING_FORMAT_CONSTRAINT_KINDS;
538
668
  var init_resolveTypeNode = __esm({
539
669
  "src/ast/resolveTypeNode.ts"() {
540
670
  "use strict";
671
+ currentProgram = null;
541
672
  SchemaExtractionError = class extends Error {
542
673
  constructor(typeText, reason, options) {
543
674
  super(`\u65E0\u6CD5\u89E3\u6790\u7C7B\u578B "${typeText}": ${reason}`, options);
@@ -577,80 +708,90 @@ function extractTypeInfo(program, filePath, typeName) {
577
708
  const sourceFile = program.getSourceFile(filePath);
578
709
  if (!sourceFile) return null;
579
710
  const checker = program.getTypeChecker();
580
- let result = null;
581
- ts3.forEachChild(sourceFile, (node) => {
582
- if (result) return;
583
- if (ts3.isInterfaceDeclaration(node) && node.name.text === typeName) {
584
- const visited = /* @__PURE__ */ new Set();
585
- visited.add(typeName);
586
- const runtimeType = withFileContext(
587
- filePath,
588
- typeName,
589
- () => resolveInterfaceDeclaration(node, checker, visited)
590
- );
591
- result = {
592
- name: typeName,
593
- properties: runtimeType.kind === "object" ? runtimeType.properties : [],
594
- runtimeType
595
- };
596
- return;
597
- }
598
- if (ts3.isTypeAliasDeclaration(node) && node.name.text === typeName) {
599
- const visited = /* @__PURE__ */ new Set();
600
- visited.add(typeName);
601
- const runtimeType = withFileContext(
602
- filePath,
603
- typeName,
604
- () => resolveTypeNode(node.type, checker, visited)
605
- );
606
- result = {
607
- name: typeName,
608
- properties: runtimeType.kind === "object" ? runtimeType.properties : [],
609
- runtimeType
610
- };
611
- return;
612
- }
613
- });
614
- return result;
711
+ setProgramContext(program);
712
+ try {
713
+ let result = null;
714
+ ts3.forEachChild(sourceFile, (node) => {
715
+ if (result) return;
716
+ if (ts3.isInterfaceDeclaration(node) && node.name.text === typeName) {
717
+ const visited = /* @__PURE__ */ new Set();
718
+ visited.add(typeName);
719
+ const runtimeType = withFileContext(
720
+ filePath,
721
+ typeName,
722
+ () => resolveInterfaceDeclaration(node, checker, visited)
723
+ );
724
+ result = {
725
+ name: typeName,
726
+ properties: runtimeType.kind === "object" ? runtimeType.properties : [],
727
+ runtimeType
728
+ };
729
+ return;
730
+ }
731
+ if (ts3.isTypeAliasDeclaration(node) && node.name.text === typeName) {
732
+ const visited = /* @__PURE__ */ new Set();
733
+ visited.add(typeName);
734
+ const runtimeType = withFileContext(
735
+ filePath,
736
+ typeName,
737
+ () => resolveTypeNode(node.type, checker, visited)
738
+ );
739
+ result = {
740
+ name: typeName,
741
+ properties: runtimeType.kind === "object" ? runtimeType.properties : [],
742
+ runtimeType
743
+ };
744
+ return;
745
+ }
746
+ });
747
+ return result;
748
+ } finally {
749
+ setProgramContext(null);
750
+ }
615
751
  }
616
752
  function extractAllTypes(program, filePath) {
617
753
  const sourceFile = program.getSourceFile(filePath);
618
754
  if (!sourceFile) return /* @__PURE__ */ new Map();
619
755
  const checker = program.getTypeChecker();
620
- const result = /* @__PURE__ */ new Map();
621
- ts3.forEachChild(sourceFile, (node) => {
622
- if (ts3.isInterfaceDeclaration(node)) {
623
- const visited = /* @__PURE__ */ new Set();
624
- visited.add(node.name.text);
625
- const runtimeType = withFileContext(
626
- filePath,
627
- node.name.text,
628
- () => resolveInterfaceDeclaration(node, checker, visited)
629
- );
630
- result.set(node.name.text, {
631
- name: node.name.text,
632
- properties: runtimeType.kind === "object" ? runtimeType.properties : [],
633
- runtimeType
634
- });
635
- return;
636
- }
637
- if (ts3.isTypeAliasDeclaration(node)) {
638
- const visited = /* @__PURE__ */ new Set();
639
- visited.add(node.name.text);
640
- const runtimeType = withFileContext(
641
- filePath,
642
- node.name.text,
643
- () => resolveTypeNode(node.type, checker, visited)
644
- );
645
- result.set(node.name.text, {
646
- name: node.name.text,
647
- properties: runtimeType.kind === "object" ? runtimeType.properties : [],
648
- runtimeType
649
- });
650
- return;
651
- }
652
- });
653
- return result;
756
+ setProgramContext(program);
757
+ try {
758
+ const result = /* @__PURE__ */ new Map();
759
+ ts3.forEachChild(sourceFile, (node) => {
760
+ if (ts3.isInterfaceDeclaration(node)) {
761
+ const visited = /* @__PURE__ */ new Set();
762
+ visited.add(node.name.text);
763
+ const runtimeType = withFileContext(
764
+ filePath,
765
+ node.name.text,
766
+ () => resolveInterfaceDeclaration(node, checker, visited)
767
+ );
768
+ result.set(node.name.text, {
769
+ name: node.name.text,
770
+ properties: runtimeType.kind === "object" ? runtimeType.properties : [],
771
+ runtimeType
772
+ });
773
+ return;
774
+ }
775
+ if (ts3.isTypeAliasDeclaration(node)) {
776
+ const visited = /* @__PURE__ */ new Set();
777
+ visited.add(node.name.text);
778
+ const runtimeType = withFileContext(
779
+ filePath,
780
+ node.name.text,
781
+ () => resolveTypeNode(node.type, checker, visited)
782
+ );
783
+ result.set(node.name.text, {
784
+ name: node.name.text,
785
+ properties: runtimeType.kind === "object" ? runtimeType.properties : [],
786
+ runtimeType
787
+ });
788
+ return;
789
+ }
790
+ });
791
+ return result;
792
+ } finally {
793
+ setProgramContext(null);
794
+ }
654
795
  }
655
796
  function withFileContext(filePath, typeName, fn) {
656
797
  try {
@@ -851,11 +992,11 @@ var init_analyzeInjection = __esm({
851
992
  });
852
993
 
853
994
  // src/cli/collectRouteSchemaSources.ts
854
- import path from "path";
995
+ import path2 from "path";
855
996
  function collectRouteSchemaSources(routes, rootDir) {
856
997
  const methodsByFile = /* @__PURE__ */ new Map();
857
998
  for (const route of routes) {
858
- const filePath = rootDir ? path.resolve(rootDir, route.filePath) : route.filePath;
999
+ const filePath = rootDir ? path2.resolve(rootDir, route.filePath) : route.filePath;
859
1000
  let entry = methodsByFile.get(filePath);
860
1001
  if (!entry) {
861
1002
  entry = { urlPath: route.urlPath, methods: /* @__PURE__ */ new Set() };
@@ -1223,8 +1364,8 @@ __export(generateSchemaFiles_exports, {
1223
1364
  getRuntimeSchemaPath: () => getRuntimeSchemaPath,
1224
1365
  getSchemaOutputPath: () => getSchemaOutputPath
1225
1366
  });
1226
- import path5 from "path";
1227
- import fs4 from "fs/promises";
1367
+ import path6 from "path";
1368
+ import fs5 from "fs/promises";
1228
1369
  function getSchemaOutputPath(sourceFile, dist, rootDir) {
1229
1370
  let rel = sourceFile.replace(/\\/g, "/");
1230
1371
  if (rel.startsWith("src/")) {
@@ -1232,7 +1373,7 @@ function getSchemaOutputPath(sourceFile, dist, rootDir) {
1232
1373
  }
1233
1374
  const idx = rel.lastIndexOf("/");
1234
1375
  const relDir = idx >= 0 ? rel.slice(0, idx) : "";
1235
- return path5.resolve(rootDir, dist, relDir, "zod.js");
1376
+ return path6.resolve(rootDir, dist, relDir, "zod.js");
1236
1377
  }
1237
1378
  function getRuntimeSchemaPath(filePath, dist, rootDir) {
1238
1379
  let rel = filePath.replace(/\\/g, "/");
@@ -1243,7 +1384,7 @@ function getRuntimeSchemaPath(filePath, dist, rootDir) {
1243
1384
  }
1244
1385
  const idx = rel.lastIndexOf("/");
1245
1386
  const relDir = idx >= 0 ? rel.slice(0, idx) : "";
1246
- return path5.resolve(rootDir, dist, relDir, "zod.js");
1387
+ return path6.resolve(rootDir, dist, relDir, "zod.js");
1247
1388
  }
1248
1389
  function getHelpersImportPath(relDir) {
1249
1390
  if (!relDir) return `./${HELPERS_FILENAME}`;
@@ -1293,7 +1434,7 @@ async function generateSchemaFiles(routes, rootDir, dist) {
1293
1434
  }
1294
1435
  const fileEntries = [];
1295
1436
  for (const [filePath, fileSources] of sourcesByFile) {
1296
- const relFile = path5.relative(rootDir, filePath).replace(/\\/g, "/");
1437
+ const relFile = path6.relative(rootDir, filePath).replace(/\\/g, "/");
1297
1438
  const outputPath = getSchemaOutputPath(relFile, dist, rootDir);
1298
1439
  const allTypes = allTypesByFile.get(filePath) ?? /* @__PURE__ */ new Map();
1299
1440
  let relForDir = relFile;
@@ -1308,7 +1449,7 @@ async function generateSchemaFiles(routes, rootDir, dist) {
1308
1449
  }
1309
1450
  const allSourceCode = fileEntries.map((e) => e.source).join("\n");
1310
1451
  if (usesCoerceHelpers(allSourceCode)) {
1311
- const helpersPath = path5.resolve(rootDir, dist, HELPERS_FILENAME);
1452
+ const helpersPath = path6.resolve(rootDir, dist, HELPERS_FILENAME);
1312
1453
  await writeSchemaFile(helpersPath, generateHelpersFileSource());
1313
1454
  }
1314
1455
  await Promise.all(
@@ -1316,8 +1457,8 @@ async function generateSchemaFiles(routes, rootDir, dist) {
1316
1457
  );
1317
1458
  }
1318
1459
  async function writeSchemaFile(outputPath, source) {
1319
- await fs4.mkdir(path5.dirname(outputPath), { recursive: true });
1320
- await fs4.writeFile(outputPath, source, "utf-8");
1460
+ await fs5.mkdir(path6.dirname(outputPath), { recursive: true });
1461
+ await fs5.writeFile(outputPath, source, "utf-8");
1321
1462
  }
1322
1463
  var init_generateSchemaFiles = __esm({
1323
1464
  "src/cli/generateSchemaFiles.ts"() {
@@ -1422,7 +1563,7 @@ function listSkills() {
1422
1563
  }
1423
1564
 
1424
1565
  // src/loader/loadAgentModule.ts
1425
- import fs6 from "fs";
1566
+ import fs7 from "fs";
1426
1567
 
1427
1568
  // src/loader/resolveExports.ts
1428
1569
  function resolveExport(module, exportName) {
@@ -1468,17 +1609,17 @@ async function importWithCacheBust(filePath, bustViteCache = false) {
1468
1609
  }
1469
1610
 
1470
1611
  // src/cli/compileOnDemand.ts
1471
- import path6 from "path";
1472
- import fs5 from "fs";
1612
+ import path7 from "path";
1613
+ import fs6 from "fs";
1473
1614
 
1474
1615
  // src/cli/compileDevRoutes.ts
1475
- import path4 from "path";
1476
- import fs3 from "fs";
1616
+ import path5 from "path";
1617
+ import fs4 from "fs";
1477
1618
  import fg from "fast-glob";
1478
1619
 
1479
1620
  // src/cli/aliasPlugin.ts
1480
- import path3 from "path";
1481
- import fs2 from "fs";
1621
+ import path4 from "path";
1622
+ import fs3 from "fs";
1482
1623
 
1483
1624
  // src/utils/resolveAlias.ts
1484
1625
  function resolveAlias(specifier, config) {
@@ -1505,11 +1646,11 @@ function resolveAlias(specifier, config) {
1505
1646
 
1506
1647
  // src/utils/readTsconfig.ts
1507
1648
  import ts6 from "typescript";
1508
- import path2 from "path";
1509
- import fs from "fs";
1649
+ import path3 from "path";
1650
+ import fs2 from "fs";
1510
1651
  function readTsconfig(rootDir) {
1511
- const tsconfigPath = path2.resolve(rootDir, "tsconfig.json");
1512
- if (!fs.existsSync(tsconfigPath)) return null;
1652
+ const tsconfigPath = path3.resolve(rootDir, "tsconfig.json");
1653
+ if (!fs2.existsSync(tsconfigPath)) return null;
1513
1654
  const configFile = ts6.readConfigFile(tsconfigPath, ts6.sys.readFile);
1514
1655
  if (configFile.error || !configFile.config) return null;
1515
1656
  const parsed = ts6.parseJsonConfigFileContent(configFile.config, ts6.sys, rootDir);
@@ -1518,7 +1659,7 @@ function readTsconfig(rootDir) {
1518
1659
  if (!rawPaths) return null;
1519
1660
  const paths = {};
1520
1661
  for (const [pattern, targets] of Object.entries(rawPaths)) {
1521
- paths[pattern] = targets.map((t) => path2.resolve(baseUrl, t));
1662
+ paths[pattern] = targets.map((t) => path3.resolve(baseUrl, t));
1522
1663
  }
1523
1664
  return { baseUrl, paths };
1524
1665
  }
@@ -1531,29 +1672,29 @@ function toProdExtension(filePath) {
1531
1672
  return filePath;
1532
1673
  }
1533
1674
  function toProdImportPath(sourceFile, importer) {
1534
- const importerDir = path3.dirname(importer);
1535
- let rel = path3.relative(importerDir, sourceFile);
1536
- rel = rel.split(path3.sep).join("/");
1675
+ const importerDir = path4.dirname(importer);
1676
+ let rel = path4.relative(importerDir, sourceFile);
1677
+ rel = rel.split(path4.sep).join("/");
1537
1678
  if (!rel.startsWith(".")) rel = "./" + rel;
1538
1679
  return toProdExtension(rel);
1539
1680
  }
1540
1681
  function toRealPath(p) {
1541
1682
  try {
1542
- return fs2.realpathSync(p);
1683
+ return fs3.realpathSync(p);
1543
1684
  } catch {
1544
1685
  return p;
1545
1686
  }
1546
1687
  }
1547
1688
  function isInsideDir(filePath, dir) {
1548
- const rel = path3.relative(dir, filePath);
1549
- return rel !== "" && !rel.startsWith("..") && !path3.isAbsolute(rel);
1689
+ const rel = path4.relative(dir, filePath);
1690
+ return rel !== "" && !rel.startsWith("..") && !path4.isAbsolute(rel);
1550
1691
  }
1551
1692
  var APP_DIR = "src";
1552
1693
  function toStrippedProdImportPath(sourceFile, rootDir) {
1553
- const appDirAbs = toRealPath(path3.resolve(rootDir, APP_DIR));
1694
+ const appDirAbs = toRealPath(path4.resolve(rootDir, APP_DIR));
1554
1695
  const sourceReal = toRealPath(sourceFile);
1555
- let rel = path3.relative(appDirAbs, sourceReal);
1556
- rel = rel.split(path3.sep).join("/");
1696
+ let rel = path4.relative(appDirAbs, sourceReal);
1697
+ rel = rel.split(path4.sep).join("/");
1557
1698
  if (!rel.startsWith(".")) rel = "./" + rel;
1558
1699
  return toProdExtension(rel);
1559
1700
  }
@@ -1568,34 +1709,34 @@ var INDEX_EXTS = [
1568
1709
  "/index.cjs"
1569
1710
  ];
1570
1711
  function resolveRelativeSpecifier(importer, specifier) {
1571
- const importerDir = path3.dirname(importer);
1572
- const base = path3.resolve(importerDir, specifier);
1712
+ const importerDir = path4.dirname(importer);
1713
+ const base = path4.resolve(importerDir, specifier);
1573
1714
  if (PROD_EXTS.some((ext) => specifier.endsWith(ext))) {
1574
- return fs2.existsSync(base) ? base : null;
1715
+ return fs3.existsSync(base) ? base : null;
1575
1716
  }
1576
1717
  if (/\.(ts|tsx|jsx)$/.test(specifier)) {
1577
- return fs2.existsSync(base) ? base : null;
1718
+ return fs3.existsSync(base) ? base : null;
1578
1719
  }
1579
1720
  for (const ext of SOURCE_EXTS) {
1580
1721
  const file = base + ext;
1581
- if (fs2.existsSync(file)) return file;
1722
+ if (fs3.existsSync(file)) return file;
1582
1723
  }
1583
1724
  for (const indexExt of INDEX_EXTS) {
1584
1725
  const file = base + indexExt;
1585
- if (fs2.existsSync(file)) return file;
1726
+ if (fs3.existsSync(file)) return file;
1586
1727
  }
1587
1728
  return null;
1588
1729
  }
1589
1730
  function createAliasPlugin(config, options) {
1590
1731
  const SPEC_RE = /(\bfrom\s*|import\s*\(\s*)(['"])([^'"]+)\2/g;
1591
- const appDirAbs = options?.rootDir ? toRealPath(path3.resolve(options.rootDir, APP_DIR)) : null;
1732
+ const appDirAbs = options?.rootDir ? toRealPath(path4.resolve(options.rootDir, APP_DIR)) : null;
1592
1733
  return {
1593
1734
  name: "faapi-alias",
1594
1735
  setup(build) {
1595
1736
  build.onLoad({ filter: /\.(ts|tsx|js|jsx|mjs|cjs)$/ }, (args) => {
1596
1737
  let source;
1597
1738
  try {
1598
- source = fs2.readFileSync(args.path, "utf8");
1739
+ source = fs3.readFileSync(args.path, "utf8");
1599
1740
  } catch {
1600
1741
  return void 0;
1601
1742
  }
@@ -1628,7 +1769,7 @@ function createAliasPlugin(config, options) {
1628
1769
  for (const candidate of candidates) {
1629
1770
  for (const ext of SOURCE_EXTS) {
1630
1771
  const file = candidate + ext;
1631
- if (fs2.existsSync(file)) {
1772
+ if (fs3.existsSync(file)) {
1632
1773
  modified = true;
1633
1774
  if (appDirAbs && importerOutsideAppDir && isInsideDir(file, appDirAbs)) {
1634
1775
  return `${prefix}${quote}${toStrippedProdImportPath(
@@ -1641,7 +1782,7 @@ function createAliasPlugin(config, options) {
1641
1782
  }
1642
1783
  for (const indexExt of INDEX_EXTS) {
1643
1784
  const file = candidate + indexExt;
1644
- if (fs2.existsSync(file)) {
1785
+ if (fs3.existsSync(file)) {
1645
1786
  modified = true;
1646
1787
  if (appDirAbs && importerOutsideAppDir && isInsideDir(file, appDirAbs)) {
1647
1788
  return `${prefix}${quote}${toStrippedProdImportPath(
@@ -1679,11 +1820,11 @@ async function compileDevRoutes(options) {
1679
1820
  if (entryPoints.length === 0) {
1680
1821
  return { compiledFiles: [] };
1681
1822
  }
1682
- const absDist = path4.resolve(rootDir, dist);
1683
- await fs3.promises.mkdir(absDist, { recursive: true });
1823
+ const absDist = path5.resolve(rootDir, dist);
1824
+ await fs4.promises.mkdir(absDist, { recursive: true });
1684
1825
  const plugins = buildAliasPlugins(rootDir);
1685
1826
  const esbuild = await import("esbuild");
1686
- const outbase = path4.resolve(rootDir, APP_DIR2);
1827
+ const outbase = path5.resolve(rootDir, APP_DIR2);
1687
1828
  const result = await esbuild.build({
1688
1829
  entryPoints,
1689
1830
  outdir: absDist,
@@ -1700,10 +1841,10 @@ async function compileDevRoutes(options) {
1700
1841
  if (result.outputFiles) {
1701
1842
  await Promise.all(
1702
1843
  result.outputFiles.map(async (file) => {
1703
- await fs3.promises.mkdir(path4.dirname(file.path), { recursive: true });
1844
+ await fs4.promises.mkdir(path5.dirname(file.path), { recursive: true });
1704
1845
  const tmp = `${file.path}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
1705
- await fs3.promises.writeFile(tmp, file.contents);
1706
- await fs3.promises.rename(tmp, file.path);
1846
+ await fs4.promises.writeFile(tmp, file.contents);
1847
+ await fs4.promises.rename(tmp, file.path);
1707
1848
  })
1708
1849
  );
1709
1850
  }
@@ -1715,8 +1856,8 @@ init_generateSchemaFiles();
1715
1856
  init_generateSchemaFiles();
1716
1857
  function isProductFresh(sourceAbsPath, productAbsPath) {
1717
1858
  try {
1718
- const srcStat = fs5.statSync(sourceAbsPath);
1719
- const prodStat = fs5.statSync(productAbsPath);
1859
+ const srcStat = fs6.statSync(sourceAbsPath);
1860
+ const prodStat = fs6.statSync(productAbsPath);
1720
1861
  return prodStat.mtimeMs >= srcStat.mtimeMs;
1721
1862
  } catch {
1722
1863
  return false;
@@ -1747,7 +1888,7 @@ async function ensureCompiled(sourceAbsPath, rootDir, dist) {
1747
1888
  if (state.compiledFiles.has(sourceAbsPath)) {
1748
1889
  return false;
1749
1890
  }
1750
- if (!fs5.existsSync(sourceAbsPath)) {
1891
+ if (!fs6.existsSync(sourceAbsPath)) {
1751
1892
  return false;
1752
1893
  }
1753
1894
  const productPath = prodSourcePathToProductPath(sourceAbsPath, rootDir, dist);
@@ -1773,11 +1914,11 @@ async function ensureCompiled(sourceAbsPath, rootDir, dist) {
1773
1914
  }
1774
1915
  }
1775
1916
  function prodSourcePathToProductPath(sourceAbsPath, rootDir, dist) {
1776
- const rel = path6.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
1917
+ const rel = path7.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
1777
1918
  if (!rel.startsWith("src/")) return null;
1778
1919
  const relWithoutSrc = rel.slice(4);
1779
1920
  const jsRel = relWithoutSrc.replace(/\.ts$/, ".js");
1780
- return path6.resolve(rootDir, dist, jsRel);
1921
+ return path7.resolve(rootDir, dist, jsRel);
1781
1922
  }
1782
1923
  function clearGeneratedSchemas() {
1783
1924
  state.generatedSchemas.clear();
@@ -1793,9 +1934,9 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
1793
1934
  if (state.generatedSchemas.has(schemaPath)) {
1794
1935
  return false;
1795
1936
  }
1796
- const prodAbsPath = path6.resolve(rootDir, routeFilePath);
1937
+ const prodAbsPath = path7.resolve(rootDir, routeFilePath);
1797
1938
  const sourceAbsPath = prodPathToSourcePath(prodAbsPath, rootDir, dist);
1798
- if (!fs5.existsSync(sourceAbsPath)) {
1939
+ if (!fs6.existsSync(sourceAbsPath)) {
1799
1940
  return false;
1800
1941
  }
1801
1942
  if (isProductFresh(sourceAbsPath, schemaPath)) {
@@ -1806,7 +1947,7 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
1806
1947
  if (fileRoutes.length === 0) {
1807
1948
  return false;
1808
1949
  }
1809
- const sourceRelPath = path6.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
1950
+ const sourceRelPath = path7.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
1810
1951
  const sourceRoutes = fileRoutes.map((r) => ({ ...r, filePath: sourceRelPath }));
1811
1952
  const generatePromise = (async () => {
1812
1953
  await generateSchemaFiles(sourceRoutes, rootDir, dist);
@@ -1827,22 +1968,22 @@ async function deleteSchemaFiles(routes, rootDir, dist) {
1827
1968
  if (deleted.has(schemaPath)) continue;
1828
1969
  deleted.add(schemaPath);
1829
1970
  try {
1830
- await fs5.promises.unlink(schemaPath);
1971
+ await fs6.promises.unlink(schemaPath);
1831
1972
  } catch {
1832
1973
  }
1833
1974
  }
1834
1975
  }
1835
1976
  function prodPathToSourcePath(prodAbsPath, rootDir, dist) {
1836
- const rel = path6.relative(rootDir, prodAbsPath).replace(/\\/g, "/");
1977
+ const rel = path7.relative(rootDir, prodAbsPath).replace(/\\/g, "/");
1837
1978
  let relWithoutDist = rel;
1838
1979
  if (relWithoutDist.startsWith(`${dist}/`)) {
1839
1980
  relWithoutDist = relWithoutDist.slice(dist.length + 1);
1840
1981
  }
1841
1982
  const srcRel = `src/${relWithoutDist}`;
1842
1983
  const tsRel = srcRel.replace(/\.js$/, ".ts");
1843
- const tsAbs = path6.resolve(rootDir, tsRel);
1844
- if (fs5.existsSync(tsAbs)) return tsAbs;
1845
- return path6.resolve(rootDir, srcRel);
1984
+ const tsAbs = path7.resolve(rootDir, tsRel);
1985
+ if (fs6.existsSync(tsAbs)) return tsAbs;
1986
+ return path7.resolve(rootDir, srcRel);
1846
1987
  }
1847
1988
  function isDevOnDemandEnabled() {
1848
1989
  return state.enabled;
@@ -1857,7 +1998,7 @@ async function loadAgentModule(filePath, hasRun, rootDir) {
1857
1998
  const dist = getDevDist();
1858
1999
  if (dist) {
1859
2000
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
1860
- if (sourcePath && fs6.existsSync(sourcePath)) {
2001
+ if (sourcePath && fs7.existsSync(sourcePath)) {
1861
2002
  try {
1862
2003
  await ensureCompiled(sourcePath, rootDir, dist);
1863
2004
  } catch (compileErr) {
@@ -1890,13 +2031,13 @@ async function loadAgentModule(filePath, hasRun, rootDir) {
1890
2031
  }
1891
2032
 
1892
2033
  // src/loader/loadToolModule.ts
1893
- import fs7 from "fs";
2034
+ import fs8 from "fs";
1894
2035
  async function loadToolModule(filePath, functionName, rootDir) {
1895
2036
  if (isDevOnDemandEnabled() && rootDir) {
1896
2037
  const dist = getDevDist();
1897
2038
  if (dist) {
1898
2039
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
1899
- if (sourcePath && fs7.existsSync(sourcePath)) {
2040
+ if (sourcePath && fs8.existsSync(sourcePath)) {
1900
2041
  try {
1901
2042
  await ensureCompiled(sourcePath, rootDir, dist);
1902
2043
  } catch (compileErr) {
@@ -1928,8 +2069,8 @@ async function loadToolModule(filePath, functionName, rootDir) {
1928
2069
  import { existsSync as existsSync2 } from "fs";
1929
2070
 
1930
2071
  // src/cli/generateToolArtifacts.ts
1931
- import path7 from "path";
1932
- import fs8 from "fs/promises";
2072
+ import path8 from "path";
2073
+ import fs9 from "fs/promises";
1933
2074
  import { existsSync } from "fs";
1934
2075
 
1935
2076
  // src/ast/extractToolMetadata.ts
@@ -2024,7 +2165,7 @@ function getToolSchemaOutputPath(sourceFile, dist, rootDir) {
2024
2165
  }
2025
2166
  const idx = rel.lastIndexOf("/");
2026
2167
  const relDir = idx >= 0 ? rel.slice(0, idx) : "";
2027
- return path7.resolve(rootDir, dist, relDir, "zod.js");
2168
+ return path8.resolve(rootDir, dist, relDir, "zod.js");
2028
2169
  }
2029
2170
  function getRuntimeToolSchemaPath(filePath, dist, rootDir) {
2030
2171
  let rel = filePath.replace(/\\/g, "/");
@@ -2035,7 +2176,7 @@ function getRuntimeToolSchemaPath(filePath, dist, rootDir) {
2035
2176
  }
2036
2177
  const idx = rel.lastIndexOf("/");
2037
2178
  const relDir = idx >= 0 ? rel.slice(0, idx) : "";
2038
- return path7.resolve(rootDir, dist, relDir, "zod.js");
2179
+ return path8.resolve(rootDir, dist, relDir, "zod.js");
2039
2180
  }
2040
2181
  function toProdFilePath(filePath, dist) {
2041
2182
  let rel = filePath.replace(/\\/g, "/");
@@ -2055,12 +2196,12 @@ function serializeTools(tools, dist = "dist") {
2055
2196
  }));
2056
2197
  }
2057
2198
  async function writeToolsModule(manifest, outputPath) {
2058
- const dir = path7.dirname(outputPath);
2059
- await fs8.mkdir(dir, { recursive: true });
2199
+ const dir = path8.dirname(outputPath);
2200
+ await fs9.mkdir(dir, { recursive: true });
2060
2201
  const content = `// \u81EA\u52A8\u751F\u6210,\u8BF7\u52FF\u624B\u52A8\u7F16\u8F91(faapi build/dev \u4EA7\u7269)
2061
2202
  export const tools = ${JSON.stringify(manifest, null, 2)};
2062
2203
  `;
2063
- await fs8.writeFile(outputPath, content, "utf-8");
2204
+ await fs9.writeFile(outputPath, content, "utf-8");
2064
2205
  }
2065
2206
  function hydrateTools(manifest) {
2066
2207
  return manifest.map((t) => ({
@@ -2075,7 +2216,7 @@ function collectToolSchemaSources(tools, rootDir) {
2075
2216
  const toolsByFile = /* @__PURE__ */ new Map();
2076
2217
  for (const tool of tools) {
2077
2218
  if (!tool.inputTypeName) continue;
2078
- const absPath = path7.resolve(rootDir, tool.filePath);
2219
+ const absPath = path8.resolve(rootDir, tool.filePath);
2079
2220
  let list = toolsByFile.get(absPath);
2080
2221
  if (!list) {
2081
2222
  list = [];
@@ -2137,15 +2278,15 @@ function generateToolSchemaFileSource(sources, allTypes, helpersImportPath) {
2137
2278
  }
2138
2279
  async function maybeGenerateHelpers(allSourceCode, distDir) {
2139
2280
  if (!usesCoerceHelpers(allSourceCode)) return;
2140
- const helpersPath = path7.resolve(distDir, HELPERS_FILENAME);
2281
+ const helpersPath = path8.resolve(distDir, HELPERS_FILENAME);
2141
2282
  if (existsSync(helpersPath)) return;
2142
- await fs8.mkdir(path7.dirname(helpersPath), { recursive: true });
2143
- await fs8.writeFile(helpersPath, generateHelpersFileSource(), "utf-8");
2283
+ await fs9.mkdir(path8.dirname(helpersPath), { recursive: true });
2284
+ await fs9.writeFile(helpersPath, generateHelpersFileSource(), "utf-8");
2144
2285
  }
2145
2286
  async function generateToolArtifacts(tools, rootDir, dist, options) {
2146
2287
  const metadata = [];
2147
2288
  for (const manifest of tools) {
2148
- const absPath = path7.resolve(rootDir, manifest.filePath);
2289
+ const absPath = path8.resolve(rootDir, manifest.filePath);
2149
2290
  const program = createProgram(absPath);
2150
2291
  const result = extractToolMetadata(program, absPath, manifest.functionName, {
2151
2292
  name: manifest.name,
@@ -2156,7 +2297,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
2156
2297
  }
2157
2298
  }
2158
2299
  const serialized = serializeTools(metadata, dist);
2159
- const toolsPath = path7.resolve(rootDir, dist, TOOLS_FILE);
2300
+ const toolsPath = path8.resolve(rootDir, dist, TOOLS_FILE);
2160
2301
  await writeToolsModule(serialized, toolsPath);
2161
2302
  if (options?.skipSchema) {
2162
2303
  return metadata;
@@ -2179,7 +2320,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
2179
2320
  }
2180
2321
  const fileEntries = [];
2181
2322
  for (const [filePath, fileSources] of sourcesByFile) {
2182
- const relFile = path7.relative(rootDir, filePath).replace(/\\/g, "/");
2323
+ const relFile = path8.relative(rootDir, filePath).replace(/\\/g, "/");
2183
2324
  const outputPath = getToolSchemaOutputPath(relFile, dist, rootDir);
2184
2325
  const allTypes = allTypesByFile.get(filePath) ?? /* @__PURE__ */ new Map();
2185
2326
  let relForDir = relFile;
@@ -2193,7 +2334,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
2193
2334
  fileEntries.push({ outputPath, source });
2194
2335
  }
2195
2336
  const allSourceCode = fileEntries.map((e) => e.source).join("\n");
2196
- const distDir = path7.resolve(rootDir, dist);
2337
+ const distDir = path8.resolve(rootDir, dist);
2197
2338
  await maybeGenerateHelpers(allSourceCode, distDir);
2198
2339
  await Promise.all(
2199
2340
  fileEntries.map(({ outputPath, source }) => writeToolSchemaFile(outputPath, source))
@@ -2201,8 +2342,8 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
2201
2342
  return metadata;
2202
2343
  }
2203
2344
  async function writeToolSchemaFile(outputPath, source) {
2204
- await fs8.mkdir(path7.dirname(outputPath), { recursive: true });
2205
- await fs8.writeFile(outputPath, source, "utf-8");
2345
+ await fs9.mkdir(path8.dirname(outputPath), { recursive: true });
2346
+ await fs9.writeFile(outputPath, source, "utf-8");
2206
2347
  }
2207
2348
 
2208
2349
  // src/loader/loadToolSchema.ts
@@ -2402,16 +2543,16 @@ function helmet(options = {}) {
2402
2543
  }
2403
2544
 
2404
2545
  // src/config/loadConfig.ts
2405
- import path8 from "path";
2406
- import fs9 from "fs";
2546
+ import path9 from "path";
2547
+ import fs10 from "fs";
2407
2548
  var CONFIG_PRODUCT_FILE = "faapi-config.js";
2408
2549
  async function loadConfig(rootDir, dist) {
2409
- const configProductPath = path8.resolve(rootDir, dist, CONFIG_PRODUCT_FILE);
2410
- if (fs9.existsSync(configProductPath)) {
2550
+ const configProductPath = path9.resolve(rootDir, dist, CONFIG_PRODUCT_FILE);
2551
+ if (fs10.existsSync(configProductPath)) {
2411
2552
  const module = await importWithCacheBust(configProductPath);
2412
2553
  return module.default ?? {};
2413
2554
  }
2414
- const hasSourceConfig = fs9.existsSync(path8.join(rootDir, "faapi.config.ts")) || fs9.existsSync(path8.join(rootDir, "faapi.config.js"));
2555
+ const hasSourceConfig = fs10.existsSync(path9.join(rootDir, "faapi.config.ts")) || fs10.existsSync(path9.join(rootDir, "faapi.config.js"));
2415
2556
  if (hasSourceConfig) {
2416
2557
  throw new Error(
2417
2558
  `[faapi] ${dist}/${CONFIG_PRODUCT_FILE} \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6267\u884C \`faapi build\`\uFF08\u6216 \`faapi dev\`\uFF09\u751F\u6210\u4EA7\u7269\u3002`
@@ -2421,8 +2562,8 @@ async function loadConfig(rootDir, dist) {
2421
2562
  }
2422
2563
 
2423
2564
  // src/cli/loadEnv.ts
2424
- import fs10 from "fs";
2425
- import path9 from "path";
2565
+ import fs11 from "fs";
2566
+ import path10 from "path";
2426
2567
  function resolveEnv() {
2427
2568
  return process.env.NODE_ENV || "development";
2428
2569
  }
@@ -2488,9 +2629,9 @@ function loadEnv(rootDir) {
2488
2629
  const files = getEnvFiles(env);
2489
2630
  const merged = {};
2490
2631
  for (const file of files) {
2491
- const filePath = path9.join(rootDir, file);
2492
- if (!fs10.existsSync(filePath)) continue;
2493
- const content = fs10.readFileSync(filePath, "utf-8");
2632
+ const filePath = path10.join(rootDir, file);
2633
+ if (!fs11.existsSync(filePath)) continue;
2634
+ const content = fs11.readFileSync(filePath, "utf-8");
2494
2635
  const parsed = parseEnvFile(content, merged);
2495
2636
  Object.assign(merged, parsed);
2496
2637
  }
@@ -2527,14 +2668,14 @@ var ValidationError = class extends FaapiError {
2527
2668
  issues;
2528
2669
  };
2529
2670
  var RouteNotFoundError = class extends FaapiError {
2530
- constructor(path18) {
2531
- super("ROUTE_NOT_FOUND", `Route not found: ${path18}`, 404);
2671
+ constructor(path19) {
2672
+ super("ROUTE_NOT_FOUND", `Route not found: ${path19}`, 404);
2532
2673
  this.name = "RouteNotFoundError";
2533
2674
  }
2534
2675
  };
2535
2676
  var MethodNotAllowedError = class extends FaapiError {
2536
- constructor(method, path18, allowedMethods) {
2537
- super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path18}`, 405);
2677
+ constructor(method, path19, allowedMethods) {
2678
+ super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path19}`, 405);
2538
2679
  this.allowedMethods = allowedMethods;
2539
2680
  this.name = "MethodNotAllowedError";
2540
2681
  }
@@ -2560,8 +2701,8 @@ var PayloadTooLargeError = class extends FaapiError {
2560
2701
  };
2561
2702
 
2562
2703
  // src/cli/createAppCore.ts
2563
- import fs15 from "fs";
2564
- import path14 from "path";
2704
+ import fs16 from "fs";
2705
+ import path15 from "path";
2565
2706
  import { PassThrough, Readable as Readable3 } from "stream";
2566
2707
 
2567
2708
  // src/router/sortRoutes.ts
@@ -2614,45 +2755,45 @@ import {
2614
2755
  import { createSecureServer as createHttp2SecureServer } from "http2";
2615
2756
  import { readFileSync } from "fs";
2616
2757
  import { Readable as Readable2 } from "stream";
2617
- import path11 from "path";
2758
+ import path12 from "path";
2618
2759
 
2619
2760
  // src/router/matchRoute.ts
2620
- function matchRoute(routes, method, path18) {
2761
+ function matchRoute(routes, method, path19) {
2621
2762
  for (const route of routes) {
2622
2763
  if (route.method !== method) {
2623
2764
  continue;
2624
2765
  }
2625
2766
  if (!route.isDynamic) {
2626
- if (route.urlPath === path18) {
2767
+ if (route.urlPath === path19) {
2627
2768
  return { route, params: {} };
2628
2769
  }
2629
2770
  continue;
2630
2771
  }
2631
- const params = matchDynamicPath(route.urlPath, path18, route.paramNames, route.isCatchAll);
2772
+ const params = matchDynamicPath(route.urlPath, path19, route.paramNames, route.isCatchAll);
2632
2773
  if (params !== null) {
2633
2774
  return { route, params };
2634
2775
  }
2635
2776
  }
2636
2777
  return null;
2637
2778
  }
2638
- function matchWsRoute(wsRoutes, path18) {
2779
+ function matchWsRoute(wsRoutes, path19) {
2639
2780
  for (const route of wsRoutes) {
2640
2781
  if (!route.isDynamic) {
2641
- if (route.urlPath === path18) {
2782
+ if (route.urlPath === path19) {
2642
2783
  return { route, params: {} };
2643
2784
  }
2644
2785
  continue;
2645
2786
  }
2646
- const params = matchDynamicPath(route.urlPath, path18, route.paramNames, route.isCatchAll);
2787
+ const params = matchDynamicPath(route.urlPath, path19, route.paramNames, route.isCatchAll);
2647
2788
  if (params !== null) {
2648
2789
  return { route, params };
2649
2790
  }
2650
2791
  }
2651
2792
  return null;
2652
2793
  }
2653
- function matchDynamicPath(pattern, path18, paramNames, isCatchAll) {
2794
+ function matchDynamicPath(pattern, path19, paramNames, isCatchAll) {
2654
2795
  const patternSegments = pattern.split("/").filter(Boolean);
2655
- const pathSegments = path18.split("/").filter(Boolean);
2796
+ const pathSegments = path19.split("/").filter(Boolean);
2656
2797
  if (isCatchAll) {
2657
2798
  const nonCatchAllCount = patternSegments.length - 1;
2658
2799
  if (pathSegments.length <= nonCatchAllCount) {
@@ -2698,7 +2839,7 @@ function matchDynamicPath(pattern, path18, paramNames, isCatchAll) {
2698
2839
  }
2699
2840
 
2700
2841
  // src/loader/loadRouteModule.ts
2701
- import fs11 from "fs";
2842
+ import fs12 from "fs";
2702
2843
 
2703
2844
  // src/loader/validateRouteModule.ts
2704
2845
  function validateRouteModule(value, method, filePath) {
@@ -2715,7 +2856,7 @@ async function loadRouteModule(filePath, method, rootDir) {
2715
2856
  const dist = getDevDist();
2716
2857
  if (dist) {
2717
2858
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
2718
- if (sourcePath && fs11.existsSync(sourcePath)) {
2859
+ if (sourcePath && fs12.existsSync(sourcePath)) {
2719
2860
  try {
2720
2861
  await ensureCompiled(sourcePath, rootDir, dist);
2721
2862
  } catch (compileErr) {
@@ -3470,9 +3611,9 @@ async function validateInput(schemaPath, method, inputType, input) {
3470
3611
  function mapZodIssues(error) {
3471
3612
  return error.issues.map((issue) => {
3472
3613
  const code = mapZodCode(issue.code, issue.message);
3473
- const path18 = issue.path.map(String).join(".") || "";
3614
+ const path19 = issue.path.map(String).join(".") || "";
3474
3615
  return {
3475
- path: path18,
3616
+ path: path19,
3476
3617
  code,
3477
3618
  expected: issue.expected ?? mapExpectedFromMessage(issue.message),
3478
3619
  received: issue.received ?? mapReceivedFromMessage(issue.message),
@@ -3534,9 +3675,9 @@ function getClientIp(req) {
3534
3675
  }
3535
3676
 
3536
3677
  // src/server/handleWsUpgrade.ts
3537
- import fs12 from "fs";
3678
+ import fs13 from "fs";
3538
3679
  import { WebSocketServer, WebSocket } from "ws";
3539
- import path10 from "path";
3680
+ import path11 from "path";
3540
3681
 
3541
3682
  // src/server/serverUtils.ts
3542
3683
  function nodeHttpToWebHeaders(req) {
@@ -3662,7 +3803,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
3662
3803
  const dist = getDevDist();
3663
3804
  if (dist) {
3664
3805
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
3665
- if (sourcePath && fs12.existsSync(sourcePath)) {
3806
+ if (sourcePath && fs13.existsSync(sourcePath)) {
3666
3807
  await ensureCompiled(sourcePath, rootDir, dist);
3667
3808
  }
3668
3809
  }
@@ -3742,7 +3883,7 @@ function attachWebSocket(options) {
3742
3883
  const finalHandler = async () => {
3743
3884
  let handlers;
3744
3885
  try {
3745
- const absoluteFilePath = path10.resolve(rootDir, route.filePath);
3886
+ const absoluteFilePath = path11.resolve(rootDir, route.filePath);
3746
3887
  handlers = await loadWsHandler(absoluteFilePath, ctx, rootDir);
3747
3888
  } catch (err) {
3748
3889
  const reason = err instanceof Error ? err.message : String(err);
@@ -3867,15 +4008,15 @@ function limitStreamSize(stream, maxSize) {
3867
4008
  }
3868
4009
  });
3869
4010
  }
3870
- function findAllowedMethods(routes, path18) {
4011
+ function findAllowedMethods(routes, path19) {
3871
4012
  const methods = /* @__PURE__ */ new Set();
3872
4013
  for (const route of routes) {
3873
- if (route.urlPath === path18) {
4014
+ if (route.urlPath === path19) {
3874
4015
  methods.add(route.method);
3875
4016
  continue;
3876
4017
  }
3877
4018
  if (route.isDynamic) {
3878
- const params = matchDynamicPath(route.urlPath, path18, route.paramNames, route.isCatchAll);
4019
+ const params = matchDynamicPath(route.urlPath, path19, route.paramNames, route.isCatchAll);
3879
4020
  if (params !== null) {
3880
4021
  methods.add(route.method);
3881
4022
  }
@@ -3967,7 +4108,7 @@ function createRoutePipeline(opts) {
3967
4108
  const match = resolveRouteOrThrow(routes, method, urlPath);
3968
4109
  ctx.params = match.params;
3969
4110
  const { route } = match;
3970
- const absoluteFilePath = path11.resolve(rootDir, route.filePath);
4111
+ const absoluteFilePath = path12.resolve(rootDir, route.filePath);
3971
4112
  const routeModule = await loadRouteModule(absoluteFilePath, route.method, rootDir);
3972
4113
  const input = await resolveInput(route.method, request);
3973
4114
  const inputType = getInputTypeForMethod(route.method);
@@ -4064,8 +4205,8 @@ function applyPluginWrappers(server, handlerWrappers, upgradeWrappers) {
4064
4205
  }
4065
4206
 
4066
4207
  // src/cli/generateRoutes.ts
4067
- import fs13 from "fs";
4068
- import path12 from "path";
4208
+ import fs14 from "fs";
4209
+ import path13 from "path";
4069
4210
  async function hydrateRoutes(manifest) {
4070
4211
  const hydrateRoute = (serialized) => ({
4071
4212
  method: serialized.method,
@@ -4090,8 +4231,8 @@ async function hydrateRoutes(manifest) {
4090
4231
  }
4091
4232
 
4092
4233
  // src/cli/generateAgentArtifacts.ts
4093
- import path13 from "path";
4094
- import fs14 from "fs/promises";
4234
+ import path14 from "path";
4235
+ import fs15 from "fs/promises";
4095
4236
 
4096
4237
  // src/ast/extractAgentMetadata.ts
4097
4238
  import ts8 from "typescript";
@@ -4305,12 +4446,12 @@ function serializeAgents(agents, dist = "dist") {
4305
4446
  }));
4306
4447
  }
4307
4448
  async function writeAgentsModule(manifest, outputPath) {
4308
- const dir = path13.dirname(outputPath);
4309
- await fs14.mkdir(dir, { recursive: true });
4449
+ const dir = path14.dirname(outputPath);
4450
+ await fs15.mkdir(dir, { recursive: true });
4310
4451
  const content = `// \u81EA\u52A8\u751F\u6210,\u8BF7\u52FF\u624B\u52A8\u7F16\u8F91(faapi build/dev \u4EA7\u7269)
4311
4452
  export const agents = ${JSON.stringify(manifest, null, 2)};
4312
4453
  `;
4313
- await fs14.writeFile(outputPath, content, "utf-8");
4454
+ await fs15.writeFile(outputPath, content, "utf-8");
4314
4455
  }
4315
4456
  function hydrateAgents(manifest) {
4316
4457
  return manifest.map((a) => ({
@@ -4328,7 +4469,7 @@ function hydrateAgents(manifest) {
4328
4469
  async function generateAgentArtifacts(agents, rootDir, dist) {
4329
4470
  const metadata = [];
4330
4471
  for (const manifest of agents) {
4331
- const absPath = path13.resolve(rootDir, manifest.filePath);
4472
+ const absPath = path14.resolve(rootDir, manifest.filePath);
4332
4473
  const program = createProgram(absPath);
4333
4474
  const result = extractAgentMetadata(program, absPath, {
4334
4475
  name: manifest.name,
@@ -4340,7 +4481,7 @@ async function generateAgentArtifacts(agents, rootDir, dist) {
4340
4481
  }
4341
4482
  }
4342
4483
  const serialized = serializeAgents(metadata, dist);
4343
- const agentsPath = path13.resolve(rootDir, dist, AGENTS_FILE);
4484
+ const agentsPath = path14.resolve(rootDir, dist, AGENTS_FILE);
4344
4485
  await writeAgentsModule(serialized, agentsPath);
4345
4486
  return metadata;
4346
4487
  }
@@ -4412,8 +4553,8 @@ var TOOLS_FILE2 = "faapi-tools.js";
4412
4553
  var AGENTS_FILE2 = "faapi-agents.js";
4413
4554
  var PATTERNS = ["src/api/**/*.ts"];
4414
4555
  async function loadAndHydrateTools(rootDir, dist) {
4415
- const toolsPath = path14.resolve(rootDir, dist, TOOLS_FILE2);
4416
- if (!fs15.existsSync(toolsPath)) {
4556
+ const toolsPath = path15.resolve(rootDir, dist, TOOLS_FILE2);
4557
+ if (!fs16.existsSync(toolsPath)) {
4417
4558
  return [];
4418
4559
  }
4419
4560
  const serialized = await importWithCacheBust(toolsPath);
@@ -4422,8 +4563,8 @@ async function loadAndHydrateTools(rootDir, dist) {
4422
4563
  return hydrated;
4423
4564
  }
4424
4565
  async function loadAndHydrateAgents(rootDir, dist) {
4425
- const agentsPath = path14.resolve(rootDir, dist, AGENTS_FILE2);
4426
- if (!fs15.existsSync(agentsPath)) {
4566
+ const agentsPath = path15.resolve(rootDir, dist, AGENTS_FILE2);
4567
+ if (!fs16.existsSync(agentsPath)) {
4427
4568
  return [];
4428
4569
  }
4429
4570
  const serialized = await importWithCacheBust(agentsPath);
@@ -4470,8 +4611,8 @@ function isFaapiConfigKey(key) {
4470
4611
  async function createAppBase(options) {
4471
4612
  const rootDir = options?.rootDir ?? process.cwd();
4472
4613
  const dist = options?.dist ?? process.env.FAAPI_DIST ?? DEFAULT_DIST;
4473
- const routesPath = path14.resolve(rootDir, dist, ROUTES_FILE);
4474
- if (!fs15.existsSync(routesPath)) {
4614
+ const routesPath = path15.resolve(rootDir, dist, ROUTES_FILE);
4615
+ if (!fs16.existsSync(routesPath)) {
4475
4616
  throw new Error(
4476
4617
  `[faapi] ${dist}/${ROUTES_FILE} \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6267\u884C \`faapi build\`\uFF08\u6216 \`faapi dev\`\uFF09\u751F\u6210\u4EA7\u7269\u3002`
4477
4618
  );
@@ -4692,17 +4833,17 @@ async function createAppBase(options) {
4692
4833
 
4693
4834
  // src/router/scanRoutes.ts
4694
4835
  import fg2 from "fast-glob";
4695
- import path15 from "path";
4696
- import fs16 from "fs";
4836
+ import path16 from "path";
4837
+ import fs17 from "fs";
4697
4838
 
4698
4839
  // src/router/constants.ts
4699
4840
  var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
4700
4841
  var HTTP_METHOD_SET = new Set(HTTP_METHODS);
4701
4842
 
4702
4843
  // src/utils/normalizePath.ts
4703
- function normalizePath(path18) {
4704
- if (!path18) return "";
4705
- let result = path18.replace(/\\/g, "/");
4844
+ function normalizePath(path19) {
4845
+ if (!path19) return "";
4846
+ let result = path19.replace(/\\/g, "/");
4706
4847
  result = result.replace(/\/+/g, "/");
4707
4848
  result = result.replace(/\/+$/, "");
4708
4849
  if (result && !result.startsWith("/")) {
@@ -4763,34 +4904,34 @@ function extractExportsFromSource(source) {
4763
4904
  return names;
4764
4905
  }
4765
4906
  function collectMiddlewarePaths(routeFilePath, rootDir, dist) {
4766
- const routeDir = path15.dirname(routeFilePath);
4767
- const resolvedRoot = path15.resolve(rootDir);
4907
+ const routeDir = path16.dirname(routeFilePath);
4908
+ const resolvedRoot = path16.resolve(rootDir);
4768
4909
  const paths = [];
4769
- let currentDir = path15.resolve(rootDir, routeDir);
4910
+ let currentDir = path16.resolve(rootDir, routeDir);
4770
4911
  while (true) {
4771
4912
  if (dist) {
4772
- const mwTsPath = path15.join(currentDir, "middlewares.ts");
4773
- const mwJsPath = path15.join(currentDir, "middlewares.js");
4774
- const absTsPath = path15.resolve(rootDir, mwTsPath);
4775
- const absJsPath = path15.resolve(rootDir, mwJsPath);
4776
- const absMwPath = fs16.existsSync(absTsPath) ? absTsPath : fs16.existsSync(absJsPath) ? absJsPath : null;
4913
+ const mwTsPath = path16.join(currentDir, "middlewares.ts");
4914
+ const mwJsPath = path16.join(currentDir, "middlewares.js");
4915
+ const absTsPath = path16.resolve(rootDir, mwTsPath);
4916
+ const absJsPath = path16.resolve(rootDir, mwJsPath);
4917
+ const absMwPath = fs17.existsSync(absTsPath) ? absTsPath : fs17.existsSync(absJsPath) ? absJsPath : null;
4777
4918
  if (absMwPath) {
4778
- const relMwPath = path15.relative(rootDir, absMwPath);
4779
- const prodAbsPath = path15.resolve(rootDir, toProdFilePath3(relMwPath, dist));
4919
+ const relMwPath = path16.relative(rootDir, absMwPath);
4920
+ const prodAbsPath = path16.resolve(rootDir, toProdFilePath3(relMwPath, dist));
4780
4921
  paths.push(prodAbsPath);
4781
4922
  }
4782
4923
  } else {
4783
4924
  for (const ext of [".ts", ".js"]) {
4784
- const mwPath = path15.join(currentDir, `middlewares${ext}`);
4785
- const absMwPath = path15.resolve(rootDir, mwPath);
4786
- if (fs16.existsSync(absMwPath)) {
4925
+ const mwPath = path16.join(currentDir, `middlewares${ext}`);
4926
+ const absMwPath = path16.resolve(rootDir, mwPath);
4927
+ if (fs17.existsSync(absMwPath)) {
4787
4928
  paths.push(absMwPath);
4788
4929
  break;
4789
4930
  }
4790
4931
  }
4791
4932
  }
4792
4933
  if (currentDir === resolvedRoot) break;
4793
- const parentDir = path15.dirname(currentDir);
4934
+ const parentDir = path16.dirname(currentDir);
4794
4935
  if (parentDir === currentDir) break;
4795
4936
  currentDir = parentDir;
4796
4937
  }
@@ -4817,7 +4958,7 @@ async function scanRoutes(rootDir, patterns, dist) {
4817
4958
  const normalizedFile = file.replace(/\\/g, "/");
4818
4959
  const fileName = normalizedFile.split("/").pop();
4819
4960
  if (fileName === "handler.ts" || fileName === "handler.js") {
4820
- const absPath = path15.resolve(rootDir, normalizedFile);
4961
+ const absPath = path16.resolve(rootDir, normalizedFile);
4821
4962
  const urlPath = filePathToUrlPath(normalizedFile);
4822
4963
  const paramNames = extractParamNames(urlPath);
4823
4964
  const isDynamic = paramNames.length > 0;
@@ -4830,7 +4971,7 @@ async function scanRoutes(rootDir, patterns, dist) {
4830
4971
  const mwPaths = collectMiddlewarePaths(normalizedFile, rootDir);
4831
4972
  middlewareBundle = await loadMergedMiddlewares(mwPaths);
4832
4973
  }
4833
- const source = await fs16.promises.readFile(absPath, "utf8").catch(() => "");
4974
+ const source = await fs17.promises.readFile(absPath, "utf8").catch(() => "");
4834
4975
  const exportNames = extractExportsFromSource(source);
4835
4976
  const methods = HTTP_METHODS.filter((m) => exportNames.has(m));
4836
4977
  for (const method of methods) {
@@ -4866,8 +5007,8 @@ async function scanRoutes(rootDir, patterns, dist) {
4866
5007
 
4867
5008
  // src/tools/scanTools.ts
4868
5009
  import fg3 from "fast-glob";
4869
- import path16 from "path";
4870
- import fs17 from "fs";
5010
+ import path17 from "path";
5011
+ import fs18 from "fs";
4871
5012
  var TOOL_PATTERNS = ["src/tools/**/*.ts"];
4872
5013
  var TOOL_EXPORT_RE = new RegExp(
4873
5014
  String.raw`export\s+(?:async\s+)?(?:function\s+|const\s+)([A-Za-z_$][\w$]*)\s*(?:\(|=)`,
@@ -4917,8 +5058,8 @@ async function scanTools(rootDir, patterns) {
4917
5058
  if (fileName !== "handler.ts" && fileName !== "handler.js") {
4918
5059
  continue;
4919
5060
  }
4920
- const absPath = path16.resolve(rootDir, normalizedFile);
4921
- const source = await fs17.promises.readFile(absPath, "utf8").catch(() => "");
5061
+ const absPath = path17.resolve(rootDir, normalizedFile);
5062
+ const source = await fs18.promises.readFile(absPath, "utf8").catch(() => "");
4922
5063
  const exportNames = extractToolExportsFromSource(source);
4923
5064
  const namespace = filePathToToolNamespace(normalizedFile);
4924
5065
  for (const fnName of exportNames) {
@@ -4942,8 +5083,8 @@ async function scanTools(rootDir, patterns) {
4942
5083
 
4943
5084
  // src/agents/scanAgents.ts
4944
5085
  import fg4 from "fast-glob";
4945
- import path17 from "path";
4946
- import fs18 from "fs";
5086
+ import path18 from "path";
5087
+ import fs19 from "fs";
4947
5088
  var DEFAULT_AGENT_PATTERNS = ["src/agents/*/handler.ts"];
4948
5089
  var RUN_EXPORT_RE = /export\s+(?:async\s+)?(?:function\s+|const\s+)run\b/;
4949
5090
  function extractAgentNameFromPath(filePath) {
@@ -4975,8 +5116,8 @@ async function scanAgents(rootDir, patterns) {
4975
5116
  if (fileName !== "handler.ts" && fileName !== "handler.js") {
4976
5117
  continue;
4977
5118
  }
4978
- const absPath = path17.resolve(rootDir, normalizedFile);
4979
- const source = await fs18.promises.readFile(absPath, "utf8").catch(() => "");
5119
+ const absPath = path18.resolve(rootDir, normalizedFile);
5120
+ const source = await fs19.promises.readFile(absPath, "utf8").catch(() => "");
4980
5121
  const { hasRun } = detectAgentExports(source);
4981
5122
  const name = extractAgentNameFromPath(normalizedFile);
4982
5123
  const prevFile = seen.get(name);