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