@faapi/faapi 6.8.0 → 6.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/index.js +384 -267
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +26 -12
- package/dist/index.js +353 -247
- package/dist/index.js.map +1 -1
- package/dist/{routeTypes-J5pPbjwR.d.ts → routeTypes-CuGMDCGB.d.ts} +20 -4
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +54 -16
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1235,13 +1235,13 @@ var init_collectRouteSchemaSources = __esm({
|
|
|
1235
1235
|
});
|
|
1236
1236
|
|
|
1237
1237
|
// src/utils/atomicWrite.ts
|
|
1238
|
-
import
|
|
1239
|
-
import
|
|
1238
|
+
import path10 from "path";
|
|
1239
|
+
import fs8 from "fs";
|
|
1240
1240
|
async function atomicWriteFile(outputPath, content) {
|
|
1241
|
-
await
|
|
1241
|
+
await fs8.promises.mkdir(path10.dirname(outputPath), { recursive: true });
|
|
1242
1242
|
const tmp = `${outputPath}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
1243
|
-
await
|
|
1244
|
-
await
|
|
1243
|
+
await fs8.promises.writeFile(tmp, content, "utf-8");
|
|
1244
|
+
await fs8.promises.rename(tmp, outputPath);
|
|
1245
1245
|
}
|
|
1246
1246
|
var init_atomicWrite = __esm({
|
|
1247
1247
|
"src/utils/atomicWrite.ts"() {
|
|
@@ -1588,7 +1588,7 @@ __export(generateSchemaFiles_exports, {
|
|
|
1588
1588
|
getRuntimeSchemaPath: () => getRuntimeSchemaPath,
|
|
1589
1589
|
getSchemaOutputPath: () => getSchemaOutputPath
|
|
1590
1590
|
});
|
|
1591
|
-
import
|
|
1591
|
+
import path11 from "path";
|
|
1592
1592
|
function getSchemaOutputPath(sourceFile, dist, rootDir) {
|
|
1593
1593
|
let rel = sourceFile.replace(/\\/g, "/");
|
|
1594
1594
|
if (rel.startsWith("src/")) {
|
|
@@ -1596,7 +1596,7 @@ function getSchemaOutputPath(sourceFile, dist, rootDir) {
|
|
|
1596
1596
|
}
|
|
1597
1597
|
const idx = rel.lastIndexOf("/");
|
|
1598
1598
|
const relDir = idx >= 0 ? rel.slice(0, idx) : "";
|
|
1599
|
-
return
|
|
1599
|
+
return path11.resolve(rootDir, dist, relDir, "zod.js");
|
|
1600
1600
|
}
|
|
1601
1601
|
function getRuntimeSchemaPath(filePath, dist, rootDir) {
|
|
1602
1602
|
let rel = filePath.replace(/\\/g, "/");
|
|
@@ -1607,7 +1607,7 @@ function getRuntimeSchemaPath(filePath, dist, rootDir) {
|
|
|
1607
1607
|
}
|
|
1608
1608
|
const idx = rel.lastIndexOf("/");
|
|
1609
1609
|
const relDir = idx >= 0 ? rel.slice(0, idx) : "";
|
|
1610
|
-
return
|
|
1610
|
+
return path11.resolve(rootDir, dist, relDir, "zod.js");
|
|
1611
1611
|
}
|
|
1612
1612
|
function getHelpersImportPath(relDir) {
|
|
1613
1613
|
if (!relDir) return `./${HELPERS_FILENAME}`;
|
|
@@ -1666,7 +1666,7 @@ async function generateSchemaFiles(routes, rootDir, dist) {
|
|
|
1666
1666
|
}
|
|
1667
1667
|
const fileEntries = [];
|
|
1668
1668
|
for (const [filePath, fileSources] of sourcesByFile) {
|
|
1669
|
-
const relFile =
|
|
1669
|
+
const relFile = path11.relative(rootDir, filePath).replace(/\\/g, "/");
|
|
1670
1670
|
const outputPath = getSchemaOutputPath(relFile, dist, rootDir);
|
|
1671
1671
|
let relForDir = relFile;
|
|
1672
1672
|
if (relForDir.startsWith("src/")) {
|
|
@@ -1685,7 +1685,7 @@ async function generateSchemaFiles(routes, rootDir, dist) {
|
|
|
1685
1685
|
}
|
|
1686
1686
|
const allSourceCode = fileEntries.map((e) => e.source).join("\n");
|
|
1687
1687
|
if (usesCoerceHelpers(allSourceCode)) {
|
|
1688
|
-
const helpersPath =
|
|
1688
|
+
const helpersPath = path11.resolve(rootDir, dist, HELPERS_FILENAME);
|
|
1689
1689
|
await writeSchemaFile(helpersPath, generateHelpersFileSource());
|
|
1690
1690
|
}
|
|
1691
1691
|
await Promise.all(
|
|
@@ -1917,7 +1917,7 @@ function createAppRegistries() {
|
|
|
1917
1917
|
var defaultRegistries = createAppRegistries();
|
|
1918
1918
|
|
|
1919
1919
|
// src/task/taskQueue.ts
|
|
1920
|
-
import
|
|
1920
|
+
import path4 from "path";
|
|
1921
1921
|
|
|
1922
1922
|
// src/errors/FaapiError.ts
|
|
1923
1923
|
var FaapiError = class extends Error {
|
|
@@ -1945,14 +1945,14 @@ var ValidationError = class extends FaapiError {
|
|
|
1945
1945
|
issues;
|
|
1946
1946
|
};
|
|
1947
1947
|
var RouteNotFoundError = class extends FaapiError {
|
|
1948
|
-
constructor(
|
|
1949
|
-
super("ROUTE_NOT_FOUND", `Route not found: ${
|
|
1948
|
+
constructor(path29) {
|
|
1949
|
+
super("ROUTE_NOT_FOUND", `Route not found: ${path29}`, 404);
|
|
1950
1950
|
this.name = "RouteNotFoundError";
|
|
1951
1951
|
}
|
|
1952
1952
|
};
|
|
1953
1953
|
var MethodNotAllowedError = class extends FaapiError {
|
|
1954
|
-
constructor(method,
|
|
1955
|
-
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);
|
|
1956
1956
|
this.allowedMethods = allowedMethods;
|
|
1957
1957
|
this.name = "MethodNotAllowedError";
|
|
1958
1958
|
}
|
|
@@ -2073,7 +2073,7 @@ var LOG_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
|
2073
2073
|
function createTaskLogger(level, scope, fields) {
|
|
2074
2074
|
function make(suffix) {
|
|
2075
2075
|
function write(lvl, message, callFields) {
|
|
2076
|
-
if (LOG_RANK[lvl] < LOG_RANK[level]) return;
|
|
2076
|
+
if (level !== undefined && LOG_RANK[lvl] < LOG_RANK[level]) return;
|
|
2077
2077
|
var entry = { level: lvl, message: message, time: new Date().toISOString() };
|
|
2078
2078
|
var fullScope = suffix === undefined ? scope : scope === undefined ? suffix : scope + ':' + suffix;
|
|
2079
2079
|
if (fullScope !== undefined) entry.scope = fullScope;
|
|
@@ -2275,6 +2275,95 @@ async function runTaskInWorker(options) {
|
|
|
2275
2275
|
});
|
|
2276
2276
|
}
|
|
2277
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
|
+
|
|
2278
2367
|
// src/logger/logger.ts
|
|
2279
2368
|
var LEVEL_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
|
|
2280
2369
|
var VALID_LEVELS = ["debug", "info", "warn", "error"];
|
|
@@ -2285,21 +2374,20 @@ function assertLogLevel(value, source) {
|
|
|
2285
2374
|
);
|
|
2286
2375
|
}
|
|
2287
2376
|
}
|
|
2288
|
-
var globalState = {
|
|
2289
|
-
level: null,
|
|
2290
|
-
sink: null,
|
|
2291
|
-
disabled: false
|
|
2292
|
-
};
|
|
2377
|
+
var globalState = { level: null, sink: null, fileSink: null, stdout: true, accessLog: false, disabled: false };
|
|
2293
2378
|
function configureLogging(config) {
|
|
2294
|
-
if (config === void 0) {
|
|
2295
|
-
globalState.level = null;
|
|
2296
|
-
globalState.sink = null;
|
|
2297
|
-
globalState.disabled = false;
|
|
2298
|
-
return;
|
|
2299
|
-
}
|
|
2300
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();
|
|
2301
2386
|
globalState.disabled = config === false;
|
|
2302
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;
|
|
2303
2391
|
if (objectConfig.level !== void 0) {
|
|
2304
2392
|
assertLogLevel(objectConfig.level, "config.log.level");
|
|
2305
2393
|
globalState.level = objectConfig.level;
|
|
@@ -2311,56 +2399,54 @@ function configureLogging(config) {
|
|
|
2311
2399
|
}
|
|
2312
2400
|
}
|
|
2313
2401
|
function globalThreshold() {
|
|
2314
|
-
|
|
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];
|
|
2315
2408
|
}
|
|
2316
2409
|
function getEffectiveLogLevel() {
|
|
2317
2410
|
return globalThreshold();
|
|
2318
2411
|
}
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
}
|
|
2323
|
-
return value;
|
|
2324
|
-
}
|
|
2325
|
-
function formatEntry(entry) {
|
|
2326
|
-
let line = `[${entry.time}] ${entry.level.toUpperCase()} `;
|
|
2327
|
-
if (entry.scope) line += `[${entry.scope}] `;
|
|
2328
|
-
line += entry.message;
|
|
2329
|
-
if (entry.fields !== void 0) {
|
|
2330
|
-
const plain = Object.fromEntries(
|
|
2331
|
-
Object.entries(entry.fields).map(([k, v]) => [k, serializeFieldValue(v)])
|
|
2332
|
-
);
|
|
2333
|
-
try {
|
|
2334
|
-
line += ` ${JSON.stringify(plain)}`;
|
|
2335
|
-
} catch (err) {
|
|
2336
|
-
line += ` [unserializable fields: ${err instanceof Error ? err.message : String(err)}]`;
|
|
2337
|
-
}
|
|
2338
|
-
}
|
|
2339
|
-
return line;
|
|
2340
|
-
}
|
|
2412
|
+
var consoleSink = (entry) => {
|
|
2413
|
+
console[CONSOLE_METHOD[entry.level]](formatEntry(entry));
|
|
2414
|
+
};
|
|
2341
2415
|
var CONSOLE_METHOD = {
|
|
2342
2416
|
debug: "debug",
|
|
2343
2417
|
info: "info",
|
|
2344
2418
|
warn: "warn",
|
|
2345
2419
|
error: "error"
|
|
2346
2420
|
};
|
|
2347
|
-
var consoleSink = (entry) => {
|
|
2348
|
-
console[CONSOLE_METHOD[entry.level]](formatEntry(entry));
|
|
2349
|
-
};
|
|
2350
2421
|
function globalDispatch(entry) {
|
|
2351
2422
|
if (globalState.disabled) return;
|
|
2352
|
-
(globalState.sink
|
|
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);
|
|
2353
2433
|
}
|
|
2354
2434
|
function writeLogEntry(entry) {
|
|
2355
|
-
if (
|
|
2435
|
+
if (belowThreshold(entry.level, globalThreshold())) return;
|
|
2356
2436
|
globalDispatch(entry);
|
|
2357
2437
|
}
|
|
2438
|
+
function flushLogging() {
|
|
2439
|
+
return globalState.fileSink ? globalState.fileSink.flush() : Promise.resolve();
|
|
2440
|
+
}
|
|
2441
|
+
function isAccessLogPiped() {
|
|
2442
|
+
return !globalState.disabled && globalState.accessLog;
|
|
2443
|
+
}
|
|
2358
2444
|
function createLogger(scope, options) {
|
|
2359
2445
|
const baseScope = scope;
|
|
2360
2446
|
const baseFields = options?.fields;
|
|
2361
2447
|
const write = (level, message, callFields, scopeSuffix) => {
|
|
2362
2448
|
const threshold = options?.level ?? globalThreshold();
|
|
2363
|
-
if (
|
|
2449
|
+
if (belowThreshold(level, threshold)) return;
|
|
2364
2450
|
const entry = {
|
|
2365
2451
|
level,
|
|
2366
2452
|
message,
|
|
@@ -2419,7 +2505,7 @@ function createTaskQueue(deps) {
|
|
|
2419
2505
|
}
|
|
2420
2506
|
const loadTaskModule = deps.loadTaskModule ?? (async (filePath) => await import(filePath));
|
|
2421
2507
|
const loadPayloadSchema = deps.loadPayloadSchema ?? (async (filePath) => {
|
|
2422
|
-
const zodPath =
|
|
2508
|
+
const zodPath = path4.join(path4.dirname(filePath), "zod.js");
|
|
2423
2509
|
try {
|
|
2424
2510
|
const mod = await import(zodPath);
|
|
2425
2511
|
const schemaKey = Object.keys(mod).find((k) => k.endsWith("Schema"));
|
|
@@ -2447,7 +2533,7 @@ function createTaskQueue(deps) {
|
|
|
2447
2533
|
const meta = registry.get(name);
|
|
2448
2534
|
schemaCache.set(
|
|
2449
2535
|
name,
|
|
2450
|
-
await loadPayloadSchema(
|
|
2536
|
+
await loadPayloadSchema(path4.resolve(rootDir, meta.filePath)).catch(() => void 0)
|
|
2451
2537
|
);
|
|
2452
2538
|
}
|
|
2453
2539
|
const schema = schemaCache.get(name);
|
|
@@ -2483,7 +2569,7 @@ function createTaskQueue(deps) {
|
|
|
2483
2569
|
let result;
|
|
2484
2570
|
if (meta.timeoutMs !== void 0 && meta.timeoutMs > 0) {
|
|
2485
2571
|
result = await (deps.runIsolated ?? runTaskInWorker)({
|
|
2486
|
-
taskModulePath:
|
|
2572
|
+
taskModulePath: path4.resolve(rootDir, meta.filePath),
|
|
2487
2573
|
payload: job.payload,
|
|
2488
2574
|
taskCtx: {
|
|
2489
2575
|
config: deps.config,
|
|
@@ -2508,7 +2594,7 @@ function createTaskQueue(deps) {
|
|
|
2508
2594
|
} else {
|
|
2509
2595
|
let mod = moduleCache2.get(job.name);
|
|
2510
2596
|
if (!mod) {
|
|
2511
|
-
mod = await loadTaskModule(
|
|
2597
|
+
mod = await loadTaskModule(path4.resolve(rootDir, meta.filePath));
|
|
2512
2598
|
moduleCache2.set(job.name, mod);
|
|
2513
2599
|
}
|
|
2514
2600
|
if (typeof mod.run !== "function") {
|
|
@@ -2745,8 +2831,8 @@ function createCronScheduler(registry, enqueue) {
|
|
|
2745
2831
|
|
|
2746
2832
|
// src/task/scanTasks.ts
|
|
2747
2833
|
import fg from "fast-glob";
|
|
2748
|
-
import
|
|
2749
|
-
import
|
|
2834
|
+
import path5 from "path";
|
|
2835
|
+
import fs3 from "fs";
|
|
2750
2836
|
var TASK_PATTERNS = ["src/tasks/**/task.ts"];
|
|
2751
2837
|
var TASK_FILENAME = "task.ts";
|
|
2752
2838
|
var CRON_RE = /(?:^|\n)\s*cron:\s*['"`]([^'"`\n]+)['"`]/;
|
|
@@ -2777,12 +2863,12 @@ async function scanTasks(rootDir, patterns) {
|
|
|
2777
2863
|
const seen = /* @__PURE__ */ new Map();
|
|
2778
2864
|
for (const file of files) {
|
|
2779
2865
|
const normalizedFile = file.replace(/\\/g, "/");
|
|
2780
|
-
const fileName =
|
|
2866
|
+
const fileName = path5.posix.basename(normalizedFile);
|
|
2781
2867
|
if (fileName !== TASK_FILENAME) {
|
|
2782
2868
|
continue;
|
|
2783
2869
|
}
|
|
2784
|
-
const absPath =
|
|
2785
|
-
const source = await
|
|
2870
|
+
const absPath = path5.resolve(rootDir, normalizedFile);
|
|
2871
|
+
const source = await fs3.promises.readFile(absPath, "utf8").catch(() => "");
|
|
2786
2872
|
const name = filePathToTaskName(normalizedFile);
|
|
2787
2873
|
const prevFile = seen.get(name);
|
|
2788
2874
|
if (prevFile) {
|
|
@@ -2855,7 +2941,7 @@ function listSkills() {
|
|
|
2855
2941
|
}
|
|
2856
2942
|
|
|
2857
2943
|
// src/loader/loadAgentModule.ts
|
|
2858
|
-
import
|
|
2944
|
+
import fs11 from "fs";
|
|
2859
2945
|
|
|
2860
2946
|
// src/loader/resolveExports.ts
|
|
2861
2947
|
function resolveExport(module, exportName) {
|
|
@@ -2901,18 +2987,18 @@ async function importWithCacheBust(filePath, bustViteCache = false) {
|
|
|
2901
2987
|
}
|
|
2902
2988
|
|
|
2903
2989
|
// src/cli/compileOnDemand.ts
|
|
2904
|
-
import
|
|
2905
|
-
import
|
|
2990
|
+
import path13 from "path";
|
|
2991
|
+
import fs10 from "fs";
|
|
2906
2992
|
|
|
2907
2993
|
// src/cli/compileSourceFiles.ts
|
|
2908
|
-
import
|
|
2909
|
-
import
|
|
2994
|
+
import path9 from "path";
|
|
2995
|
+
import fs7 from "fs";
|
|
2910
2996
|
import fg2 from "fast-glob";
|
|
2911
2997
|
|
|
2912
2998
|
// src/cli/aliasPlugin.ts
|
|
2913
2999
|
import ts7 from "typescript";
|
|
2914
|
-
import
|
|
2915
|
-
import
|
|
3000
|
+
import path8 from "path";
|
|
3001
|
+
import fs6 from "fs";
|
|
2916
3002
|
|
|
2917
3003
|
// src/utils/resolveAlias.ts
|
|
2918
3004
|
function resolveAlias(specifier, config) {
|
|
@@ -2938,8 +3024,8 @@ function resolveAlias(specifier, config) {
|
|
|
2938
3024
|
}
|
|
2939
3025
|
|
|
2940
3026
|
// src/utils/prodPaths.ts
|
|
2941
|
-
import
|
|
2942
|
-
import
|
|
3027
|
+
import path6 from "path";
|
|
3028
|
+
import fs4 from "fs";
|
|
2943
3029
|
var APP_DIR = "src";
|
|
2944
3030
|
var ROUTE_PATTERNS = ["src/api/**/*.ts"];
|
|
2945
3031
|
function toProdFilePath(filePath, dist) {
|
|
@@ -2958,27 +3044,27 @@ function toProdExtension(filePath) {
|
|
|
2958
3044
|
}
|
|
2959
3045
|
function toRealPath(p) {
|
|
2960
3046
|
try {
|
|
2961
|
-
return
|
|
3047
|
+
return fs4.realpathSync(p);
|
|
2962
3048
|
} catch {
|
|
2963
3049
|
return p;
|
|
2964
3050
|
}
|
|
2965
3051
|
}
|
|
2966
3052
|
function isInsideDir(filePath, dir) {
|
|
2967
|
-
const rel =
|
|
2968
|
-
return rel !== "" && !rel.startsWith("..") && !
|
|
3053
|
+
const rel = path6.relative(dir, filePath);
|
|
3054
|
+
return rel !== "" && !rel.startsWith("..") && !path6.isAbsolute(rel);
|
|
2969
3055
|
}
|
|
2970
3056
|
|
|
2971
3057
|
// src/utils/readTsconfig.ts
|
|
2972
3058
|
import ts6 from "typescript";
|
|
2973
|
-
import
|
|
2974
|
-
import
|
|
3059
|
+
import path7 from "path";
|
|
3060
|
+
import fs5 from "fs";
|
|
2975
3061
|
var tsconfigCache = /* @__PURE__ */ new Map();
|
|
2976
3062
|
function readTsconfig(rootDir) {
|
|
2977
|
-
const tsconfigPath =
|
|
2978
|
-
if (!
|
|
3063
|
+
const tsconfigPath = path7.resolve(rootDir, "tsconfig.json");
|
|
3064
|
+
if (!fs5.existsSync(tsconfigPath)) return null;
|
|
2979
3065
|
let mtimeMs;
|
|
2980
3066
|
try {
|
|
2981
|
-
mtimeMs =
|
|
3067
|
+
mtimeMs = fs5.statSync(tsconfigPath).mtimeMs;
|
|
2982
3068
|
} catch {
|
|
2983
3069
|
return null;
|
|
2984
3070
|
}
|
|
@@ -2994,7 +3080,7 @@ function readTsconfig(rootDir) {
|
|
|
2994
3080
|
const config = rawPaths ? (() => {
|
|
2995
3081
|
const paths = {};
|
|
2996
3082
|
for (const [pattern, targets] of Object.entries(rawPaths)) {
|
|
2997
|
-
paths[pattern] = targets.map((t) =>
|
|
3083
|
+
paths[pattern] = targets.map((t) => path7.resolve(baseUrl, t));
|
|
2998
3084
|
}
|
|
2999
3085
|
return { baseUrl, paths };
|
|
3000
3086
|
})() : null;
|
|
@@ -3004,26 +3090,26 @@ function readTsconfig(rootDir) {
|
|
|
3004
3090
|
|
|
3005
3091
|
// src/cli/aliasPlugin.ts
|
|
3006
3092
|
function toProdImportPath(sourceFile, importer) {
|
|
3007
|
-
const importerDir =
|
|
3008
|
-
let rel =
|
|
3009
|
-
rel = rel.split(
|
|
3093
|
+
const importerDir = path8.dirname(importer);
|
|
3094
|
+
let rel = path8.relative(importerDir, sourceFile);
|
|
3095
|
+
rel = rel.split(path8.sep).join("/");
|
|
3010
3096
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
3011
3097
|
return toProdExtension(rel);
|
|
3012
3098
|
}
|
|
3013
3099
|
function toStrippedProdImportPath(sourceFile, rootDir) {
|
|
3014
|
-
const appDirAbs = toRealPath(
|
|
3100
|
+
const appDirAbs = toRealPath(path8.resolve(rootDir, APP_DIR));
|
|
3015
3101
|
const sourceReal = toRealPath(sourceFile);
|
|
3016
|
-
let rel =
|
|
3017
|
-
rel = rel.split(
|
|
3102
|
+
let rel = path8.relative(appDirAbs, sourceReal);
|
|
3103
|
+
rel = rel.split(path8.sep).join("/");
|
|
3018
3104
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
3019
3105
|
return toProdExtension(rel);
|
|
3020
3106
|
}
|
|
3021
3107
|
function toProdImportFromImporter(importer, rootDir, relFromDist) {
|
|
3022
|
-
const importerRel =
|
|
3023
|
-
const importerProdDir =
|
|
3108
|
+
const importerRel = path8.relative(toRealPath(path8.resolve(rootDir)), toRealPath(importer)).split(path8.sep).join("/");
|
|
3109
|
+
const importerProdDir = path8.posix.dirname(toProdExtension(importerRel));
|
|
3024
3110
|
if (importerProdDir === ".") return relFromDist;
|
|
3025
3111
|
const target = relFromDist.replace(/^\.\//, "");
|
|
3026
|
-
let rel =
|
|
3112
|
+
let rel = path8.posix.relative(importerProdDir, target);
|
|
3027
3113
|
if (!rel.startsWith(".")) rel = "./" + rel;
|
|
3028
3114
|
return rel;
|
|
3029
3115
|
}
|
|
@@ -3038,41 +3124,41 @@ var INDEX_EXTS = [
|
|
|
3038
3124
|
"/index.cjs"
|
|
3039
3125
|
];
|
|
3040
3126
|
function resolveRelativeSpecifier(importer, specifier) {
|
|
3041
|
-
const importerDir =
|
|
3042
|
-
const base =
|
|
3127
|
+
const importerDir = path8.dirname(importer);
|
|
3128
|
+
const base = path8.resolve(importerDir, specifier);
|
|
3043
3129
|
if (PROD_EXTS.some((ext) => specifier.endsWith(ext))) {
|
|
3044
|
-
if (
|
|
3130
|
+
if (fs6.existsSync(base)) return base;
|
|
3045
3131
|
if (base.endsWith(".js")) {
|
|
3046
3132
|
for (const ext of [".ts", ".tsx", ".jsx"]) {
|
|
3047
3133
|
const file = base.slice(0, -3) + ext;
|
|
3048
|
-
if (
|
|
3134
|
+
if (fs6.existsSync(file)) return file;
|
|
3049
3135
|
}
|
|
3050
3136
|
}
|
|
3051
3137
|
return null;
|
|
3052
3138
|
}
|
|
3053
3139
|
if (/\.(ts|tsx|jsx)$/.test(specifier)) {
|
|
3054
|
-
return
|
|
3140
|
+
return fs6.existsSync(base) ? base : null;
|
|
3055
3141
|
}
|
|
3056
3142
|
for (const ext of SOURCE_EXTS) {
|
|
3057
3143
|
const file = base + ext;
|
|
3058
|
-
if (
|
|
3144
|
+
if (fs6.existsSync(file)) return file;
|
|
3059
3145
|
}
|
|
3060
3146
|
for (const indexExt of INDEX_EXTS) {
|
|
3061
3147
|
const file = base + indexExt;
|
|
3062
|
-
if (
|
|
3148
|
+
if (fs6.existsSync(file)) return file;
|
|
3063
3149
|
}
|
|
3064
3150
|
return null;
|
|
3065
3151
|
}
|
|
3066
3152
|
function createAliasPlugin(config, options) {
|
|
3067
|
-
const appDirAbs = options?.rootDir ? toRealPath(
|
|
3153
|
+
const appDirAbs = options?.rootDir ? toRealPath(path8.resolve(options.rootDir, APP_DIR)) : null;
|
|
3068
3154
|
const probeCandidateFile = (candidate) => {
|
|
3069
3155
|
for (const ext of SOURCE_EXTS) {
|
|
3070
3156
|
const file = candidate + ext;
|
|
3071
|
-
if (
|
|
3157
|
+
if (fs6.existsSync(file)) return file;
|
|
3072
3158
|
}
|
|
3073
3159
|
for (const indexExt of INDEX_EXTS) {
|
|
3074
3160
|
const file = candidate + indexExt;
|
|
3075
|
-
if (
|
|
3161
|
+
if (fs6.existsSync(file)) return file;
|
|
3076
3162
|
}
|
|
3077
3163
|
return null;
|
|
3078
3164
|
};
|
|
@@ -3082,7 +3168,7 @@ function createAliasPlugin(config, options) {
|
|
|
3082
3168
|
build.onLoad({ filter: /\.(ts|tsx|js|jsx|mjs|cjs)$/ }, (args) => {
|
|
3083
3169
|
let source;
|
|
3084
3170
|
try {
|
|
3085
|
-
source =
|
|
3171
|
+
source = fs6.readFileSync(args.path, "utf8");
|
|
3086
3172
|
} catch {
|
|
3087
3173
|
return void 0;
|
|
3088
3174
|
}
|
|
@@ -3207,11 +3293,11 @@ async function compileSourceFiles(options) {
|
|
|
3207
3293
|
if (entryPoints.length === 0) {
|
|
3208
3294
|
return { compiledFiles: [] };
|
|
3209
3295
|
}
|
|
3210
|
-
const absDist =
|
|
3211
|
-
await
|
|
3296
|
+
const absDist = path9.resolve(rootDir, dist);
|
|
3297
|
+
await fs7.promises.mkdir(absDist, { recursive: true });
|
|
3212
3298
|
const plugins = buildAliasPlugins(rootDir);
|
|
3213
3299
|
const esbuild = await import("esbuild");
|
|
3214
|
-
const outbase =
|
|
3300
|
+
const outbase = path9.resolve(rootDir, APP_DIR);
|
|
3215
3301
|
const result = await esbuild.build({
|
|
3216
3302
|
entryPoints,
|
|
3217
3303
|
outdir: absDist,
|
|
@@ -3231,10 +3317,10 @@ async function compileSourceFiles(options) {
|
|
|
3231
3317
|
if (atomicWrite && result.outputFiles) {
|
|
3232
3318
|
await Promise.all(
|
|
3233
3319
|
result.outputFiles.map(async (file) => {
|
|
3234
|
-
await
|
|
3320
|
+
await fs7.promises.mkdir(path9.dirname(file.path), { recursive: true });
|
|
3235
3321
|
const tmp = `${file.path}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
|
|
3236
|
-
await
|
|
3237
|
-
await
|
|
3322
|
+
await fs7.promises.writeFile(tmp, file.contents);
|
|
3323
|
+
await fs7.promises.rename(tmp, file.path);
|
|
3238
3324
|
})
|
|
3239
3325
|
);
|
|
3240
3326
|
}
|
|
@@ -3251,8 +3337,8 @@ init_generateSchemaFiles();
|
|
|
3251
3337
|
init_generateSchemaFiles();
|
|
3252
3338
|
|
|
3253
3339
|
// src/cli/collectImports.ts
|
|
3254
|
-
import
|
|
3255
|
-
import
|
|
3340
|
+
import path12 from "path";
|
|
3341
|
+
import fs9 from "fs";
|
|
3256
3342
|
var SPEC_RE = /(\bfrom\s*|import\s*\(\s*)(['"])([^'"]+)\2/g;
|
|
3257
3343
|
function extractImportSpecifiers(source) {
|
|
3258
3344
|
const specifiers = [];
|
|
@@ -3264,10 +3350,10 @@ function extractImportSpecifiers(source) {
|
|
|
3264
3350
|
return specifiers;
|
|
3265
3351
|
}
|
|
3266
3352
|
function resolveSpecifierFromDir(dir, specifier) {
|
|
3267
|
-
return resolveRelativeSpecifier(
|
|
3353
|
+
return resolveRelativeSpecifier(path12.join(dir, "__faapi_probe__.ts"), specifier);
|
|
3268
3354
|
}
|
|
3269
3355
|
async function collectRelativeImports(entryFiles, rootDir) {
|
|
3270
|
-
const appDirAbs = toRealPath(
|
|
3356
|
+
const appDirAbs = toRealPath(path12.resolve(rootDir, "src"));
|
|
3271
3357
|
const tsconfig = readTsconfig(rootDir);
|
|
3272
3358
|
const visited = /* @__PURE__ */ new Set();
|
|
3273
3359
|
const insideFiles = /* @__PURE__ */ new Set();
|
|
@@ -3277,7 +3363,7 @@ async function collectRelativeImports(entryFiles, rootDir) {
|
|
|
3277
3363
|
visited.add(filePath);
|
|
3278
3364
|
let source;
|
|
3279
3365
|
try {
|
|
3280
|
-
source = await
|
|
3366
|
+
source = await fs9.promises.readFile(filePath, "utf8");
|
|
3281
3367
|
} catch {
|
|
3282
3368
|
return;
|
|
3283
3369
|
}
|
|
@@ -3299,7 +3385,7 @@ async function collectRelativeImports(entryFiles, rootDir) {
|
|
|
3299
3385
|
resolved = null;
|
|
3300
3386
|
}
|
|
3301
3387
|
if (!resolved) continue;
|
|
3302
|
-
if (!isInsideDir(toRealPath(resolved), toRealPath(
|
|
3388
|
+
if (!isInsideDir(toRealPath(resolved), toRealPath(path12.resolve(rootDir)))) continue;
|
|
3303
3389
|
if (isInsideDir(toRealPath(resolved), appDirAbs)) {
|
|
3304
3390
|
insideFiles.add(resolved);
|
|
3305
3391
|
} else {
|
|
@@ -3320,8 +3406,8 @@ async function collectRelativeImports(entryFiles, rootDir) {
|
|
|
3320
3406
|
// src/cli/compileOnDemand.ts
|
|
3321
3407
|
function isProductFresh(sourceAbsPath, productAbsPath) {
|
|
3322
3408
|
try {
|
|
3323
|
-
const srcStat =
|
|
3324
|
-
const prodStat =
|
|
3409
|
+
const srcStat = fs10.statSync(sourceAbsPath);
|
|
3410
|
+
const prodStat = fs10.statSync(productAbsPath);
|
|
3325
3411
|
return prodStat.mtimeMs >= srcStat.mtimeMs;
|
|
3326
3412
|
} catch {
|
|
3327
3413
|
return false;
|
|
@@ -3353,7 +3439,7 @@ async function ensureCompiled(sourceAbsPath, rootDir, dist) {
|
|
|
3353
3439
|
if (state.compiledFiles.has(sourceAbsPath)) {
|
|
3354
3440
|
return false;
|
|
3355
3441
|
}
|
|
3356
|
-
if (!
|
|
3442
|
+
if (!fs10.existsSync(sourceAbsPath)) {
|
|
3357
3443
|
return false;
|
|
3358
3444
|
}
|
|
3359
3445
|
const productPath = prodSourcePathToProductPath(sourceAbsPath, rootDir, dist);
|
|
@@ -3403,11 +3489,11 @@ async function ensureMiddlewaresCompiled(middlewarePaths, rootDir) {
|
|
|
3403
3489
|
}
|
|
3404
3490
|
}
|
|
3405
3491
|
function prodSourcePathToProductPath(sourceAbsPath, rootDir, dist) {
|
|
3406
|
-
const rel =
|
|
3492
|
+
const rel = path13.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
|
|
3407
3493
|
if (!rel.startsWith("src/")) return null;
|
|
3408
3494
|
const relWithoutSrc = rel.slice(4);
|
|
3409
3495
|
const jsRel = relWithoutSrc.replace(/\.ts$/, ".js");
|
|
3410
|
-
return
|
|
3496
|
+
return path13.resolve(rootDir, dist, jsRel);
|
|
3411
3497
|
}
|
|
3412
3498
|
function clearGeneratedSchemas() {
|
|
3413
3499
|
state.generatedSchemas.clear();
|
|
@@ -3423,9 +3509,9 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
|
|
|
3423
3509
|
if (state.generatedSchemas.has(schemaPath)) {
|
|
3424
3510
|
return false;
|
|
3425
3511
|
}
|
|
3426
|
-
const prodAbsPath =
|
|
3512
|
+
const prodAbsPath = path13.resolve(rootDir, routeFilePath);
|
|
3427
3513
|
const sourceAbsPath = prodPathToSourcePath(prodAbsPath, rootDir, dist);
|
|
3428
|
-
if (!
|
|
3514
|
+
if (!fs10.existsSync(sourceAbsPath)) {
|
|
3429
3515
|
return false;
|
|
3430
3516
|
}
|
|
3431
3517
|
if (isProductFresh(sourceAbsPath, schemaPath)) {
|
|
@@ -3436,7 +3522,7 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
|
|
|
3436
3522
|
if (fileRoutes.length === 0) {
|
|
3437
3523
|
return false;
|
|
3438
3524
|
}
|
|
3439
|
-
const sourceRelPath =
|
|
3525
|
+
const sourceRelPath = path13.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
|
|
3440
3526
|
const sourceRoutes = fileRoutes.map((r) => ({ ...r, filePath: sourceRelPath }));
|
|
3441
3527
|
const generatePromise = (async () => {
|
|
3442
3528
|
await generateSchemaFiles(sourceRoutes, rootDir, dist);
|
|
@@ -3457,7 +3543,7 @@ async function deleteSchemaFiles(routes, rootDir, dist) {
|
|
|
3457
3543
|
if (deleted.has(schemaPath)) continue;
|
|
3458
3544
|
deleted.add(schemaPath);
|
|
3459
3545
|
try {
|
|
3460
|
-
await
|
|
3546
|
+
await fs10.promises.unlink(schemaPath);
|
|
3461
3547
|
} catch {
|
|
3462
3548
|
}
|
|
3463
3549
|
}
|
|
@@ -3466,19 +3552,19 @@ var sourcePathCache = /* @__PURE__ */ new Map();
|
|
|
3466
3552
|
function prodPathToSourcePath(prodAbsPath, rootDir, dist) {
|
|
3467
3553
|
const cached = sourcePathCache.get(prodAbsPath);
|
|
3468
3554
|
if (cached) return cached;
|
|
3469
|
-
const rel =
|
|
3555
|
+
const rel = path13.relative(rootDir, prodAbsPath).replace(/\\/g, "/");
|
|
3470
3556
|
let relWithoutDist = rel;
|
|
3471
3557
|
if (relWithoutDist.startsWith(`${dist}/`)) {
|
|
3472
3558
|
relWithoutDist = relWithoutDist.slice(dist.length + 1);
|
|
3473
3559
|
}
|
|
3474
3560
|
const srcRel = `src/${relWithoutDist}`;
|
|
3475
3561
|
const tsRel = srcRel.replace(/\.js$/, ".ts");
|
|
3476
|
-
const tsAbs =
|
|
3562
|
+
const tsAbs = path13.resolve(rootDir, tsRel);
|
|
3477
3563
|
let result;
|
|
3478
|
-
if (
|
|
3564
|
+
if (fs10.existsSync(tsAbs)) {
|
|
3479
3565
|
result = tsAbs;
|
|
3480
3566
|
} else {
|
|
3481
|
-
result =
|
|
3567
|
+
result = path13.resolve(rootDir, srcRel);
|
|
3482
3568
|
}
|
|
3483
3569
|
sourcePathCache.set(prodAbsPath, result);
|
|
3484
3570
|
return result;
|
|
@@ -3496,7 +3582,7 @@ async function loadAgentModule(filePath, hasRun, rootDir) {
|
|
|
3496
3582
|
const dist = getDevDist();
|
|
3497
3583
|
if (dist) {
|
|
3498
3584
|
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
3499
|
-
if (sourcePath &&
|
|
3585
|
+
if (sourcePath && fs11.existsSync(sourcePath)) {
|
|
3500
3586
|
try {
|
|
3501
3587
|
await ensureCompiled(sourcePath, rootDir, dist);
|
|
3502
3588
|
} catch (compileErr) {
|
|
@@ -3529,13 +3615,13 @@ async function loadAgentModule(filePath, hasRun, rootDir) {
|
|
|
3529
3615
|
}
|
|
3530
3616
|
|
|
3531
3617
|
// src/loader/loadToolModule.ts
|
|
3532
|
-
import
|
|
3618
|
+
import fs12 from "fs";
|
|
3533
3619
|
async function loadToolModule(filePath, functionName, rootDir) {
|
|
3534
3620
|
if (isDevOnDemandEnabled() && rootDir) {
|
|
3535
3621
|
const dist = getDevDist();
|
|
3536
3622
|
if (dist) {
|
|
3537
3623
|
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
3538
|
-
if (sourcePath &&
|
|
3624
|
+
if (sourcePath && fs12.existsSync(sourcePath)) {
|
|
3539
3625
|
try {
|
|
3540
3626
|
await ensureCompiled(sourcePath, rootDir, dist);
|
|
3541
3627
|
} catch (compileErr) {
|
|
@@ -3567,7 +3653,7 @@ async function loadToolModule(filePath, functionName, rootDir) {
|
|
|
3567
3653
|
import { existsSync as existsSync2 } from "fs";
|
|
3568
3654
|
|
|
3569
3655
|
// src/cli/generateToolArtifacts.ts
|
|
3570
|
-
import
|
|
3656
|
+
import path14 from "path";
|
|
3571
3657
|
import { existsSync } from "fs";
|
|
3572
3658
|
|
|
3573
3659
|
// src/ast/extractToolMetadata.ts
|
|
@@ -3691,7 +3777,7 @@ function collectToolSchemaSources(tools, rootDir) {
|
|
|
3691
3777
|
const toolsByFile = /* @__PURE__ */ new Map();
|
|
3692
3778
|
for (const tool of tools) {
|
|
3693
3779
|
if (!tool.inputTypeName) continue;
|
|
3694
|
-
const absPath =
|
|
3780
|
+
const absPath = path14.resolve(rootDir, tool.filePath);
|
|
3695
3781
|
let list = toolsByFile.get(absPath);
|
|
3696
3782
|
if (!list) {
|
|
3697
3783
|
list = [];
|
|
@@ -3751,15 +3837,15 @@ function generateToolSchemaFileSource(sources, resolveType, helpersImportPath) {
|
|
|
3751
3837
|
}
|
|
3752
3838
|
async function maybeGenerateHelpers(allSourceCode, distDir) {
|
|
3753
3839
|
if (!usesCoerceHelpers(allSourceCode)) return;
|
|
3754
|
-
const helpersPath =
|
|
3840
|
+
const helpersPath = path14.resolve(distDir, HELPERS_FILENAME);
|
|
3755
3841
|
if (existsSync(helpersPath)) return;
|
|
3756
3842
|
await atomicWriteFile(helpersPath, generateHelpersFileSource());
|
|
3757
3843
|
}
|
|
3758
3844
|
async function generateToolArtifacts(tools, rootDir, dist, options) {
|
|
3759
3845
|
const metadata = [];
|
|
3760
|
-
const programByFile = createPrograms(tools.map((m) =>
|
|
3846
|
+
const programByFile = createPrograms(tools.map((m) => path14.resolve(rootDir, m.filePath)));
|
|
3761
3847
|
for (const manifest of tools) {
|
|
3762
|
-
const absPath =
|
|
3848
|
+
const absPath = path14.resolve(rootDir, manifest.filePath);
|
|
3763
3849
|
const program = programByFile.get(absPath);
|
|
3764
3850
|
const result = extractToolMetadata(program, absPath, manifest.functionName, {
|
|
3765
3851
|
name: manifest.name,
|
|
@@ -3770,7 +3856,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
|
|
|
3770
3856
|
}
|
|
3771
3857
|
}
|
|
3772
3858
|
const serialized = serializeTools(metadata, dist);
|
|
3773
|
-
const toolsPath =
|
|
3859
|
+
const toolsPath = path14.resolve(rootDir, dist, TOOLS_FILE);
|
|
3774
3860
|
await writeToolsModule(serialized, toolsPath);
|
|
3775
3861
|
if (options?.skipSchema) {
|
|
3776
3862
|
return metadata;
|
|
@@ -3793,7 +3879,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
|
|
|
3793
3879
|
}
|
|
3794
3880
|
const fileEntries = [];
|
|
3795
3881
|
for (const [filePath, fileSources] of sourcesByFile) {
|
|
3796
|
-
const relFile =
|
|
3882
|
+
const relFile = path14.relative(rootDir, filePath).replace(/\\/g, "/");
|
|
3797
3883
|
const outputPath = getSchemaOutputPath(relFile, dist, rootDir);
|
|
3798
3884
|
const resolver = resolversByFile.get(filePath);
|
|
3799
3885
|
let relForDir = relFile;
|
|
@@ -3811,7 +3897,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
|
|
|
3811
3897
|
fileEntries.push({ outputPath, source });
|
|
3812
3898
|
}
|
|
3813
3899
|
const allSourceCode = fileEntries.map((e) => e.source).join("\n");
|
|
3814
|
-
const distDir =
|
|
3900
|
+
const distDir = path14.resolve(rootDir, dist);
|
|
3815
3901
|
await maybeGenerateHelpers(allSourceCode, distDir);
|
|
3816
3902
|
await Promise.all(
|
|
3817
3903
|
fileEntries.map(({ outputPath, source }) => writeToolSchemaFile(outputPath, source))
|
|
@@ -3925,9 +4011,28 @@ function cors(options = {}) {
|
|
|
3925
4011
|
}
|
|
3926
4012
|
|
|
3927
4013
|
// src/middleware/logger.ts
|
|
4014
|
+
function levelForStatus(status) {
|
|
4015
|
+
if (status >= 500) return "error";
|
|
4016
|
+
if (status >= 400) return "warn";
|
|
4017
|
+
return "info";
|
|
4018
|
+
}
|
|
4019
|
+
function defaultLog(entry, text) {
|
|
4020
|
+
if (isAccessLogPiped()) {
|
|
4021
|
+
const logEntry = {
|
|
4022
|
+
level: levelForStatus(entry.status),
|
|
4023
|
+
message: text,
|
|
4024
|
+
time: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4025
|
+
scope: "access",
|
|
4026
|
+
fields: entry
|
|
4027
|
+
};
|
|
4028
|
+
writeLogEntry(logEntry);
|
|
4029
|
+
return;
|
|
4030
|
+
}
|
|
4031
|
+
console.log(entry);
|
|
4032
|
+
}
|
|
3928
4033
|
function logger(options = {}) {
|
|
3929
4034
|
return async (ctx, next) => {
|
|
3930
|
-
const log = options.log ??
|
|
4035
|
+
const log = options.log ?? defaultLog;
|
|
3931
4036
|
const start = Date.now();
|
|
3932
4037
|
try {
|
|
3933
4038
|
const response = await next();
|
|
@@ -4022,16 +4127,16 @@ function helmet(options = {}) {
|
|
|
4022
4127
|
}
|
|
4023
4128
|
|
|
4024
4129
|
// src/config/loadConfig.ts
|
|
4025
|
-
import
|
|
4026
|
-
import
|
|
4130
|
+
import path15 from "path";
|
|
4131
|
+
import fs13 from "fs";
|
|
4027
4132
|
var CONFIG_PRODUCT_FILE = "faapi-config.js";
|
|
4028
4133
|
async function loadConfig(rootDir, dist) {
|
|
4029
|
-
const configProductPath =
|
|
4030
|
-
if (
|
|
4134
|
+
const configProductPath = path15.resolve(rootDir, dist, CONFIG_PRODUCT_FILE);
|
|
4135
|
+
if (fs13.existsSync(configProductPath)) {
|
|
4031
4136
|
const module = await importWithCacheBust(configProductPath);
|
|
4032
4137
|
return module.default ?? {};
|
|
4033
4138
|
}
|
|
4034
|
-
const hasSourceConfig =
|
|
4139
|
+
const hasSourceConfig = fs13.existsSync(path15.join(rootDir, "faapi.config.ts")) || fs13.existsSync(path15.join(rootDir, "faapi.config.js"));
|
|
4035
4140
|
if (hasSourceConfig) {
|
|
4036
4141
|
throw new Error(
|
|
4037
4142
|
`[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`
|
|
@@ -4041,8 +4146,8 @@ async function loadConfig(rootDir, dist) {
|
|
|
4041
4146
|
}
|
|
4042
4147
|
|
|
4043
4148
|
// src/cli/loadEnv.ts
|
|
4044
|
-
import
|
|
4045
|
-
import
|
|
4149
|
+
import fs14 from "fs";
|
|
4150
|
+
import path16 from "path";
|
|
4046
4151
|
function resolveEnv() {
|
|
4047
4152
|
return process.env.NODE_ENV || "development";
|
|
4048
4153
|
}
|
|
@@ -4109,9 +4214,9 @@ function loadEnv(rootDir) {
|
|
|
4109
4214
|
const files = getEnvFiles(env);
|
|
4110
4215
|
const merged = {};
|
|
4111
4216
|
for (const file of files) {
|
|
4112
|
-
const filePath =
|
|
4113
|
-
if (!
|
|
4114
|
-
const content =
|
|
4217
|
+
const filePath = path16.join(rootDir, file);
|
|
4218
|
+
if (!fs14.existsSync(filePath)) continue;
|
|
4219
|
+
const content = fs14.readFileSync(filePath, "utf-8");
|
|
4115
4220
|
const parsed = parseEnvFile(content, merged);
|
|
4116
4221
|
Object.assign(merged, parsed);
|
|
4117
4222
|
}
|
|
@@ -4123,8 +4228,8 @@ function loadEnv(rootDir) {
|
|
|
4123
4228
|
}
|
|
4124
4229
|
|
|
4125
4230
|
// src/cli/createAppCore.ts
|
|
4126
|
-
import
|
|
4127
|
-
import
|
|
4231
|
+
import fs19 from "fs";
|
|
4232
|
+
import path24 from "path";
|
|
4128
4233
|
import { PassThrough, Readable as Readable3 } from "stream";
|
|
4129
4234
|
|
|
4130
4235
|
// src/router/sortRoutes.ts
|
|
@@ -4177,7 +4282,7 @@ import {
|
|
|
4177
4282
|
import { createSecureServer as createHttp2SecureServer } from "http2";
|
|
4178
4283
|
import { readFileSync } from "fs";
|
|
4179
4284
|
import { Readable as Readable2 } from "stream";
|
|
4180
|
-
import
|
|
4285
|
+
import path18 from "path";
|
|
4181
4286
|
|
|
4182
4287
|
// src/router/matchRoute.ts
|
|
4183
4288
|
var httpIndexCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -4219,18 +4324,18 @@ function getWsIndex(routes) {
|
|
|
4219
4324
|
wsIndexCache.set(routes, index);
|
|
4220
4325
|
return index;
|
|
4221
4326
|
}
|
|
4222
|
-
function matchRoute(routes, method,
|
|
4327
|
+
function matchRoute(routes, method, path29) {
|
|
4223
4328
|
const index = getHttpIndex(routes);
|
|
4224
4329
|
const upper = method.toUpperCase();
|
|
4225
|
-
const hit = matchByMethod(index, upper,
|
|
4330
|
+
const hit = matchByMethod(index, upper, path29);
|
|
4226
4331
|
if (hit) return hit;
|
|
4227
4332
|
if (upper === "HEAD") {
|
|
4228
|
-
return matchByMethod(index, "GET",
|
|
4333
|
+
return matchByMethod(index, "GET", path29);
|
|
4229
4334
|
}
|
|
4230
4335
|
return null;
|
|
4231
4336
|
}
|
|
4232
|
-
function matchByMethod(index, method,
|
|
4233
|
-
const staticHit = index.static.get(`${method}|${
|
|
4337
|
+
function matchByMethod(index, method, path29) {
|
|
4338
|
+
const staticHit = index.static.get(`${method}|${path29}`);
|
|
4234
4339
|
if (staticHit) {
|
|
4235
4340
|
return { route: staticHit, params: {} };
|
|
4236
4341
|
}
|
|
@@ -4239,31 +4344,31 @@ function matchByMethod(index, method, path28) {
|
|
|
4239
4344
|
if (route.method !== method) {
|
|
4240
4345
|
continue;
|
|
4241
4346
|
}
|
|
4242
|
-
const params = matchSegments(entry.segments,
|
|
4347
|
+
const params = matchSegments(entry.segments, path29, route.paramNames, route.isCatchAll);
|
|
4243
4348
|
if (params !== null) {
|
|
4244
4349
|
return { route, params };
|
|
4245
4350
|
}
|
|
4246
4351
|
}
|
|
4247
4352
|
return null;
|
|
4248
4353
|
}
|
|
4249
|
-
function matchWsRoute(wsRoutes,
|
|
4354
|
+
function matchWsRoute(wsRoutes, path29) {
|
|
4250
4355
|
const index = getWsIndex(wsRoutes);
|
|
4251
|
-
const staticHit = index.static.get(
|
|
4356
|
+
const staticHit = index.static.get(path29);
|
|
4252
4357
|
if (staticHit) {
|
|
4253
4358
|
return { route: staticHit, params: {} };
|
|
4254
4359
|
}
|
|
4255
4360
|
for (const route of index.dynamics) {
|
|
4256
|
-
const params = matchDynamicPath(route.urlPath,
|
|
4361
|
+
const params = matchDynamicPath(route.urlPath, path29, route.paramNames, route.isCatchAll);
|
|
4257
4362
|
if (params !== null) {
|
|
4258
4363
|
return { route, params };
|
|
4259
4364
|
}
|
|
4260
4365
|
}
|
|
4261
4366
|
return null;
|
|
4262
4367
|
}
|
|
4263
|
-
function findAllowedMethods(routes,
|
|
4368
|
+
function findAllowedMethods(routes, path29) {
|
|
4264
4369
|
const index = getHttpIndex(routes);
|
|
4265
4370
|
const methods = /* @__PURE__ */ new Set();
|
|
4266
|
-
const staticMethods = index.methodsByStaticPath.get(
|
|
4371
|
+
const staticMethods = index.methodsByStaticPath.get(path29);
|
|
4267
4372
|
if (staticMethods) {
|
|
4268
4373
|
for (const method of staticMethods) {
|
|
4269
4374
|
methods.add(method);
|
|
@@ -4272,7 +4377,7 @@ function findAllowedMethods(routes, path28) {
|
|
|
4272
4377
|
for (const entry of index.dynamics) {
|
|
4273
4378
|
const params = matchSegments(
|
|
4274
4379
|
entry.segments,
|
|
4275
|
-
|
|
4380
|
+
path29,
|
|
4276
4381
|
entry.route.paramNames,
|
|
4277
4382
|
entry.route.isCatchAll
|
|
4278
4383
|
);
|
|
@@ -4285,11 +4390,11 @@ function findAllowedMethods(routes, path28) {
|
|
|
4285
4390
|
}
|
|
4286
4391
|
return Array.from(methods);
|
|
4287
4392
|
}
|
|
4288
|
-
function matchDynamicPath(pattern,
|
|
4289
|
-
return matchSegments(pattern.split("/").filter(Boolean),
|
|
4393
|
+
function matchDynamicPath(pattern, path29, paramNames, isCatchAll) {
|
|
4394
|
+
return matchSegments(pattern.split("/").filter(Boolean), path29, paramNames, isCatchAll);
|
|
4290
4395
|
}
|
|
4291
|
-
function matchSegments(patternSegments,
|
|
4292
|
-
const pathSegments =
|
|
4396
|
+
function matchSegments(patternSegments, path29, paramNames, isCatchAll) {
|
|
4397
|
+
const pathSegments = path29.split("/").filter(Boolean);
|
|
4293
4398
|
if (isCatchAll) {
|
|
4294
4399
|
const nonCatchAllCount = patternSegments.length - 1;
|
|
4295
4400
|
if (pathSegments.length <= nonCatchAllCount) {
|
|
@@ -5196,9 +5301,9 @@ async function validateInput(schemaPath, method, inputType, input) {
|
|
|
5196
5301
|
function mapZodIssues(error) {
|
|
5197
5302
|
return error.issues.map((issue) => {
|
|
5198
5303
|
const code = mapZodCode(issue);
|
|
5199
|
-
const
|
|
5304
|
+
const path29 = issue.path.map(String).join(".") || "";
|
|
5200
5305
|
return {
|
|
5201
|
-
path:
|
|
5306
|
+
path: path29,
|
|
5202
5307
|
code,
|
|
5203
5308
|
expected: issue.expected ?? mapExpectedFromMessage(issue.message),
|
|
5204
5309
|
received: issue.received ?? mapReceivedFromMessage(issue.message),
|
|
@@ -5430,9 +5535,9 @@ function etag(options = {}) {
|
|
|
5430
5535
|
}
|
|
5431
5536
|
|
|
5432
5537
|
// src/server/handleWsUpgrade.ts
|
|
5433
|
-
import
|
|
5538
|
+
import fs15 from "fs";
|
|
5434
5539
|
import { WebSocketServer, WebSocket } from "ws";
|
|
5435
|
-
import
|
|
5540
|
+
import path17 from "path";
|
|
5436
5541
|
|
|
5437
5542
|
// src/server/serverUtils.ts
|
|
5438
5543
|
function nodeHttpToWebHeaders(req) {
|
|
@@ -5567,7 +5672,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
|
|
|
5567
5672
|
const dist = getDevDist();
|
|
5568
5673
|
if (dist) {
|
|
5569
5674
|
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
5570
|
-
if (sourcePath &&
|
|
5675
|
+
if (sourcePath && fs15.existsSync(sourcePath)) {
|
|
5571
5676
|
await ensureCompiled(sourcePath, rootDir, dist);
|
|
5572
5677
|
}
|
|
5573
5678
|
}
|
|
@@ -5681,7 +5786,7 @@ function attachWebSocket(options) {
|
|
|
5681
5786
|
const finalHandler = async () => {
|
|
5682
5787
|
let handlers;
|
|
5683
5788
|
try {
|
|
5684
|
-
const absoluteFilePath =
|
|
5789
|
+
const absoluteFilePath = path17.resolve(rootDir, route.filePath);
|
|
5685
5790
|
handlers = await loadWsHandler(absoluteFilePath, ctx, rootDir);
|
|
5686
5791
|
} catch (err) {
|
|
5687
5792
|
const reason = err instanceof Error ? err.message : String(err);
|
|
@@ -5934,7 +6039,7 @@ function getRoutePaths(route, rootDir, dist) {
|
|
|
5934
6039
|
let cached = routePathCache.get(route);
|
|
5935
6040
|
if (!cached) {
|
|
5936
6041
|
cached = {
|
|
5937
|
-
absFilePath:
|
|
6042
|
+
absFilePath: path18.resolve(rootDir, route.filePath),
|
|
5938
6043
|
schemaPath: getRuntimeSchemaPath(route.filePath, dist, rootDir)
|
|
5939
6044
|
};
|
|
5940
6045
|
routePathCache.set(route, cached);
|
|
@@ -6056,8 +6161,8 @@ function applyPluginWrappers(server, handlerWrappers, upgradeWrappers) {
|
|
|
6056
6161
|
}
|
|
6057
6162
|
|
|
6058
6163
|
// src/cli/generateRoutes.ts
|
|
6059
|
-
import
|
|
6060
|
-
import
|
|
6164
|
+
import fs16 from "fs";
|
|
6165
|
+
import path19 from "path";
|
|
6061
6166
|
async function hydrateRoutes(manifest) {
|
|
6062
6167
|
const hydrateRoute = (serialized) => ({
|
|
6063
6168
|
method: serialized.method,
|
|
@@ -6082,7 +6187,7 @@ async function hydrateRoutes(manifest) {
|
|
|
6082
6187
|
}
|
|
6083
6188
|
|
|
6084
6189
|
// src/cli/generateAgentArtifacts.ts
|
|
6085
|
-
import
|
|
6190
|
+
import path20 from "path";
|
|
6086
6191
|
|
|
6087
6192
|
// src/ast/extractAgentMetadata.ts
|
|
6088
6193
|
import ts10 from "typescript";
|
|
@@ -6355,9 +6460,9 @@ function validateAgentList(metadata) {
|
|
|
6355
6460
|
}
|
|
6356
6461
|
async function generateAgentArtifacts(agents, rootDir, dist) {
|
|
6357
6462
|
const metadata = [];
|
|
6358
|
-
const programByFile = createPrograms(agents.map((m) =>
|
|
6463
|
+
const programByFile = createPrograms(agents.map((m) => path20.resolve(rootDir, m.filePath)));
|
|
6359
6464
|
for (const manifest of agents) {
|
|
6360
|
-
const absPath =
|
|
6465
|
+
const absPath = path20.resolve(rootDir, manifest.filePath);
|
|
6361
6466
|
const program = programByFile.get(absPath);
|
|
6362
6467
|
const result = extractAgentMetadata(program, absPath, {
|
|
6363
6468
|
name: manifest.name,
|
|
@@ -6373,13 +6478,13 @@ async function generateAgentArtifacts(agents, rootDir, dist) {
|
|
|
6373
6478
|
}
|
|
6374
6479
|
validateAgentList(metadata);
|
|
6375
6480
|
const serialized = serializeAgents(metadata, dist);
|
|
6376
|
-
const agentsPath =
|
|
6481
|
+
const agentsPath = path20.resolve(rootDir, dist, AGENTS_FILE);
|
|
6377
6482
|
await writeAgentsModule(serialized, agentsPath);
|
|
6378
6483
|
return metadata;
|
|
6379
6484
|
}
|
|
6380
6485
|
|
|
6381
6486
|
// src/cli/generateTaskArtifacts.ts
|
|
6382
|
-
import
|
|
6487
|
+
import path21 from "path";
|
|
6383
6488
|
init_createProgram();
|
|
6384
6489
|
init_atomicWrite();
|
|
6385
6490
|
init_generateSchemaFiles();
|
|
@@ -6418,7 +6523,7 @@ function collectTaskSchemaSources(tasks, rootDir) {
|
|
|
6418
6523
|
const tasksByFile = /* @__PURE__ */ new Map();
|
|
6419
6524
|
for (const task of tasks) {
|
|
6420
6525
|
if (!task.inputTypeName) continue;
|
|
6421
|
-
const absPath =
|
|
6526
|
+
const absPath = path21.resolve(rootDir, task.filePath);
|
|
6422
6527
|
let list = tasksByFile.get(absPath);
|
|
6423
6528
|
if (!list) {
|
|
6424
6529
|
list = [];
|
|
@@ -6475,9 +6580,9 @@ function generateTaskSchemaFileSource(sources, resolveType, helpersImportPath) {
|
|
|
6475
6580
|
async function generateTaskArtifacts(manifests, rootDir, dist) {
|
|
6476
6581
|
const metadata = [];
|
|
6477
6582
|
if (manifests.length > 0) {
|
|
6478
|
-
const programByFile = createPrograms(manifests.map((m) =>
|
|
6583
|
+
const programByFile = createPrograms(manifests.map((m) => path21.resolve(rootDir, m.filePath)));
|
|
6479
6584
|
for (const manifest of manifests) {
|
|
6480
|
-
const absPath =
|
|
6585
|
+
const absPath = path21.resolve(rootDir, manifest.filePath);
|
|
6481
6586
|
const result = extractToolMetadata(programByFile.get(absPath), absPath, "run", {
|
|
6482
6587
|
name: manifest.name,
|
|
6483
6588
|
filePath: manifest.filePath
|
|
@@ -6488,7 +6593,7 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
|
|
|
6488
6593
|
}
|
|
6489
6594
|
}
|
|
6490
6595
|
const serialized = serializeTasks(manifests, dist);
|
|
6491
|
-
const tasksPath =
|
|
6596
|
+
const tasksPath = path21.resolve(rootDir, dist, TASKS_FILE);
|
|
6492
6597
|
await writeTasksModule(serialized, tasksPath);
|
|
6493
6598
|
if (metadata.length === 0) {
|
|
6494
6599
|
return hydrateTasks(serialized);
|
|
@@ -6508,7 +6613,7 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
|
|
|
6508
6613
|
}
|
|
6509
6614
|
const fileEntries = [];
|
|
6510
6615
|
for (const [filePath, fileSources] of sourcesByFile) {
|
|
6511
|
-
const relFile =
|
|
6616
|
+
const relFile = path21.relative(rootDir, filePath).replace(/\\/g, "/");
|
|
6512
6617
|
const outputPath = getSchemaOutputPath(relFile, dist, rootDir);
|
|
6513
6618
|
const resolver = resolversByFile.get(filePath);
|
|
6514
6619
|
let relForDir = relFile;
|
|
@@ -6527,7 +6632,7 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
|
|
|
6527
6632
|
}
|
|
6528
6633
|
const allSourceCode = fileEntries.map((e) => e.source).join("\n");
|
|
6529
6634
|
if (usesCoerceHelpers(allSourceCode)) {
|
|
6530
|
-
const helpersPath =
|
|
6635
|
+
const helpersPath = path21.resolve(rootDir, dist, HELPERS_FILENAME);
|
|
6531
6636
|
const { existsSync: existsSync3 } = await import("fs");
|
|
6532
6637
|
if (!existsSync3(helpersPath)) {
|
|
6533
6638
|
await atomicWriteFile(helpersPath, generateHelpersFileSource());
|
|
@@ -6559,18 +6664,18 @@ function createIdleTaskDriver() {
|
|
|
6559
6664
|
}
|
|
6560
6665
|
|
|
6561
6666
|
// src/cli/loadPlugins.ts
|
|
6562
|
-
import
|
|
6563
|
-
import
|
|
6667
|
+
import path23 from "path";
|
|
6668
|
+
import fs18 from "fs";
|
|
6564
6669
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
6565
6670
|
|
|
6566
6671
|
// src/cli/compileConfig.ts
|
|
6567
|
-
import
|
|
6568
|
-
import
|
|
6672
|
+
import path22 from "path";
|
|
6673
|
+
import fs17 from "fs";
|
|
6569
6674
|
async function compileProjectModules(entryPoints, rootDir, dist) {
|
|
6570
6675
|
const { insideFiles, outsideFiles } = await collectRelativeImports(entryPoints, rootDir);
|
|
6571
6676
|
const esbuild = await import("esbuild");
|
|
6572
6677
|
const aliasPlugins = buildAliasPlugins(rootDir);
|
|
6573
|
-
const absDist =
|
|
6678
|
+
const absDist = path22.resolve(rootDir, dist);
|
|
6574
6679
|
await esbuild.build({
|
|
6575
6680
|
entryPoints: [...entryPoints, ...outsideFiles],
|
|
6576
6681
|
outdir: absDist,
|
|
@@ -6584,7 +6689,7 @@ async function compileProjectModules(entryPoints, rootDir, dist) {
|
|
|
6584
6689
|
logLevel: "silent"
|
|
6585
6690
|
});
|
|
6586
6691
|
if (insideFiles.length > 0) {
|
|
6587
|
-
const appOutbase =
|
|
6692
|
+
const appOutbase = path22.resolve(rootDir, "src");
|
|
6588
6693
|
await esbuild.build({
|
|
6589
6694
|
entryPoints: insideFiles,
|
|
6590
6695
|
outdir: absDist,
|
|
@@ -6665,37 +6770,37 @@ async function loadPlugins(declarations, ctx, rootDir, dist) {
|
|
|
6665
6770
|
var TS_EXTS = /\.(ts|tsx|mts|cts)$/;
|
|
6666
6771
|
var JS_EXTS = /\.(js|mjs|cjs|jsx)$/;
|
|
6667
6772
|
function resolveLocalPluginSource(specifier, baseDir) {
|
|
6668
|
-
const base =
|
|
6669
|
-
if ((TS_EXTS.test(base) || JS_EXTS.test(base)) &&
|
|
6773
|
+
const base = path23.isAbsolute(specifier) ? specifier : path23.resolve(baseDir, specifier);
|
|
6774
|
+
if ((TS_EXTS.test(base) || JS_EXTS.test(base)) && fs18.existsSync(base)) return base;
|
|
6670
6775
|
for (const ext of [".ts", ".js"]) {
|
|
6671
|
-
if (
|
|
6776
|
+
if (fs18.existsSync(base + ext)) return base + ext;
|
|
6672
6777
|
}
|
|
6673
6778
|
for (const indexExt of ["/index.ts", "/index.js"]) {
|
|
6674
|
-
if (
|
|
6779
|
+
if (fs18.existsSync(base + indexExt)) return base + indexExt;
|
|
6675
6780
|
}
|
|
6676
6781
|
return null;
|
|
6677
6782
|
}
|
|
6678
6783
|
function mirrorProductPath(sourcePath, baseDir, distDir) {
|
|
6679
|
-
let rel =
|
|
6784
|
+
let rel = path23.relative(baseDir, sourcePath).replace(/\\/g, "/");
|
|
6680
6785
|
if (rel.startsWith("src/")) rel = rel.slice(4);
|
|
6681
|
-
return
|
|
6786
|
+
return path23.resolve(distDir, rel.replace(TS_EXTS, ".js"));
|
|
6682
6787
|
}
|
|
6683
6788
|
function isSourceNewer(sourcePath, productPath) {
|
|
6684
6789
|
try {
|
|
6685
|
-
return
|
|
6790
|
+
return fs18.statSync(sourcePath).mtimeMs > fs18.statSync(productPath).mtimeMs;
|
|
6686
6791
|
} catch {
|
|
6687
6792
|
return true;
|
|
6688
6793
|
}
|
|
6689
6794
|
}
|
|
6690
6795
|
async function importPluginModule(specifier, baseDir, dist) {
|
|
6691
6796
|
const isRelative = specifier.startsWith("./") || specifier.startsWith("../");
|
|
6692
|
-
if (!isRelative && !
|
|
6797
|
+
if (!isRelative && !path23.isAbsolute(specifier)) {
|
|
6693
6798
|
return import(specifier);
|
|
6694
6799
|
}
|
|
6695
|
-
const distDir = dist ?
|
|
6800
|
+
const distDir = dist ? path23.resolve(baseDir, dist) : null;
|
|
6696
6801
|
const sourcePath = resolveLocalPluginSource(specifier, baseDir);
|
|
6697
6802
|
const productPath = sourcePath && distDir ? mirrorProductPath(sourcePath, baseDir, distDir) : null;
|
|
6698
|
-
if (productPath !== null &&
|
|
6803
|
+
if (productPath !== null && fs18.existsSync(productPath) && (sourcePath === null || !isSourceNewer(sourcePath, productPath))) {
|
|
6699
6804
|
return import(pathToFileURL3(productPath).href);
|
|
6700
6805
|
}
|
|
6701
6806
|
if (sourcePath && TS_EXTS.test(sourcePath)) {
|
|
@@ -6704,13 +6809,13 @@ async function importPluginModule(specifier, baseDir, dist) {
|
|
|
6704
6809
|
`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.`
|
|
6705
6810
|
);
|
|
6706
6811
|
}
|
|
6707
|
-
const relFromRoot =
|
|
6812
|
+
const relFromRoot = path23.relative(baseDir, sourcePath).replace(/\\/g, "/");
|
|
6708
6813
|
if (relFromRoot.startsWith("src/")) {
|
|
6709
6814
|
await ensureCompiled(sourcePath, baseDir, dist);
|
|
6710
6815
|
} else {
|
|
6711
6816
|
await compileProjectModules([sourcePath], baseDir, dist);
|
|
6712
6817
|
}
|
|
6713
|
-
if (productPath &&
|
|
6818
|
+
if (productPath && fs18.existsSync(productPath)) {
|
|
6714
6819
|
return import(pathToFileURL3(productPath).href);
|
|
6715
6820
|
}
|
|
6716
6821
|
}
|
|
@@ -6722,7 +6827,7 @@ async function importPluginModule(specifier, baseDir, dist) {
|
|
|
6722
6827
|
`${specifier}/index.ts`,
|
|
6723
6828
|
`${specifier}.js`,
|
|
6724
6829
|
`${specifier}/index.js`
|
|
6725
|
-
].map((c) =>
|
|
6830
|
+
].map((c) => path23.isAbsolute(c) ? c : path23.join(baseDir, c));
|
|
6726
6831
|
throw new Error(
|
|
6727
6832
|
`Cannot find local plugin "${specifier}" (resolved from ${baseDir}). Expected one of:
|
|
6728
6833
|
${candidates.join("\n ")}
|
|
@@ -6753,8 +6858,8 @@ var ROUTES_FILE = "faapi-routes.js";
|
|
|
6753
6858
|
var TOOLS_FILE2 = "faapi-tools.js";
|
|
6754
6859
|
var AGENTS_FILE2 = "faapi-agents.js";
|
|
6755
6860
|
async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries) {
|
|
6756
|
-
const toolsPath =
|
|
6757
|
-
if (!
|
|
6861
|
+
const toolsPath = path24.resolve(rootDir, dist, TOOLS_FILE2);
|
|
6862
|
+
if (!fs19.existsSync(toolsPath)) {
|
|
6758
6863
|
return [];
|
|
6759
6864
|
}
|
|
6760
6865
|
const serialized = await importWithCacheBust(toolsPath);
|
|
@@ -6763,8 +6868,8 @@ async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries
|
|
|
6763
6868
|
return hydrated;
|
|
6764
6869
|
}
|
|
6765
6870
|
async function loadAndHydrateAgents(rootDir, dist, registries = defaultRegistries) {
|
|
6766
|
-
const agentsPath =
|
|
6767
|
-
if (!
|
|
6871
|
+
const agentsPath = path24.resolve(rootDir, dist, AGENTS_FILE2);
|
|
6872
|
+
if (!fs19.existsSync(agentsPath)) {
|
|
6768
6873
|
return [];
|
|
6769
6874
|
}
|
|
6770
6875
|
const serialized = await importWithCacheBust(agentsPath);
|
|
@@ -6779,8 +6884,8 @@ function getTaskDriverOptions(config) {
|
|
|
6779
6884
|
return void 0;
|
|
6780
6885
|
}
|
|
6781
6886
|
async function loadAndHydrateTasks(rootDir, dist, registries = defaultRegistries) {
|
|
6782
|
-
const tasksPath =
|
|
6783
|
-
if (!
|
|
6887
|
+
const tasksPath = path24.resolve(rootDir, dist, TASKS_FILE);
|
|
6888
|
+
if (!fs19.existsSync(tasksPath)) {
|
|
6784
6889
|
return [];
|
|
6785
6890
|
}
|
|
6786
6891
|
const serialized = await importWithCacheBust(tasksPath);
|
|
@@ -6849,8 +6954,8 @@ function isFaapiConfigKey(key) {
|
|
|
6849
6954
|
async function createAppBase(options) {
|
|
6850
6955
|
const rootDir = options?.rootDir ?? process.cwd();
|
|
6851
6956
|
const dist = options?.dist ?? process.env.FAAPI_DIST ?? DEFAULT_DIST;
|
|
6852
|
-
const routesPath =
|
|
6853
|
-
if (!
|
|
6957
|
+
const routesPath = path24.resolve(rootDir, dist, ROUTES_FILE);
|
|
6958
|
+
if (!fs19.existsSync(routesPath)) {
|
|
6854
6959
|
throw new Error(
|
|
6855
6960
|
`[faapi] ${dist}/${ROUTES_FILE} \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6267\u884C \`faapi build\`\uFF08\u6216 \`faapi dev\`\uFF09\u751F\u6210\u4EA7\u7269\u3002`
|
|
6856
6961
|
);
|
|
@@ -7178,21 +7283,21 @@ async function createAppBase(options) {
|
|
|
7178
7283
|
}
|
|
7179
7284
|
|
|
7180
7285
|
// src/cli/createDevApp.ts
|
|
7181
|
-
import
|
|
7286
|
+
import path28 from "path";
|
|
7182
7287
|
|
|
7183
7288
|
// src/router/scanRoutes.ts
|
|
7184
7289
|
import fg3 from "fast-glob";
|
|
7185
|
-
import
|
|
7186
|
-
import
|
|
7290
|
+
import path25 from "path";
|
|
7291
|
+
import fs20 from "fs";
|
|
7187
7292
|
|
|
7188
7293
|
// src/router/constants.ts
|
|
7189
7294
|
var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
7190
7295
|
var HTTP_METHOD_SET = new Set(HTTP_METHODS);
|
|
7191
7296
|
|
|
7192
7297
|
// src/utils/normalizePath.ts
|
|
7193
|
-
function normalizePath(
|
|
7194
|
-
if (!
|
|
7195
|
-
let result =
|
|
7298
|
+
function normalizePath(path29) {
|
|
7299
|
+
if (!path29) return "";
|
|
7300
|
+
let result = path29.replace(/\\/g, "/");
|
|
7196
7301
|
result = result.replace(/\/+/g, "/");
|
|
7197
7302
|
result = result.replace(/\/+$/, "");
|
|
7198
7303
|
if (result && !result.startsWith("/")) {
|
|
@@ -7253,34 +7358,34 @@ function extractExportsFromSource(source) {
|
|
|
7253
7358
|
return names;
|
|
7254
7359
|
}
|
|
7255
7360
|
function collectMiddlewarePaths(routeFilePath, rootDir, dist) {
|
|
7256
|
-
const routeDir =
|
|
7257
|
-
const resolvedRoot =
|
|
7361
|
+
const routeDir = path25.dirname(routeFilePath);
|
|
7362
|
+
const resolvedRoot = path25.resolve(rootDir);
|
|
7258
7363
|
const paths = [];
|
|
7259
|
-
let currentDir =
|
|
7364
|
+
let currentDir = path25.resolve(rootDir, routeDir);
|
|
7260
7365
|
while (true) {
|
|
7261
7366
|
if (dist) {
|
|
7262
|
-
const mwTsPath =
|
|
7263
|
-
const mwJsPath =
|
|
7264
|
-
const absTsPath =
|
|
7265
|
-
const absJsPath =
|
|
7266
|
-
const absMwPath =
|
|
7367
|
+
const mwTsPath = path25.join(currentDir, "middlewares.ts");
|
|
7368
|
+
const mwJsPath = path25.join(currentDir, "middlewares.js");
|
|
7369
|
+
const absTsPath = path25.resolve(rootDir, mwTsPath);
|
|
7370
|
+
const absJsPath = path25.resolve(rootDir, mwJsPath);
|
|
7371
|
+
const absMwPath = fs20.existsSync(absTsPath) ? absTsPath : fs20.existsSync(absJsPath) ? absJsPath : null;
|
|
7267
7372
|
if (absMwPath) {
|
|
7268
|
-
const relMwPath =
|
|
7269
|
-
const prodAbsPath =
|
|
7373
|
+
const relMwPath = path25.relative(rootDir, absMwPath);
|
|
7374
|
+
const prodAbsPath = path25.resolve(rootDir, toProdFilePath(relMwPath, dist));
|
|
7270
7375
|
paths.push(prodAbsPath);
|
|
7271
7376
|
}
|
|
7272
7377
|
} else {
|
|
7273
7378
|
for (const ext of [".ts", ".js"]) {
|
|
7274
|
-
const mwPath =
|
|
7275
|
-
const absMwPath =
|
|
7276
|
-
if (
|
|
7379
|
+
const mwPath = path25.join(currentDir, `middlewares${ext}`);
|
|
7380
|
+
const absMwPath = path25.resolve(rootDir, mwPath);
|
|
7381
|
+
if (fs20.existsSync(absMwPath)) {
|
|
7277
7382
|
paths.push(absMwPath);
|
|
7278
7383
|
break;
|
|
7279
7384
|
}
|
|
7280
7385
|
}
|
|
7281
7386
|
}
|
|
7282
7387
|
if (currentDir === resolvedRoot) break;
|
|
7283
|
-
const parentDir =
|
|
7388
|
+
const parentDir = path25.dirname(currentDir);
|
|
7284
7389
|
if (parentDir === currentDir) break;
|
|
7285
7390
|
currentDir = parentDir;
|
|
7286
7391
|
}
|
|
@@ -7299,7 +7404,7 @@ async function scanRoutes(rootDir, patterns, dist) {
|
|
|
7299
7404
|
const normalizedFile = file.replace(/\\/g, "/");
|
|
7300
7405
|
const fileName = normalizedFile.split("/").pop();
|
|
7301
7406
|
if (fileName === "handler.ts" || fileName === "handler.js") {
|
|
7302
|
-
const absPath =
|
|
7407
|
+
const absPath = path25.resolve(rootDir, normalizedFile);
|
|
7303
7408
|
const urlPath = filePathToUrlPath(normalizedFile);
|
|
7304
7409
|
const paramNames = extractParamNames(urlPath);
|
|
7305
7410
|
const isDynamic = paramNames.length > 0;
|
|
@@ -7312,7 +7417,7 @@ async function scanRoutes(rootDir, patterns, dist) {
|
|
|
7312
7417
|
const mwPaths = collectMiddlewarePaths(normalizedFile, rootDir);
|
|
7313
7418
|
middlewareBundle = await loadMergedMiddlewares(mwPaths);
|
|
7314
7419
|
}
|
|
7315
|
-
const source = await
|
|
7420
|
+
const source = await fs20.promises.readFile(absPath, "utf8").catch(() => "");
|
|
7316
7421
|
const exportNames = extractExportsFromSource(source);
|
|
7317
7422
|
const methods = HTTP_METHODS.filter((m) => exportNames.has(m));
|
|
7318
7423
|
for (const method of methods) {
|
|
@@ -7348,8 +7453,8 @@ async function scanRoutes(rootDir, patterns, dist) {
|
|
|
7348
7453
|
|
|
7349
7454
|
// src/tools/scanTools.ts
|
|
7350
7455
|
import fg4 from "fast-glob";
|
|
7351
|
-
import
|
|
7352
|
-
import
|
|
7456
|
+
import path26 from "path";
|
|
7457
|
+
import fs21 from "fs";
|
|
7353
7458
|
var TOOL_PATTERNS = ["src/tools/**/*.ts"];
|
|
7354
7459
|
var TOOL_EXPORT_RE = new RegExp(
|
|
7355
7460
|
String.raw`export\s+(?:async\s+)?(?:function\s+|const\s+)([A-Za-z_$][\w$]*)\s*(?:\(|=)`,
|
|
@@ -7399,8 +7504,8 @@ async function scanTools(rootDir, patterns) {
|
|
|
7399
7504
|
if (fileName !== "handler.ts" && fileName !== "handler.js") {
|
|
7400
7505
|
continue;
|
|
7401
7506
|
}
|
|
7402
|
-
const absPath =
|
|
7403
|
-
const source = await
|
|
7507
|
+
const absPath = path26.resolve(rootDir, normalizedFile);
|
|
7508
|
+
const source = await fs21.promises.readFile(absPath, "utf8").catch(() => "");
|
|
7404
7509
|
const exportNames = extractToolExportsFromSource(source);
|
|
7405
7510
|
const namespace = filePathToToolNamespace(normalizedFile);
|
|
7406
7511
|
for (const fnName of exportNames) {
|
|
@@ -7424,8 +7529,8 @@ async function scanTools(rootDir, patterns) {
|
|
|
7424
7529
|
|
|
7425
7530
|
// src/agents/scanAgents.ts
|
|
7426
7531
|
import fg5 from "fast-glob";
|
|
7427
|
-
import
|
|
7428
|
-
import
|
|
7532
|
+
import path27 from "path";
|
|
7533
|
+
import fs22 from "fs";
|
|
7429
7534
|
var DEFAULT_AGENT_PATTERNS = ["src/agents/**/handler.ts"];
|
|
7430
7535
|
var RUN_EXPORT_RE = /export\s+(?:async\s+)?(?:function\s+|const\s+)run\b/;
|
|
7431
7536
|
function extractAgentNameFromPath(filePath) {
|
|
@@ -7457,8 +7562,8 @@ async function scanAgents(rootDir, patterns) {
|
|
|
7457
7562
|
if (fileName !== "handler.ts" && fileName !== "handler.js") {
|
|
7458
7563
|
continue;
|
|
7459
7564
|
}
|
|
7460
|
-
const absPath =
|
|
7461
|
-
const source = await
|
|
7565
|
+
const absPath = path27.resolve(rootDir, normalizedFile);
|
|
7566
|
+
const source = await fs22.promises.readFile(absPath, "utf8").catch(() => "");
|
|
7462
7567
|
const { hasRun } = detectAgentExports(source);
|
|
7463
7568
|
const name = extractAgentNameFromPath(normalizedFile);
|
|
7464
7569
|
const prevFile = seen.get(name);
|
|
@@ -7528,7 +7633,7 @@ async function createDevApp(options) {
|
|
|
7528
7633
|
invalidateProgramCache();
|
|
7529
7634
|
const tasks = await scanTasks(ctx.rootDir, TASK_PATTERNS);
|
|
7530
7635
|
for (const task of tasks) {
|
|
7531
|
-
await ensureCompiled(
|
|
7636
|
+
await ensureCompiled(path28.resolve(ctx.rootDir, task.filePath), ctx.rootDir, ctx.dist);
|
|
7532
7637
|
}
|
|
7533
7638
|
await generateTaskArtifacts(tasks, ctx.rootDir, ctx.dist);
|
|
7534
7639
|
ctx.taskQueue.invalidateModules();
|
|
@@ -7569,6 +7674,7 @@ export {
|
|
|
7569
7674
|
createTaskRegistriesView,
|
|
7570
7675
|
createTaskRegistry,
|
|
7571
7676
|
extractTypeInfo,
|
|
7677
|
+
flushLogging,
|
|
7572
7678
|
getAgent,
|
|
7573
7679
|
getAgentEntry,
|
|
7574
7680
|
getApp,
|