@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/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"() {
@@ -1350,53 +1491,27 @@ function getTool(name) {
1350
1491
  return registry.get(name);
1351
1492
  }
1352
1493
 
1353
- // src/injection/skillRegistry.ts
1354
- var registry2 = /* @__PURE__ */ new Map();
1355
- function hydrateSkillRegistry(skills) {
1356
- const next = /* @__PURE__ */ new Map();
1357
- for (const skill of skills) {
1358
- next.set(skill.name, skill);
1359
- }
1360
- registry2 = next;
1361
- }
1362
- function clearSkillRegistry() {
1363
- registry2 = /* @__PURE__ */ new Map();
1364
- }
1365
- function upsertSkill(core) {
1366
- registry2.set(core.name, core);
1367
- }
1368
- function removeSkill(name) {
1369
- registry2.delete(name);
1370
- }
1371
- function getSkill(name) {
1372
- return registry2.get(name);
1373
- }
1374
- function listSkills() {
1375
- return Array.from(registry2.values());
1376
- }
1377
-
1378
1494
  // src/injection/agentRegistry.ts
1379
- var registry3 = /* @__PURE__ */ new Map();
1495
+ var registry2 = /* @__PURE__ */ new Map();
1380
1496
  function hydrateAgentRegistry(agents) {
1381
1497
  const next = /* @__PURE__ */ new Map();
1382
1498
  for (const agent of agents) {
1383
1499
  next.set(agent.name, agent);
1384
1500
  }
1385
- registry3 = next;
1501
+ registry2 = next;
1386
1502
  }
1387
1503
  function clearAgentRegistry() {
1388
- registry3 = /* @__PURE__ */ new Map();
1504
+ registry2 = /* @__PURE__ */ new Map();
1389
1505
  }
1390
1506
  function getAgent(name) {
1391
- return getSkill(name) ?? registry3.get(name);
1507
+ return registry2.get(name);
1392
1508
  }
1393
1509
  function getAgentEntry(name) {
1394
- return registry3.get(name);
1510
+ return registry2.get(name);
1395
1511
  }
1396
1512
  function listAgents() {
1397
1513
  const merged = /* @__PURE__ */ new Map();
1398
- for (const agent of registry3.values()) merged.set(agent.name, agent);
1399
- for (const skill of listSkills()) merged.set(skill.name, skill);
1514
+ for (const agent of registry2.values()) merged.set(agent.name, agent);
1400
1515
  return Array.from(merged.values());
1401
1516
  }
1402
1517
  function resolveAgentTools(name) {
@@ -1422,8 +1537,33 @@ function resolveSubAgents(name) {
1422
1537
  return result;
1423
1538
  }
1424
1539
 
1540
+ // src/injection/skillRegistry.ts
1541
+ var registry3 = /* @__PURE__ */ new Map();
1542
+ function hydrateSkillRegistry(skills) {
1543
+ const next = /* @__PURE__ */ new Map();
1544
+ for (const skill of skills) {
1545
+ next.set(skill.name, skill);
1546
+ }
1547
+ registry3 = next;
1548
+ }
1549
+ function clearSkillRegistry() {
1550
+ registry3 = /* @__PURE__ */ new Map();
1551
+ }
1552
+ function upsertSkill(core) {
1553
+ registry3.set(core.name, core);
1554
+ }
1555
+ function removeSkill(name) {
1556
+ registry3.delete(name);
1557
+ }
1558
+ function getSkill(name) {
1559
+ return registry3.get(name);
1560
+ }
1561
+ function listSkills() {
1562
+ return Array.from(registry3.values());
1563
+ }
1564
+
1425
1565
  // src/loader/loadAgentModule.ts
1426
- import fs6 from "fs";
1566
+ import fs7 from "fs";
1427
1567
 
1428
1568
  // src/loader/resolveExports.ts
1429
1569
  function resolveExport(module, exportName) {
@@ -1469,17 +1609,17 @@ async function importWithCacheBust(filePath, bustViteCache = false) {
1469
1609
  }
1470
1610
 
1471
1611
  // src/cli/compileOnDemand.ts
1472
- import path6 from "path";
1473
- import fs5 from "fs";
1612
+ import path7 from "path";
1613
+ import fs6 from "fs";
1474
1614
 
1475
1615
  // src/cli/compileDevRoutes.ts
1476
- import path4 from "path";
1477
- import fs3 from "fs";
1616
+ import path5 from "path";
1617
+ import fs4 from "fs";
1478
1618
  import fg from "fast-glob";
1479
1619
 
1480
1620
  // src/cli/aliasPlugin.ts
1481
- import path3 from "path";
1482
- import fs2 from "fs";
1621
+ import path4 from "path";
1622
+ import fs3 from "fs";
1483
1623
 
1484
1624
  // src/utils/resolveAlias.ts
1485
1625
  function resolveAlias(specifier, config) {
@@ -1506,11 +1646,11 @@ function resolveAlias(specifier, config) {
1506
1646
 
1507
1647
  // src/utils/readTsconfig.ts
1508
1648
  import ts6 from "typescript";
1509
- import path2 from "path";
1510
- import fs from "fs";
1649
+ import path3 from "path";
1650
+ import fs2 from "fs";
1511
1651
  function readTsconfig(rootDir) {
1512
- const tsconfigPath = path2.resolve(rootDir, "tsconfig.json");
1513
- if (!fs.existsSync(tsconfigPath)) return null;
1652
+ const tsconfigPath = path3.resolve(rootDir, "tsconfig.json");
1653
+ if (!fs2.existsSync(tsconfigPath)) return null;
1514
1654
  const configFile = ts6.readConfigFile(tsconfigPath, ts6.sys.readFile);
1515
1655
  if (configFile.error || !configFile.config) return null;
1516
1656
  const parsed = ts6.parseJsonConfigFileContent(configFile.config, ts6.sys, rootDir);
@@ -1519,7 +1659,7 @@ function readTsconfig(rootDir) {
1519
1659
  if (!rawPaths) return null;
1520
1660
  const paths = {};
1521
1661
  for (const [pattern, targets] of Object.entries(rawPaths)) {
1522
- paths[pattern] = targets.map((t) => path2.resolve(baseUrl, t));
1662
+ paths[pattern] = targets.map((t) => path3.resolve(baseUrl, t));
1523
1663
  }
1524
1664
  return { baseUrl, paths };
1525
1665
  }
@@ -1532,29 +1672,29 @@ function toProdExtension(filePath) {
1532
1672
  return filePath;
1533
1673
  }
1534
1674
  function toProdImportPath(sourceFile, importer) {
1535
- const importerDir = path3.dirname(importer);
1536
- let rel = path3.relative(importerDir, sourceFile);
1537
- 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("/");
1538
1678
  if (!rel.startsWith(".")) rel = "./" + rel;
1539
1679
  return toProdExtension(rel);
1540
1680
  }
1541
1681
  function toRealPath(p) {
1542
1682
  try {
1543
- return fs2.realpathSync(p);
1683
+ return fs3.realpathSync(p);
1544
1684
  } catch {
1545
1685
  return p;
1546
1686
  }
1547
1687
  }
1548
1688
  function isInsideDir(filePath, dir) {
1549
- const rel = path3.relative(dir, filePath);
1550
- return rel !== "" && !rel.startsWith("..") && !path3.isAbsolute(rel);
1689
+ const rel = path4.relative(dir, filePath);
1690
+ return rel !== "" && !rel.startsWith("..") && !path4.isAbsolute(rel);
1551
1691
  }
1552
1692
  var APP_DIR = "src";
1553
1693
  function toStrippedProdImportPath(sourceFile, rootDir) {
1554
- const appDirAbs = toRealPath(path3.resolve(rootDir, APP_DIR));
1694
+ const appDirAbs = toRealPath(path4.resolve(rootDir, APP_DIR));
1555
1695
  const sourceReal = toRealPath(sourceFile);
1556
- let rel = path3.relative(appDirAbs, sourceReal);
1557
- rel = rel.split(path3.sep).join("/");
1696
+ let rel = path4.relative(appDirAbs, sourceReal);
1697
+ rel = rel.split(path4.sep).join("/");
1558
1698
  if (!rel.startsWith(".")) rel = "./" + rel;
1559
1699
  return toProdExtension(rel);
1560
1700
  }
@@ -1569,34 +1709,34 @@ var INDEX_EXTS = [
1569
1709
  "/index.cjs"
1570
1710
  ];
1571
1711
  function resolveRelativeSpecifier(importer, specifier) {
1572
- const importerDir = path3.dirname(importer);
1573
- const base = path3.resolve(importerDir, specifier);
1712
+ const importerDir = path4.dirname(importer);
1713
+ const base = path4.resolve(importerDir, specifier);
1574
1714
  if (PROD_EXTS.some((ext) => specifier.endsWith(ext))) {
1575
- return fs2.existsSync(base) ? base : null;
1715
+ return fs3.existsSync(base) ? base : null;
1576
1716
  }
1577
1717
  if (/\.(ts|tsx|jsx)$/.test(specifier)) {
1578
- return fs2.existsSync(base) ? base : null;
1718
+ return fs3.existsSync(base) ? base : null;
1579
1719
  }
1580
1720
  for (const ext of SOURCE_EXTS) {
1581
1721
  const file = base + ext;
1582
- if (fs2.existsSync(file)) return file;
1722
+ if (fs3.existsSync(file)) return file;
1583
1723
  }
1584
1724
  for (const indexExt of INDEX_EXTS) {
1585
1725
  const file = base + indexExt;
1586
- if (fs2.existsSync(file)) return file;
1726
+ if (fs3.existsSync(file)) return file;
1587
1727
  }
1588
1728
  return null;
1589
1729
  }
1590
1730
  function createAliasPlugin(config, options) {
1591
1731
  const SPEC_RE = /(\bfrom\s*|import\s*\(\s*)(['"])([^'"]+)\2/g;
1592
- 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;
1593
1733
  return {
1594
1734
  name: "faapi-alias",
1595
1735
  setup(build) {
1596
1736
  build.onLoad({ filter: /\.(ts|tsx|js|jsx|mjs|cjs)$/ }, (args) => {
1597
1737
  let source;
1598
1738
  try {
1599
- source = fs2.readFileSync(args.path, "utf8");
1739
+ source = fs3.readFileSync(args.path, "utf8");
1600
1740
  } catch {
1601
1741
  return void 0;
1602
1742
  }
@@ -1629,7 +1769,7 @@ function createAliasPlugin(config, options) {
1629
1769
  for (const candidate of candidates) {
1630
1770
  for (const ext of SOURCE_EXTS) {
1631
1771
  const file = candidate + ext;
1632
- if (fs2.existsSync(file)) {
1772
+ if (fs3.existsSync(file)) {
1633
1773
  modified = true;
1634
1774
  if (appDirAbs && importerOutsideAppDir && isInsideDir(file, appDirAbs)) {
1635
1775
  return `${prefix}${quote}${toStrippedProdImportPath(
@@ -1642,7 +1782,7 @@ function createAliasPlugin(config, options) {
1642
1782
  }
1643
1783
  for (const indexExt of INDEX_EXTS) {
1644
1784
  const file = candidate + indexExt;
1645
- if (fs2.existsSync(file)) {
1785
+ if (fs3.existsSync(file)) {
1646
1786
  modified = true;
1647
1787
  if (appDirAbs && importerOutsideAppDir && isInsideDir(file, appDirAbs)) {
1648
1788
  return `${prefix}${quote}${toStrippedProdImportPath(
@@ -1680,11 +1820,11 @@ async function compileDevRoutes(options) {
1680
1820
  if (entryPoints.length === 0) {
1681
1821
  return { compiledFiles: [] };
1682
1822
  }
1683
- const absDist = path4.resolve(rootDir, dist);
1684
- await fs3.promises.mkdir(absDist, { recursive: true });
1823
+ const absDist = path5.resolve(rootDir, dist);
1824
+ await fs4.promises.mkdir(absDist, { recursive: true });
1685
1825
  const plugins = buildAliasPlugins(rootDir);
1686
1826
  const esbuild = await import("esbuild");
1687
- const outbase = path4.resolve(rootDir, APP_DIR2);
1827
+ const outbase = path5.resolve(rootDir, APP_DIR2);
1688
1828
  const result = await esbuild.build({
1689
1829
  entryPoints,
1690
1830
  outdir: absDist,
@@ -1701,10 +1841,10 @@ async function compileDevRoutes(options) {
1701
1841
  if (result.outputFiles) {
1702
1842
  await Promise.all(
1703
1843
  result.outputFiles.map(async (file) => {
1704
- await fs3.promises.mkdir(path4.dirname(file.path), { recursive: true });
1844
+ await fs4.promises.mkdir(path5.dirname(file.path), { recursive: true });
1705
1845
  const tmp = `${file.path}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
1706
- await fs3.promises.writeFile(tmp, file.contents);
1707
- await fs3.promises.rename(tmp, file.path);
1846
+ await fs4.promises.writeFile(tmp, file.contents);
1847
+ await fs4.promises.rename(tmp, file.path);
1708
1848
  })
1709
1849
  );
1710
1850
  }
@@ -1716,8 +1856,8 @@ init_generateSchemaFiles();
1716
1856
  init_generateSchemaFiles();
1717
1857
  function isProductFresh(sourceAbsPath, productAbsPath) {
1718
1858
  try {
1719
- const srcStat = fs5.statSync(sourceAbsPath);
1720
- const prodStat = fs5.statSync(productAbsPath);
1859
+ const srcStat = fs6.statSync(sourceAbsPath);
1860
+ const prodStat = fs6.statSync(productAbsPath);
1721
1861
  return prodStat.mtimeMs >= srcStat.mtimeMs;
1722
1862
  } catch {
1723
1863
  return false;
@@ -1748,7 +1888,7 @@ async function ensureCompiled(sourceAbsPath, rootDir, dist) {
1748
1888
  if (state.compiledFiles.has(sourceAbsPath)) {
1749
1889
  return false;
1750
1890
  }
1751
- if (!fs5.existsSync(sourceAbsPath)) {
1891
+ if (!fs6.existsSync(sourceAbsPath)) {
1752
1892
  return false;
1753
1893
  }
1754
1894
  const productPath = prodSourcePathToProductPath(sourceAbsPath, rootDir, dist);
@@ -1774,11 +1914,11 @@ async function ensureCompiled(sourceAbsPath, rootDir, dist) {
1774
1914
  }
1775
1915
  }
1776
1916
  function prodSourcePathToProductPath(sourceAbsPath, rootDir, dist) {
1777
- const rel = path6.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
1917
+ const rel = path7.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
1778
1918
  if (!rel.startsWith("src/")) return null;
1779
1919
  const relWithoutSrc = rel.slice(4);
1780
1920
  const jsRel = relWithoutSrc.replace(/\.ts$/, ".js");
1781
- return path6.resolve(rootDir, dist, jsRel);
1921
+ return path7.resolve(rootDir, dist, jsRel);
1782
1922
  }
1783
1923
  function clearGeneratedSchemas() {
1784
1924
  state.generatedSchemas.clear();
@@ -1794,9 +1934,9 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
1794
1934
  if (state.generatedSchemas.has(schemaPath)) {
1795
1935
  return false;
1796
1936
  }
1797
- const prodAbsPath = path6.resolve(rootDir, routeFilePath);
1937
+ const prodAbsPath = path7.resolve(rootDir, routeFilePath);
1798
1938
  const sourceAbsPath = prodPathToSourcePath(prodAbsPath, rootDir, dist);
1799
- if (!fs5.existsSync(sourceAbsPath)) {
1939
+ if (!fs6.existsSync(sourceAbsPath)) {
1800
1940
  return false;
1801
1941
  }
1802
1942
  if (isProductFresh(sourceAbsPath, schemaPath)) {
@@ -1807,7 +1947,7 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
1807
1947
  if (fileRoutes.length === 0) {
1808
1948
  return false;
1809
1949
  }
1810
- const sourceRelPath = path6.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
1950
+ const sourceRelPath = path7.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
1811
1951
  const sourceRoutes = fileRoutes.map((r) => ({ ...r, filePath: sourceRelPath }));
1812
1952
  const generatePromise = (async () => {
1813
1953
  await generateSchemaFiles(sourceRoutes, rootDir, dist);
@@ -1828,22 +1968,22 @@ async function deleteSchemaFiles(routes, rootDir, dist) {
1828
1968
  if (deleted.has(schemaPath)) continue;
1829
1969
  deleted.add(schemaPath);
1830
1970
  try {
1831
- await fs5.promises.unlink(schemaPath);
1971
+ await fs6.promises.unlink(schemaPath);
1832
1972
  } catch {
1833
1973
  }
1834
1974
  }
1835
1975
  }
1836
1976
  function prodPathToSourcePath(prodAbsPath, rootDir, dist) {
1837
- const rel = path6.relative(rootDir, prodAbsPath).replace(/\\/g, "/");
1977
+ const rel = path7.relative(rootDir, prodAbsPath).replace(/\\/g, "/");
1838
1978
  let relWithoutDist = rel;
1839
1979
  if (relWithoutDist.startsWith(`${dist}/`)) {
1840
1980
  relWithoutDist = relWithoutDist.slice(dist.length + 1);
1841
1981
  }
1842
1982
  const srcRel = `src/${relWithoutDist}`;
1843
1983
  const tsRel = srcRel.replace(/\.js$/, ".ts");
1844
- const tsAbs = path6.resolve(rootDir, tsRel);
1845
- if (fs5.existsSync(tsAbs)) return tsAbs;
1846
- 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);
1847
1987
  }
1848
1988
  function isDevOnDemandEnabled() {
1849
1989
  return state.enabled;
@@ -1858,7 +1998,7 @@ async function loadAgentModule(filePath, hasRun, rootDir) {
1858
1998
  const dist = getDevDist();
1859
1999
  if (dist) {
1860
2000
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
1861
- if (sourcePath && fs6.existsSync(sourcePath)) {
2001
+ if (sourcePath && fs7.existsSync(sourcePath)) {
1862
2002
  try {
1863
2003
  await ensureCompiled(sourcePath, rootDir, dist);
1864
2004
  } catch (compileErr) {
@@ -1891,13 +2031,13 @@ async function loadAgentModule(filePath, hasRun, rootDir) {
1891
2031
  }
1892
2032
 
1893
2033
  // src/loader/loadToolModule.ts
1894
- import fs7 from "fs";
2034
+ import fs8 from "fs";
1895
2035
  async function loadToolModule(filePath, functionName, rootDir) {
1896
2036
  if (isDevOnDemandEnabled() && rootDir) {
1897
2037
  const dist = getDevDist();
1898
2038
  if (dist) {
1899
2039
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
1900
- if (sourcePath && fs7.existsSync(sourcePath)) {
2040
+ if (sourcePath && fs8.existsSync(sourcePath)) {
1901
2041
  try {
1902
2042
  await ensureCompiled(sourcePath, rootDir, dist);
1903
2043
  } catch (compileErr) {
@@ -1929,8 +2069,8 @@ async function loadToolModule(filePath, functionName, rootDir) {
1929
2069
  import { existsSync as existsSync2 } from "fs";
1930
2070
 
1931
2071
  // src/cli/generateToolArtifacts.ts
1932
- import path7 from "path";
1933
- import fs8 from "fs/promises";
2072
+ import path8 from "path";
2073
+ import fs9 from "fs/promises";
1934
2074
  import { existsSync } from "fs";
1935
2075
 
1936
2076
  // src/ast/extractToolMetadata.ts
@@ -2025,7 +2165,7 @@ function getToolSchemaOutputPath(sourceFile, dist, rootDir) {
2025
2165
  }
2026
2166
  const idx = rel.lastIndexOf("/");
2027
2167
  const relDir = idx >= 0 ? rel.slice(0, idx) : "";
2028
- return path7.resolve(rootDir, dist, relDir, "zod.js");
2168
+ return path8.resolve(rootDir, dist, relDir, "zod.js");
2029
2169
  }
2030
2170
  function getRuntimeToolSchemaPath(filePath, dist, rootDir) {
2031
2171
  let rel = filePath.replace(/\\/g, "/");
@@ -2036,7 +2176,7 @@ function getRuntimeToolSchemaPath(filePath, dist, rootDir) {
2036
2176
  }
2037
2177
  const idx = rel.lastIndexOf("/");
2038
2178
  const relDir = idx >= 0 ? rel.slice(0, idx) : "";
2039
- return path7.resolve(rootDir, dist, relDir, "zod.js");
2179
+ return path8.resolve(rootDir, dist, relDir, "zod.js");
2040
2180
  }
2041
2181
  function toProdFilePath(filePath, dist) {
2042
2182
  let rel = filePath.replace(/\\/g, "/");
@@ -2056,12 +2196,12 @@ function serializeTools(tools, dist = "dist") {
2056
2196
  }));
2057
2197
  }
2058
2198
  async function writeToolsModule(manifest, outputPath) {
2059
- const dir = path7.dirname(outputPath);
2060
- await fs8.mkdir(dir, { recursive: true });
2199
+ const dir = path8.dirname(outputPath);
2200
+ await fs9.mkdir(dir, { recursive: true });
2061
2201
  const content = `// \u81EA\u52A8\u751F\u6210,\u8BF7\u52FF\u624B\u52A8\u7F16\u8F91(faapi build/dev \u4EA7\u7269)
2062
2202
  export const tools = ${JSON.stringify(manifest, null, 2)};
2063
2203
  `;
2064
- await fs8.writeFile(outputPath, content, "utf-8");
2204
+ await fs9.writeFile(outputPath, content, "utf-8");
2065
2205
  }
2066
2206
  function hydrateTools(manifest) {
2067
2207
  return manifest.map((t) => ({
@@ -2076,7 +2216,7 @@ function collectToolSchemaSources(tools, rootDir) {
2076
2216
  const toolsByFile = /* @__PURE__ */ new Map();
2077
2217
  for (const tool of tools) {
2078
2218
  if (!tool.inputTypeName) continue;
2079
- const absPath = path7.resolve(rootDir, tool.filePath);
2219
+ const absPath = path8.resolve(rootDir, tool.filePath);
2080
2220
  let list = toolsByFile.get(absPath);
2081
2221
  if (!list) {
2082
2222
  list = [];
@@ -2138,15 +2278,15 @@ function generateToolSchemaFileSource(sources, allTypes, helpersImportPath) {
2138
2278
  }
2139
2279
  async function maybeGenerateHelpers(allSourceCode, distDir) {
2140
2280
  if (!usesCoerceHelpers(allSourceCode)) return;
2141
- const helpersPath = path7.resolve(distDir, HELPERS_FILENAME);
2281
+ const helpersPath = path8.resolve(distDir, HELPERS_FILENAME);
2142
2282
  if (existsSync(helpersPath)) return;
2143
- await fs8.mkdir(path7.dirname(helpersPath), { recursive: true });
2144
- await fs8.writeFile(helpersPath, generateHelpersFileSource(), "utf-8");
2283
+ await fs9.mkdir(path8.dirname(helpersPath), { recursive: true });
2284
+ await fs9.writeFile(helpersPath, generateHelpersFileSource(), "utf-8");
2145
2285
  }
2146
2286
  async function generateToolArtifacts(tools, rootDir, dist, options) {
2147
2287
  const metadata = [];
2148
2288
  for (const manifest of tools) {
2149
- const absPath = path7.resolve(rootDir, manifest.filePath);
2289
+ const absPath = path8.resolve(rootDir, manifest.filePath);
2150
2290
  const program = createProgram(absPath);
2151
2291
  const result = extractToolMetadata(program, absPath, manifest.functionName, {
2152
2292
  name: manifest.name,
@@ -2157,7 +2297,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
2157
2297
  }
2158
2298
  }
2159
2299
  const serialized = serializeTools(metadata, dist);
2160
- const toolsPath = path7.resolve(rootDir, dist, TOOLS_FILE);
2300
+ const toolsPath = path8.resolve(rootDir, dist, TOOLS_FILE);
2161
2301
  await writeToolsModule(serialized, toolsPath);
2162
2302
  if (options?.skipSchema) {
2163
2303
  return metadata;
@@ -2180,7 +2320,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
2180
2320
  }
2181
2321
  const fileEntries = [];
2182
2322
  for (const [filePath, fileSources] of sourcesByFile) {
2183
- const relFile = path7.relative(rootDir, filePath).replace(/\\/g, "/");
2323
+ const relFile = path8.relative(rootDir, filePath).replace(/\\/g, "/");
2184
2324
  const outputPath = getToolSchemaOutputPath(relFile, dist, rootDir);
2185
2325
  const allTypes = allTypesByFile.get(filePath) ?? /* @__PURE__ */ new Map();
2186
2326
  let relForDir = relFile;
@@ -2194,7 +2334,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
2194
2334
  fileEntries.push({ outputPath, source });
2195
2335
  }
2196
2336
  const allSourceCode = fileEntries.map((e) => e.source).join("\n");
2197
- const distDir = path7.resolve(rootDir, dist);
2337
+ const distDir = path8.resolve(rootDir, dist);
2198
2338
  await maybeGenerateHelpers(allSourceCode, distDir);
2199
2339
  await Promise.all(
2200
2340
  fileEntries.map(({ outputPath, source }) => writeToolSchemaFile(outputPath, source))
@@ -2202,8 +2342,8 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
2202
2342
  return metadata;
2203
2343
  }
2204
2344
  async function writeToolSchemaFile(outputPath, source) {
2205
- await fs8.mkdir(path7.dirname(outputPath), { recursive: true });
2206
- await fs8.writeFile(outputPath, source, "utf-8");
2345
+ await fs9.mkdir(path8.dirname(outputPath), { recursive: true });
2346
+ await fs9.writeFile(outputPath, source, "utf-8");
2207
2347
  }
2208
2348
 
2209
2349
  // src/loader/loadToolSchema.ts
@@ -2403,16 +2543,16 @@ function helmet(options = {}) {
2403
2543
  }
2404
2544
 
2405
2545
  // src/config/loadConfig.ts
2406
- import path8 from "path";
2407
- import fs9 from "fs";
2546
+ import path9 from "path";
2547
+ import fs10 from "fs";
2408
2548
  var CONFIG_PRODUCT_FILE = "faapi-config.js";
2409
2549
  async function loadConfig(rootDir, dist) {
2410
- const configProductPath = path8.resolve(rootDir, dist, CONFIG_PRODUCT_FILE);
2411
- if (fs9.existsSync(configProductPath)) {
2550
+ const configProductPath = path9.resolve(rootDir, dist, CONFIG_PRODUCT_FILE);
2551
+ if (fs10.existsSync(configProductPath)) {
2412
2552
  const module = await importWithCacheBust(configProductPath);
2413
2553
  return module.default ?? {};
2414
2554
  }
2415
- 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"));
2416
2556
  if (hasSourceConfig) {
2417
2557
  throw new Error(
2418
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`
@@ -2422,8 +2562,8 @@ async function loadConfig(rootDir, dist) {
2422
2562
  }
2423
2563
 
2424
2564
  // src/cli/loadEnv.ts
2425
- import fs10 from "fs";
2426
- import path9 from "path";
2565
+ import fs11 from "fs";
2566
+ import path10 from "path";
2427
2567
  function resolveEnv() {
2428
2568
  return process.env.NODE_ENV || "development";
2429
2569
  }
@@ -2489,9 +2629,9 @@ function loadEnv(rootDir) {
2489
2629
  const files = getEnvFiles(env);
2490
2630
  const merged = {};
2491
2631
  for (const file of files) {
2492
- const filePath = path9.join(rootDir, file);
2493
- if (!fs10.existsSync(filePath)) continue;
2494
- 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");
2495
2635
  const parsed = parseEnvFile(content, merged);
2496
2636
  Object.assign(merged, parsed);
2497
2637
  }
@@ -2528,14 +2668,14 @@ var ValidationError = class extends FaapiError {
2528
2668
  issues;
2529
2669
  };
2530
2670
  var RouteNotFoundError = class extends FaapiError {
2531
- constructor(path18) {
2532
- super("ROUTE_NOT_FOUND", `Route not found: ${path18}`, 404);
2671
+ constructor(path19) {
2672
+ super("ROUTE_NOT_FOUND", `Route not found: ${path19}`, 404);
2533
2673
  this.name = "RouteNotFoundError";
2534
2674
  }
2535
2675
  };
2536
2676
  var MethodNotAllowedError = class extends FaapiError {
2537
- constructor(method, path18, allowedMethods) {
2538
- 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);
2539
2679
  this.allowedMethods = allowedMethods;
2540
2680
  this.name = "MethodNotAllowedError";
2541
2681
  }
@@ -2561,8 +2701,8 @@ var PayloadTooLargeError = class extends FaapiError {
2561
2701
  };
2562
2702
 
2563
2703
  // src/cli/createAppCore.ts
2564
- import fs15 from "fs";
2565
- import path14 from "path";
2704
+ import fs16 from "fs";
2705
+ import path15 from "path";
2566
2706
  import { PassThrough, Readable as Readable3 } from "stream";
2567
2707
 
2568
2708
  // src/router/sortRoutes.ts
@@ -2615,45 +2755,45 @@ import {
2615
2755
  import { createSecureServer as createHttp2SecureServer } from "http2";
2616
2756
  import { readFileSync } from "fs";
2617
2757
  import { Readable as Readable2 } from "stream";
2618
- import path11 from "path";
2758
+ import path12 from "path";
2619
2759
 
2620
2760
  // src/router/matchRoute.ts
2621
- function matchRoute(routes, method, path18) {
2761
+ function matchRoute(routes, method, path19) {
2622
2762
  for (const route of routes) {
2623
2763
  if (route.method !== method) {
2624
2764
  continue;
2625
2765
  }
2626
2766
  if (!route.isDynamic) {
2627
- if (route.urlPath === path18) {
2767
+ if (route.urlPath === path19) {
2628
2768
  return { route, params: {} };
2629
2769
  }
2630
2770
  continue;
2631
2771
  }
2632
- const params = matchDynamicPath(route.urlPath, path18, route.paramNames, route.isCatchAll);
2772
+ const params = matchDynamicPath(route.urlPath, path19, route.paramNames, route.isCatchAll);
2633
2773
  if (params !== null) {
2634
2774
  return { route, params };
2635
2775
  }
2636
2776
  }
2637
2777
  return null;
2638
2778
  }
2639
- function matchWsRoute(wsRoutes, path18) {
2779
+ function matchWsRoute(wsRoutes, path19) {
2640
2780
  for (const route of wsRoutes) {
2641
2781
  if (!route.isDynamic) {
2642
- if (route.urlPath === path18) {
2782
+ if (route.urlPath === path19) {
2643
2783
  return { route, params: {} };
2644
2784
  }
2645
2785
  continue;
2646
2786
  }
2647
- const params = matchDynamicPath(route.urlPath, path18, route.paramNames, route.isCatchAll);
2787
+ const params = matchDynamicPath(route.urlPath, path19, route.paramNames, route.isCatchAll);
2648
2788
  if (params !== null) {
2649
2789
  return { route, params };
2650
2790
  }
2651
2791
  }
2652
2792
  return null;
2653
2793
  }
2654
- function matchDynamicPath(pattern, path18, paramNames, isCatchAll) {
2794
+ function matchDynamicPath(pattern, path19, paramNames, isCatchAll) {
2655
2795
  const patternSegments = pattern.split("/").filter(Boolean);
2656
- const pathSegments = path18.split("/").filter(Boolean);
2796
+ const pathSegments = path19.split("/").filter(Boolean);
2657
2797
  if (isCatchAll) {
2658
2798
  const nonCatchAllCount = patternSegments.length - 1;
2659
2799
  if (pathSegments.length <= nonCatchAllCount) {
@@ -2699,7 +2839,7 @@ function matchDynamicPath(pattern, path18, paramNames, isCatchAll) {
2699
2839
  }
2700
2840
 
2701
2841
  // src/loader/loadRouteModule.ts
2702
- import fs11 from "fs";
2842
+ import fs12 from "fs";
2703
2843
 
2704
2844
  // src/loader/validateRouteModule.ts
2705
2845
  function validateRouteModule(value, method, filePath) {
@@ -2716,7 +2856,7 @@ async function loadRouteModule(filePath, method, rootDir) {
2716
2856
  const dist = getDevDist();
2717
2857
  if (dist) {
2718
2858
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
2719
- if (sourcePath && fs11.existsSync(sourcePath)) {
2859
+ if (sourcePath && fs12.existsSync(sourcePath)) {
2720
2860
  try {
2721
2861
  await ensureCompiled(sourcePath, rootDir, dist);
2722
2862
  } catch (compileErr) {
@@ -3471,9 +3611,9 @@ async function validateInput(schemaPath, method, inputType, input) {
3471
3611
  function mapZodIssues(error) {
3472
3612
  return error.issues.map((issue) => {
3473
3613
  const code = mapZodCode(issue.code, issue.message);
3474
- const path18 = issue.path.map(String).join(".") || "";
3614
+ const path19 = issue.path.map(String).join(".") || "";
3475
3615
  return {
3476
- path: path18,
3616
+ path: path19,
3477
3617
  code,
3478
3618
  expected: issue.expected ?? mapExpectedFromMessage(issue.message),
3479
3619
  received: issue.received ?? mapReceivedFromMessage(issue.message),
@@ -3535,9 +3675,9 @@ function getClientIp(req) {
3535
3675
  }
3536
3676
 
3537
3677
  // src/server/handleWsUpgrade.ts
3538
- import fs12 from "fs";
3678
+ import fs13 from "fs";
3539
3679
  import { WebSocketServer, WebSocket } from "ws";
3540
- import path10 from "path";
3680
+ import path11 from "path";
3541
3681
 
3542
3682
  // src/server/serverUtils.ts
3543
3683
  function nodeHttpToWebHeaders(req) {
@@ -3663,7 +3803,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
3663
3803
  const dist = getDevDist();
3664
3804
  if (dist) {
3665
3805
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
3666
- if (sourcePath && fs12.existsSync(sourcePath)) {
3806
+ if (sourcePath && fs13.existsSync(sourcePath)) {
3667
3807
  await ensureCompiled(sourcePath, rootDir, dist);
3668
3808
  }
3669
3809
  }
@@ -3743,7 +3883,7 @@ function attachWebSocket(options) {
3743
3883
  const finalHandler = async () => {
3744
3884
  let handlers;
3745
3885
  try {
3746
- const absoluteFilePath = path10.resolve(rootDir, route.filePath);
3886
+ const absoluteFilePath = path11.resolve(rootDir, route.filePath);
3747
3887
  handlers = await loadWsHandler(absoluteFilePath, ctx, rootDir);
3748
3888
  } catch (err) {
3749
3889
  const reason = err instanceof Error ? err.message : String(err);
@@ -3868,15 +4008,15 @@ function limitStreamSize(stream, maxSize) {
3868
4008
  }
3869
4009
  });
3870
4010
  }
3871
- function findAllowedMethods(routes, path18) {
4011
+ function findAllowedMethods(routes, path19) {
3872
4012
  const methods = /* @__PURE__ */ new Set();
3873
4013
  for (const route of routes) {
3874
- if (route.urlPath === path18) {
4014
+ if (route.urlPath === path19) {
3875
4015
  methods.add(route.method);
3876
4016
  continue;
3877
4017
  }
3878
4018
  if (route.isDynamic) {
3879
- const params = matchDynamicPath(route.urlPath, path18, route.paramNames, route.isCatchAll);
4019
+ const params = matchDynamicPath(route.urlPath, path19, route.paramNames, route.isCatchAll);
3880
4020
  if (params !== null) {
3881
4021
  methods.add(route.method);
3882
4022
  }
@@ -3968,7 +4108,7 @@ function createRoutePipeline(opts) {
3968
4108
  const match = resolveRouteOrThrow(routes, method, urlPath);
3969
4109
  ctx.params = match.params;
3970
4110
  const { route } = match;
3971
- const absoluteFilePath = path11.resolve(rootDir, route.filePath);
4111
+ const absoluteFilePath = path12.resolve(rootDir, route.filePath);
3972
4112
  const routeModule = await loadRouteModule(absoluteFilePath, route.method, rootDir);
3973
4113
  const input = await resolveInput(route.method, request);
3974
4114
  const inputType = getInputTypeForMethod(route.method);
@@ -4065,8 +4205,8 @@ function applyPluginWrappers(server, handlerWrappers, upgradeWrappers) {
4065
4205
  }
4066
4206
 
4067
4207
  // src/cli/generateRoutes.ts
4068
- import fs13 from "fs";
4069
- import path12 from "path";
4208
+ import fs14 from "fs";
4209
+ import path13 from "path";
4070
4210
  async function hydrateRoutes(manifest) {
4071
4211
  const hydrateRoute = (serialized) => ({
4072
4212
  method: serialized.method,
@@ -4091,8 +4231,8 @@ async function hydrateRoutes(manifest) {
4091
4231
  }
4092
4232
 
4093
4233
  // src/cli/generateAgentArtifacts.ts
4094
- import path13 from "path";
4095
- import fs14 from "fs/promises";
4234
+ import path14 from "path";
4235
+ import fs15 from "fs/promises";
4096
4236
 
4097
4237
  // src/ast/extractAgentMetadata.ts
4098
4238
  import ts8 from "typescript";
@@ -4306,12 +4446,12 @@ function serializeAgents(agents, dist = "dist") {
4306
4446
  }));
4307
4447
  }
4308
4448
  async function writeAgentsModule(manifest, outputPath) {
4309
- const dir = path13.dirname(outputPath);
4310
- await fs14.mkdir(dir, { recursive: true });
4449
+ const dir = path14.dirname(outputPath);
4450
+ await fs15.mkdir(dir, { recursive: true });
4311
4451
  const content = `// \u81EA\u52A8\u751F\u6210,\u8BF7\u52FF\u624B\u52A8\u7F16\u8F91(faapi build/dev \u4EA7\u7269)
4312
4452
  export const agents = ${JSON.stringify(manifest, null, 2)};
4313
4453
  `;
4314
- await fs14.writeFile(outputPath, content, "utf-8");
4454
+ await fs15.writeFile(outputPath, content, "utf-8");
4315
4455
  }
4316
4456
  function hydrateAgents(manifest) {
4317
4457
  return manifest.map((a) => ({
@@ -4329,7 +4469,7 @@ function hydrateAgents(manifest) {
4329
4469
  async function generateAgentArtifacts(agents, rootDir, dist) {
4330
4470
  const metadata = [];
4331
4471
  for (const manifest of agents) {
4332
- const absPath = path13.resolve(rootDir, manifest.filePath);
4472
+ const absPath = path14.resolve(rootDir, manifest.filePath);
4333
4473
  const program = createProgram(absPath);
4334
4474
  const result = extractAgentMetadata(program, absPath, {
4335
4475
  name: manifest.name,
@@ -4341,7 +4481,7 @@ async function generateAgentArtifacts(agents, rootDir, dist) {
4341
4481
  }
4342
4482
  }
4343
4483
  const serialized = serializeAgents(metadata, dist);
4344
- const agentsPath = path13.resolve(rootDir, dist, AGENTS_FILE);
4484
+ const agentsPath = path14.resolve(rootDir, dist, AGENTS_FILE);
4345
4485
  await writeAgentsModule(serialized, agentsPath);
4346
4486
  return metadata;
4347
4487
  }
@@ -4413,8 +4553,8 @@ var TOOLS_FILE2 = "faapi-tools.js";
4413
4553
  var AGENTS_FILE2 = "faapi-agents.js";
4414
4554
  var PATTERNS = ["src/api/**/*.ts"];
4415
4555
  async function loadAndHydrateTools(rootDir, dist) {
4416
- const toolsPath = path14.resolve(rootDir, dist, TOOLS_FILE2);
4417
- if (!fs15.existsSync(toolsPath)) {
4556
+ const toolsPath = path15.resolve(rootDir, dist, TOOLS_FILE2);
4557
+ if (!fs16.existsSync(toolsPath)) {
4418
4558
  return [];
4419
4559
  }
4420
4560
  const serialized = await importWithCacheBust(toolsPath);
@@ -4423,8 +4563,8 @@ async function loadAndHydrateTools(rootDir, dist) {
4423
4563
  return hydrated;
4424
4564
  }
4425
4565
  async function loadAndHydrateAgents(rootDir, dist) {
4426
- const agentsPath = path14.resolve(rootDir, dist, AGENTS_FILE2);
4427
- if (!fs15.existsSync(agentsPath)) {
4566
+ const agentsPath = path15.resolve(rootDir, dist, AGENTS_FILE2);
4567
+ if (!fs16.existsSync(agentsPath)) {
4428
4568
  return [];
4429
4569
  }
4430
4570
  const serialized = await importWithCacheBust(agentsPath);
@@ -4471,8 +4611,8 @@ function isFaapiConfigKey(key) {
4471
4611
  async function createAppBase(options) {
4472
4612
  const rootDir = options?.rootDir ?? process.cwd();
4473
4613
  const dist = options?.dist ?? process.env.FAAPI_DIST ?? DEFAULT_DIST;
4474
- const routesPath = path14.resolve(rootDir, dist, ROUTES_FILE);
4475
- if (!fs15.existsSync(routesPath)) {
4614
+ const routesPath = path15.resolve(rootDir, dist, ROUTES_FILE);
4615
+ if (!fs16.existsSync(routesPath)) {
4476
4616
  throw new Error(
4477
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`
4478
4618
  );
@@ -4693,17 +4833,17 @@ async function createAppBase(options) {
4693
4833
 
4694
4834
  // src/router/scanRoutes.ts
4695
4835
  import fg2 from "fast-glob";
4696
- import path15 from "path";
4697
- import fs16 from "fs";
4836
+ import path16 from "path";
4837
+ import fs17 from "fs";
4698
4838
 
4699
4839
  // src/router/constants.ts
4700
4840
  var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
4701
4841
  var HTTP_METHOD_SET = new Set(HTTP_METHODS);
4702
4842
 
4703
4843
  // src/utils/normalizePath.ts
4704
- function normalizePath(path18) {
4705
- if (!path18) return "";
4706
- let result = path18.replace(/\\/g, "/");
4844
+ function normalizePath(path19) {
4845
+ if (!path19) return "";
4846
+ let result = path19.replace(/\\/g, "/");
4707
4847
  result = result.replace(/\/+/g, "/");
4708
4848
  result = result.replace(/\/+$/, "");
4709
4849
  if (result && !result.startsWith("/")) {
@@ -4764,34 +4904,34 @@ function extractExportsFromSource(source) {
4764
4904
  return names;
4765
4905
  }
4766
4906
  function collectMiddlewarePaths(routeFilePath, rootDir, dist) {
4767
- const routeDir = path15.dirname(routeFilePath);
4768
- const resolvedRoot = path15.resolve(rootDir);
4907
+ const routeDir = path16.dirname(routeFilePath);
4908
+ const resolvedRoot = path16.resolve(rootDir);
4769
4909
  const paths = [];
4770
- let currentDir = path15.resolve(rootDir, routeDir);
4910
+ let currentDir = path16.resolve(rootDir, routeDir);
4771
4911
  while (true) {
4772
4912
  if (dist) {
4773
- const mwTsPath = path15.join(currentDir, "middlewares.ts");
4774
- const mwJsPath = path15.join(currentDir, "middlewares.js");
4775
- const absTsPath = path15.resolve(rootDir, mwTsPath);
4776
- const absJsPath = path15.resolve(rootDir, mwJsPath);
4777
- 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;
4778
4918
  if (absMwPath) {
4779
- const relMwPath = path15.relative(rootDir, absMwPath);
4780
- const prodAbsPath = path15.resolve(rootDir, toProdFilePath3(relMwPath, dist));
4919
+ const relMwPath = path16.relative(rootDir, absMwPath);
4920
+ const prodAbsPath = path16.resolve(rootDir, toProdFilePath3(relMwPath, dist));
4781
4921
  paths.push(prodAbsPath);
4782
4922
  }
4783
4923
  } else {
4784
4924
  for (const ext of [".ts", ".js"]) {
4785
- const mwPath = path15.join(currentDir, `middlewares${ext}`);
4786
- const absMwPath = path15.resolve(rootDir, mwPath);
4787
- if (fs16.existsSync(absMwPath)) {
4925
+ const mwPath = path16.join(currentDir, `middlewares${ext}`);
4926
+ const absMwPath = path16.resolve(rootDir, mwPath);
4927
+ if (fs17.existsSync(absMwPath)) {
4788
4928
  paths.push(absMwPath);
4789
4929
  break;
4790
4930
  }
4791
4931
  }
4792
4932
  }
4793
4933
  if (currentDir === resolvedRoot) break;
4794
- const parentDir = path15.dirname(currentDir);
4934
+ const parentDir = path16.dirname(currentDir);
4795
4935
  if (parentDir === currentDir) break;
4796
4936
  currentDir = parentDir;
4797
4937
  }
@@ -4818,7 +4958,7 @@ async function scanRoutes(rootDir, patterns, dist) {
4818
4958
  const normalizedFile = file.replace(/\\/g, "/");
4819
4959
  const fileName = normalizedFile.split("/").pop();
4820
4960
  if (fileName === "handler.ts" || fileName === "handler.js") {
4821
- const absPath = path15.resolve(rootDir, normalizedFile);
4961
+ const absPath = path16.resolve(rootDir, normalizedFile);
4822
4962
  const urlPath = filePathToUrlPath(normalizedFile);
4823
4963
  const paramNames = extractParamNames(urlPath);
4824
4964
  const isDynamic = paramNames.length > 0;
@@ -4831,7 +4971,7 @@ async function scanRoutes(rootDir, patterns, dist) {
4831
4971
  const mwPaths = collectMiddlewarePaths(normalizedFile, rootDir);
4832
4972
  middlewareBundle = await loadMergedMiddlewares(mwPaths);
4833
4973
  }
4834
- const source = await fs16.promises.readFile(absPath, "utf8").catch(() => "");
4974
+ const source = await fs17.promises.readFile(absPath, "utf8").catch(() => "");
4835
4975
  const exportNames = extractExportsFromSource(source);
4836
4976
  const methods = HTTP_METHODS.filter((m) => exportNames.has(m));
4837
4977
  for (const method of methods) {
@@ -4867,8 +5007,8 @@ async function scanRoutes(rootDir, patterns, dist) {
4867
5007
 
4868
5008
  // src/tools/scanTools.ts
4869
5009
  import fg3 from "fast-glob";
4870
- import path16 from "path";
4871
- import fs17 from "fs";
5010
+ import path17 from "path";
5011
+ import fs18 from "fs";
4872
5012
  var TOOL_PATTERNS = ["src/tools/**/*.ts"];
4873
5013
  var TOOL_EXPORT_RE = new RegExp(
4874
5014
  String.raw`export\s+(?:async\s+)?(?:function\s+|const\s+)([A-Za-z_$][\w$]*)\s*(?:\(|=)`,
@@ -4918,8 +5058,8 @@ async function scanTools(rootDir, patterns) {
4918
5058
  if (fileName !== "handler.ts" && fileName !== "handler.js") {
4919
5059
  continue;
4920
5060
  }
4921
- const absPath = path16.resolve(rootDir, normalizedFile);
4922
- 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(() => "");
4923
5063
  const exportNames = extractToolExportsFromSource(source);
4924
5064
  const namespace = filePathToToolNamespace(normalizedFile);
4925
5065
  for (const fnName of exportNames) {
@@ -4943,8 +5083,8 @@ async function scanTools(rootDir, patterns) {
4943
5083
 
4944
5084
  // src/agents/scanAgents.ts
4945
5085
  import fg4 from "fast-glob";
4946
- import path17 from "path";
4947
- import fs18 from "fs";
5086
+ import path18 from "path";
5087
+ import fs19 from "fs";
4948
5088
  var DEFAULT_AGENT_PATTERNS = ["src/agents/*/handler.ts"];
4949
5089
  var RUN_EXPORT_RE = /export\s+(?:async\s+)?(?:function\s+|const\s+)run\b/;
4950
5090
  function extractAgentNameFromPath(filePath) {
@@ -4976,8 +5116,8 @@ async function scanAgents(rootDir, patterns) {
4976
5116
  if (fileName !== "handler.ts" && fileName !== "handler.js") {
4977
5117
  continue;
4978
5118
  }
4979
- const absPath = path17.resolve(rootDir, normalizedFile);
4980
- 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(() => "");
4981
5121
  const { hasRun } = detectAgentExports(source);
4982
5122
  const name = extractAgentNameFromPath(normalizedFile);
4983
5123
  const prevFile = seen.get(name);