@faapi/faapi 6.7.0 → 6.9.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 +539 -233
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +50 -3
- package/dist/index.js +494 -210
- package/dist/index.js.map +1 -1
- package/dist/{routeTypes-CsL7xtqu.d.ts → routeTypes-CuGMDCGB.d.ts} +121 -2
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +136 -2
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1122,8 +1122,10 @@ var init_resolveInjection = __esm({
|
|
|
1122
1122
|
// Phase 2.3
|
|
1123
1123
|
agents: "agents",
|
|
1124
1124
|
// Phase 2.3
|
|
1125
|
-
tasks: "tasks"
|
|
1125
|
+
tasks: "tasks",
|
|
1126
1126
|
// 任务子系统:TaskClient(入队/查询)
|
|
1127
|
+
log: "log"
|
|
1128
|
+
// 请求级日志器(ctx.log 同一实例:scope http,自动带 requestId 等字段)
|
|
1127
1129
|
};
|
|
1128
1130
|
injectionCache = /* @__PURE__ */ new WeakMap();
|
|
1129
1131
|
}
|
|
@@ -1233,13 +1235,13 @@ var init_collectRouteSchemaSources = __esm({
|
|
|
1233
1235
|
});
|
|
1234
1236
|
|
|
1235
1237
|
// src/utils/atomicWrite.ts
|
|
1236
|
-
import
|
|
1237
|
-
import
|
|
1238
|
+
import path10 from "path";
|
|
1239
|
+
import fs8 from "fs";
|
|
1238
1240
|
async function atomicWriteFile(outputPath, content) {
|
|
1239
|
-
await
|
|
1241
|
+
await fs8.promises.mkdir(path10.dirname(outputPath), { recursive: true });
|
|
1240
1242
|
const tmp = `${outputPath}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
1241
|
-
await
|
|
1242
|
-
await
|
|
1243
|
+
await fs8.promises.writeFile(tmp, content, "utf-8");
|
|
1244
|
+
await fs8.promises.rename(tmp, outputPath);
|
|
1243
1245
|
}
|
|
1244
1246
|
var init_atomicWrite = __esm({
|
|
1245
1247
|
"src/utils/atomicWrite.ts"() {
|
|
@@ -1586,7 +1588,7 @@ __export(generateSchemaFiles_exports, {
|
|
|
1586
1588
|
getRuntimeSchemaPath: () => getRuntimeSchemaPath,
|
|
1587
1589
|
getSchemaOutputPath: () => getSchemaOutputPath
|
|
1588
1590
|
});
|
|
1589
|
-
import
|
|
1591
|
+
import path11 from "path";
|
|
1590
1592
|
function getSchemaOutputPath(sourceFile, dist, rootDir) {
|
|
1591
1593
|
let rel = sourceFile.replace(/\\/g, "/");
|
|
1592
1594
|
if (rel.startsWith("src/")) {
|
|
@@ -1594,7 +1596,7 @@ function getSchemaOutputPath(sourceFile, dist, rootDir) {
|
|
|
1594
1596
|
}
|
|
1595
1597
|
const idx = rel.lastIndexOf("/");
|
|
1596
1598
|
const relDir = idx >= 0 ? rel.slice(0, idx) : "";
|
|
1597
|
-
return
|
|
1599
|
+
return path11.resolve(rootDir, dist, relDir, "zod.js");
|
|
1598
1600
|
}
|
|
1599
1601
|
function getRuntimeSchemaPath(filePath, dist, rootDir) {
|
|
1600
1602
|
let rel = filePath.replace(/\\/g, "/");
|
|
@@ -1605,7 +1607,7 @@ function getRuntimeSchemaPath(filePath, dist, rootDir) {
|
|
|
1605
1607
|
}
|
|
1606
1608
|
const idx = rel.lastIndexOf("/");
|
|
1607
1609
|
const relDir = idx >= 0 ? rel.slice(0, idx) : "";
|
|
1608
|
-
return
|
|
1610
|
+
return path11.resolve(rootDir, dist, relDir, "zod.js");
|
|
1609
1611
|
}
|
|
1610
1612
|
function getHelpersImportPath(relDir) {
|
|
1611
1613
|
if (!relDir) return `./${HELPERS_FILENAME}`;
|
|
@@ -1664,7 +1666,7 @@ async function generateSchemaFiles(routes, rootDir, dist) {
|
|
|
1664
1666
|
}
|
|
1665
1667
|
const fileEntries = [];
|
|
1666
1668
|
for (const [filePath, fileSources] of sourcesByFile) {
|
|
1667
|
-
const relFile =
|
|
1669
|
+
const relFile = path11.relative(rootDir, filePath).replace(/\\/g, "/");
|
|
1668
1670
|
const outputPath = getSchemaOutputPath(relFile, dist, rootDir);
|
|
1669
1671
|
let relForDir = relFile;
|
|
1670
1672
|
if (relForDir.startsWith("src/")) {
|
|
@@ -1683,7 +1685,7 @@ async function generateSchemaFiles(routes, rootDir, dist) {
|
|
|
1683
1685
|
}
|
|
1684
1686
|
const allSourceCode = fileEntries.map((e) => e.source).join("\n");
|
|
1685
1687
|
if (usesCoerceHelpers(allSourceCode)) {
|
|
1686
|
-
const helpersPath =
|
|
1688
|
+
const helpersPath = path11.resolve(rootDir, dist, HELPERS_FILENAME);
|
|
1687
1689
|
await writeSchemaFile(helpersPath, generateHelpersFileSource());
|
|
1688
1690
|
}
|
|
1689
1691
|
await Promise.all(
|
|
@@ -1915,7 +1917,7 @@ function createAppRegistries() {
|
|
|
1915
1917
|
var defaultRegistries = createAppRegistries();
|
|
1916
1918
|
|
|
1917
1919
|
// src/task/taskQueue.ts
|
|
1918
|
-
import
|
|
1920
|
+
import path4 from "path";
|
|
1919
1921
|
|
|
1920
1922
|
// src/errors/FaapiError.ts
|
|
1921
1923
|
var FaapiError = class extends Error {
|
|
@@ -1943,14 +1945,14 @@ var ValidationError = class extends FaapiError {
|
|
|
1943
1945
|
issues;
|
|
1944
1946
|
};
|
|
1945
1947
|
var RouteNotFoundError = class extends FaapiError {
|
|
1946
|
-
constructor(
|
|
1947
|
-
super("ROUTE_NOT_FOUND", `Route not found: ${
|
|
1948
|
+
constructor(path29) {
|
|
1949
|
+
super("ROUTE_NOT_FOUND", `Route not found: ${path29}`, 404);
|
|
1948
1950
|
this.name = "RouteNotFoundError";
|
|
1949
1951
|
}
|
|
1950
1952
|
};
|
|
1951
1953
|
var MethodNotAllowedError = class extends FaapiError {
|
|
1952
|
-
constructor(method,
|
|
1953
|
-
super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${
|
|
1954
|
+
constructor(method, path29, allowedMethods) {
|
|
1955
|
+
super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path29}`, 405);
|
|
1954
1956
|
this.allowedMethods = allowedMethods;
|
|
1955
1957
|
this.name = "MethodNotAllowedError";
|
|
1956
1958
|
}
|
|
@@ -2066,6 +2068,36 @@ function serializeError(err) {
|
|
|
2066
2068
|
return { name: 'Error', message: String(err), stack: undefined, props: {} };
|
|
2067
2069
|
}
|
|
2068
2070
|
`;
|
|
2071
|
+
var BUILD_LOGGER_SOURCE = `
|
|
2072
|
+
var LOG_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
2073
|
+
function createTaskLogger(level, scope, fields) {
|
|
2074
|
+
function make(suffix) {
|
|
2075
|
+
function write(lvl, message, callFields) {
|
|
2076
|
+
if (level !== undefined && LOG_RANK[lvl] < LOG_RANK[level]) return;
|
|
2077
|
+
var entry = { level: lvl, message: message, time: new Date().toISOString() };
|
|
2078
|
+
var fullScope = suffix === undefined ? scope : scope === undefined ? suffix : scope + ':' + suffix;
|
|
2079
|
+
if (fullScope !== undefined) entry.scope = fullScope;
|
|
2080
|
+
if (fields !== undefined || callFields !== undefined) {
|
|
2081
|
+
entry.fields = Object.assign({}, fields, callFields);
|
|
2082
|
+
}
|
|
2083
|
+
try {
|
|
2084
|
+
parentPort.postMessage({ type: 'log', entry: entry });
|
|
2085
|
+
} catch (_) {
|
|
2086
|
+
entry.fields = { warning: 'log fields not cloneable across worker boundary, dropped' };
|
|
2087
|
+
parentPort.postMessage({ type: 'log', entry: entry });
|
|
2088
|
+
}
|
|
2089
|
+
}
|
|
2090
|
+
return {
|
|
2091
|
+
debug: function (m, f) { write('debug', m, f); },
|
|
2092
|
+
info: function (m, f) { write('info', m, f); },
|
|
2093
|
+
warn: function (m, f) { write('warn', m, f); },
|
|
2094
|
+
error: function (m, f) { write('error', m, f); },
|
|
2095
|
+
child: function (cs) { return make(suffix === undefined ? cs : suffix + ':' + cs); },
|
|
2096
|
+
};
|
|
2097
|
+
}
|
|
2098
|
+
return make(undefined);
|
|
2099
|
+
}
|
|
2100
|
+
`;
|
|
2069
2101
|
function buildWrapperSource(moduleUrl) {
|
|
2070
2102
|
return `
|
|
2071
2103
|
import { parentPort } from 'node:worker_threads';
|
|
@@ -2075,6 +2107,8 @@ ${BUILD_VIEW_SOURCE}
|
|
|
2075
2107
|
|
|
2076
2108
|
${SERIALIZE_ERROR_SOURCE}
|
|
2077
2109
|
|
|
2110
|
+
${BUILD_LOGGER_SOURCE}
|
|
2111
|
+
|
|
2078
2112
|
const run = mod.run;
|
|
2079
2113
|
if (typeof run !== 'function') {
|
|
2080
2114
|
parentPort.postMessage({
|
|
@@ -2094,7 +2128,8 @@ if (typeof run !== 'function') {
|
|
|
2094
2128
|
try {
|
|
2095
2129
|
const registries = buildRegistriesView(msg.registries);
|
|
2096
2130
|
const progress = (value) => parentPort.postMessage({ type: 'progress', value });
|
|
2097
|
-
const
|
|
2131
|
+
const taskLog = msg.log ? createTaskLogger(msg.log.level, msg.log.scope, msg.log.fields) : undefined;
|
|
2132
|
+
const result = await run(payload, { ...taskCtx, signal: controller.signal, registries, progress, log: taskLog });
|
|
2098
2133
|
parentPort.postMessage({ type: 'done', result });
|
|
2099
2134
|
} catch (err) {
|
|
2100
2135
|
const serialized = serializeError(err);
|
|
@@ -2202,6 +2237,8 @@ async function runTaskInWorker(options) {
|
|
|
2202
2237
|
finish(() => reject(reviveError(msg.error)));
|
|
2203
2238
|
} else if (msg?.type === "progress") {
|
|
2204
2239
|
options.onProgress?.(msg.value);
|
|
2240
|
+
} else if (msg?.type === "log") {
|
|
2241
|
+
options.onLog?.(msg.entry);
|
|
2205
2242
|
}
|
|
2206
2243
|
}
|
|
2207
2244
|
);
|
|
@@ -2225,7 +2262,8 @@ async function runTaskInWorker(options) {
|
|
|
2225
2262
|
type: "run",
|
|
2226
2263
|
payload,
|
|
2227
2264
|
taskCtx: { config: safeConfig(taskCtx.config), job: taskCtx.job },
|
|
2228
|
-
registries: options.registries
|
|
2265
|
+
registries: options.registries,
|
|
2266
|
+
log: options.log
|
|
2229
2267
|
});
|
|
2230
2268
|
} catch (err) {
|
|
2231
2269
|
finish(
|
|
@@ -2237,6 +2275,201 @@ async function runTaskInWorker(options) {
|
|
|
2237
2275
|
});
|
|
2238
2276
|
}
|
|
2239
2277
|
|
|
2278
|
+
// src/logger/formatEntry.ts
|
|
2279
|
+
function serializeFieldValue(value) {
|
|
2280
|
+
if (value instanceof Error) {
|
|
2281
|
+
return { name: value.name, message: value.message, stack: value.stack };
|
|
2282
|
+
}
|
|
2283
|
+
return value;
|
|
2284
|
+
}
|
|
2285
|
+
function formatEntry(entry) {
|
|
2286
|
+
let line = `[${entry.time}] ${entry.level.toUpperCase()} `;
|
|
2287
|
+
if (entry.scope) line += `[${entry.scope}] `;
|
|
2288
|
+
line += entry.message;
|
|
2289
|
+
if (entry.fields !== void 0) {
|
|
2290
|
+
const plain = Object.fromEntries(
|
|
2291
|
+
Object.entries(entry.fields).map(([k, v]) => [k, serializeFieldValue(v)])
|
|
2292
|
+
);
|
|
2293
|
+
try {
|
|
2294
|
+
line += ` ${JSON.stringify(plain)}`;
|
|
2295
|
+
} catch (err) {
|
|
2296
|
+
line += ` [unserializable fields: ${err instanceof Error ? err.message : String(err)}]`;
|
|
2297
|
+
}
|
|
2298
|
+
}
|
|
2299
|
+
return line;
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
// src/logger/fileSink.ts
|
|
2303
|
+
import fs2 from "fs";
|
|
2304
|
+
import path3 from "path";
|
|
2305
|
+
var LEVEL_FILES = ["debug", "info", "warn", "error"];
|
|
2306
|
+
function createFileLogSink(options) {
|
|
2307
|
+
fs2.mkdirSync(options.dir, { recursive: true });
|
|
2308
|
+
const streams = /* @__PURE__ */ new Map();
|
|
2309
|
+
const getStream = (name) => {
|
|
2310
|
+
if (streams.has(name)) return streams.get(name);
|
|
2311
|
+
return void 0;
|
|
2312
|
+
};
|
|
2313
|
+
const openStream = (name) => {
|
|
2314
|
+
const stream = fs2.createWriteStream(path3.join(options.dir, `${name}.log`), { flags: "a" });
|
|
2315
|
+
stream.on("error", () => {
|
|
2316
|
+
});
|
|
2317
|
+
streams.set(name, stream);
|
|
2318
|
+
};
|
|
2319
|
+
const fileNames = options.splitByLevel ? [...LEVEL_FILES] : ["app", "error"];
|
|
2320
|
+
for (const name of fileNames) openStream(name);
|
|
2321
|
+
let pendingCount = 0;
|
|
2322
|
+
let drainWaiters = [];
|
|
2323
|
+
const onWriteDone = () => {
|
|
2324
|
+
pendingCount--;
|
|
2325
|
+
if (pendingCount === 0 && drainWaiters.length > 0) {
|
|
2326
|
+
const waiters = drainWaiters;
|
|
2327
|
+
drainWaiters = [];
|
|
2328
|
+
for (const waiter of waiters) waiter();
|
|
2329
|
+
}
|
|
2330
|
+
};
|
|
2331
|
+
const write = (entry) => {
|
|
2332
|
+
const line = `${formatEntry(entry)}
|
|
2333
|
+
`;
|
|
2334
|
+
const target = options.splitByLevel ? entry.level : "app";
|
|
2335
|
+
const main = getStream(target);
|
|
2336
|
+
if (main) {
|
|
2337
|
+
pendingCount++;
|
|
2338
|
+
main.write(line, onWriteDone);
|
|
2339
|
+
}
|
|
2340
|
+
if (!options.splitByLevel && entry.level === "error") {
|
|
2341
|
+
const dup = getStream("error");
|
|
2342
|
+
if (dup) {
|
|
2343
|
+
pendingCount++;
|
|
2344
|
+
dup.write(line, onWriteDone);
|
|
2345
|
+
}
|
|
2346
|
+
}
|
|
2347
|
+
};
|
|
2348
|
+
const flush = () => new Promise((resolve) => {
|
|
2349
|
+
if (pendingCount === 0) {
|
|
2350
|
+
resolve();
|
|
2351
|
+
return;
|
|
2352
|
+
}
|
|
2353
|
+
drainWaiters.push(resolve);
|
|
2354
|
+
});
|
|
2355
|
+
const close = () => Promise.all(
|
|
2356
|
+
[...streams.values()].map(
|
|
2357
|
+
(stream) => new Promise((resolve) => {
|
|
2358
|
+
stream.end(() => resolve());
|
|
2359
|
+
})
|
|
2360
|
+
)
|
|
2361
|
+
).then(() => {
|
|
2362
|
+
streams.clear();
|
|
2363
|
+
});
|
|
2364
|
+
return { write, flush, close };
|
|
2365
|
+
}
|
|
2366
|
+
|
|
2367
|
+
// src/logger/logger.ts
|
|
2368
|
+
var LEVEL_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
2369
|
+
var VALID_LEVELS = ["debug", "info", "warn", "error"];
|
|
2370
|
+
function assertLogLevel(value, source) {
|
|
2371
|
+
if (typeof value !== "string" || !VALID_LEVELS.includes(value)) {
|
|
2372
|
+
throw new Error(
|
|
2373
|
+
`[faapi] Invalid log level from ${source}: ${String(value)}. Expected one of: ${VALID_LEVELS.join(", ")}.`
|
|
2374
|
+
);
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
var globalState = { level: null, sink: null, fileSink: null, stdout: true, accessLog: false, disabled: false };
|
|
2378
|
+
function configureLogging(config) {
|
|
2379
|
+
const objectConfig = typeof config === "object" ? config : {};
|
|
2380
|
+
if (objectConfig.sink && objectConfig.dir) {
|
|
2381
|
+
throw new Error(
|
|
2382
|
+
"[faapi] config.log.sink and config.log.dir are mutually exclusive: pick one output pipeline (custom sink OR built-in file logs)."
|
|
2383
|
+
);
|
|
2384
|
+
}
|
|
2385
|
+
void globalState.fileSink?.close();
|
|
2386
|
+
globalState.disabled = config === false;
|
|
2387
|
+
globalState.sink = objectConfig.sink ?? null;
|
|
2388
|
+
globalState.accessLog = objectConfig.accessLog ?? objectConfig.dir !== void 0;
|
|
2389
|
+
globalState.stdout = objectConfig.stdout ?? true;
|
|
2390
|
+
globalState.fileSink = objectConfig.dir ? createFileLogSink({ dir: objectConfig.dir, splitByLevel: objectConfig.splitByLevel }) : null;
|
|
2391
|
+
if (objectConfig.level !== void 0) {
|
|
2392
|
+
assertLogLevel(objectConfig.level, "config.log.level");
|
|
2393
|
+
globalState.level = objectConfig.level;
|
|
2394
|
+
} else if (process.env.LOG_LEVEL !== void 0) {
|
|
2395
|
+
assertLogLevel(process.env.LOG_LEVEL, "LOG_LEVEL env");
|
|
2396
|
+
globalState.level = process.env.LOG_LEVEL;
|
|
2397
|
+
} else {
|
|
2398
|
+
globalState.level = null;
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
function globalThreshold() {
|
|
2402
|
+
if (globalState.level) return globalState.level;
|
|
2403
|
+
if (globalState.fileSink) return void 0;
|
|
2404
|
+
return "info";
|
|
2405
|
+
}
|
|
2406
|
+
function belowThreshold(level, threshold) {
|
|
2407
|
+
return threshold !== void 0 && LEVEL_RANK[level] < LEVEL_RANK[threshold];
|
|
2408
|
+
}
|
|
2409
|
+
function getEffectiveLogLevel() {
|
|
2410
|
+
return globalThreshold();
|
|
2411
|
+
}
|
|
2412
|
+
var consoleSink = (entry) => {
|
|
2413
|
+
console[CONSOLE_METHOD[entry.level]](formatEntry(entry));
|
|
2414
|
+
};
|
|
2415
|
+
var CONSOLE_METHOD = {
|
|
2416
|
+
debug: "debug",
|
|
2417
|
+
info: "info",
|
|
2418
|
+
warn: "warn",
|
|
2419
|
+
error: "error"
|
|
2420
|
+
};
|
|
2421
|
+
function globalDispatch(entry) {
|
|
2422
|
+
if (globalState.disabled) return;
|
|
2423
|
+
if (globalState.sink) {
|
|
2424
|
+
globalState.sink(entry);
|
|
2425
|
+
return;
|
|
2426
|
+
}
|
|
2427
|
+
if (globalState.fileSink) {
|
|
2428
|
+
globalState.fileSink.write(entry);
|
|
2429
|
+
if (globalState.stdout) consoleSink(entry);
|
|
2430
|
+
return;
|
|
2431
|
+
}
|
|
2432
|
+
consoleSink(entry);
|
|
2433
|
+
}
|
|
2434
|
+
function writeLogEntry(entry) {
|
|
2435
|
+
if (belowThreshold(entry.level, globalThreshold())) return;
|
|
2436
|
+
globalDispatch(entry);
|
|
2437
|
+
}
|
|
2438
|
+
function isAccessLogPiped() {
|
|
2439
|
+
return !globalState.disabled && globalState.accessLog;
|
|
2440
|
+
}
|
|
2441
|
+
function createLogger(scope, options) {
|
|
2442
|
+
const baseScope = scope;
|
|
2443
|
+
const baseFields = options?.fields;
|
|
2444
|
+
const write = (level, message, callFields, scopeSuffix) => {
|
|
2445
|
+
const threshold = options?.level ?? globalThreshold();
|
|
2446
|
+
if (belowThreshold(level, threshold)) return;
|
|
2447
|
+
const entry = {
|
|
2448
|
+
level,
|
|
2449
|
+
message,
|
|
2450
|
+
time: (/* @__PURE__ */ new Date()).toISOString()
|
|
2451
|
+
};
|
|
2452
|
+
const fullScope = scopeSuffix === void 0 ? baseScope : baseScope === void 0 ? scopeSuffix : `${baseScope}:${scopeSuffix}`;
|
|
2453
|
+
if (fullScope !== void 0) entry.scope = fullScope;
|
|
2454
|
+
if (baseFields !== void 0 || callFields !== void 0) {
|
|
2455
|
+
entry.fields = { ...baseFields, ...callFields };
|
|
2456
|
+
}
|
|
2457
|
+
if (options?.sink) {
|
|
2458
|
+
options.sink(entry);
|
|
2459
|
+
} else {
|
|
2460
|
+
globalDispatch(entry);
|
|
2461
|
+
}
|
|
2462
|
+
};
|
|
2463
|
+
const makeLogger = (scopeSuffix) => ({
|
|
2464
|
+
debug: (message, fields) => write("debug", message, fields, scopeSuffix),
|
|
2465
|
+
info: (message, fields) => write("info", message, fields, scopeSuffix),
|
|
2466
|
+
warn: (message, fields) => write("warn", message, fields, scopeSuffix),
|
|
2467
|
+
error: (message, fields) => write("error", message, fields, scopeSuffix),
|
|
2468
|
+
child: (childScope) => makeLogger(scopeSuffix === void 0 ? childScope : `${scopeSuffix}:${childScope}`)
|
|
2469
|
+
});
|
|
2470
|
+
return makeLogger(void 0);
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2240
2473
|
// src/task/taskQueue.ts
|
|
2241
2474
|
var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["done", "failed", "cancelled"]);
|
|
2242
2475
|
var MAX_FINISHED_RECORDS = 1e3;
|
|
@@ -2269,7 +2502,7 @@ function createTaskQueue(deps) {
|
|
|
2269
2502
|
}
|
|
2270
2503
|
const loadTaskModule = deps.loadTaskModule ?? (async (filePath) => await import(filePath));
|
|
2271
2504
|
const loadPayloadSchema = deps.loadPayloadSchema ?? (async (filePath) => {
|
|
2272
|
-
const zodPath =
|
|
2505
|
+
const zodPath = path4.join(path4.dirname(filePath), "zod.js");
|
|
2273
2506
|
try {
|
|
2274
2507
|
const mod = await import(zodPath);
|
|
2275
2508
|
const schemaKey = Object.keys(mod).find((k) => k.endsWith("Schema"));
|
|
@@ -2297,7 +2530,7 @@ function createTaskQueue(deps) {
|
|
|
2297
2530
|
const meta = registry.get(name);
|
|
2298
2531
|
schemaCache.set(
|
|
2299
2532
|
name,
|
|
2300
|
-
await loadPayloadSchema(
|
|
2533
|
+
await loadPayloadSchema(path4.resolve(rootDir, meta.filePath)).catch(() => void 0)
|
|
2301
2534
|
);
|
|
2302
2535
|
}
|
|
2303
2536
|
const schema = schemaCache.get(name);
|
|
@@ -2333,24 +2566,32 @@ function createTaskQueue(deps) {
|
|
|
2333
2566
|
let result;
|
|
2334
2567
|
if (meta.timeoutMs !== void 0 && meta.timeoutMs > 0) {
|
|
2335
2568
|
result = await (deps.runIsolated ?? runTaskInWorker)({
|
|
2336
|
-
taskModulePath:
|
|
2569
|
+
taskModulePath: path4.resolve(rootDir, meta.filePath),
|
|
2337
2570
|
payload: job.payload,
|
|
2338
2571
|
taskCtx: {
|
|
2339
2572
|
config: deps.config,
|
|
2340
2573
|
job: { id: job.id, name: job.name, attempt: job.attempt }
|
|
2341
2574
|
},
|
|
2342
2575
|
registries: snapshotRegistries(),
|
|
2576
|
+
// 日志配置随 workerData 下发(纯数据),worker 内联重建 taskCtx.log,
|
|
2577
|
+
// 条目回传宿主走统一管道(scope/fields 与进程内路径一致)
|
|
2578
|
+
log: {
|
|
2579
|
+
level: getEffectiveLogLevel(),
|
|
2580
|
+
scope: `task:${job.name}`,
|
|
2581
|
+
fields: { jobId: job.id, task: job.name, attempt: job.attempt }
|
|
2582
|
+
},
|
|
2343
2583
|
timeoutMs: meta.timeoutMs,
|
|
2344
2584
|
graceMs: meta.graceMs,
|
|
2345
2585
|
externalSignal: job.signal,
|
|
2346
2586
|
onProgress: (value) => {
|
|
2347
2587
|
if (record.status === "running") record.progress = value;
|
|
2348
|
-
}
|
|
2588
|
+
},
|
|
2589
|
+
onLog: writeLogEntry
|
|
2349
2590
|
});
|
|
2350
2591
|
} else {
|
|
2351
2592
|
let mod = moduleCache2.get(job.name);
|
|
2352
2593
|
if (!mod) {
|
|
2353
|
-
mod = await loadTaskModule(
|
|
2594
|
+
mod = await loadTaskModule(path4.resolve(rootDir, meta.filePath));
|
|
2354
2595
|
moduleCache2.set(job.name, mod);
|
|
2355
2596
|
}
|
|
2356
2597
|
if (typeof mod.run !== "function") {
|
|
@@ -2361,6 +2602,9 @@ function createTaskQueue(deps) {
|
|
|
2361
2602
|
config: deps.config,
|
|
2362
2603
|
job: { id: job.id, name: job.name, attempt: job.attempt },
|
|
2363
2604
|
registries: registriesView,
|
|
2605
|
+
log: createLogger(`task:${job.name}`, {
|
|
2606
|
+
fields: { jobId: job.id, task: job.name, attempt: job.attempt }
|
|
2607
|
+
}),
|
|
2364
2608
|
progress: (value) => {
|
|
2365
2609
|
if (record.status === "running") record.progress = value;
|
|
2366
2610
|
}
|
|
@@ -2584,8 +2828,8 @@ function createCronScheduler(registry, enqueue) {
|
|
|
2584
2828
|
|
|
2585
2829
|
// src/task/scanTasks.ts
|
|
2586
2830
|
import fg from "fast-glob";
|
|
2587
|
-
import
|
|
2588
|
-
import
|
|
2831
|
+
import path5 from "path";
|
|
2832
|
+
import fs3 from "fs";
|
|
2589
2833
|
var TASK_PATTERNS = ["src/tasks/**/task.ts"];
|
|
2590
2834
|
var TASK_FILENAME = "task.ts";
|
|
2591
2835
|
var CRON_RE = /(?:^|\n)\s*cron:\s*['"`]([^'"`\n]+)['"`]/;
|
|
@@ -2616,12 +2860,12 @@ async function scanTasks(rootDir, patterns) {
|
|
|
2616
2860
|
const seen = /* @__PURE__ */ new Map();
|
|
2617
2861
|
for (const file of files) {
|
|
2618
2862
|
const normalizedFile = file.replace(/\\/g, "/");
|
|
2619
|
-
const fileName =
|
|
2863
|
+
const fileName = path5.posix.basename(normalizedFile);
|
|
2620
2864
|
if (fileName !== TASK_FILENAME) {
|
|
2621
2865
|
continue;
|
|
2622
2866
|
}
|
|
2623
|
-
const absPath =
|
|
2624
|
-
const source = await
|
|
2867
|
+
const absPath = path5.resolve(rootDir, normalizedFile);
|
|
2868
|
+
const source = await fs3.promises.readFile(absPath, "utf8").catch(() => "");
|
|
2625
2869
|
const name = filePathToTaskName(normalizedFile);
|
|
2626
2870
|
const prevFile = seen.get(name);
|
|
2627
2871
|
if (prevFile) {
|
|
@@ -2694,7 +2938,7 @@ function listSkills() {
|
|
|
2694
2938
|
}
|
|
2695
2939
|
|
|
2696
2940
|
// src/loader/loadAgentModule.ts
|
|
2697
|
-
import
|
|
2941
|
+
import fs11 from "fs";
|
|
2698
2942
|
|
|
2699
2943
|
// src/loader/resolveExports.ts
|
|
2700
2944
|
function resolveExport(module, exportName) {
|
|
@@ -2740,18 +2984,18 @@ async function importWithCacheBust(filePath, bustViteCache = false) {
|
|
|
2740
2984
|
}
|
|
2741
2985
|
|
|
2742
2986
|
// src/cli/compileOnDemand.ts
|
|
2743
|
-
import
|
|
2744
|
-
import
|
|
2987
|
+
import path13 from "path";
|
|
2988
|
+
import fs10 from "fs";
|
|
2745
2989
|
|
|
2746
2990
|
// src/cli/compileSourceFiles.ts
|
|
2747
|
-
import
|
|
2748
|
-
import
|
|
2991
|
+
import path9 from "path";
|
|
2992
|
+
import fs7 from "fs";
|
|
2749
2993
|
import fg2 from "fast-glob";
|
|
2750
2994
|
|
|
2751
2995
|
// src/cli/aliasPlugin.ts
|
|
2752
2996
|
import ts7 from "typescript";
|
|
2753
|
-
import
|
|
2754
|
-
import
|
|
2997
|
+
import path8 from "path";
|
|
2998
|
+
import fs6 from "fs";
|
|
2755
2999
|
|
|
2756
3000
|
// src/utils/resolveAlias.ts
|
|
2757
3001
|
function resolveAlias(specifier, config) {
|
|
@@ -2777,8 +3021,8 @@ function resolveAlias(specifier, config) {
|
|
|
2777
3021
|
}
|
|
2778
3022
|
|
|
2779
3023
|
// src/utils/prodPaths.ts
|
|
2780
|
-
import
|
|
2781
|
-
import
|
|
3024
|
+
import path6 from "path";
|
|
3025
|
+
import fs4 from "fs";
|
|
2782
3026
|
var APP_DIR = "src";
|
|
2783
3027
|
var ROUTE_PATTERNS = ["src/api/**/*.ts"];
|
|
2784
3028
|
function toProdFilePath(filePath, dist) {
|
|
@@ -2797,27 +3041,27 @@ function toProdExtension(filePath) {
|
|
|
2797
3041
|
}
|
|
2798
3042
|
function toRealPath(p) {
|
|
2799
3043
|
try {
|
|
2800
|
-
return
|
|
3044
|
+
return fs4.realpathSync(p);
|
|
2801
3045
|
} catch {
|
|
2802
3046
|
return p;
|
|
2803
3047
|
}
|
|
2804
3048
|
}
|
|
2805
3049
|
function isInsideDir(filePath, dir) {
|
|
2806
|
-
const rel =
|
|
2807
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
3050
|
+
const rel = path6.relative(dir, filePath);
|
|
3051
|
+
return rel !== "" && !rel.startsWith("..") && !path6.isAbsolute(rel);
|
|
2808
3052
|
}
|
|
2809
3053
|
|
|
2810
3054
|
// src/utils/readTsconfig.ts
|
|
2811
3055
|
import ts6 from "typescript";
|
|
2812
|
-
import
|
|
2813
|
-
import
|
|
3056
|
+
import path7 from "path";
|
|
3057
|
+
import fs5 from "fs";
|
|
2814
3058
|
var tsconfigCache = /* @__PURE__ */ new Map();
|
|
2815
3059
|
function readTsconfig(rootDir) {
|
|
2816
|
-
const tsconfigPath =
|
|
2817
|
-
if (!
|
|
3060
|
+
const tsconfigPath = path7.resolve(rootDir, "tsconfig.json");
|
|
3061
|
+
if (!fs5.existsSync(tsconfigPath)) return null;
|
|
2818
3062
|
let mtimeMs;
|
|
2819
3063
|
try {
|
|
2820
|
-
mtimeMs =
|
|
3064
|
+
mtimeMs = fs5.statSync(tsconfigPath).mtimeMs;
|
|
2821
3065
|
} catch {
|
|
2822
3066
|
return null;
|
|
2823
3067
|
}
|
|
@@ -2833,7 +3077,7 @@ function readTsconfig(rootDir) {
|
|
|
2833
3077
|
const config = rawPaths ? (() => {
|
|
2834
3078
|
const paths = {};
|
|
2835
3079
|
for (const [pattern, targets] of Object.entries(rawPaths)) {
|
|
2836
|
-
paths[pattern] = targets.map((t) =>
|
|
3080
|
+
paths[pattern] = targets.map((t) => path7.resolve(baseUrl, t));
|
|
2837
3081
|
}
|
|
2838
3082
|
return { baseUrl, paths };
|
|
2839
3083
|
})() : null;
|
|
@@ -2843,26 +3087,26 @@ function readTsconfig(rootDir) {
|
|
|
2843
3087
|
|
|
2844
3088
|
// src/cli/aliasPlugin.ts
|
|
2845
3089
|
function toProdImportPath(sourceFile, importer) {
|
|
2846
|
-
const importerDir =
|
|
2847
|
-
let rel =
|
|
2848
|
-
rel = rel.split(
|
|
3090
|
+
const importerDir = path8.dirname(importer);
|
|
3091
|
+
let rel = path8.relative(importerDir, sourceFile);
|
|
3092
|
+
rel = rel.split(path8.sep).join("/");
|
|
2849
3093
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
2850
3094
|
return toProdExtension(rel);
|
|
2851
3095
|
}
|
|
2852
3096
|
function toStrippedProdImportPath(sourceFile, rootDir) {
|
|
2853
|
-
const appDirAbs = toRealPath(
|
|
3097
|
+
const appDirAbs = toRealPath(path8.resolve(rootDir, APP_DIR));
|
|
2854
3098
|
const sourceReal = toRealPath(sourceFile);
|
|
2855
|
-
let rel =
|
|
2856
|
-
rel = rel.split(
|
|
3099
|
+
let rel = path8.relative(appDirAbs, sourceReal);
|
|
3100
|
+
rel = rel.split(path8.sep).join("/");
|
|
2857
3101
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
2858
3102
|
return toProdExtension(rel);
|
|
2859
3103
|
}
|
|
2860
3104
|
function toProdImportFromImporter(importer, rootDir, relFromDist) {
|
|
2861
|
-
const importerRel =
|
|
2862
|
-
const importerProdDir =
|
|
3105
|
+
const importerRel = path8.relative(toRealPath(path8.resolve(rootDir)), toRealPath(importer)).split(path8.sep).join("/");
|
|
3106
|
+
const importerProdDir = path8.posix.dirname(toProdExtension(importerRel));
|
|
2863
3107
|
if (importerProdDir === ".") return relFromDist;
|
|
2864
3108
|
const target = relFromDist.replace(/^\.\//, "");
|
|
2865
|
-
let rel =
|
|
3109
|
+
let rel = path8.posix.relative(importerProdDir, target);
|
|
2866
3110
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
2867
3111
|
return rel;
|
|
2868
3112
|
}
|
|
@@ -2877,41 +3121,41 @@ var INDEX_EXTS = [
|
|
|
2877
3121
|
"/index.cjs"
|
|
2878
3122
|
];
|
|
2879
3123
|
function resolveRelativeSpecifier(importer, specifier) {
|
|
2880
|
-
const importerDir =
|
|
2881
|
-
const base =
|
|
3124
|
+
const importerDir = path8.dirname(importer);
|
|
3125
|
+
const base = path8.resolve(importerDir, specifier);
|
|
2882
3126
|
if (PROD_EXTS.some((ext) => specifier.endsWith(ext))) {
|
|
2883
|
-
if (
|
|
3127
|
+
if (fs6.existsSync(base)) return base;
|
|
2884
3128
|
if (base.endsWith(".js")) {
|
|
2885
3129
|
for (const ext of [".ts", ".tsx", ".jsx"]) {
|
|
2886
3130
|
const file = base.slice(0, -3) + ext;
|
|
2887
|
-
if (
|
|
3131
|
+
if (fs6.existsSync(file)) return file;
|
|
2888
3132
|
}
|
|
2889
3133
|
}
|
|
2890
3134
|
return null;
|
|
2891
3135
|
}
|
|
2892
3136
|
if (/\.(ts|tsx|jsx)$/.test(specifier)) {
|
|
2893
|
-
return
|
|
3137
|
+
return fs6.existsSync(base) ? base : null;
|
|
2894
3138
|
}
|
|
2895
3139
|
for (const ext of SOURCE_EXTS) {
|
|
2896
3140
|
const file = base + ext;
|
|
2897
|
-
if (
|
|
3141
|
+
if (fs6.existsSync(file)) return file;
|
|
2898
3142
|
}
|
|
2899
3143
|
for (const indexExt of INDEX_EXTS) {
|
|
2900
3144
|
const file = base + indexExt;
|
|
2901
|
-
if (
|
|
3145
|
+
if (fs6.existsSync(file)) return file;
|
|
2902
3146
|
}
|
|
2903
3147
|
return null;
|
|
2904
3148
|
}
|
|
2905
3149
|
function createAliasPlugin(config, options) {
|
|
2906
|
-
const appDirAbs = options?.rootDir ? toRealPath(
|
|
3150
|
+
const appDirAbs = options?.rootDir ? toRealPath(path8.resolve(options.rootDir, APP_DIR)) : null;
|
|
2907
3151
|
const probeCandidateFile = (candidate) => {
|
|
2908
3152
|
for (const ext of SOURCE_EXTS) {
|
|
2909
3153
|
const file = candidate + ext;
|
|
2910
|
-
if (
|
|
3154
|
+
if (fs6.existsSync(file)) return file;
|
|
2911
3155
|
}
|
|
2912
3156
|
for (const indexExt of INDEX_EXTS) {
|
|
2913
3157
|
const file = candidate + indexExt;
|
|
2914
|
-
if (
|
|
3158
|
+
if (fs6.existsSync(file)) return file;
|
|
2915
3159
|
}
|
|
2916
3160
|
return null;
|
|
2917
3161
|
};
|
|
@@ -2921,7 +3165,7 @@ function createAliasPlugin(config, options) {
|
|
|
2921
3165
|
build.onLoad({ filter: /\.(ts|tsx|js|jsx|mjs|cjs)$/ }, (args) => {
|
|
2922
3166
|
let source;
|
|
2923
3167
|
try {
|
|
2924
|
-
source =
|
|
3168
|
+
source = fs6.readFileSync(args.path, "utf8");
|
|
2925
3169
|
} catch {
|
|
2926
3170
|
return void 0;
|
|
2927
3171
|
}
|
|
@@ -3046,11 +3290,11 @@ async function compileSourceFiles(options) {
|
|
|
3046
3290
|
if (entryPoints.length === 0) {
|
|
3047
3291
|
return { compiledFiles: [] };
|
|
3048
3292
|
}
|
|
3049
|
-
const absDist =
|
|
3050
|
-
await
|
|
3293
|
+
const absDist = path9.resolve(rootDir, dist);
|
|
3294
|
+
await fs7.promises.mkdir(absDist, { recursive: true });
|
|
3051
3295
|
const plugins = buildAliasPlugins(rootDir);
|
|
3052
3296
|
const esbuild = await import("esbuild");
|
|
3053
|
-
const outbase =
|
|
3297
|
+
const outbase = path9.resolve(rootDir, APP_DIR);
|
|
3054
3298
|
const result = await esbuild.build({
|
|
3055
3299
|
entryPoints,
|
|
3056
3300
|
outdir: absDist,
|
|
@@ -3070,10 +3314,10 @@ async function compileSourceFiles(options) {
|
|
|
3070
3314
|
if (atomicWrite && result.outputFiles) {
|
|
3071
3315
|
await Promise.all(
|
|
3072
3316
|
result.outputFiles.map(async (file) => {
|
|
3073
|
-
await
|
|
3317
|
+
await fs7.promises.mkdir(path9.dirname(file.path), { recursive: true });
|
|
3074
3318
|
const tmp = `${file.path}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
3075
|
-
await
|
|
3076
|
-
await
|
|
3319
|
+
await fs7.promises.writeFile(tmp, file.contents);
|
|
3320
|
+
await fs7.promises.rename(tmp, file.path);
|
|
3077
3321
|
})
|
|
3078
3322
|
);
|
|
3079
3323
|
}
|
|
@@ -3090,8 +3334,8 @@ init_generateSchemaFiles();
|
|
|
3090
3334
|
init_generateSchemaFiles();
|
|
3091
3335
|
|
|
3092
3336
|
// src/cli/collectImports.ts
|
|
3093
|
-
import
|
|
3094
|
-
import
|
|
3337
|
+
import path12 from "path";
|
|
3338
|
+
import fs9 from "fs";
|
|
3095
3339
|
var SPEC_RE = /(\bfrom\s*|import\s*\(\s*)(['"])([^'"]+)\2/g;
|
|
3096
3340
|
function extractImportSpecifiers(source) {
|
|
3097
3341
|
const specifiers = [];
|
|
@@ -3103,10 +3347,10 @@ function extractImportSpecifiers(source) {
|
|
|
3103
3347
|
return specifiers;
|
|
3104
3348
|
}
|
|
3105
3349
|
function resolveSpecifierFromDir(dir, specifier) {
|
|
3106
|
-
return resolveRelativeSpecifier(
|
|
3350
|
+
return resolveRelativeSpecifier(path12.join(dir, "__faapi_probe__.ts"), specifier);
|
|
3107
3351
|
}
|
|
3108
3352
|
async function collectRelativeImports(entryFiles, rootDir) {
|
|
3109
|
-
const appDirAbs = toRealPath(
|
|
3353
|
+
const appDirAbs = toRealPath(path12.resolve(rootDir, "src"));
|
|
3110
3354
|
const tsconfig = readTsconfig(rootDir);
|
|
3111
3355
|
const visited = /* @__PURE__ */ new Set();
|
|
3112
3356
|
const insideFiles = /* @__PURE__ */ new Set();
|
|
@@ -3116,7 +3360,7 @@ async function collectRelativeImports(entryFiles, rootDir) {
|
|
|
3116
3360
|
visited.add(filePath);
|
|
3117
3361
|
let source;
|
|
3118
3362
|
try {
|
|
3119
|
-
source = await
|
|
3363
|
+
source = await fs9.promises.readFile(filePath, "utf8");
|
|
3120
3364
|
} catch {
|
|
3121
3365
|
return;
|
|
3122
3366
|
}
|
|
@@ -3138,7 +3382,7 @@ async function collectRelativeImports(entryFiles, rootDir) {
|
|
|
3138
3382
|
resolved = null;
|
|
3139
3383
|
}
|
|
3140
3384
|
if (!resolved) continue;
|
|
3141
|
-
if (!isInsideDir(toRealPath(resolved), toRealPath(
|
|
3385
|
+
if (!isInsideDir(toRealPath(resolved), toRealPath(path12.resolve(rootDir)))) continue;
|
|
3142
3386
|
if (isInsideDir(toRealPath(resolved), appDirAbs)) {
|
|
3143
3387
|
insideFiles.add(resolved);
|
|
3144
3388
|
} else {
|
|
@@ -3159,8 +3403,8 @@ async function collectRelativeImports(entryFiles, rootDir) {
|
|
|
3159
3403
|
// src/cli/compileOnDemand.ts
|
|
3160
3404
|
function isProductFresh(sourceAbsPath, productAbsPath) {
|
|
3161
3405
|
try {
|
|
3162
|
-
const srcStat =
|
|
3163
|
-
const prodStat =
|
|
3406
|
+
const srcStat = fs10.statSync(sourceAbsPath);
|
|
3407
|
+
const prodStat = fs10.statSync(productAbsPath);
|
|
3164
3408
|
return prodStat.mtimeMs >= srcStat.mtimeMs;
|
|
3165
3409
|
} catch {
|
|
3166
3410
|
return false;
|
|
@@ -3192,7 +3436,7 @@ async function ensureCompiled(sourceAbsPath, rootDir, dist) {
|
|
|
3192
3436
|
if (state.compiledFiles.has(sourceAbsPath)) {
|
|
3193
3437
|
return false;
|
|
3194
3438
|
}
|
|
3195
|
-
if (!
|
|
3439
|
+
if (!fs10.existsSync(sourceAbsPath)) {
|
|
3196
3440
|
return false;
|
|
3197
3441
|
}
|
|
3198
3442
|
const productPath = prodSourcePathToProductPath(sourceAbsPath, rootDir, dist);
|
|
@@ -3242,11 +3486,11 @@ async function ensureMiddlewaresCompiled(middlewarePaths, rootDir) {
|
|
|
3242
3486
|
}
|
|
3243
3487
|
}
|
|
3244
3488
|
function prodSourcePathToProductPath(sourceAbsPath, rootDir, dist) {
|
|
3245
|
-
const rel =
|
|
3489
|
+
const rel = path13.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
|
|
3246
3490
|
if (!rel.startsWith("src/")) return null;
|
|
3247
3491
|
const relWithoutSrc = rel.slice(4);
|
|
3248
3492
|
const jsRel = relWithoutSrc.replace(/\.ts$/, ".js");
|
|
3249
|
-
return
|
|
3493
|
+
return path13.resolve(rootDir, dist, jsRel);
|
|
3250
3494
|
}
|
|
3251
3495
|
function clearGeneratedSchemas() {
|
|
3252
3496
|
state.generatedSchemas.clear();
|
|
@@ -3262,9 +3506,9 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
|
|
|
3262
3506
|
if (state.generatedSchemas.has(schemaPath)) {
|
|
3263
3507
|
return false;
|
|
3264
3508
|
}
|
|
3265
|
-
const prodAbsPath =
|
|
3509
|
+
const prodAbsPath = path13.resolve(rootDir, routeFilePath);
|
|
3266
3510
|
const sourceAbsPath = prodPathToSourcePath(prodAbsPath, rootDir, dist);
|
|
3267
|
-
if (!
|
|
3511
|
+
if (!fs10.existsSync(sourceAbsPath)) {
|
|
3268
3512
|
return false;
|
|
3269
3513
|
}
|
|
3270
3514
|
if (isProductFresh(sourceAbsPath, schemaPath)) {
|
|
@@ -3275,7 +3519,7 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
|
|
|
3275
3519
|
if (fileRoutes.length === 0) {
|
|
3276
3520
|
return false;
|
|
3277
3521
|
}
|
|
3278
|
-
const sourceRelPath =
|
|
3522
|
+
const sourceRelPath = path13.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
|
|
3279
3523
|
const sourceRoutes = fileRoutes.map((r) => ({ ...r, filePath: sourceRelPath }));
|
|
3280
3524
|
const generatePromise = (async () => {
|
|
3281
3525
|
await generateSchemaFiles(sourceRoutes, rootDir, dist);
|
|
@@ -3296,7 +3540,7 @@ async function deleteSchemaFiles(routes, rootDir, dist) {
|
|
|
3296
3540
|
if (deleted.has(schemaPath)) continue;
|
|
3297
3541
|
deleted.add(schemaPath);
|
|
3298
3542
|
try {
|
|
3299
|
-
await
|
|
3543
|
+
await fs10.promises.unlink(schemaPath);
|
|
3300
3544
|
} catch {
|
|
3301
3545
|
}
|
|
3302
3546
|
}
|
|
@@ -3305,19 +3549,19 @@ var sourcePathCache = /* @__PURE__ */ new Map();
|
|
|
3305
3549
|
function prodPathToSourcePath(prodAbsPath, rootDir, dist) {
|
|
3306
3550
|
const cached = sourcePathCache.get(prodAbsPath);
|
|
3307
3551
|
if (cached) return cached;
|
|
3308
|
-
const rel =
|
|
3552
|
+
const rel = path13.relative(rootDir, prodAbsPath).replace(/\\/g, "/");
|
|
3309
3553
|
let relWithoutDist = rel;
|
|
3310
3554
|
if (relWithoutDist.startsWith(`${dist}/`)) {
|
|
3311
3555
|
relWithoutDist = relWithoutDist.slice(dist.length + 1);
|
|
3312
3556
|
}
|
|
3313
3557
|
const srcRel = `src/${relWithoutDist}`;
|
|
3314
3558
|
const tsRel = srcRel.replace(/\.js$/, ".ts");
|
|
3315
|
-
const tsAbs =
|
|
3559
|
+
const tsAbs = path13.resolve(rootDir, tsRel);
|
|
3316
3560
|
let result;
|
|
3317
|
-
if (
|
|
3561
|
+
if (fs10.existsSync(tsAbs)) {
|
|
3318
3562
|
result = tsAbs;
|
|
3319
3563
|
} else {
|
|
3320
|
-
result =
|
|
3564
|
+
result = path13.resolve(rootDir, srcRel);
|
|
3321
3565
|
}
|
|
3322
3566
|
sourcePathCache.set(prodAbsPath, result);
|
|
3323
3567
|
return result;
|
|
@@ -3335,7 +3579,7 @@ async function loadAgentModule(filePath, hasRun, rootDir) {
|
|
|
3335
3579
|
const dist = getDevDist();
|
|
3336
3580
|
if (dist) {
|
|
3337
3581
|
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
3338
|
-
if (sourcePath &&
|
|
3582
|
+
if (sourcePath && fs11.existsSync(sourcePath)) {
|
|
3339
3583
|
try {
|
|
3340
3584
|
await ensureCompiled(sourcePath, rootDir, dist);
|
|
3341
3585
|
} catch (compileErr) {
|
|
@@ -3368,13 +3612,13 @@ async function loadAgentModule(filePath, hasRun, rootDir) {
|
|
|
3368
3612
|
}
|
|
3369
3613
|
|
|
3370
3614
|
// src/loader/loadToolModule.ts
|
|
3371
|
-
import
|
|
3615
|
+
import fs12 from "fs";
|
|
3372
3616
|
async function loadToolModule(filePath, functionName, rootDir) {
|
|
3373
3617
|
if (isDevOnDemandEnabled() && rootDir) {
|
|
3374
3618
|
const dist = getDevDist();
|
|
3375
3619
|
if (dist) {
|
|
3376
3620
|
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
3377
|
-
if (sourcePath &&
|
|
3621
|
+
if (sourcePath && fs12.existsSync(sourcePath)) {
|
|
3378
3622
|
try {
|
|
3379
3623
|
await ensureCompiled(sourcePath, rootDir, dist);
|
|
3380
3624
|
} catch (compileErr) {
|
|
@@ -3406,7 +3650,7 @@ async function loadToolModule(filePath, functionName, rootDir) {
|
|
|
3406
3650
|
import { existsSync as existsSync2 } from "fs";
|
|
3407
3651
|
|
|
3408
3652
|
// src/cli/generateToolArtifacts.ts
|
|
3409
|
-
import
|
|
3653
|
+
import path14 from "path";
|
|
3410
3654
|
import { existsSync } from "fs";
|
|
3411
3655
|
|
|
3412
3656
|
// src/ast/extractToolMetadata.ts
|
|
@@ -3530,7 +3774,7 @@ function collectToolSchemaSources(tools, rootDir) {
|
|
|
3530
3774
|
const toolsByFile = /* @__PURE__ */ new Map();
|
|
3531
3775
|
for (const tool of tools) {
|
|
3532
3776
|
if (!tool.inputTypeName) continue;
|
|
3533
|
-
const absPath =
|
|
3777
|
+
const absPath = path14.resolve(rootDir, tool.filePath);
|
|
3534
3778
|
let list = toolsByFile.get(absPath);
|
|
3535
3779
|
if (!list) {
|
|
3536
3780
|
list = [];
|
|
@@ -3590,15 +3834,15 @@ function generateToolSchemaFileSource(sources, resolveType, helpersImportPath) {
|
|
|
3590
3834
|
}
|
|
3591
3835
|
async function maybeGenerateHelpers(allSourceCode, distDir) {
|
|
3592
3836
|
if (!usesCoerceHelpers(allSourceCode)) return;
|
|
3593
|
-
const helpersPath =
|
|
3837
|
+
const helpersPath = path14.resolve(distDir, HELPERS_FILENAME);
|
|
3594
3838
|
if (existsSync(helpersPath)) return;
|
|
3595
3839
|
await atomicWriteFile(helpersPath, generateHelpersFileSource());
|
|
3596
3840
|
}
|
|
3597
3841
|
async function generateToolArtifacts(tools, rootDir, dist, options) {
|
|
3598
3842
|
const metadata = [];
|
|
3599
|
-
const programByFile = createPrograms(tools.map((m) =>
|
|
3843
|
+
const programByFile = createPrograms(tools.map((m) => path14.resolve(rootDir, m.filePath)));
|
|
3600
3844
|
for (const manifest of tools) {
|
|
3601
|
-
const absPath =
|
|
3845
|
+
const absPath = path14.resolve(rootDir, manifest.filePath);
|
|
3602
3846
|
const program = programByFile.get(absPath);
|
|
3603
3847
|
const result = extractToolMetadata(program, absPath, manifest.functionName, {
|
|
3604
3848
|
name: manifest.name,
|
|
@@ -3609,7 +3853,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
|
|
|
3609
3853
|
}
|
|
3610
3854
|
}
|
|
3611
3855
|
const serialized = serializeTools(metadata, dist);
|
|
3612
|
-
const toolsPath =
|
|
3856
|
+
const toolsPath = path14.resolve(rootDir, dist, TOOLS_FILE);
|
|
3613
3857
|
await writeToolsModule(serialized, toolsPath);
|
|
3614
3858
|
if (options?.skipSchema) {
|
|
3615
3859
|
return metadata;
|
|
@@ -3632,7 +3876,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
|
|
|
3632
3876
|
}
|
|
3633
3877
|
const fileEntries = [];
|
|
3634
3878
|
for (const [filePath, fileSources] of sourcesByFile) {
|
|
3635
|
-
const relFile =
|
|
3879
|
+
const relFile = path14.relative(rootDir, filePath).replace(/\\/g, "/");
|
|
3636
3880
|
const outputPath = getSchemaOutputPath(relFile, dist, rootDir);
|
|
3637
3881
|
const resolver = resolversByFile.get(filePath);
|
|
3638
3882
|
let relForDir = relFile;
|
|
@@ -3650,7 +3894,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
|
|
|
3650
3894
|
fileEntries.push({ outputPath, source });
|
|
3651
3895
|
}
|
|
3652
3896
|
const allSourceCode = fileEntries.map((e) => e.source).join("\n");
|
|
3653
|
-
const distDir =
|
|
3897
|
+
const distDir = path14.resolve(rootDir, dist);
|
|
3654
3898
|
await maybeGenerateHelpers(allSourceCode, distDir);
|
|
3655
3899
|
await Promise.all(
|
|
3656
3900
|
fileEntries.map(({ outputPath, source }) => writeToolSchemaFile(outputPath, source))
|
|
@@ -3764,14 +4008,34 @@ function cors(options = {}) {
|
|
|
3764
4008
|
}
|
|
3765
4009
|
|
|
3766
4010
|
// src/middleware/logger.ts
|
|
4011
|
+
function levelForStatus(status) {
|
|
4012
|
+
if (status >= 500) return "error";
|
|
4013
|
+
if (status >= 400) return "warn";
|
|
4014
|
+
return "info";
|
|
4015
|
+
}
|
|
4016
|
+
function defaultLog(entry, text) {
|
|
4017
|
+
if (isAccessLogPiped()) {
|
|
4018
|
+
const logEntry = {
|
|
4019
|
+
level: levelForStatus(entry.status),
|
|
4020
|
+
message: text,
|
|
4021
|
+
time: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4022
|
+
scope: "access",
|
|
4023
|
+
fields: entry
|
|
4024
|
+
};
|
|
4025
|
+
writeLogEntry(logEntry);
|
|
4026
|
+
return;
|
|
4027
|
+
}
|
|
4028
|
+
console.log(entry);
|
|
4029
|
+
}
|
|
3767
4030
|
function logger(options = {}) {
|
|
3768
4031
|
return async (ctx, next) => {
|
|
3769
|
-
const log = options.log ??
|
|
4032
|
+
const log = options.log ?? defaultLog;
|
|
3770
4033
|
const start = Date.now();
|
|
3771
4034
|
try {
|
|
3772
4035
|
const response = await next();
|
|
3773
4036
|
const duration = Date.now() - start;
|
|
3774
4037
|
const entry = {
|
|
4038
|
+
requestId: ctx.requestId,
|
|
3775
4039
|
method: ctx.method,
|
|
3776
4040
|
path: ctx.path,
|
|
3777
4041
|
status: response.status,
|
|
@@ -3784,6 +4048,7 @@ function logger(options = {}) {
|
|
|
3784
4048
|
const message = err instanceof Error ? err.message : String(err);
|
|
3785
4049
|
const status = err?.statusCode ?? 500;
|
|
3786
4050
|
const entry = {
|
|
4051
|
+
requestId: ctx.requestId,
|
|
3787
4052
|
method: ctx.method,
|
|
3788
4053
|
path: ctx.path,
|
|
3789
4054
|
status,
|
|
@@ -3859,16 +4124,16 @@ function helmet(options = {}) {
|
|
|
3859
4124
|
}
|
|
3860
4125
|
|
|
3861
4126
|
// src/config/loadConfig.ts
|
|
3862
|
-
import
|
|
3863
|
-
import
|
|
4127
|
+
import path15 from "path";
|
|
4128
|
+
import fs13 from "fs";
|
|
3864
4129
|
var CONFIG_PRODUCT_FILE = "faapi-config.js";
|
|
3865
4130
|
async function loadConfig(rootDir, dist) {
|
|
3866
|
-
const configProductPath =
|
|
3867
|
-
if (
|
|
4131
|
+
const configProductPath = path15.resolve(rootDir, dist, CONFIG_PRODUCT_FILE);
|
|
4132
|
+
if (fs13.existsSync(configProductPath)) {
|
|
3868
4133
|
const module = await importWithCacheBust(configProductPath);
|
|
3869
4134
|
return module.default ?? {};
|
|
3870
4135
|
}
|
|
3871
|
-
const hasSourceConfig =
|
|
4136
|
+
const hasSourceConfig = fs13.existsSync(path15.join(rootDir, "faapi.config.ts")) || fs13.existsSync(path15.join(rootDir, "faapi.config.js"));
|
|
3872
4137
|
if (hasSourceConfig) {
|
|
3873
4138
|
throw new Error(
|
|
3874
4139
|
`[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`
|
|
@@ -3878,8 +4143,8 @@ async function loadConfig(rootDir, dist) {
|
|
|
3878
4143
|
}
|
|
3879
4144
|
|
|
3880
4145
|
// src/cli/loadEnv.ts
|
|
3881
|
-
import
|
|
3882
|
-
import
|
|
4146
|
+
import fs14 from "fs";
|
|
4147
|
+
import path16 from "path";
|
|
3883
4148
|
function resolveEnv() {
|
|
3884
4149
|
return process.env.NODE_ENV || "development";
|
|
3885
4150
|
}
|
|
@@ -3946,9 +4211,9 @@ function loadEnv(rootDir) {
|
|
|
3946
4211
|
const files = getEnvFiles(env);
|
|
3947
4212
|
const merged = {};
|
|
3948
4213
|
for (const file of files) {
|
|
3949
|
-
const filePath =
|
|
3950
|
-
if (!
|
|
3951
|
-
const content =
|
|
4214
|
+
const filePath = path16.join(rootDir, file);
|
|
4215
|
+
if (!fs14.existsSync(filePath)) continue;
|
|
4216
|
+
const content = fs14.readFileSync(filePath, "utf-8");
|
|
3952
4217
|
const parsed = parseEnvFile(content, merged);
|
|
3953
4218
|
Object.assign(merged, parsed);
|
|
3954
4219
|
}
|
|
@@ -3960,8 +4225,8 @@ function loadEnv(rootDir) {
|
|
|
3960
4225
|
}
|
|
3961
4226
|
|
|
3962
4227
|
// src/cli/createAppCore.ts
|
|
3963
|
-
import
|
|
3964
|
-
import
|
|
4228
|
+
import fs19 from "fs";
|
|
4229
|
+
import path24 from "path";
|
|
3965
4230
|
import { PassThrough, Readable as Readable3 } from "stream";
|
|
3966
4231
|
|
|
3967
4232
|
// src/router/sortRoutes.ts
|
|
@@ -4014,7 +4279,7 @@ import {
|
|
|
4014
4279
|
import { createSecureServer as createHttp2SecureServer } from "http2";
|
|
4015
4280
|
import { readFileSync } from "fs";
|
|
4016
4281
|
import { Readable as Readable2 } from "stream";
|
|
4017
|
-
import
|
|
4282
|
+
import path18 from "path";
|
|
4018
4283
|
|
|
4019
4284
|
// src/router/matchRoute.ts
|
|
4020
4285
|
var httpIndexCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -4056,18 +4321,18 @@ function getWsIndex(routes) {
|
|
|
4056
4321
|
wsIndexCache.set(routes, index);
|
|
4057
4322
|
return index;
|
|
4058
4323
|
}
|
|
4059
|
-
function matchRoute(routes, method,
|
|
4324
|
+
function matchRoute(routes, method, path29) {
|
|
4060
4325
|
const index = getHttpIndex(routes);
|
|
4061
4326
|
const upper = method.toUpperCase();
|
|
4062
|
-
const hit = matchByMethod(index, upper,
|
|
4327
|
+
const hit = matchByMethod(index, upper, path29);
|
|
4063
4328
|
if (hit) return hit;
|
|
4064
4329
|
if (upper === "HEAD") {
|
|
4065
|
-
return matchByMethod(index, "GET",
|
|
4330
|
+
return matchByMethod(index, "GET", path29);
|
|
4066
4331
|
}
|
|
4067
4332
|
return null;
|
|
4068
4333
|
}
|
|
4069
|
-
function matchByMethod(index, method,
|
|
4070
|
-
const staticHit = index.static.get(`${method}|${
|
|
4334
|
+
function matchByMethod(index, method, path29) {
|
|
4335
|
+
const staticHit = index.static.get(`${method}|${path29}`);
|
|
4071
4336
|
if (staticHit) {
|
|
4072
4337
|
return { route: staticHit, params: {} };
|
|
4073
4338
|
}
|
|
@@ -4076,31 +4341,31 @@ function matchByMethod(index, method, path28) {
|
|
|
4076
4341
|
if (route.method !== method) {
|
|
4077
4342
|
continue;
|
|
4078
4343
|
}
|
|
4079
|
-
const params = matchSegments(entry.segments,
|
|
4344
|
+
const params = matchSegments(entry.segments, path29, route.paramNames, route.isCatchAll);
|
|
4080
4345
|
if (params !== null) {
|
|
4081
4346
|
return { route, params };
|
|
4082
4347
|
}
|
|
4083
4348
|
}
|
|
4084
4349
|
return null;
|
|
4085
4350
|
}
|
|
4086
|
-
function matchWsRoute(wsRoutes,
|
|
4351
|
+
function matchWsRoute(wsRoutes, path29) {
|
|
4087
4352
|
const index = getWsIndex(wsRoutes);
|
|
4088
|
-
const staticHit = index.static.get(
|
|
4353
|
+
const staticHit = index.static.get(path29);
|
|
4089
4354
|
if (staticHit) {
|
|
4090
4355
|
return { route: staticHit, params: {} };
|
|
4091
4356
|
}
|
|
4092
4357
|
for (const route of index.dynamics) {
|
|
4093
|
-
const params = matchDynamicPath(route.urlPath,
|
|
4358
|
+
const params = matchDynamicPath(route.urlPath, path29, route.paramNames, route.isCatchAll);
|
|
4094
4359
|
if (params !== null) {
|
|
4095
4360
|
return { route, params };
|
|
4096
4361
|
}
|
|
4097
4362
|
}
|
|
4098
4363
|
return null;
|
|
4099
4364
|
}
|
|
4100
|
-
function findAllowedMethods(routes,
|
|
4365
|
+
function findAllowedMethods(routes, path29) {
|
|
4101
4366
|
const index = getHttpIndex(routes);
|
|
4102
4367
|
const methods = /* @__PURE__ */ new Set();
|
|
4103
|
-
const staticMethods = index.methodsByStaticPath.get(
|
|
4368
|
+
const staticMethods = index.methodsByStaticPath.get(path29);
|
|
4104
4369
|
if (staticMethods) {
|
|
4105
4370
|
for (const method of staticMethods) {
|
|
4106
4371
|
methods.add(method);
|
|
@@ -4109,7 +4374,7 @@ function findAllowedMethods(routes, path28) {
|
|
|
4109
4374
|
for (const entry of index.dynamics) {
|
|
4110
4375
|
const params = matchSegments(
|
|
4111
4376
|
entry.segments,
|
|
4112
|
-
|
|
4377
|
+
path29,
|
|
4113
4378
|
entry.route.paramNames,
|
|
4114
4379
|
entry.route.isCatchAll
|
|
4115
4380
|
);
|
|
@@ -4122,11 +4387,11 @@ function findAllowedMethods(routes, path28) {
|
|
|
4122
4387
|
}
|
|
4123
4388
|
return Array.from(methods);
|
|
4124
4389
|
}
|
|
4125
|
-
function matchDynamicPath(pattern,
|
|
4126
|
-
return matchSegments(pattern.split("/").filter(Boolean),
|
|
4390
|
+
function matchDynamicPath(pattern, path29, paramNames, isCatchAll) {
|
|
4391
|
+
return matchSegments(pattern.split("/").filter(Boolean), path29, paramNames, isCatchAll);
|
|
4127
4392
|
}
|
|
4128
|
-
function matchSegments(patternSegments,
|
|
4129
|
-
const pathSegments =
|
|
4393
|
+
function matchSegments(patternSegments, path29, paramNames, isCatchAll) {
|
|
4394
|
+
const pathSegments = path29.split("/").filter(Boolean);
|
|
4130
4395
|
if (isCatchAll) {
|
|
4131
4396
|
const nonCatchAllCount = patternSegments.length - 1;
|
|
4132
4397
|
if (pathSegments.length <= nonCatchAllCount) {
|
|
@@ -4406,6 +4671,12 @@ function formatErrorResponse(error, config) {
|
|
|
4406
4671
|
}
|
|
4407
4672
|
|
|
4408
4673
|
// src/runtime/createContext.ts
|
|
4674
|
+
function resolveRequestId(request) {
|
|
4675
|
+
const header = request.headers.get("x-request-id");
|
|
4676
|
+
const first = header?.split(",")[0]?.trim();
|
|
4677
|
+
if (first) return first;
|
|
4678
|
+
return crypto.randomUUID();
|
|
4679
|
+
}
|
|
4409
4680
|
function parseCookies(cookieHeader) {
|
|
4410
4681
|
const cookies = /* @__PURE__ */ new Map();
|
|
4411
4682
|
if (!cookieHeader) return cookies;
|
|
@@ -4439,7 +4710,13 @@ function createContextFromUrl(request, url, params, config = {}, ip = "", regist
|
|
|
4439
4710
|
for (const [key, val] of parsedCookies) {
|
|
4440
4711
|
cookiesObj[key] = val;
|
|
4441
4712
|
}
|
|
4713
|
+
const requestId = resolveRequestId(request);
|
|
4714
|
+
const log = createLogger("http", {
|
|
4715
|
+
fields: { requestId, method: request.method, path: url.pathname }
|
|
4716
|
+
});
|
|
4442
4717
|
const ctx = {
|
|
4718
|
+
requestId,
|
|
4719
|
+
log,
|
|
4443
4720
|
request,
|
|
4444
4721
|
params,
|
|
4445
4722
|
query: url.searchParams,
|
|
@@ -4824,6 +5101,9 @@ function getBuiltinInjectionValue(type, ctx, body) {
|
|
|
4824
5101
|
// 任务子系统:注入 TaskClient(入队/查询);未注册工厂(无 app 编排)时 undefined
|
|
4825
5102
|
case "tasks":
|
|
4826
5103
|
return ctx.registries ? ctx.registries.taskHandle.get(ctx) : void 0;
|
|
5104
|
+
// 请求级日志器:与 ctx.log 同一实例(scope http,自动带 requestId/method/path 字段)
|
|
5105
|
+
case "log":
|
|
5106
|
+
return ctx.log;
|
|
4827
5107
|
default:
|
|
4828
5108
|
return void 0;
|
|
4829
5109
|
}
|
|
@@ -5018,9 +5298,9 @@ async function validateInput(schemaPath, method, inputType, input) {
|
|
|
5018
5298
|
function mapZodIssues(error) {
|
|
5019
5299
|
return error.issues.map((issue) => {
|
|
5020
5300
|
const code = mapZodCode(issue);
|
|
5021
|
-
const
|
|
5301
|
+
const path29 = issue.path.map(String).join(".") || "";
|
|
5022
5302
|
return {
|
|
5023
|
-
path:
|
|
5303
|
+
path: path29,
|
|
5024
5304
|
code,
|
|
5025
5305
|
expected: issue.expected ?? mapExpectedFromMessage(issue.message),
|
|
5026
5306
|
received: issue.received ?? mapReceivedFromMessage(issue.message),
|
|
@@ -5252,9 +5532,9 @@ function etag(options = {}) {
|
|
|
5252
5532
|
}
|
|
5253
5533
|
|
|
5254
5534
|
// src/server/handleWsUpgrade.ts
|
|
5255
|
-
import
|
|
5535
|
+
import fs15 from "fs";
|
|
5256
5536
|
import { WebSocketServer, WebSocket } from "ws";
|
|
5257
|
-
import
|
|
5537
|
+
import path17 from "path";
|
|
5258
5538
|
|
|
5259
5539
|
// src/server/serverUtils.ts
|
|
5260
5540
|
function nodeHttpToWebHeaders(req) {
|
|
@@ -5389,7 +5669,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
|
|
|
5389
5669
|
const dist = getDevDist();
|
|
5390
5670
|
if (dist) {
|
|
5391
5671
|
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
5392
|
-
if (sourcePath &&
|
|
5672
|
+
if (sourcePath && fs15.existsSync(sourcePath)) {
|
|
5393
5673
|
await ensureCompiled(sourcePath, rootDir, dist);
|
|
5394
5674
|
}
|
|
5395
5675
|
}
|
|
@@ -5503,7 +5783,7 @@ function attachWebSocket(options) {
|
|
|
5503
5783
|
const finalHandler = async () => {
|
|
5504
5784
|
let handlers;
|
|
5505
5785
|
try {
|
|
5506
|
-
const absoluteFilePath =
|
|
5786
|
+
const absoluteFilePath = path17.resolve(rootDir, route.filePath);
|
|
5507
5787
|
handlers = await loadWsHandler(absoluteFilePath, ctx, rootDir);
|
|
5508
5788
|
} catch (err) {
|
|
5509
5789
|
const reason = err instanceof Error ? err.message : String(err);
|
|
@@ -5756,7 +6036,7 @@ function getRoutePaths(route, rootDir, dist) {
|
|
|
5756
6036
|
let cached = routePathCache.get(route);
|
|
5757
6037
|
if (!cached) {
|
|
5758
6038
|
cached = {
|
|
5759
|
-
absFilePath:
|
|
6039
|
+
absFilePath: path18.resolve(rootDir, route.filePath),
|
|
5760
6040
|
schemaPath: getRuntimeSchemaPath(route.filePath, dist, rootDir)
|
|
5761
6041
|
};
|
|
5762
6042
|
routePathCache.set(route, cached);
|
|
@@ -5878,8 +6158,8 @@ function applyPluginWrappers(server, handlerWrappers, upgradeWrappers) {
|
|
|
5878
6158
|
}
|
|
5879
6159
|
|
|
5880
6160
|
// src/cli/generateRoutes.ts
|
|
5881
|
-
import
|
|
5882
|
-
import
|
|
6161
|
+
import fs16 from "fs";
|
|
6162
|
+
import path19 from "path";
|
|
5883
6163
|
async function hydrateRoutes(manifest) {
|
|
5884
6164
|
const hydrateRoute = (serialized) => ({
|
|
5885
6165
|
method: serialized.method,
|
|
@@ -5904,7 +6184,7 @@ async function hydrateRoutes(manifest) {
|
|
|
5904
6184
|
}
|
|
5905
6185
|
|
|
5906
6186
|
// src/cli/generateAgentArtifacts.ts
|
|
5907
|
-
import
|
|
6187
|
+
import path20 from "path";
|
|
5908
6188
|
|
|
5909
6189
|
// src/ast/extractAgentMetadata.ts
|
|
5910
6190
|
import ts10 from "typescript";
|
|
@@ -6177,9 +6457,9 @@ function validateAgentList(metadata) {
|
|
|
6177
6457
|
}
|
|
6178
6458
|
async function generateAgentArtifacts(agents, rootDir, dist) {
|
|
6179
6459
|
const metadata = [];
|
|
6180
|
-
const programByFile = createPrograms(agents.map((m) =>
|
|
6460
|
+
const programByFile = createPrograms(agents.map((m) => path20.resolve(rootDir, m.filePath)));
|
|
6181
6461
|
for (const manifest of agents) {
|
|
6182
|
-
const absPath =
|
|
6462
|
+
const absPath = path20.resolve(rootDir, manifest.filePath);
|
|
6183
6463
|
const program = programByFile.get(absPath);
|
|
6184
6464
|
const result = extractAgentMetadata(program, absPath, {
|
|
6185
6465
|
name: manifest.name,
|
|
@@ -6195,13 +6475,13 @@ async function generateAgentArtifacts(agents, rootDir, dist) {
|
|
|
6195
6475
|
}
|
|
6196
6476
|
validateAgentList(metadata);
|
|
6197
6477
|
const serialized = serializeAgents(metadata, dist);
|
|
6198
|
-
const agentsPath =
|
|
6478
|
+
const agentsPath = path20.resolve(rootDir, dist, AGENTS_FILE);
|
|
6199
6479
|
await writeAgentsModule(serialized, agentsPath);
|
|
6200
6480
|
return metadata;
|
|
6201
6481
|
}
|
|
6202
6482
|
|
|
6203
6483
|
// src/cli/generateTaskArtifacts.ts
|
|
6204
|
-
import
|
|
6484
|
+
import path21 from "path";
|
|
6205
6485
|
init_createProgram();
|
|
6206
6486
|
init_atomicWrite();
|
|
6207
6487
|
init_generateSchemaFiles();
|
|
@@ -6240,7 +6520,7 @@ function collectTaskSchemaSources(tasks, rootDir) {
|
|
|
6240
6520
|
const tasksByFile = /* @__PURE__ */ new Map();
|
|
6241
6521
|
for (const task of tasks) {
|
|
6242
6522
|
if (!task.inputTypeName) continue;
|
|
6243
|
-
const absPath =
|
|
6523
|
+
const absPath = path21.resolve(rootDir, task.filePath);
|
|
6244
6524
|
let list = tasksByFile.get(absPath);
|
|
6245
6525
|
if (!list) {
|
|
6246
6526
|
list = [];
|
|
@@ -6297,9 +6577,9 @@ function generateTaskSchemaFileSource(sources, resolveType, helpersImportPath) {
|
|
|
6297
6577
|
async function generateTaskArtifacts(manifests, rootDir, dist) {
|
|
6298
6578
|
const metadata = [];
|
|
6299
6579
|
if (manifests.length > 0) {
|
|
6300
|
-
const programByFile = createPrograms(manifests.map((m) =>
|
|
6580
|
+
const programByFile = createPrograms(manifests.map((m) => path21.resolve(rootDir, m.filePath)));
|
|
6301
6581
|
for (const manifest of manifests) {
|
|
6302
|
-
const absPath =
|
|
6582
|
+
const absPath = path21.resolve(rootDir, manifest.filePath);
|
|
6303
6583
|
const result = extractToolMetadata(programByFile.get(absPath), absPath, "run", {
|
|
6304
6584
|
name: manifest.name,
|
|
6305
6585
|
filePath: manifest.filePath
|
|
@@ -6310,7 +6590,7 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
|
|
|
6310
6590
|
}
|
|
6311
6591
|
}
|
|
6312
6592
|
const serialized = serializeTasks(manifests, dist);
|
|
6313
|
-
const tasksPath =
|
|
6593
|
+
const tasksPath = path21.resolve(rootDir, dist, TASKS_FILE);
|
|
6314
6594
|
await writeTasksModule(serialized, tasksPath);
|
|
6315
6595
|
if (metadata.length === 0) {
|
|
6316
6596
|
return hydrateTasks(serialized);
|
|
@@ -6330,7 +6610,7 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
|
|
|
6330
6610
|
}
|
|
6331
6611
|
const fileEntries = [];
|
|
6332
6612
|
for (const [filePath, fileSources] of sourcesByFile) {
|
|
6333
|
-
const relFile =
|
|
6613
|
+
const relFile = path21.relative(rootDir, filePath).replace(/\\/g, "/");
|
|
6334
6614
|
const outputPath = getSchemaOutputPath(relFile, dist, rootDir);
|
|
6335
6615
|
const resolver = resolversByFile.get(filePath);
|
|
6336
6616
|
let relForDir = relFile;
|
|
@@ -6349,7 +6629,7 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
|
|
|
6349
6629
|
}
|
|
6350
6630
|
const allSourceCode = fileEntries.map((e) => e.source).join("\n");
|
|
6351
6631
|
if (usesCoerceHelpers(allSourceCode)) {
|
|
6352
|
-
const helpersPath =
|
|
6632
|
+
const helpersPath = path21.resolve(rootDir, dist, HELPERS_FILENAME);
|
|
6353
6633
|
const { existsSync: existsSync3 } = await import("fs");
|
|
6354
6634
|
if (!existsSync3(helpersPath)) {
|
|
6355
6635
|
await atomicWriteFile(helpersPath, generateHelpersFileSource());
|
|
@@ -6381,18 +6661,18 @@ function createIdleTaskDriver() {
|
|
|
6381
6661
|
}
|
|
6382
6662
|
|
|
6383
6663
|
// src/cli/loadPlugins.ts
|
|
6384
|
-
import
|
|
6385
|
-
import
|
|
6664
|
+
import path23 from "path";
|
|
6665
|
+
import fs18 from "fs";
|
|
6386
6666
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
6387
6667
|
|
|
6388
6668
|
// src/cli/compileConfig.ts
|
|
6389
|
-
import
|
|
6390
|
-
import
|
|
6669
|
+
import path22 from "path";
|
|
6670
|
+
import fs17 from "fs";
|
|
6391
6671
|
async function compileProjectModules(entryPoints, rootDir, dist) {
|
|
6392
6672
|
const { insideFiles, outsideFiles } = await collectRelativeImports(entryPoints, rootDir);
|
|
6393
6673
|
const esbuild = await import("esbuild");
|
|
6394
6674
|
const aliasPlugins = buildAliasPlugins(rootDir);
|
|
6395
|
-
const absDist =
|
|
6675
|
+
const absDist = path22.resolve(rootDir, dist);
|
|
6396
6676
|
await esbuild.build({
|
|
6397
6677
|
entryPoints: [...entryPoints, ...outsideFiles],
|
|
6398
6678
|
outdir: absDist,
|
|
@@ -6406,7 +6686,7 @@ async function compileProjectModules(entryPoints, rootDir, dist) {
|
|
|
6406
6686
|
logLevel: "silent"
|
|
6407
6687
|
});
|
|
6408
6688
|
if (insideFiles.length > 0) {
|
|
6409
|
-
const appOutbase =
|
|
6689
|
+
const appOutbase = path22.resolve(rootDir, "src");
|
|
6410
6690
|
await esbuild.build({
|
|
6411
6691
|
entryPoints: insideFiles,
|
|
6412
6692
|
outdir: absDist,
|
|
@@ -6487,37 +6767,37 @@ async function loadPlugins(declarations, ctx, rootDir, dist) {
|
|
|
6487
6767
|
var TS_EXTS = /\.(ts|tsx|mts|cts)$/;
|
|
6488
6768
|
var JS_EXTS = /\.(js|mjs|cjs|jsx)$/;
|
|
6489
6769
|
function resolveLocalPluginSource(specifier, baseDir) {
|
|
6490
|
-
const base =
|
|
6491
|
-
if ((TS_EXTS.test(base) || JS_EXTS.test(base)) &&
|
|
6770
|
+
const base = path23.isAbsolute(specifier) ? specifier : path23.resolve(baseDir, specifier);
|
|
6771
|
+
if ((TS_EXTS.test(base) || JS_EXTS.test(base)) && fs18.existsSync(base)) return base;
|
|
6492
6772
|
for (const ext of [".ts", ".js"]) {
|
|
6493
|
-
if (
|
|
6773
|
+
if (fs18.existsSync(base + ext)) return base + ext;
|
|
6494
6774
|
}
|
|
6495
6775
|
for (const indexExt of ["/index.ts", "/index.js"]) {
|
|
6496
|
-
if (
|
|
6776
|
+
if (fs18.existsSync(base + indexExt)) return base + indexExt;
|
|
6497
6777
|
}
|
|
6498
6778
|
return null;
|
|
6499
6779
|
}
|
|
6500
6780
|
function mirrorProductPath(sourcePath, baseDir, distDir) {
|
|
6501
|
-
let rel =
|
|
6781
|
+
let rel = path23.relative(baseDir, sourcePath).replace(/\\/g, "/");
|
|
6502
6782
|
if (rel.startsWith("src/")) rel = rel.slice(4);
|
|
6503
|
-
return
|
|
6783
|
+
return path23.resolve(distDir, rel.replace(TS_EXTS, ".js"));
|
|
6504
6784
|
}
|
|
6505
6785
|
function isSourceNewer(sourcePath, productPath) {
|
|
6506
6786
|
try {
|
|
6507
|
-
return
|
|
6787
|
+
return fs18.statSync(sourcePath).mtimeMs > fs18.statSync(productPath).mtimeMs;
|
|
6508
6788
|
} catch {
|
|
6509
6789
|
return true;
|
|
6510
6790
|
}
|
|
6511
6791
|
}
|
|
6512
6792
|
async function importPluginModule(specifier, baseDir, dist) {
|
|
6513
6793
|
const isRelative = specifier.startsWith("./") || specifier.startsWith("../");
|
|
6514
|
-
if (!isRelative && !
|
|
6794
|
+
if (!isRelative && !path23.isAbsolute(specifier)) {
|
|
6515
6795
|
return import(specifier);
|
|
6516
6796
|
}
|
|
6517
|
-
const distDir = dist ?
|
|
6797
|
+
const distDir = dist ? path23.resolve(baseDir, dist) : null;
|
|
6518
6798
|
const sourcePath = resolveLocalPluginSource(specifier, baseDir);
|
|
6519
6799
|
const productPath = sourcePath && distDir ? mirrorProductPath(sourcePath, baseDir, distDir) : null;
|
|
6520
|
-
if (productPath !== null &&
|
|
6800
|
+
if (productPath !== null && fs18.existsSync(productPath) && (sourcePath === null || !isSourceNewer(sourcePath, productPath))) {
|
|
6521
6801
|
return import(pathToFileURL3(productPath).href);
|
|
6522
6802
|
}
|
|
6523
6803
|
if (sourcePath && TS_EXTS.test(sourcePath)) {
|
|
@@ -6526,13 +6806,13 @@ async function importPluginModule(specifier, baseDir, dist) {
|
|
|
6526
6806
|
`Local plugin "${specifier}" has no up-to-date build artifact (dist is stale or missing). Run "faapi build" first, or use "faapi dev" for on-demand compilation.`
|
|
6527
6807
|
);
|
|
6528
6808
|
}
|
|
6529
|
-
const relFromRoot =
|
|
6809
|
+
const relFromRoot = path23.relative(baseDir, sourcePath).replace(/\\/g, "/");
|
|
6530
6810
|
if (relFromRoot.startsWith("src/")) {
|
|
6531
6811
|
await ensureCompiled(sourcePath, baseDir, dist);
|
|
6532
6812
|
} else {
|
|
6533
6813
|
await compileProjectModules([sourcePath], baseDir, dist);
|
|
6534
6814
|
}
|
|
6535
|
-
if (productPath &&
|
|
6815
|
+
if (productPath && fs18.existsSync(productPath)) {
|
|
6536
6816
|
return import(pathToFileURL3(productPath).href);
|
|
6537
6817
|
}
|
|
6538
6818
|
}
|
|
@@ -6544,7 +6824,7 @@ async function importPluginModule(specifier, baseDir, dist) {
|
|
|
6544
6824
|
`${specifier}/index.ts`,
|
|
6545
6825
|
`${specifier}.js`,
|
|
6546
6826
|
`${specifier}/index.js`
|
|
6547
|
-
].map((c) =>
|
|
6827
|
+
].map((c) => path23.isAbsolute(c) ? c : path23.join(baseDir, c));
|
|
6548
6828
|
throw new Error(
|
|
6549
6829
|
`Cannot find local plugin "${specifier}" (resolved from ${baseDir}). Expected one of:
|
|
6550
6830
|
${candidates.join("\n ")}
|
|
@@ -6575,8 +6855,8 @@ var ROUTES_FILE = "faapi-routes.js";
|
|
|
6575
6855
|
var TOOLS_FILE2 = "faapi-tools.js";
|
|
6576
6856
|
var AGENTS_FILE2 = "faapi-agents.js";
|
|
6577
6857
|
async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries) {
|
|
6578
|
-
const toolsPath =
|
|
6579
|
-
if (!
|
|
6858
|
+
const toolsPath = path24.resolve(rootDir, dist, TOOLS_FILE2);
|
|
6859
|
+
if (!fs19.existsSync(toolsPath)) {
|
|
6580
6860
|
return [];
|
|
6581
6861
|
}
|
|
6582
6862
|
const serialized = await importWithCacheBust(toolsPath);
|
|
@@ -6585,8 +6865,8 @@ async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries
|
|
|
6585
6865
|
return hydrated;
|
|
6586
6866
|
}
|
|
6587
6867
|
async function loadAndHydrateAgents(rootDir, dist, registries = defaultRegistries) {
|
|
6588
|
-
const agentsPath =
|
|
6589
|
-
if (!
|
|
6868
|
+
const agentsPath = path24.resolve(rootDir, dist, AGENTS_FILE2);
|
|
6869
|
+
if (!fs19.existsSync(agentsPath)) {
|
|
6590
6870
|
return [];
|
|
6591
6871
|
}
|
|
6592
6872
|
const serialized = await importWithCacheBust(agentsPath);
|
|
@@ -6601,8 +6881,8 @@ function getTaskDriverOptions(config) {
|
|
|
6601
6881
|
return void 0;
|
|
6602
6882
|
}
|
|
6603
6883
|
async function loadAndHydrateTasks(rootDir, dist, registries = defaultRegistries) {
|
|
6604
|
-
const tasksPath =
|
|
6605
|
-
if (!
|
|
6884
|
+
const tasksPath = path24.resolve(rootDir, dist, TASKS_FILE);
|
|
6885
|
+
if (!fs19.existsSync(tasksPath)) {
|
|
6606
6886
|
return [];
|
|
6607
6887
|
}
|
|
6608
6888
|
const serialized = await importWithCacheBust(tasksPath);
|
|
@@ -6659,6 +6939,7 @@ var FAAPI_CONFIG_KEYS = /* @__PURE__ */ new Set([
|
|
|
6659
6939
|
"etag",
|
|
6660
6940
|
"bodyLimit",
|
|
6661
6941
|
"logger",
|
|
6942
|
+
"log",
|
|
6662
6943
|
"http2",
|
|
6663
6944
|
"trustedProxy",
|
|
6664
6945
|
"response",
|
|
@@ -6670,13 +6951,14 @@ function isFaapiConfigKey(key) {
|
|
|
6670
6951
|
async function createAppBase(options) {
|
|
6671
6952
|
const rootDir = options?.rootDir ?? process.cwd();
|
|
6672
6953
|
const dist = options?.dist ?? process.env.FAAPI_DIST ?? DEFAULT_DIST;
|
|
6673
|
-
const routesPath =
|
|
6674
|
-
if (!
|
|
6954
|
+
const routesPath = path24.resolve(rootDir, dist, ROUTES_FILE);
|
|
6955
|
+
if (!fs19.existsSync(routesPath)) {
|
|
6675
6956
|
throw new Error(
|
|
6676
6957
|
`[faapi] ${dist}/${ROUTES_FILE} \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6267\u884C \`faapi build\`\uFF08\u6216 \`faapi dev\`\uFF09\u751F\u6210\u4EA7\u7269\u3002`
|
|
6677
6958
|
);
|
|
6678
6959
|
}
|
|
6679
6960
|
const config = await loadConfig(rootDir, dist);
|
|
6961
|
+
configureLogging(config?.log);
|
|
6680
6962
|
const serialized = await importWithCacheBust(routesPath);
|
|
6681
6963
|
const hydrated = await hydrateRoutes(serialized);
|
|
6682
6964
|
let sorted = sortRoutes(hydrated.routes);
|
|
@@ -6998,21 +7280,21 @@ async function createAppBase(options) {
|
|
|
6998
7280
|
}
|
|
6999
7281
|
|
|
7000
7282
|
// src/cli/createDevApp.ts
|
|
7001
|
-
import
|
|
7283
|
+
import path28 from "path";
|
|
7002
7284
|
|
|
7003
7285
|
// src/router/scanRoutes.ts
|
|
7004
7286
|
import fg3 from "fast-glob";
|
|
7005
|
-
import
|
|
7006
|
-
import
|
|
7287
|
+
import path25 from "path";
|
|
7288
|
+
import fs20 from "fs";
|
|
7007
7289
|
|
|
7008
7290
|
// src/router/constants.ts
|
|
7009
7291
|
var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
7010
7292
|
var HTTP_METHOD_SET = new Set(HTTP_METHODS);
|
|
7011
7293
|
|
|
7012
7294
|
// src/utils/normalizePath.ts
|
|
7013
|
-
function normalizePath(
|
|
7014
|
-
if (!
|
|
7015
|
-
let result =
|
|
7295
|
+
function normalizePath(path29) {
|
|
7296
|
+
if (!path29) return "";
|
|
7297
|
+
let result = path29.replace(/\\/g, "/");
|
|
7016
7298
|
result = result.replace(/\/+/g, "/");
|
|
7017
7299
|
result = result.replace(/\/+$/, "");
|
|
7018
7300
|
if (result && !result.startsWith("/")) {
|
|
@@ -7073,34 +7355,34 @@ function extractExportsFromSource(source) {
|
|
|
7073
7355
|
return names;
|
|
7074
7356
|
}
|
|
7075
7357
|
function collectMiddlewarePaths(routeFilePath, rootDir, dist) {
|
|
7076
|
-
const routeDir =
|
|
7077
|
-
const resolvedRoot =
|
|
7358
|
+
const routeDir = path25.dirname(routeFilePath);
|
|
7359
|
+
const resolvedRoot = path25.resolve(rootDir);
|
|
7078
7360
|
const paths = [];
|
|
7079
|
-
let currentDir =
|
|
7361
|
+
let currentDir = path25.resolve(rootDir, routeDir);
|
|
7080
7362
|
while (true) {
|
|
7081
7363
|
if (dist) {
|
|
7082
|
-
const mwTsPath =
|
|
7083
|
-
const mwJsPath =
|
|
7084
|
-
const absTsPath =
|
|
7085
|
-
const absJsPath =
|
|
7086
|
-
const absMwPath =
|
|
7364
|
+
const mwTsPath = path25.join(currentDir, "middlewares.ts");
|
|
7365
|
+
const mwJsPath = path25.join(currentDir, "middlewares.js");
|
|
7366
|
+
const absTsPath = path25.resolve(rootDir, mwTsPath);
|
|
7367
|
+
const absJsPath = path25.resolve(rootDir, mwJsPath);
|
|
7368
|
+
const absMwPath = fs20.existsSync(absTsPath) ? absTsPath : fs20.existsSync(absJsPath) ? absJsPath : null;
|
|
7087
7369
|
if (absMwPath) {
|
|
7088
|
-
const relMwPath =
|
|
7089
|
-
const prodAbsPath =
|
|
7370
|
+
const relMwPath = path25.relative(rootDir, absMwPath);
|
|
7371
|
+
const prodAbsPath = path25.resolve(rootDir, toProdFilePath(relMwPath, dist));
|
|
7090
7372
|
paths.push(prodAbsPath);
|
|
7091
7373
|
}
|
|
7092
7374
|
} else {
|
|
7093
7375
|
for (const ext of [".ts", ".js"]) {
|
|
7094
|
-
const mwPath =
|
|
7095
|
-
const absMwPath =
|
|
7096
|
-
if (
|
|
7376
|
+
const mwPath = path25.join(currentDir, `middlewares${ext}`);
|
|
7377
|
+
const absMwPath = path25.resolve(rootDir, mwPath);
|
|
7378
|
+
if (fs20.existsSync(absMwPath)) {
|
|
7097
7379
|
paths.push(absMwPath);
|
|
7098
7380
|
break;
|
|
7099
7381
|
}
|
|
7100
7382
|
}
|
|
7101
7383
|
}
|
|
7102
7384
|
if (currentDir === resolvedRoot) break;
|
|
7103
|
-
const parentDir =
|
|
7385
|
+
const parentDir = path25.dirname(currentDir);
|
|
7104
7386
|
if (parentDir === currentDir) break;
|
|
7105
7387
|
currentDir = parentDir;
|
|
7106
7388
|
}
|
|
@@ -7119,7 +7401,7 @@ async function scanRoutes(rootDir, patterns, dist) {
|
|
|
7119
7401
|
const normalizedFile = file.replace(/\\/g, "/");
|
|
7120
7402
|
const fileName = normalizedFile.split("/").pop();
|
|
7121
7403
|
if (fileName === "handler.ts" || fileName === "handler.js") {
|
|
7122
|
-
const absPath =
|
|
7404
|
+
const absPath = path25.resolve(rootDir, normalizedFile);
|
|
7123
7405
|
const urlPath = filePathToUrlPath(normalizedFile);
|
|
7124
7406
|
const paramNames = extractParamNames(urlPath);
|
|
7125
7407
|
const isDynamic = paramNames.length > 0;
|
|
@@ -7132,7 +7414,7 @@ async function scanRoutes(rootDir, patterns, dist) {
|
|
|
7132
7414
|
const mwPaths = collectMiddlewarePaths(normalizedFile, rootDir);
|
|
7133
7415
|
middlewareBundle = await loadMergedMiddlewares(mwPaths);
|
|
7134
7416
|
}
|
|
7135
|
-
const source = await
|
|
7417
|
+
const source = await fs20.promises.readFile(absPath, "utf8").catch(() => "");
|
|
7136
7418
|
const exportNames = extractExportsFromSource(source);
|
|
7137
7419
|
const methods = HTTP_METHODS.filter((m) => exportNames.has(m));
|
|
7138
7420
|
for (const method of methods) {
|
|
@@ -7168,8 +7450,8 @@ async function scanRoutes(rootDir, patterns, dist) {
|
|
|
7168
7450
|
|
|
7169
7451
|
// src/tools/scanTools.ts
|
|
7170
7452
|
import fg4 from "fast-glob";
|
|
7171
|
-
import
|
|
7172
|
-
import
|
|
7453
|
+
import path26 from "path";
|
|
7454
|
+
import fs21 from "fs";
|
|
7173
7455
|
var TOOL_PATTERNS = ["src/tools/**/*.ts"];
|
|
7174
7456
|
var TOOL_EXPORT_RE = new RegExp(
|
|
7175
7457
|
String.raw`export\s+(?:async\s+)?(?:function\s+|const\s+)([A-Za-z_$][\w$]*)\s*(?:\(|=)`,
|
|
@@ -7219,8 +7501,8 @@ async function scanTools(rootDir, patterns) {
|
|
|
7219
7501
|
if (fileName !== "handler.ts" && fileName !== "handler.js") {
|
|
7220
7502
|
continue;
|
|
7221
7503
|
}
|
|
7222
|
-
const absPath =
|
|
7223
|
-
const source = await
|
|
7504
|
+
const absPath = path26.resolve(rootDir, normalizedFile);
|
|
7505
|
+
const source = await fs21.promises.readFile(absPath, "utf8").catch(() => "");
|
|
7224
7506
|
const exportNames = extractToolExportsFromSource(source);
|
|
7225
7507
|
const namespace = filePathToToolNamespace(normalizedFile);
|
|
7226
7508
|
for (const fnName of exportNames) {
|
|
@@ -7244,8 +7526,8 @@ async function scanTools(rootDir, patterns) {
|
|
|
7244
7526
|
|
|
7245
7527
|
// src/agents/scanAgents.ts
|
|
7246
7528
|
import fg5 from "fast-glob";
|
|
7247
|
-
import
|
|
7248
|
-
import
|
|
7529
|
+
import path27 from "path";
|
|
7530
|
+
import fs22 from "fs";
|
|
7249
7531
|
var DEFAULT_AGENT_PATTERNS = ["src/agents/**/handler.ts"];
|
|
7250
7532
|
var RUN_EXPORT_RE = /export\s+(?:async\s+)?(?:function\s+|const\s+)run\b/;
|
|
7251
7533
|
function extractAgentNameFromPath(filePath) {
|
|
@@ -7277,8 +7559,8 @@ async function scanAgents(rootDir, patterns) {
|
|
|
7277
7559
|
if (fileName !== "handler.ts" && fileName !== "handler.js") {
|
|
7278
7560
|
continue;
|
|
7279
7561
|
}
|
|
7280
|
-
const absPath =
|
|
7281
|
-
const source = await
|
|
7562
|
+
const absPath = path27.resolve(rootDir, normalizedFile);
|
|
7563
|
+
const source = await fs22.promises.readFile(absPath, "utf8").catch(() => "");
|
|
7282
7564
|
const { hasRun } = detectAgentExports(source);
|
|
7283
7565
|
const name = extractAgentNameFromPath(normalizedFile);
|
|
7284
7566
|
const prevFile = seen.get(name);
|
|
@@ -7348,7 +7630,7 @@ async function createDevApp(options) {
|
|
|
7348
7630
|
invalidateProgramCache();
|
|
7349
7631
|
const tasks = await scanTasks(ctx.rootDir, TASK_PATTERNS);
|
|
7350
7632
|
for (const task of tasks) {
|
|
7351
|
-
await ensureCompiled(
|
|
7633
|
+
await ensureCompiled(path28.resolve(ctx.rootDir, task.filePath), ctx.rootDir, ctx.dist);
|
|
7352
7634
|
}
|
|
7353
7635
|
await generateTaskArtifacts(tasks, ctx.rootDir, ctx.dist);
|
|
7354
7636
|
ctx.taskQueue.invalidateModules();
|
|
@@ -7375,11 +7657,13 @@ export {
|
|
|
7375
7657
|
ValidationError,
|
|
7376
7658
|
clearAgentHandleFactory,
|
|
7377
7659
|
collectRouteSchemaSources,
|
|
7660
|
+
configureLogging,
|
|
7378
7661
|
cors,
|
|
7379
7662
|
createProdApp as createApp,
|
|
7380
7663
|
createAppRegistries,
|
|
7381
7664
|
createCronScheduler,
|
|
7382
7665
|
createDevApp,
|
|
7666
|
+
createLogger,
|
|
7383
7667
|
createProdApp,
|
|
7384
7668
|
createProgram,
|
|
7385
7669
|
createPrograms,
|