@faapi/faapi 5.1.0 → 5.3.0
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 +238 -173
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +154 -89
- package/dist/index.js.map +1 -1
- package/dist/{routeTypes-DG0eL3l5.d.ts → routeTypes-Bm--uTbm.d.ts} +2 -2
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +109 -52
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -115,6 +115,7 @@ var init_readTsconfig = __esm({
|
|
|
115
115
|
});
|
|
116
116
|
|
|
117
117
|
// src/cli/aliasPlugin.ts
|
|
118
|
+
import ts2 from "typescript";
|
|
118
119
|
import path3 from "path";
|
|
119
120
|
import fs3 from "fs";
|
|
120
121
|
function toProdImportPath(sourceFile, importer) {
|
|
@@ -145,7 +146,14 @@ function resolveRelativeSpecifier(importer, specifier) {
|
|
|
145
146
|
const importerDir = path3.dirname(importer);
|
|
146
147
|
const base = path3.resolve(importerDir, specifier);
|
|
147
148
|
if (PROD_EXTS.some((ext) => specifier.endsWith(ext))) {
|
|
148
|
-
|
|
149
|
+
if (fs3.existsSync(base)) return base;
|
|
150
|
+
if (base.endsWith(".js")) {
|
|
151
|
+
for (const ext of [".ts", ".tsx", ".jsx"]) {
|
|
152
|
+
const file = base.slice(0, -3) + ext;
|
|
153
|
+
if (fs3.existsSync(file)) return file;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
149
157
|
}
|
|
150
158
|
if (/\.(ts|tsx|jsx)$/.test(specifier)) {
|
|
151
159
|
return fs3.existsSync(base) ? base : null;
|
|
@@ -161,8 +169,18 @@ function resolveRelativeSpecifier(importer, specifier) {
|
|
|
161
169
|
return null;
|
|
162
170
|
}
|
|
163
171
|
function createAliasPlugin(config, options) {
|
|
164
|
-
const SPEC_RE2 = /(\bfrom\s*|import\s*\(\s*)(['"])([^'"]+)\2/g;
|
|
165
172
|
const appDirAbs = options?.rootDir ? toRealPath(path3.resolve(options.rootDir, APP_DIR)) : null;
|
|
173
|
+
const probeCandidateFile = (candidate) => {
|
|
174
|
+
for (const ext of SOURCE_EXTS) {
|
|
175
|
+
const file = candidate + ext;
|
|
176
|
+
if (fs3.existsSync(file)) return file;
|
|
177
|
+
}
|
|
178
|
+
for (const indexExt of INDEX_EXTS) {
|
|
179
|
+
const file = candidate + indexExt;
|
|
180
|
+
if (fs3.existsSync(file)) return file;
|
|
181
|
+
}
|
|
182
|
+
return null;
|
|
183
|
+
};
|
|
166
184
|
return {
|
|
167
185
|
name: "faapi-alias",
|
|
168
186
|
setup(build) {
|
|
@@ -175,64 +193,103 @@ function createAliasPlugin(config, options) {
|
|
|
175
193
|
}
|
|
176
194
|
const importer = args.path;
|
|
177
195
|
const importerOutsideAppDir = appDirAbs ? !isInsideDir(importer, appDirAbs) : false;
|
|
178
|
-
|
|
179
|
-
const
|
|
196
|
+
const sourceFile = ts2.createSourceFile(importer, source, ts2.ScriptTarget.Latest, false);
|
|
197
|
+
const literals = [];
|
|
198
|
+
const visit = (node) => {
|
|
199
|
+
if (ts2.isImportDeclaration(node)) {
|
|
200
|
+
if (!node.importClause?.isTypeOnly && node.moduleSpecifier) {
|
|
201
|
+
if (ts2.isStringLiteral(node.moduleSpecifier)) literals.push(node.moduleSpecifier);
|
|
202
|
+
}
|
|
203
|
+
} else if (ts2.isExportDeclaration(node)) {
|
|
204
|
+
if (!node.isTypeOnly && node.moduleSpecifier) {
|
|
205
|
+
if (ts2.isStringLiteral(node.moduleSpecifier)) literals.push(node.moduleSpecifier);
|
|
206
|
+
}
|
|
207
|
+
} else if (ts2.isCallExpression(node) && node.expression.kind === ts2.SyntaxKind.ImportKeyword && node.arguments[0] && ts2.isStringLiteral(node.arguments[0])) {
|
|
208
|
+
literals.push(node.arguments[0]);
|
|
209
|
+
}
|
|
210
|
+
ts2.forEachChild(node, visit);
|
|
211
|
+
};
|
|
212
|
+
ts2.forEachChild(sourceFile, visit);
|
|
213
|
+
const replacements = [];
|
|
214
|
+
const unresolvable = [];
|
|
215
|
+
for (const lit of literals) {
|
|
216
|
+
const specifier = lit.text;
|
|
180
217
|
if (specifier.startsWith("/") || specifier.startsWith("file:") || specifier.startsWith("node:")) {
|
|
181
|
-
|
|
218
|
+
continue;
|
|
182
219
|
}
|
|
183
220
|
if (specifier.startsWith("./") || specifier.startsWith("../")) {
|
|
184
221
|
const resolved = resolveRelativeSpecifier(importer, specifier);
|
|
185
|
-
if (resolved) {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
189
|
-
if (appDirAbs && importerOutsideAppDir && isInsideDir(resolved, appDirAbs)) {
|
|
190
|
-
modified = true;
|
|
191
|
-
return `${prefix}${quote}${toProdImportFromImporter(
|
|
192
|
-
importer,
|
|
193
|
-
options.rootDir,
|
|
194
|
-
toStrippedProdImportPath(resolved, options.rootDir)
|
|
195
|
-
)}${quote}`;
|
|
196
|
-
}
|
|
197
|
-
modified = true;
|
|
198
|
-
return `${prefix}${quote}${toProdImportPath(resolved, importer)}${quote}`;
|
|
222
|
+
if (!resolved) {
|
|
223
|
+
unresolvable.push(lit);
|
|
224
|
+
continue;
|
|
199
225
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
importer,
|
|
211
|
-
options.rootDir,
|
|
212
|
-
toStrippedProdImportPath(file, options.rootDir)
|
|
213
|
-
)}${quote}`;
|
|
214
|
-
}
|
|
215
|
-
return `${prefix}${quote}${toProdImportPath(file, importer)}${quote}`;
|
|
216
|
-
}
|
|
226
|
+
if (PROD_EXTS.some((ext) => specifier.endsWith(ext))) continue;
|
|
227
|
+
let prodPath;
|
|
228
|
+
if (appDirAbs && importerOutsideAppDir && isInsideDir(resolved, appDirAbs)) {
|
|
229
|
+
prodPath = toProdImportFromImporter(
|
|
230
|
+
importer,
|
|
231
|
+
options.rootDir,
|
|
232
|
+
toStrippedProdImportPath(resolved, options.rootDir)
|
|
233
|
+
);
|
|
234
|
+
} else {
|
|
235
|
+
prodPath = toProdImportPath(resolved, importer);
|
|
217
236
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
237
|
+
const quote = source[lit.getStart(sourceFile)];
|
|
238
|
+
replacements.push({
|
|
239
|
+
start: lit.getStart(sourceFile),
|
|
240
|
+
end: lit.getEnd(),
|
|
241
|
+
text: quote + prodPath + quote
|
|
242
|
+
});
|
|
243
|
+
continue;
|
|
244
|
+
}
|
|
245
|
+
for (const candidate of resolveAlias(specifier, config)) {
|
|
246
|
+
const file = probeCandidateFile(candidate);
|
|
247
|
+
if (!file) continue;
|
|
248
|
+
let prodPath;
|
|
249
|
+
if (appDirAbs && importerOutsideAppDir && isInsideDir(file, appDirAbs)) {
|
|
250
|
+
prodPath = toProdImportFromImporter(
|
|
251
|
+
importer,
|
|
252
|
+
options.rootDir,
|
|
253
|
+
toStrippedProdImportPath(file, options.rootDir)
|
|
254
|
+
);
|
|
255
|
+
} else {
|
|
256
|
+
prodPath = toProdImportPath(file, importer);
|
|
231
257
|
}
|
|
258
|
+
const quote = source[lit.getStart(sourceFile)];
|
|
259
|
+
replacements.push({
|
|
260
|
+
start: lit.getStart(sourceFile),
|
|
261
|
+
end: lit.getEnd(),
|
|
262
|
+
text: quote + prodPath + quote
|
|
263
|
+
});
|
|
264
|
+
break;
|
|
232
265
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
266
|
+
}
|
|
267
|
+
if (unresolvable.length > 0) {
|
|
268
|
+
const lineStarts = sourceFile.getLineStarts();
|
|
269
|
+
return {
|
|
270
|
+
errors: unresolvable.map((lit) => {
|
|
271
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(
|
|
272
|
+
lit.getStart(sourceFile)
|
|
273
|
+
);
|
|
274
|
+
const lineEnd = line + 1 < lineStarts.length ? lineStarts[line + 1] : sourceFile.getEnd();
|
|
275
|
+
return {
|
|
276
|
+
text: `\u65E0\u6CD5\u89E3\u6790\u7684\u76F8\u5BF9\u5BFC\u5165 "${lit.text}"\u2014\u2014\u9879\u76EE\u5185\u4E0D\u5B58\u5728\u5BF9\u5E94\u6E90\u6587\u4EF6\uFF08faapi \u9010\u6587\u4EF6\u7F16\u8BD1\uFF08bundle: false\uFF09\u4E0D\u89E3\u6790\u4F9D\u8D56\uFF0C\u8BE5\u5BFC\u5165\u4F1A\u539F\u6837\u8FDB\u5165\u4EA7\u7269\uFF0C\u751F\u4EA7 Node ESM \u8FD0\u884C\u65F6\u62A5 ERR_MODULE_NOT_FOUND\uFF09\u3002\u8BF7\u4FEE\u6B63\u8DEF\u5F84\u6216\u8865\u5168\u540E\u7F00`,
|
|
277
|
+
location: {
|
|
278
|
+
file: importer,
|
|
279
|
+
line: line + 1,
|
|
280
|
+
column: character,
|
|
281
|
+
lineText: source.slice(lineStarts[line], lineEnd).replace(/\r?\n$/, "")
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
})
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
if (replacements.length === 0) return void 0;
|
|
288
|
+
replacements.sort((a, b) => b.start - a.start);
|
|
289
|
+
let newSource = source;
|
|
290
|
+
for (const r of replacements) {
|
|
291
|
+
newSource = newSource.slice(0, r.start) + r.text + newSource.slice(r.end);
|
|
292
|
+
}
|
|
236
293
|
return { contents: newSource, loader: "default" };
|
|
237
294
|
});
|
|
238
295
|
}
|
|
@@ -653,8 +710,8 @@ var init_parseRouteFile = __esm({
|
|
|
653
710
|
|
|
654
711
|
// src/utils/importWithCacheBust.ts
|
|
655
712
|
import { pathToFileURL } from "url";
|
|
656
|
-
function setLoadTimestamp(
|
|
657
|
-
loadTs =
|
|
713
|
+
function setLoadTimestamp(ts11) {
|
|
714
|
+
loadTs = ts11;
|
|
658
715
|
}
|
|
659
716
|
function getVitestImportActual() {
|
|
660
717
|
const vi = globalThis.vi;
|
|
@@ -997,14 +1054,14 @@ var init_scanTools = __esm({
|
|
|
997
1054
|
});
|
|
998
1055
|
|
|
999
1056
|
// src/ast/jsDocMetadata.ts
|
|
1000
|
-
import
|
|
1057
|
+
import ts3 from "typescript";
|
|
1001
1058
|
function hasExportModifier(node) {
|
|
1002
|
-
if (!
|
|
1003
|
-
const modifiers =
|
|
1004
|
-
return !!modifiers?.some((m) => m.kind ===
|
|
1059
|
+
if (!ts3.canHaveModifiers(node)) return false;
|
|
1060
|
+
const modifiers = ts3.getModifiers(node);
|
|
1061
|
+
return !!modifiers?.some((m) => m.kind === ts3.SyntaxKind.ExportKeyword);
|
|
1005
1062
|
}
|
|
1006
1063
|
function getJSDocFromNode(node) {
|
|
1007
|
-
const apiDocs =
|
|
1064
|
+
const apiDocs = ts3.getJSDocCommentsAndTags(node).filter((entry) => ts3.isJSDoc(entry));
|
|
1008
1065
|
if (apiDocs.length > 0) return apiDocs[0];
|
|
1009
1066
|
const directDocs = node.jsDoc;
|
|
1010
1067
|
if (directDocs && directDocs.length > 0) return directDocs[0];
|
|
@@ -1035,7 +1092,7 @@ var init_jsDocMetadata = __esm({
|
|
|
1035
1092
|
});
|
|
1036
1093
|
|
|
1037
1094
|
// src/ast/extractToolMetadata.ts
|
|
1038
|
-
import
|
|
1095
|
+
import ts4 from "typescript";
|
|
1039
1096
|
function extractToolMetadata(program, filePath, functionName, pathMeta) {
|
|
1040
1097
|
const sourceFile = program.getSourceFile(filePath);
|
|
1041
1098
|
if (!sourceFile) return null;
|
|
@@ -1056,18 +1113,18 @@ function extractToolMetadata(program, filePath, functionName, pathMeta) {
|
|
|
1056
1113
|
}
|
|
1057
1114
|
function findExportedFunction(sourceFile, functionName) {
|
|
1058
1115
|
let result = null;
|
|
1059
|
-
|
|
1116
|
+
ts4.forEachChild(sourceFile, (node) => {
|
|
1060
1117
|
if (result) return;
|
|
1061
|
-
if (
|
|
1118
|
+
if (ts4.isFunctionDeclaration(node) && hasExportModifier(node) && node.name?.text === functionName) {
|
|
1062
1119
|
result = { fn: node, jsDocOwner: node };
|
|
1063
1120
|
return;
|
|
1064
1121
|
}
|
|
1065
|
-
if (
|
|
1122
|
+
if (ts4.isVariableStatement(node) && hasExportModifier(node)) {
|
|
1066
1123
|
for (const decl of node.declarationList.declarations) {
|
|
1067
1124
|
if (result) break;
|
|
1068
|
-
const nameText =
|
|
1125
|
+
const nameText = ts4.isIdentifier(decl.name) ? decl.name.text : decl.name.getText(sourceFile);
|
|
1069
1126
|
if (nameText !== functionName || !decl.initializer) continue;
|
|
1070
|
-
if (
|
|
1127
|
+
if (ts4.isArrowFunction(decl.initializer) || ts4.isFunctionExpression(decl.initializer)) {
|
|
1071
1128
|
result = { fn: decl.initializer, jsDocOwner: node };
|
|
1072
1129
|
}
|
|
1073
1130
|
}
|
|
@@ -1079,7 +1136,7 @@ function getFirstParamTypeName(fn, sourceFile) {
|
|
|
1079
1136
|
const firstParam = fn.parameters[0];
|
|
1080
1137
|
if (!firstParam) return void 0;
|
|
1081
1138
|
if (!firstParam.type) return void 0;
|
|
1082
|
-
if (!
|
|
1139
|
+
if (!ts4.isTypeReferenceNode(firstParam.type)) return void 0;
|
|
1083
1140
|
return firstParam.type.typeName.getText(sourceFile);
|
|
1084
1141
|
}
|
|
1085
1142
|
var init_extractToolMetadata = __esm({
|
|
@@ -1090,7 +1147,7 @@ var init_extractToolMetadata = __esm({
|
|
|
1090
1147
|
});
|
|
1091
1148
|
|
|
1092
1149
|
// src/ast/createProgram.ts
|
|
1093
|
-
import
|
|
1150
|
+
import ts5 from "typescript";
|
|
1094
1151
|
import fs10 from "fs";
|
|
1095
1152
|
import path10 from "path";
|
|
1096
1153
|
function invalidateProgramCache() {
|
|
@@ -1116,16 +1173,16 @@ function parseTsConfig(tsconfigPath) {
|
|
|
1116
1173
|
if (cached) return cached;
|
|
1117
1174
|
const result = { fileNames: [] };
|
|
1118
1175
|
try {
|
|
1119
|
-
const configFile =
|
|
1176
|
+
const configFile = ts5.readConfigFile(tsconfigPath, (p) => fs10.readFileSync(p, "utf-8"));
|
|
1120
1177
|
if (configFile.error) {
|
|
1121
1178
|
tsConfigCache.set(tsconfigPath, result);
|
|
1122
1179
|
return result;
|
|
1123
1180
|
}
|
|
1124
1181
|
const config = configFile.config ?? {};
|
|
1125
1182
|
const basePath = path10.dirname(tsconfigPath);
|
|
1126
|
-
const parsed =
|
|
1183
|
+
const parsed = ts5.parseJsonConfigFileContent(
|
|
1127
1184
|
config,
|
|
1128
|
-
|
|
1185
|
+
ts5.sys,
|
|
1129
1186
|
basePath,
|
|
1130
1187
|
/* existingOptions */
|
|
1131
1188
|
void 0,
|
|
@@ -1190,9 +1247,9 @@ function createPrograms(filePaths) {
|
|
|
1190
1247
|
function buildProgram(entryFiles, tsconfigPath) {
|
|
1191
1248
|
const options = {
|
|
1192
1249
|
strict: true,
|
|
1193
|
-
target:
|
|
1194
|
-
module:
|
|
1195
|
-
moduleResolution:
|
|
1250
|
+
target: ts5.ScriptTarget.ES2022,
|
|
1251
|
+
module: ts5.ModuleKind.NodeNext,
|
|
1252
|
+
moduleResolution: ts5.ModuleResolutionKind.NodeNext,
|
|
1196
1253
|
skipLibCheck: true,
|
|
1197
1254
|
noEmit: true
|
|
1198
1255
|
};
|
|
@@ -1213,7 +1270,7 @@ function buildProgram(entryFiles, tsconfigPath) {
|
|
|
1213
1270
|
}
|
|
1214
1271
|
}
|
|
1215
1272
|
}
|
|
1216
|
-
return
|
|
1273
|
+
return ts5.createProgram(rootNames, options);
|
|
1217
1274
|
}
|
|
1218
1275
|
var programCache, tsConfigCache;
|
|
1219
1276
|
var init_createProgram = __esm({
|
|
@@ -1225,86 +1282,86 @@ var init_createProgram = __esm({
|
|
|
1225
1282
|
});
|
|
1226
1283
|
|
|
1227
1284
|
// src/ast/resolveTypeNode.ts
|
|
1228
|
-
import
|
|
1285
|
+
import ts6 from "typescript";
|
|
1229
1286
|
function setProgramContext(program) {
|
|
1230
1287
|
currentProgram = program;
|
|
1231
1288
|
}
|
|
1232
1289
|
function resolveTypeNode(typeNode, checker, visited = /* @__PURE__ */ new Set(), bindings = /* @__PURE__ */ new Map()) {
|
|
1233
1290
|
const kind = typeNode.kind;
|
|
1234
1291
|
switch (kind) {
|
|
1235
|
-
case
|
|
1292
|
+
case ts6.SyntaxKind.StringKeyword:
|
|
1236
1293
|
return { kind: "string" };
|
|
1237
|
-
case
|
|
1294
|
+
case ts6.SyntaxKind.NumberKeyword:
|
|
1238
1295
|
return { kind: "number" };
|
|
1239
|
-
case
|
|
1296
|
+
case ts6.SyntaxKind.BooleanKeyword:
|
|
1240
1297
|
return { kind: "boolean" };
|
|
1241
|
-
case
|
|
1298
|
+
case ts6.SyntaxKind.BigIntKeyword:
|
|
1242
1299
|
throw new SchemaExtractionError(
|
|
1243
1300
|
typeNode.getText(),
|
|
1244
1301
|
"bigint \u65E0\u6CD5\u901A\u8FC7 HTTP/JSON \u4F20\u8F93,\u8BF7\u6539\u7528 string \u6216 number"
|
|
1245
1302
|
);
|
|
1246
|
-
case
|
|
1303
|
+
case ts6.SyntaxKind.SymbolKeyword:
|
|
1247
1304
|
throw new SchemaExtractionError(typeNode.getText(), "symbol \u65E0\u6CD5\u901A\u8FC7 HTTP/JSON \u4F20\u8F93");
|
|
1248
|
-
case
|
|
1305
|
+
case ts6.SyntaxKind.NullKeyword:
|
|
1249
1306
|
return { kind: "null" };
|
|
1250
|
-
case
|
|
1307
|
+
case ts6.SyntaxKind.UndefinedKeyword:
|
|
1251
1308
|
return { kind: "undefined" };
|
|
1252
|
-
case
|
|
1309
|
+
case ts6.SyntaxKind.UnknownKeyword:
|
|
1253
1310
|
return { kind: "any" };
|
|
1254
|
-
case
|
|
1311
|
+
case ts6.SyntaxKind.AnyKeyword:
|
|
1255
1312
|
throw new SchemaExtractionError(typeNode.getText(), "any \u4E0D\u652F\u6301\uFF0C\u8BF7\u4F7F\u7528 unknown \u8868\u793A\u4E0D\u6821\u9A8C");
|
|
1256
|
-
case
|
|
1313
|
+
case ts6.SyntaxKind.VoidKeyword:
|
|
1257
1314
|
throw new SchemaExtractionError(typeNode.getText(), "void \u4E0D\u652F\u6301\u8FD0\u884C\u65F6\u6821\u9A8C");
|
|
1258
|
-
case
|
|
1315
|
+
case ts6.SyntaxKind.NeverKeyword:
|
|
1259
1316
|
throw new SchemaExtractionError(typeNode.getText(), "never \u4E0D\u652F\u6301\u8FD0\u884C\u65F6\u6821\u9A8C");
|
|
1260
|
-
case
|
|
1317
|
+
case ts6.SyntaxKind.ObjectKeyword:
|
|
1261
1318
|
throw new SchemaExtractionError(
|
|
1262
1319
|
typeNode.getText(),
|
|
1263
1320
|
"object \u4E0D\u652F\u6301\uFF0C\u8BF7\u4F7F\u7528\u5177\u4F53\u5BF9\u8C61\u7C7B\u578B\u6216 unknown"
|
|
1264
1321
|
);
|
|
1265
1322
|
}
|
|
1266
|
-
if (
|
|
1323
|
+
if (ts6.isLiteralTypeNode(typeNode)) {
|
|
1267
1324
|
const literal = typeNode.literal;
|
|
1268
|
-
if (
|
|
1325
|
+
if (ts6.isStringLiteral(literal)) {
|
|
1269
1326
|
return { kind: "literal", value: literal.text };
|
|
1270
1327
|
}
|
|
1271
|
-
if (
|
|
1328
|
+
if (ts6.isNumericLiteral(literal)) {
|
|
1272
1329
|
return { kind: "literal", value: Number(literal.text) };
|
|
1273
1330
|
}
|
|
1274
|
-
if (literal.kind ===
|
|
1331
|
+
if (literal.kind === ts6.SyntaxKind.TrueKeyword) {
|
|
1275
1332
|
return { kind: "literal", value: true };
|
|
1276
1333
|
}
|
|
1277
|
-
if (literal.kind ===
|
|
1334
|
+
if (literal.kind === ts6.SyntaxKind.FalseKeyword) {
|
|
1278
1335
|
return { kind: "literal", value: false };
|
|
1279
1336
|
}
|
|
1280
|
-
if (literal.kind ===
|
|
1337
|
+
if (literal.kind === ts6.SyntaxKind.NullKeyword) {
|
|
1281
1338
|
return { kind: "null" };
|
|
1282
1339
|
}
|
|
1283
1340
|
throw new SchemaExtractionError(typeNode.getText(), "\u4E0D\u652F\u6301\u7684\u5B57\u9762\u91CF\u7C7B\u578B");
|
|
1284
1341
|
}
|
|
1285
|
-
if (
|
|
1342
|
+
if (ts6.isArrayTypeNode(typeNode)) {
|
|
1286
1343
|
return {
|
|
1287
1344
|
kind: "array",
|
|
1288
1345
|
element: resolveTypeNode(typeNode.elementType, checker, visited, bindings)
|
|
1289
1346
|
};
|
|
1290
1347
|
}
|
|
1291
|
-
if (
|
|
1348
|
+
if (ts6.isTupleTypeNode(typeNode)) {
|
|
1292
1349
|
const elements = typeNode.elements.map((e) => {
|
|
1293
|
-
if (
|
|
1350
|
+
if (ts6.isRestTypeNode(e)) {
|
|
1294
1351
|
const inner = resolveTypeNode(e.type, checker, visited, bindings);
|
|
1295
1352
|
if (inner.kind === "array") {
|
|
1296
1353
|
return { type: inner.element, optional: false, rest: true };
|
|
1297
1354
|
}
|
|
1298
1355
|
return { type: inner, optional: false, rest: true };
|
|
1299
1356
|
}
|
|
1300
|
-
if (
|
|
1357
|
+
if (ts6.isNamedTupleMember(e)) {
|
|
1301
1358
|
return {
|
|
1302
1359
|
type: resolveTypeNode(e.type, checker, visited, bindings),
|
|
1303
1360
|
optional: !!e.questionToken,
|
|
1304
1361
|
rest: false
|
|
1305
1362
|
};
|
|
1306
1363
|
}
|
|
1307
|
-
if (
|
|
1364
|
+
if (ts6.isOptionalTypeNode(e)) {
|
|
1308
1365
|
return {
|
|
1309
1366
|
type: resolveTypeNode(e.type, checker, visited, bindings),
|
|
1310
1367
|
optional: true,
|
|
@@ -1319,11 +1376,11 @@ function resolveTypeNode(typeNode, checker, visited = /* @__PURE__ */ new Set(),
|
|
|
1319
1376
|
});
|
|
1320
1377
|
return { kind: "tuple", elements };
|
|
1321
1378
|
}
|
|
1322
|
-
if (
|
|
1379
|
+
if (ts6.isUnionTypeNode(typeNode)) {
|
|
1323
1380
|
const members = typeNode.types.map((t) => resolveTypeNode(t, checker, visited, bindings));
|
|
1324
1381
|
return { kind: "union", members };
|
|
1325
1382
|
}
|
|
1326
|
-
if (
|
|
1383
|
+
if (ts6.isIntersectionTypeNode(typeNode)) {
|
|
1327
1384
|
const propMap = /* @__PURE__ */ new Map();
|
|
1328
1385
|
for (const t of typeNode.types) {
|
|
1329
1386
|
const resolved = resolveTypeNode(t, checker, visited, bindings);
|
|
@@ -1353,19 +1410,19 @@ function resolveTypeNode(typeNode, checker, visited = /* @__PURE__ */ new Set(),
|
|
|
1353
1410
|
}
|
|
1354
1411
|
return { kind: "object", properties: [...propMap.values()] };
|
|
1355
1412
|
}
|
|
1356
|
-
if (
|
|
1413
|
+
if (ts6.isTypeLiteralNode(typeNode)) {
|
|
1357
1414
|
return resolveTypeLiteral(typeNode, checker, visited, bindings);
|
|
1358
1415
|
}
|
|
1359
|
-
if (
|
|
1416
|
+
if (ts6.isTypeOperatorNode(typeNode) && typeNode.operator === ts6.SyntaxKind.KeyOfKeyword) {
|
|
1360
1417
|
return resolveKeyOf(typeNode, checker);
|
|
1361
1418
|
}
|
|
1362
|
-
if (
|
|
1419
|
+
if (ts6.isTypeOperatorNode(typeNode) && typeNode.operator === ts6.SyntaxKind.ReadonlyKeyword) {
|
|
1363
1420
|
return resolveTypeNode(typeNode.type, checker, visited, bindings);
|
|
1364
1421
|
}
|
|
1365
|
-
if (
|
|
1422
|
+
if (ts6.isTypeReferenceNode(typeNode)) {
|
|
1366
1423
|
return resolveTypeReference(typeNode, checker, visited, bindings);
|
|
1367
1424
|
}
|
|
1368
|
-
if (
|
|
1425
|
+
if (ts6.isExpressionWithTypeArguments(typeNode)) {
|
|
1369
1426
|
return resolveTypeReference(
|
|
1370
1427
|
{
|
|
1371
1428
|
getText: () => typeNode.getText(),
|
|
@@ -1383,14 +1440,14 @@ function resolveTypeLiteral(typeNode, checker, visited = /* @__PURE__ */ new Set
|
|
|
1383
1440
|
const properties = [];
|
|
1384
1441
|
let catchall;
|
|
1385
1442
|
for (const member of typeNode.members) {
|
|
1386
|
-
if (
|
|
1443
|
+
if (ts6.isMethodSignature(member) || ts6.isGetAccessorDeclaration(member) || ts6.isSetAccessorDeclaration(member)) {
|
|
1387
1444
|
throw SchemaExtractionError.at(
|
|
1388
1445
|
member,
|
|
1389
1446
|
member.getText(),
|
|
1390
1447
|
"\u5BF9\u8C61\u7C7B\u578B\u542B\u65B9\u6CD5\u7B7E\u540D\u6216\u5B58\u53D6\u5668,\u8FD0\u884C\u65F6 JSON \u6570\u636E\u65E0\u6CD5\u6821\u9A8C\u65B9\u6CD5\u2014\u2014\u8BF7\u6539\u7528\u5177\u4F53\u5C5E\u6027\u7C7B\u578B"
|
|
1391
1448
|
);
|
|
1392
1449
|
}
|
|
1393
|
-
if (
|
|
1450
|
+
if (ts6.isPropertySignature(member) && member.name) {
|
|
1394
1451
|
const name = member.name.getText();
|
|
1395
1452
|
const optional = !!member.questionToken;
|
|
1396
1453
|
const type = member.type ? resolveTypeNode(member.type, checker, visited, bindings) : { kind: "any" };
|
|
@@ -1400,7 +1457,7 @@ function resolveTypeLiteral(typeNode, checker, visited = /* @__PURE__ */ new Set
|
|
|
1400
1457
|
constraints.length > 0 ? { name, type, optional, constraints } : { name, type, optional }
|
|
1401
1458
|
);
|
|
1402
1459
|
}
|
|
1403
|
-
if (
|
|
1460
|
+
if (ts6.isIndexSignatureDeclaration(member)) {
|
|
1404
1461
|
catchall = member.type ? resolveTypeNode(member.type, checker, visited, bindings) : { kind: "any" };
|
|
1405
1462
|
}
|
|
1406
1463
|
}
|
|
@@ -1580,11 +1637,11 @@ function resolveTypeReference(typeNode, checker, visited = /* @__PURE__ */ new S
|
|
|
1580
1637
|
}
|
|
1581
1638
|
visited.add(typeName);
|
|
1582
1639
|
if (checker) {
|
|
1583
|
-
const symbol =
|
|
1640
|
+
const symbol = ts6.isIdentifier(typeNode.typeName) || ts6.isQualifiedName(typeNode.typeName) ? checker.getSymbolAtLocation(typeNode.typeName) : void 0;
|
|
1584
1641
|
if (symbol) {
|
|
1585
1642
|
const declaration = symbol.declarations?.[0];
|
|
1586
1643
|
if (declaration) {
|
|
1587
|
-
if (
|
|
1644
|
+
if (ts6.isInterfaceDeclaration(declaration)) {
|
|
1588
1645
|
return resolveInterfaceDeclaration(
|
|
1589
1646
|
declaration,
|
|
1590
1647
|
checker,
|
|
@@ -1593,7 +1650,7 @@ function resolveTypeReference(typeNode, checker, visited = /* @__PURE__ */ new S
|
|
|
1593
1650
|
typeNode.typeArguments
|
|
1594
1651
|
);
|
|
1595
1652
|
}
|
|
1596
|
-
if (
|
|
1653
|
+
if (ts6.isTypeAliasDeclaration(declaration)) {
|
|
1597
1654
|
const declBindings = bindTypeParameters(
|
|
1598
1655
|
declaration.typeParameters,
|
|
1599
1656
|
typeNode.typeArguments,
|
|
@@ -1604,10 +1661,10 @@ function resolveTypeReference(typeNode, checker, visited = /* @__PURE__ */ new S
|
|
|
1604
1661
|
);
|
|
1605
1662
|
return resolveTypeNode(declaration.type, checker, visited, declBindings);
|
|
1606
1663
|
}
|
|
1607
|
-
if (
|
|
1664
|
+
if (ts6.isEnumDeclaration(declaration)) {
|
|
1608
1665
|
return resolveEnumDeclaration(declaration);
|
|
1609
1666
|
}
|
|
1610
|
-
if (
|
|
1667
|
+
if (ts6.isImportSpecifier(declaration) || ts6.isImportClause(declaration)) {
|
|
1611
1668
|
const resolved = resolveImportAlias(
|
|
1612
1669
|
typeNode,
|
|
1613
1670
|
symbol,
|
|
@@ -1649,10 +1706,10 @@ function resolveImportAlias(typeNode, symbol, checker, visited, bindings = /* @_
|
|
|
1649
1706
|
const aliased = checker.getAliasedSymbol(symbol);
|
|
1650
1707
|
if (aliased && aliased.declarations && aliased.declarations.length > 0) {
|
|
1651
1708
|
const decl = aliased.declarations[0];
|
|
1652
|
-
if (
|
|
1709
|
+
if (ts6.isInterfaceDeclaration(decl)) {
|
|
1653
1710
|
return resolveInterfaceDeclaration(decl, checker, visited, bindings, typeArguments);
|
|
1654
1711
|
}
|
|
1655
|
-
if (
|
|
1712
|
+
if (ts6.isTypeAliasDeclaration(decl)) {
|
|
1656
1713
|
const declBindings = bindTypeParameters(
|
|
1657
1714
|
decl.typeParameters,
|
|
1658
1715
|
typeArguments,
|
|
@@ -1663,7 +1720,7 @@ function resolveImportAlias(typeNode, symbol, checker, visited, bindings = /* @_
|
|
|
1663
1720
|
);
|
|
1664
1721
|
return resolveTypeNode(decl.type, checker, visited, declBindings);
|
|
1665
1722
|
}
|
|
1666
|
-
if (
|
|
1723
|
+
if (ts6.isEnumDeclaration(decl)) {
|
|
1667
1724
|
return resolveEnumDeclaration(decl);
|
|
1668
1725
|
}
|
|
1669
1726
|
}
|
|
@@ -1701,13 +1758,13 @@ function resolveImportAlias(typeNode, symbol, checker, visited, bindings = /* @_
|
|
|
1701
1758
|
}
|
|
1702
1759
|
function findTopLevelDecl(sourceFile, typeName) {
|
|
1703
1760
|
let found = null;
|
|
1704
|
-
|
|
1761
|
+
ts6.forEachChild(sourceFile, (node) => {
|
|
1705
1762
|
if (found) return;
|
|
1706
|
-
if (
|
|
1763
|
+
if (ts6.isInterfaceDeclaration(node) && node.name.text === typeName) {
|
|
1707
1764
|
found = { kind: "interface", node };
|
|
1708
|
-
} else if (
|
|
1765
|
+
} else if (ts6.isTypeAliasDeclaration(node) && node.name.text === typeName) {
|
|
1709
1766
|
found = { kind: "typeAlias", node };
|
|
1710
|
-
} else if (
|
|
1767
|
+
} else if (ts6.isEnumDeclaration(node) && node.name.text === typeName) {
|
|
1711
1768
|
found = { kind: "enum", node };
|
|
1712
1769
|
}
|
|
1713
1770
|
});
|
|
@@ -1718,9 +1775,9 @@ function resolveEnumDeclaration(node) {
|
|
|
1718
1775
|
let nextNumericValue = 0;
|
|
1719
1776
|
for (const member of node.members) {
|
|
1720
1777
|
if (member.initializer) {
|
|
1721
|
-
if (
|
|
1778
|
+
if (ts6.isStringLiteral(member.initializer)) {
|
|
1722
1779
|
members.push({ kind: "literal", value: member.initializer.text });
|
|
1723
|
-
} else if (
|
|
1780
|
+
} else if (ts6.isNumericLiteral(member.initializer)) {
|
|
1724
1781
|
const num = Number(member.initializer.text);
|
|
1725
1782
|
members.push({ kind: "literal", value: num });
|
|
1726
1783
|
nextNumericValue = num + 1;
|
|
@@ -1750,7 +1807,7 @@ function resolveInterfaceDeclaration(node, checker, visited = /* @__PURE__ */ ne
|
|
|
1750
1807
|
node
|
|
1751
1808
|
);
|
|
1752
1809
|
for (const heritageClause of node.heritageClauses ?? []) {
|
|
1753
|
-
if (heritageClause.token ===
|
|
1810
|
+
if (heritageClause.token === ts6.SyntaxKind.ExtendsKeyword) {
|
|
1754
1811
|
for (const expr of heritageClause.types) {
|
|
1755
1812
|
const parentType = resolveTypeNode(expr, checker, visited, bindings);
|
|
1756
1813
|
if (parentType.kind === "object") {
|
|
@@ -1762,14 +1819,14 @@ function resolveInterfaceDeclaration(node, checker, visited = /* @__PURE__ */ ne
|
|
|
1762
1819
|
}
|
|
1763
1820
|
}
|
|
1764
1821
|
for (const member of node.members) {
|
|
1765
|
-
if (
|
|
1822
|
+
if (ts6.isMethodSignature(member) || ts6.isGetAccessorDeclaration(member) || ts6.isSetAccessorDeclaration(member)) {
|
|
1766
1823
|
throw SchemaExtractionError.at(
|
|
1767
1824
|
member,
|
|
1768
1825
|
member.getText(),
|
|
1769
1826
|
"\u63A5\u53E3\u542B\u65B9\u6CD5\u7B7E\u540D\u6216\u5B58\u53D6\u5668,\u8FD0\u884C\u65F6 JSON \u6570\u636E\u65E0\u6CD5\u6821\u9A8C\u65B9\u6CD5\u2014\u2014\u8BF7\u6539\u7528\u5177\u4F53\u5C5E\u6027\u7C7B\u578B"
|
|
1770
1827
|
);
|
|
1771
1828
|
}
|
|
1772
|
-
if (
|
|
1829
|
+
if (ts6.isPropertySignature(member) && member.name) {
|
|
1773
1830
|
const name = member.name.getText();
|
|
1774
1831
|
const optional = !!member.questionToken;
|
|
1775
1832
|
const type = member.type ? resolveTypeNode(member.type, checker, visited, bindings) : { kind: "any" };
|
|
@@ -1780,7 +1837,7 @@ function resolveInterfaceDeclaration(node, checker, visited = /* @__PURE__ */ ne
|
|
|
1780
1837
|
constraints.length > 0 ? { name, type, optional, constraints } : { name, type, optional }
|
|
1781
1838
|
);
|
|
1782
1839
|
}
|
|
1783
|
-
if (
|
|
1840
|
+
if (ts6.isIndexSignatureDeclaration(member)) {
|
|
1784
1841
|
catchall = member.type ? resolveTypeNode(member.type, checker, visited, bindings) : { kind: "any" };
|
|
1785
1842
|
}
|
|
1786
1843
|
}
|
|
@@ -1790,7 +1847,7 @@ function resolveInterfaceDeclaration(node, checker, visited = /* @__PURE__ */ ne
|
|
|
1790
1847
|
return catchall !== void 0 ? { kind: "object", properties, catchall } : { kind: "object", properties };
|
|
1791
1848
|
}
|
|
1792
1849
|
function extractConstraintsFromJsDoc(node, fieldName) {
|
|
1793
|
-
const jsDocs =
|
|
1850
|
+
const jsDocs = ts6.getJSDocCommentsAndTags(node).filter((entry) => ts6.isJSDoc(entry));
|
|
1794
1851
|
if (jsDocs.length === 0) return [];
|
|
1795
1852
|
const constraints = [];
|
|
1796
1853
|
for (const jsDoc of jsDocs) {
|
|
@@ -1971,7 +2028,7 @@ var init_resolveTypeNode = __esm({
|
|
|
1971
2028
|
});
|
|
1972
2029
|
|
|
1973
2030
|
// src/ast/extractHandlerTypes.ts
|
|
1974
|
-
import
|
|
2031
|
+
import ts7 from "typescript";
|
|
1975
2032
|
function extractTypeInfo(program, filePath, typeName) {
|
|
1976
2033
|
const sourceFile = program.getSourceFile(filePath);
|
|
1977
2034
|
if (!sourceFile) return null;
|
|
@@ -1979,9 +2036,9 @@ function extractTypeInfo(program, filePath, typeName) {
|
|
|
1979
2036
|
setProgramContext(program);
|
|
1980
2037
|
try {
|
|
1981
2038
|
let result = null;
|
|
1982
|
-
|
|
2039
|
+
ts7.forEachChild(sourceFile, (node) => {
|
|
1983
2040
|
if (result) return;
|
|
1984
|
-
if (
|
|
2041
|
+
if (ts7.isInterfaceDeclaration(node) && node.name.text === typeName) {
|
|
1985
2042
|
const visited = /* @__PURE__ */ new Set();
|
|
1986
2043
|
visited.add(typeName);
|
|
1987
2044
|
const runtimeType = withFileContext(
|
|
@@ -1996,7 +2053,7 @@ function extractTypeInfo(program, filePath, typeName) {
|
|
|
1996
2053
|
};
|
|
1997
2054
|
return;
|
|
1998
2055
|
}
|
|
1999
|
-
if (
|
|
2056
|
+
if (ts7.isTypeAliasDeclaration(node) && node.name.text === typeName) {
|
|
2000
2057
|
const visited = /* @__PURE__ */ new Set();
|
|
2001
2058
|
visited.add(typeName);
|
|
2002
2059
|
const runtimeType = withFileContext(
|
|
@@ -2106,7 +2163,7 @@ var init_schemaName = __esm({
|
|
|
2106
2163
|
});
|
|
2107
2164
|
|
|
2108
2165
|
// src/injection/resolveInjection.ts
|
|
2109
|
-
import
|
|
2166
|
+
import ts8 from "typescript";
|
|
2110
2167
|
function resolveInjection(fn) {
|
|
2111
2168
|
const cached = injectionCache.get(fn);
|
|
2112
2169
|
if (cached) {
|
|
@@ -2127,53 +2184,53 @@ function resolveInjection(fn) {
|
|
|
2127
2184
|
return items;
|
|
2128
2185
|
}
|
|
2129
2186
|
function extractParamsWithAst(fnStr) {
|
|
2130
|
-
const sourceFile =
|
|
2187
|
+
const sourceFile = ts8.createSourceFile(
|
|
2131
2188
|
"__faapi_injection__.ts",
|
|
2132
2189
|
fnStr,
|
|
2133
|
-
|
|
2190
|
+
ts8.ScriptTarget.Latest,
|
|
2134
2191
|
true
|
|
2135
2192
|
);
|
|
2136
2193
|
const paramNames = [];
|
|
2137
2194
|
function visit(node) {
|
|
2138
|
-
if (
|
|
2195
|
+
if (ts8.isFunctionDeclaration(node) && node.parameters.length > 0) {
|
|
2139
2196
|
for (const param of node.parameters) {
|
|
2140
2197
|
extractParamName(param, paramNames);
|
|
2141
2198
|
}
|
|
2142
2199
|
return;
|
|
2143
2200
|
}
|
|
2144
|
-
if ((
|
|
2201
|
+
if ((ts8.isArrowFunction(node) || ts8.isFunctionExpression(node)) && node.parameters.length > 0) {
|
|
2145
2202
|
for (const param of node.parameters) {
|
|
2146
2203
|
extractParamName(param, paramNames);
|
|
2147
2204
|
}
|
|
2148
2205
|
return;
|
|
2149
2206
|
}
|
|
2150
|
-
|
|
2207
|
+
ts8.forEachChild(node, visit);
|
|
2151
2208
|
}
|
|
2152
2209
|
visit(sourceFile);
|
|
2153
2210
|
return paramNames.map((name) => ({ name }));
|
|
2154
2211
|
}
|
|
2155
2212
|
function extractParamName(param, names) {
|
|
2156
2213
|
const name = param.name;
|
|
2157
|
-
if (
|
|
2214
|
+
if (ts8.isIdentifier(name)) {
|
|
2158
2215
|
names.push(name.text);
|
|
2159
2216
|
return;
|
|
2160
2217
|
}
|
|
2161
|
-
if (
|
|
2218
|
+
if (ts8.isObjectBindingPattern(name)) {
|
|
2162
2219
|
for (const element of name.elements) {
|
|
2163
|
-
if (
|
|
2220
|
+
if (ts8.isBindingElement(element)) {
|
|
2164
2221
|
const elemName = element.name;
|
|
2165
|
-
if (
|
|
2222
|
+
if (ts8.isIdentifier(elemName)) {
|
|
2166
2223
|
names.push(elemName.text);
|
|
2167
2224
|
}
|
|
2168
2225
|
}
|
|
2169
2226
|
}
|
|
2170
2227
|
return;
|
|
2171
2228
|
}
|
|
2172
|
-
if (
|
|
2229
|
+
if (ts8.isArrayBindingPattern(name)) {
|
|
2173
2230
|
for (const element of name.elements) {
|
|
2174
|
-
if (element &&
|
|
2231
|
+
if (element && ts8.isBindingElement(element)) {
|
|
2175
2232
|
const elemName = element.name;
|
|
2176
|
-
if (
|
|
2233
|
+
if (ts8.isIdentifier(elemName)) {
|
|
2177
2234
|
names.push(elemName.text);
|
|
2178
2235
|
}
|
|
2179
2236
|
}
|
|
@@ -2209,11 +2266,11 @@ var init_resolveInjection = __esm({
|
|
|
2209
2266
|
});
|
|
2210
2267
|
|
|
2211
2268
|
// src/injection/analyzeInjection.ts
|
|
2212
|
-
import
|
|
2269
|
+
import ts9 from "typescript";
|
|
2213
2270
|
function analyzeInjectionInSourceFile(sourceFile, functionName) {
|
|
2214
2271
|
const params = [];
|
|
2215
|
-
|
|
2216
|
-
if (
|
|
2272
|
+
ts9.forEachChild(sourceFile, (node) => {
|
|
2273
|
+
if (ts9.isFunctionDeclaration(node) && node.name?.text === functionName) {
|
|
2217
2274
|
for (const param of node.parameters) {
|
|
2218
2275
|
const paramMeta = analyzeParam(param, sourceFile);
|
|
2219
2276
|
params.push(paramMeta);
|
|
@@ -2227,9 +2284,9 @@ function analyzeParam(param, sourceFile) {
|
|
|
2227
2284
|
const type = PARAM_TYPE_MAP[name] || "unknown";
|
|
2228
2285
|
const result = { name, type };
|
|
2229
2286
|
if (param.type) {
|
|
2230
|
-
if (
|
|
2287
|
+
if (ts9.isTypeReferenceNode(param.type)) {
|
|
2231
2288
|
result.typeName = param.type.typeName.getText(sourceFile);
|
|
2232
|
-
} else if (
|
|
2289
|
+
} else if (ts9.isTypeLiteralNode(param.type)) {
|
|
2233
2290
|
result.schema = extractSchema(param.type, sourceFile);
|
|
2234
2291
|
}
|
|
2235
2292
|
}
|
|
@@ -2238,7 +2295,7 @@ function analyzeParam(param, sourceFile) {
|
|
|
2238
2295
|
function extractSchema(typeNode, sourceFile) {
|
|
2239
2296
|
const schema = [];
|
|
2240
2297
|
for (const member of typeNode.members) {
|
|
2241
|
-
if (
|
|
2298
|
+
if (ts9.isPropertySignature(member) && member.name && ts9.isIdentifier(member.name)) {
|
|
2242
2299
|
const propName = member.name.text;
|
|
2243
2300
|
const optional = !!member.questionToken;
|
|
2244
2301
|
const propType = member.type?.getText(sourceFile) || "unknown";
|
|
@@ -3005,7 +3062,7 @@ var init_scanAgents = __esm({
|
|
|
3005
3062
|
});
|
|
3006
3063
|
|
|
3007
3064
|
// src/ast/extractAgentMetadata.ts
|
|
3008
|
-
import
|
|
3065
|
+
import ts10 from "typescript";
|
|
3009
3066
|
function extractAgentMetadata(program, filePath, pathMeta) {
|
|
3010
3067
|
const sourceFile = program.getSourceFile(filePath);
|
|
3011
3068
|
if (!sourceFile) return null;
|
|
@@ -3014,7 +3071,7 @@ function extractAgentMetadata(program, filePath, pathMeta) {
|
|
|
3014
3071
|
throw SchemaExtractionError.at(
|
|
3015
3072
|
sourceFile,
|
|
3016
3073
|
"config.systemPrompt",
|
|
3017
|
-
"agent \u5FC5\u586B\u2014\u2014\u8BF7\u5728 config \u5757\u58F0\u660E\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF08\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\
|
|
3074
|
+
"agent \u5FC5\u586B\u2014\u2014\u8BF7\u5728 config \u5757\u58F0\u660E\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF08\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u3001\u65E0\u63D2\u503C\u6A21\u677F\u5B57\u7B26\u4E32\u6216\u5176 + \u62FC\u63A5\uFF09",
|
|
3018
3075
|
sourceFile
|
|
3019
3076
|
);
|
|
3020
3077
|
}
|
|
@@ -3048,23 +3105,23 @@ function extractAgentMetadata(program, filePath, pathMeta) {
|
|
|
3048
3105
|
}
|
|
3049
3106
|
function findConfigExport(sourceFile) {
|
|
3050
3107
|
let result = null;
|
|
3051
|
-
|
|
3108
|
+
ts10.forEachChild(sourceFile, (node) => {
|
|
3052
3109
|
if (result) return;
|
|
3053
|
-
if (
|
|
3110
|
+
if (ts10.isVariableStatement(node) && hasExportModifier(node)) {
|
|
3054
3111
|
for (const decl of node.declarationList.declarations) {
|
|
3055
3112
|
if (result) break;
|
|
3056
|
-
const nameText =
|
|
3113
|
+
const nameText = ts10.isIdentifier(decl.name) ? decl.name.text : "";
|
|
3057
3114
|
if (nameText !== "config" || !decl.initializer) continue;
|
|
3058
|
-
if (
|
|
3115
|
+
if (ts10.isObjectLiteralExpression(decl.initializer)) {
|
|
3059
3116
|
result = { jsDocOwner: node, objectLiteral: decl.initializer };
|
|
3060
|
-
} else if (
|
|
3117
|
+
} else if (ts10.isArrowFunction(decl.initializer)) {
|
|
3061
3118
|
result = { jsDocOwner: node, objectLiteral: getReturnObjectLiteral(decl.initializer) };
|
|
3062
3119
|
} else {
|
|
3063
3120
|
result = { jsDocOwner: node, objectLiteral: null };
|
|
3064
3121
|
}
|
|
3065
3122
|
}
|
|
3066
3123
|
}
|
|
3067
|
-
if (
|
|
3124
|
+
if (ts10.isFunctionDeclaration(node) && hasExportModifier(node) && node.name?.text === "config") {
|
|
3068
3125
|
const returnObj = getReturnObjectLiteral(node);
|
|
3069
3126
|
result = { jsDocOwner: node, objectLiteral: returnObj };
|
|
3070
3127
|
}
|
|
@@ -3074,12 +3131,12 @@ function findConfigExport(sourceFile) {
|
|
|
3074
3131
|
function getReturnObjectLiteral(fn) {
|
|
3075
3132
|
const body = fn.body;
|
|
3076
3133
|
if (!body) return null;
|
|
3077
|
-
if (
|
|
3134
|
+
if (ts10.isObjectLiteralExpression(body)) {
|
|
3078
3135
|
return body;
|
|
3079
3136
|
}
|
|
3080
|
-
if (
|
|
3137
|
+
if (ts10.isBlock(body)) {
|
|
3081
3138
|
for (const stmt of body.statements) {
|
|
3082
|
-
if (
|
|
3139
|
+
if (ts10.isReturnStatement(stmt) && stmt.expression && ts10.isObjectLiteralExpression(stmt.expression)) {
|
|
3083
3140
|
return stmt.expression;
|
|
3084
3141
|
}
|
|
3085
3142
|
}
|
|
@@ -3093,8 +3150,8 @@ function extractConfigFields(objLit, sourceFile) {
|
|
|
3093
3150
|
let model;
|
|
3094
3151
|
let maxTurns;
|
|
3095
3152
|
for (const prop of objLit.properties) {
|
|
3096
|
-
if (
|
|
3097
|
-
if (!
|
|
3153
|
+
if (ts10.isSpreadAssignment(prop)) continue;
|
|
3154
|
+
if (!ts10.isPropertyAssignment(prop)) {
|
|
3098
3155
|
throw SchemaExtractionError.at(
|
|
3099
3156
|
prop,
|
|
3100
3157
|
"config",
|
|
@@ -3135,19 +3192,26 @@ function extractConfigFields(objLit, sourceFile) {
|
|
|
3135
3192
|
throw SchemaExtractionError.at(
|
|
3136
3193
|
objLit,
|
|
3137
3194
|
"config.systemPrompt",
|
|
3138
|
-
"agent \u5FC5\u586B\u2014\u2014\u8BF7\u5728 config \u5757\u58F0\u660E\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF08\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\
|
|
3195
|
+
"agent \u5FC5\u586B\u2014\u2014\u8BF7\u5728 config \u5757\u58F0\u660E\u7CFB\u7EDF\u63D0\u793A\u8BCD\uFF08\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u3001\u65E0\u63D2\u503C\u6A21\u677F\u5B57\u7B26\u4E32\u6216\u5176 + \u62FC\u63A5\uFF09",
|
|
3139
3196
|
sourceFile
|
|
3140
3197
|
);
|
|
3141
3198
|
}
|
|
3142
3199
|
return { systemPrompt, tools, agents, model, maxTurns };
|
|
3143
3200
|
}
|
|
3144
3201
|
function getPropertyName(name) {
|
|
3145
|
-
if (
|
|
3146
|
-
if (
|
|
3202
|
+
if (ts10.isIdentifier(name)) return name.text;
|
|
3203
|
+
if (ts10.isStringLiteral(name)) return name.text;
|
|
3147
3204
|
return null;
|
|
3148
3205
|
}
|
|
3149
3206
|
function extractStringValue(expr) {
|
|
3150
3207
|
if (isStringLikeLiteral(expr)) return expr.text;
|
|
3208
|
+
if (ts10.isBinaryExpression(expr) && expr.operatorToken.kind === ts10.SyntaxKind.PlusToken) {
|
|
3209
|
+
const left = extractStringValue(expr.left);
|
|
3210
|
+
if (left === void 0) return void 0;
|
|
3211
|
+
const right = extractStringValue(expr.right);
|
|
3212
|
+
if (right === void 0) return void 0;
|
|
3213
|
+
return left + right;
|
|
3214
|
+
}
|
|
3151
3215
|
return void 0;
|
|
3152
3216
|
}
|
|
3153
3217
|
function requireStringValue(prop, fieldName, sourceFile) {
|
|
@@ -3156,7 +3220,7 @@ function requireStringValue(prop, fieldName, sourceFile) {
|
|
|
3156
3220
|
throw SchemaExtractionError.at(
|
|
3157
3221
|
prop.initializer,
|
|
3158
3222
|
`config.${fieldName}`,
|
|
3159
|
-
"\u4EC5\u652F\u6301\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\
|
|
3223
|
+
"\u4EC5\u652F\u6301\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u3001\u65E0\u63D2\u503C\u6A21\u677F\u5B57\u7B26\u4E32\u6216\u5176 + \u62FC\u63A5\uFF08\u542B\u63D2\u503C\u7684\u6A21\u677F\u5B57\u7B26\u4E32/\u53D8\u91CF\u5F15\u7528/\u6570\u5B57\u65E0\u6CD5\u9759\u6001\u6C42\u503C\u4E3A\u5B57\u7B26\u4E32\uFF09",
|
|
3160
3224
|
sourceFile
|
|
3161
3225
|
);
|
|
3162
3226
|
}
|
|
@@ -3168,7 +3232,7 @@ function requireStringArrayValue(prop, fieldName, sourceFile) {
|
|
|
3168
3232
|
throw SchemaExtractionError.at(
|
|
3169
3233
|
prop.initializer,
|
|
3170
3234
|
`config.${fieldName}`,
|
|
3171
|
-
"\u4EC5\u652F\u6301\u5168\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u6570\u7EC4\uFF08\u5143\u7D20\u4E3A\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\
|
|
3235
|
+
"\u4EC5\u652F\u6301\u5168\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u6570\u7EC4\uFF08\u5143\u7D20\u4E3A\u5B57\u7B26\u4E32\u5B57\u9762\u91CF\u3001\u65E0\u63D2\u503C\u6A21\u677F\u5B57\u7B26\u4E32\u6216\u5176 + \u62FC\u63A5\uFF09",
|
|
3172
3236
|
sourceFile
|
|
3173
3237
|
);
|
|
3174
3238
|
}
|
|
@@ -3187,21 +3251,22 @@ function requireNumberValue(prop, fieldName, sourceFile) {
|
|
|
3187
3251
|
return value;
|
|
3188
3252
|
}
|
|
3189
3253
|
function extractNumberValue(expr) {
|
|
3190
|
-
if (
|
|
3254
|
+
if (ts10.isNumericLiteral(expr)) {
|
|
3191
3255
|
const num = Number(expr.text);
|
|
3192
3256
|
return Number.isNaN(num) ? void 0 : num;
|
|
3193
3257
|
}
|
|
3194
3258
|
return void 0;
|
|
3195
3259
|
}
|
|
3196
3260
|
function isStringLikeLiteral(node) {
|
|
3197
|
-
return
|
|
3261
|
+
return ts10.isStringLiteral(node) || ts10.isNoSubstitutionTemplateLiteral(node);
|
|
3198
3262
|
}
|
|
3199
3263
|
function extractStringArrayValue(expr) {
|
|
3200
|
-
if (!
|
|
3264
|
+
if (!ts10.isArrayLiteralExpression(expr)) return void 0;
|
|
3201
3265
|
const values = [];
|
|
3202
3266
|
for (const element of expr.elements) {
|
|
3203
|
-
|
|
3204
|
-
|
|
3267
|
+
const value = extractStringValue(element);
|
|
3268
|
+
if (value === void 0) return void 0;
|
|
3269
|
+
values.push(value);
|
|
3205
3270
|
}
|
|
3206
3271
|
return values;
|
|
3207
3272
|
}
|