@faapi/faapi 6.8.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/index.js CHANGED
@@ -1235,13 +1235,13 @@ var init_collectRouteSchemaSources = __esm({
1235
1235
  });
1236
1236
 
1237
1237
  // src/utils/atomicWrite.ts
1238
- import path9 from "path";
1239
- import fs7 from "fs";
1238
+ import path10 from "path";
1239
+ import fs8 from "fs";
1240
1240
  async function atomicWriteFile(outputPath, content) {
1241
- await fs7.promises.mkdir(path9.dirname(outputPath), { recursive: true });
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 fs7.promises.writeFile(tmp, content, "utf-8");
1244
- await fs7.promises.rename(tmp, outputPath);
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 path10 from "path";
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 path10.resolve(rootDir, dist, relDir, "zod.js");
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 path10.resolve(rootDir, dist, relDir, "zod.js");
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 = path10.relative(rootDir, filePath).replace(/\\/g, "/");
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 = path10.resolve(rootDir, dist, HELPERS_FILENAME);
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 path3 from "path";
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(path28) {
1949
- super("ROUTE_NOT_FOUND", `Route not found: ${path28}`, 404);
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, path28, allowedMethods) {
1955
- super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path28}`, 405);
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,51 @@ function configureLogging(config) {
2311
2399
  }
2312
2400
  }
2313
2401
  function globalThreshold() {
2314
- return globalState.level ?? "info";
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
- function serializeFieldValue(value) {
2320
- if (value instanceof Error) {
2321
- return { name: value.name, message: value.message, stack: value.stack };
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 ?? consoleSink)(entry);
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 (LEVEL_RANK[entry.level] < LEVEL_RANK[globalThreshold()]) return;
2435
+ if (belowThreshold(entry.level, globalThreshold())) return;
2356
2436
  globalDispatch(entry);
2357
2437
  }
2438
+ function isAccessLogPiped() {
2439
+ return !globalState.disabled && globalState.accessLog;
2440
+ }
2358
2441
  function createLogger(scope, options) {
2359
2442
  const baseScope = scope;
2360
2443
  const baseFields = options?.fields;
2361
2444
  const write = (level, message, callFields, scopeSuffix) => {
2362
2445
  const threshold = options?.level ?? globalThreshold();
2363
- if (LEVEL_RANK[level] < LEVEL_RANK[threshold]) return;
2446
+ if (belowThreshold(level, threshold)) return;
2364
2447
  const entry = {
2365
2448
  level,
2366
2449
  message,
@@ -2419,7 +2502,7 @@ function createTaskQueue(deps) {
2419
2502
  }
2420
2503
  const loadTaskModule = deps.loadTaskModule ?? (async (filePath) => await import(filePath));
2421
2504
  const loadPayloadSchema = deps.loadPayloadSchema ?? (async (filePath) => {
2422
- const zodPath = path3.join(path3.dirname(filePath), "zod.js");
2505
+ const zodPath = path4.join(path4.dirname(filePath), "zod.js");
2423
2506
  try {
2424
2507
  const mod = await import(zodPath);
2425
2508
  const schemaKey = Object.keys(mod).find((k) => k.endsWith("Schema"));
@@ -2447,7 +2530,7 @@ function createTaskQueue(deps) {
2447
2530
  const meta = registry.get(name);
2448
2531
  schemaCache.set(
2449
2532
  name,
2450
- await loadPayloadSchema(path3.resolve(rootDir, meta.filePath)).catch(() => void 0)
2533
+ await loadPayloadSchema(path4.resolve(rootDir, meta.filePath)).catch(() => void 0)
2451
2534
  );
2452
2535
  }
2453
2536
  const schema = schemaCache.get(name);
@@ -2483,7 +2566,7 @@ function createTaskQueue(deps) {
2483
2566
  let result;
2484
2567
  if (meta.timeoutMs !== void 0 && meta.timeoutMs > 0) {
2485
2568
  result = await (deps.runIsolated ?? runTaskInWorker)({
2486
- taskModulePath: path3.resolve(rootDir, meta.filePath),
2569
+ taskModulePath: path4.resolve(rootDir, meta.filePath),
2487
2570
  payload: job.payload,
2488
2571
  taskCtx: {
2489
2572
  config: deps.config,
@@ -2508,7 +2591,7 @@ function createTaskQueue(deps) {
2508
2591
  } else {
2509
2592
  let mod = moduleCache2.get(job.name);
2510
2593
  if (!mod) {
2511
- mod = await loadTaskModule(path3.resolve(rootDir, meta.filePath));
2594
+ mod = await loadTaskModule(path4.resolve(rootDir, meta.filePath));
2512
2595
  moduleCache2.set(job.name, mod);
2513
2596
  }
2514
2597
  if (typeof mod.run !== "function") {
@@ -2745,8 +2828,8 @@ function createCronScheduler(registry, enqueue) {
2745
2828
 
2746
2829
  // src/task/scanTasks.ts
2747
2830
  import fg from "fast-glob";
2748
- import path4 from "path";
2749
- import fs2 from "fs";
2831
+ import path5 from "path";
2832
+ import fs3 from "fs";
2750
2833
  var TASK_PATTERNS = ["src/tasks/**/task.ts"];
2751
2834
  var TASK_FILENAME = "task.ts";
2752
2835
  var CRON_RE = /(?:^|\n)\s*cron:\s*['"`]([^'"`\n]+)['"`]/;
@@ -2777,12 +2860,12 @@ async function scanTasks(rootDir, patterns) {
2777
2860
  const seen = /* @__PURE__ */ new Map();
2778
2861
  for (const file of files) {
2779
2862
  const normalizedFile = file.replace(/\\/g, "/");
2780
- const fileName = path4.posix.basename(normalizedFile);
2863
+ const fileName = path5.posix.basename(normalizedFile);
2781
2864
  if (fileName !== TASK_FILENAME) {
2782
2865
  continue;
2783
2866
  }
2784
- const absPath = path4.resolve(rootDir, normalizedFile);
2785
- const source = await fs2.promises.readFile(absPath, "utf8").catch(() => "");
2867
+ const absPath = path5.resolve(rootDir, normalizedFile);
2868
+ const source = await fs3.promises.readFile(absPath, "utf8").catch(() => "");
2786
2869
  const name = filePathToTaskName(normalizedFile);
2787
2870
  const prevFile = seen.get(name);
2788
2871
  if (prevFile) {
@@ -2855,7 +2938,7 @@ function listSkills() {
2855
2938
  }
2856
2939
 
2857
2940
  // src/loader/loadAgentModule.ts
2858
- import fs10 from "fs";
2941
+ import fs11 from "fs";
2859
2942
 
2860
2943
  // src/loader/resolveExports.ts
2861
2944
  function resolveExport(module, exportName) {
@@ -2901,18 +2984,18 @@ async function importWithCacheBust(filePath, bustViteCache = false) {
2901
2984
  }
2902
2985
 
2903
2986
  // src/cli/compileOnDemand.ts
2904
- import path12 from "path";
2905
- import fs9 from "fs";
2987
+ import path13 from "path";
2988
+ import fs10 from "fs";
2906
2989
 
2907
2990
  // src/cli/compileSourceFiles.ts
2908
- import path8 from "path";
2909
- import fs6 from "fs";
2991
+ import path9 from "path";
2992
+ import fs7 from "fs";
2910
2993
  import fg2 from "fast-glob";
2911
2994
 
2912
2995
  // src/cli/aliasPlugin.ts
2913
2996
  import ts7 from "typescript";
2914
- import path7 from "path";
2915
- import fs5 from "fs";
2997
+ import path8 from "path";
2998
+ import fs6 from "fs";
2916
2999
 
2917
3000
  // src/utils/resolveAlias.ts
2918
3001
  function resolveAlias(specifier, config) {
@@ -2938,8 +3021,8 @@ function resolveAlias(specifier, config) {
2938
3021
  }
2939
3022
 
2940
3023
  // src/utils/prodPaths.ts
2941
- import path5 from "path";
2942
- import fs3 from "fs";
3024
+ import path6 from "path";
3025
+ import fs4 from "fs";
2943
3026
  var APP_DIR = "src";
2944
3027
  var ROUTE_PATTERNS = ["src/api/**/*.ts"];
2945
3028
  function toProdFilePath(filePath, dist) {
@@ -2958,27 +3041,27 @@ function toProdExtension(filePath) {
2958
3041
  }
2959
3042
  function toRealPath(p) {
2960
3043
  try {
2961
- return fs3.realpathSync(p);
3044
+ return fs4.realpathSync(p);
2962
3045
  } catch {
2963
3046
  return p;
2964
3047
  }
2965
3048
  }
2966
3049
  function isInsideDir(filePath, dir) {
2967
- const rel = path5.relative(dir, filePath);
2968
- return rel !== "" && !rel.startsWith("..") && !path5.isAbsolute(rel);
3050
+ const rel = path6.relative(dir, filePath);
3051
+ return rel !== "" && !rel.startsWith("..") && !path6.isAbsolute(rel);
2969
3052
  }
2970
3053
 
2971
3054
  // src/utils/readTsconfig.ts
2972
3055
  import ts6 from "typescript";
2973
- import path6 from "path";
2974
- import fs4 from "fs";
3056
+ import path7 from "path";
3057
+ import fs5 from "fs";
2975
3058
  var tsconfigCache = /* @__PURE__ */ new Map();
2976
3059
  function readTsconfig(rootDir) {
2977
- const tsconfigPath = path6.resolve(rootDir, "tsconfig.json");
2978
- if (!fs4.existsSync(tsconfigPath)) return null;
3060
+ const tsconfigPath = path7.resolve(rootDir, "tsconfig.json");
3061
+ if (!fs5.existsSync(tsconfigPath)) return null;
2979
3062
  let mtimeMs;
2980
3063
  try {
2981
- mtimeMs = fs4.statSync(tsconfigPath).mtimeMs;
3064
+ mtimeMs = fs5.statSync(tsconfigPath).mtimeMs;
2982
3065
  } catch {
2983
3066
  return null;
2984
3067
  }
@@ -2994,7 +3077,7 @@ function readTsconfig(rootDir) {
2994
3077
  const config = rawPaths ? (() => {
2995
3078
  const paths = {};
2996
3079
  for (const [pattern, targets] of Object.entries(rawPaths)) {
2997
- paths[pattern] = targets.map((t) => path6.resolve(baseUrl, t));
3080
+ paths[pattern] = targets.map((t) => path7.resolve(baseUrl, t));
2998
3081
  }
2999
3082
  return { baseUrl, paths };
3000
3083
  })() : null;
@@ -3004,26 +3087,26 @@ function readTsconfig(rootDir) {
3004
3087
 
3005
3088
  // src/cli/aliasPlugin.ts
3006
3089
  function toProdImportPath(sourceFile, importer) {
3007
- const importerDir = path7.dirname(importer);
3008
- let rel = path7.relative(importerDir, sourceFile);
3009
- rel = rel.split(path7.sep).join("/");
3090
+ const importerDir = path8.dirname(importer);
3091
+ let rel = path8.relative(importerDir, sourceFile);
3092
+ rel = rel.split(path8.sep).join("/");
3010
3093
  if (!rel.startsWith(".")) rel = "./" + rel;
3011
3094
  return toProdExtension(rel);
3012
3095
  }
3013
3096
  function toStrippedProdImportPath(sourceFile, rootDir) {
3014
- const appDirAbs = toRealPath(path7.resolve(rootDir, APP_DIR));
3097
+ const appDirAbs = toRealPath(path8.resolve(rootDir, APP_DIR));
3015
3098
  const sourceReal = toRealPath(sourceFile);
3016
- let rel = path7.relative(appDirAbs, sourceReal);
3017
- rel = rel.split(path7.sep).join("/");
3099
+ let rel = path8.relative(appDirAbs, sourceReal);
3100
+ rel = rel.split(path8.sep).join("/");
3018
3101
  if (!rel.startsWith(".")) rel = "./" + rel;
3019
3102
  return toProdExtension(rel);
3020
3103
  }
3021
3104
  function toProdImportFromImporter(importer, rootDir, relFromDist) {
3022
- const importerRel = path7.relative(toRealPath(path7.resolve(rootDir)), toRealPath(importer)).split(path7.sep).join("/");
3023
- const importerProdDir = path7.posix.dirname(toProdExtension(importerRel));
3105
+ const importerRel = path8.relative(toRealPath(path8.resolve(rootDir)), toRealPath(importer)).split(path8.sep).join("/");
3106
+ const importerProdDir = path8.posix.dirname(toProdExtension(importerRel));
3024
3107
  if (importerProdDir === ".") return relFromDist;
3025
3108
  const target = relFromDist.replace(/^\.\//, "");
3026
- let rel = path7.posix.relative(importerProdDir, target);
3109
+ let rel = path8.posix.relative(importerProdDir, target);
3027
3110
  if (!rel.startsWith(".")) rel = "./" + rel;
3028
3111
  return rel;
3029
3112
  }
@@ -3038,41 +3121,41 @@ var INDEX_EXTS = [
3038
3121
  "/index.cjs"
3039
3122
  ];
3040
3123
  function resolveRelativeSpecifier(importer, specifier) {
3041
- const importerDir = path7.dirname(importer);
3042
- const base = path7.resolve(importerDir, specifier);
3124
+ const importerDir = path8.dirname(importer);
3125
+ const base = path8.resolve(importerDir, specifier);
3043
3126
  if (PROD_EXTS.some((ext) => specifier.endsWith(ext))) {
3044
- if (fs5.existsSync(base)) return base;
3127
+ if (fs6.existsSync(base)) return base;
3045
3128
  if (base.endsWith(".js")) {
3046
3129
  for (const ext of [".ts", ".tsx", ".jsx"]) {
3047
3130
  const file = base.slice(0, -3) + ext;
3048
- if (fs5.existsSync(file)) return file;
3131
+ if (fs6.existsSync(file)) return file;
3049
3132
  }
3050
3133
  }
3051
3134
  return null;
3052
3135
  }
3053
3136
  if (/\.(ts|tsx|jsx)$/.test(specifier)) {
3054
- return fs5.existsSync(base) ? base : null;
3137
+ return fs6.existsSync(base) ? base : null;
3055
3138
  }
3056
3139
  for (const ext of SOURCE_EXTS) {
3057
3140
  const file = base + ext;
3058
- if (fs5.existsSync(file)) return file;
3141
+ if (fs6.existsSync(file)) return file;
3059
3142
  }
3060
3143
  for (const indexExt of INDEX_EXTS) {
3061
3144
  const file = base + indexExt;
3062
- if (fs5.existsSync(file)) return file;
3145
+ if (fs6.existsSync(file)) return file;
3063
3146
  }
3064
3147
  return null;
3065
3148
  }
3066
3149
  function createAliasPlugin(config, options) {
3067
- const appDirAbs = options?.rootDir ? toRealPath(path7.resolve(options.rootDir, APP_DIR)) : null;
3150
+ const appDirAbs = options?.rootDir ? toRealPath(path8.resolve(options.rootDir, APP_DIR)) : null;
3068
3151
  const probeCandidateFile = (candidate) => {
3069
3152
  for (const ext of SOURCE_EXTS) {
3070
3153
  const file = candidate + ext;
3071
- if (fs5.existsSync(file)) return file;
3154
+ if (fs6.existsSync(file)) return file;
3072
3155
  }
3073
3156
  for (const indexExt of INDEX_EXTS) {
3074
3157
  const file = candidate + indexExt;
3075
- if (fs5.existsSync(file)) return file;
3158
+ if (fs6.existsSync(file)) return file;
3076
3159
  }
3077
3160
  return null;
3078
3161
  };
@@ -3082,7 +3165,7 @@ function createAliasPlugin(config, options) {
3082
3165
  build.onLoad({ filter: /\.(ts|tsx|js|jsx|mjs|cjs)$/ }, (args) => {
3083
3166
  let source;
3084
3167
  try {
3085
- source = fs5.readFileSync(args.path, "utf8");
3168
+ source = fs6.readFileSync(args.path, "utf8");
3086
3169
  } catch {
3087
3170
  return void 0;
3088
3171
  }
@@ -3207,11 +3290,11 @@ async function compileSourceFiles(options) {
3207
3290
  if (entryPoints.length === 0) {
3208
3291
  return { compiledFiles: [] };
3209
3292
  }
3210
- const absDist = path8.resolve(rootDir, dist);
3211
- await fs6.promises.mkdir(absDist, { recursive: true });
3293
+ const absDist = path9.resolve(rootDir, dist);
3294
+ await fs7.promises.mkdir(absDist, { recursive: true });
3212
3295
  const plugins = buildAliasPlugins(rootDir);
3213
3296
  const esbuild = await import("esbuild");
3214
- const outbase = path8.resolve(rootDir, APP_DIR);
3297
+ const outbase = path9.resolve(rootDir, APP_DIR);
3215
3298
  const result = await esbuild.build({
3216
3299
  entryPoints,
3217
3300
  outdir: absDist,
@@ -3231,10 +3314,10 @@ async function compileSourceFiles(options) {
3231
3314
  if (atomicWrite && result.outputFiles) {
3232
3315
  await Promise.all(
3233
3316
  result.outputFiles.map(async (file) => {
3234
- await fs6.promises.mkdir(path8.dirname(file.path), { recursive: true });
3317
+ await fs7.promises.mkdir(path9.dirname(file.path), { recursive: true });
3235
3318
  const tmp = `${file.path}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
3236
- await fs6.promises.writeFile(tmp, file.contents);
3237
- await fs6.promises.rename(tmp, file.path);
3319
+ await fs7.promises.writeFile(tmp, file.contents);
3320
+ await fs7.promises.rename(tmp, file.path);
3238
3321
  })
3239
3322
  );
3240
3323
  }
@@ -3251,8 +3334,8 @@ init_generateSchemaFiles();
3251
3334
  init_generateSchemaFiles();
3252
3335
 
3253
3336
  // src/cli/collectImports.ts
3254
- import path11 from "path";
3255
- import fs8 from "fs";
3337
+ import path12 from "path";
3338
+ import fs9 from "fs";
3256
3339
  var SPEC_RE = /(\bfrom\s*|import\s*\(\s*)(['"])([^'"]+)\2/g;
3257
3340
  function extractImportSpecifiers(source) {
3258
3341
  const specifiers = [];
@@ -3264,10 +3347,10 @@ function extractImportSpecifiers(source) {
3264
3347
  return specifiers;
3265
3348
  }
3266
3349
  function resolveSpecifierFromDir(dir, specifier) {
3267
- return resolveRelativeSpecifier(path11.join(dir, "__faapi_probe__.ts"), specifier);
3350
+ return resolveRelativeSpecifier(path12.join(dir, "__faapi_probe__.ts"), specifier);
3268
3351
  }
3269
3352
  async function collectRelativeImports(entryFiles, rootDir) {
3270
- const appDirAbs = toRealPath(path11.resolve(rootDir, "src"));
3353
+ const appDirAbs = toRealPath(path12.resolve(rootDir, "src"));
3271
3354
  const tsconfig = readTsconfig(rootDir);
3272
3355
  const visited = /* @__PURE__ */ new Set();
3273
3356
  const insideFiles = /* @__PURE__ */ new Set();
@@ -3277,7 +3360,7 @@ async function collectRelativeImports(entryFiles, rootDir) {
3277
3360
  visited.add(filePath);
3278
3361
  let source;
3279
3362
  try {
3280
- source = await fs8.promises.readFile(filePath, "utf8");
3363
+ source = await fs9.promises.readFile(filePath, "utf8");
3281
3364
  } catch {
3282
3365
  return;
3283
3366
  }
@@ -3299,7 +3382,7 @@ async function collectRelativeImports(entryFiles, rootDir) {
3299
3382
  resolved = null;
3300
3383
  }
3301
3384
  if (!resolved) continue;
3302
- if (!isInsideDir(toRealPath(resolved), toRealPath(path11.resolve(rootDir)))) continue;
3385
+ if (!isInsideDir(toRealPath(resolved), toRealPath(path12.resolve(rootDir)))) continue;
3303
3386
  if (isInsideDir(toRealPath(resolved), appDirAbs)) {
3304
3387
  insideFiles.add(resolved);
3305
3388
  } else {
@@ -3320,8 +3403,8 @@ async function collectRelativeImports(entryFiles, rootDir) {
3320
3403
  // src/cli/compileOnDemand.ts
3321
3404
  function isProductFresh(sourceAbsPath, productAbsPath) {
3322
3405
  try {
3323
- const srcStat = fs9.statSync(sourceAbsPath);
3324
- const prodStat = fs9.statSync(productAbsPath);
3406
+ const srcStat = fs10.statSync(sourceAbsPath);
3407
+ const prodStat = fs10.statSync(productAbsPath);
3325
3408
  return prodStat.mtimeMs >= srcStat.mtimeMs;
3326
3409
  } catch {
3327
3410
  return false;
@@ -3353,7 +3436,7 @@ async function ensureCompiled(sourceAbsPath, rootDir, dist) {
3353
3436
  if (state.compiledFiles.has(sourceAbsPath)) {
3354
3437
  return false;
3355
3438
  }
3356
- if (!fs9.existsSync(sourceAbsPath)) {
3439
+ if (!fs10.existsSync(sourceAbsPath)) {
3357
3440
  return false;
3358
3441
  }
3359
3442
  const productPath = prodSourcePathToProductPath(sourceAbsPath, rootDir, dist);
@@ -3403,11 +3486,11 @@ async function ensureMiddlewaresCompiled(middlewarePaths, rootDir) {
3403
3486
  }
3404
3487
  }
3405
3488
  function prodSourcePathToProductPath(sourceAbsPath, rootDir, dist) {
3406
- const rel = path12.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
3489
+ const rel = path13.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
3407
3490
  if (!rel.startsWith("src/")) return null;
3408
3491
  const relWithoutSrc = rel.slice(4);
3409
3492
  const jsRel = relWithoutSrc.replace(/\.ts$/, ".js");
3410
- return path12.resolve(rootDir, dist, jsRel);
3493
+ return path13.resolve(rootDir, dist, jsRel);
3411
3494
  }
3412
3495
  function clearGeneratedSchemas() {
3413
3496
  state.generatedSchemas.clear();
@@ -3423,9 +3506,9 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
3423
3506
  if (state.generatedSchemas.has(schemaPath)) {
3424
3507
  return false;
3425
3508
  }
3426
- const prodAbsPath = path12.resolve(rootDir, routeFilePath);
3509
+ const prodAbsPath = path13.resolve(rootDir, routeFilePath);
3427
3510
  const sourceAbsPath = prodPathToSourcePath(prodAbsPath, rootDir, dist);
3428
- if (!fs9.existsSync(sourceAbsPath)) {
3511
+ if (!fs10.existsSync(sourceAbsPath)) {
3429
3512
  return false;
3430
3513
  }
3431
3514
  if (isProductFresh(sourceAbsPath, schemaPath)) {
@@ -3436,7 +3519,7 @@ async function ensureSchemaGenerated(schemaPath, routeFilePath, routes, rootDir,
3436
3519
  if (fileRoutes.length === 0) {
3437
3520
  return false;
3438
3521
  }
3439
- const sourceRelPath = path12.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
3522
+ const sourceRelPath = path13.relative(rootDir, sourceAbsPath).replace(/\\/g, "/");
3440
3523
  const sourceRoutes = fileRoutes.map((r) => ({ ...r, filePath: sourceRelPath }));
3441
3524
  const generatePromise = (async () => {
3442
3525
  await generateSchemaFiles(sourceRoutes, rootDir, dist);
@@ -3457,7 +3540,7 @@ async function deleteSchemaFiles(routes, rootDir, dist) {
3457
3540
  if (deleted.has(schemaPath)) continue;
3458
3541
  deleted.add(schemaPath);
3459
3542
  try {
3460
- await fs9.promises.unlink(schemaPath);
3543
+ await fs10.promises.unlink(schemaPath);
3461
3544
  } catch {
3462
3545
  }
3463
3546
  }
@@ -3466,19 +3549,19 @@ var sourcePathCache = /* @__PURE__ */ new Map();
3466
3549
  function prodPathToSourcePath(prodAbsPath, rootDir, dist) {
3467
3550
  const cached = sourcePathCache.get(prodAbsPath);
3468
3551
  if (cached) return cached;
3469
- const rel = path12.relative(rootDir, prodAbsPath).replace(/\\/g, "/");
3552
+ const rel = path13.relative(rootDir, prodAbsPath).replace(/\\/g, "/");
3470
3553
  let relWithoutDist = rel;
3471
3554
  if (relWithoutDist.startsWith(`${dist}/`)) {
3472
3555
  relWithoutDist = relWithoutDist.slice(dist.length + 1);
3473
3556
  }
3474
3557
  const srcRel = `src/${relWithoutDist}`;
3475
3558
  const tsRel = srcRel.replace(/\.js$/, ".ts");
3476
- const tsAbs = path12.resolve(rootDir, tsRel);
3559
+ const tsAbs = path13.resolve(rootDir, tsRel);
3477
3560
  let result;
3478
- if (fs9.existsSync(tsAbs)) {
3561
+ if (fs10.existsSync(tsAbs)) {
3479
3562
  result = tsAbs;
3480
3563
  } else {
3481
- result = path12.resolve(rootDir, srcRel);
3564
+ result = path13.resolve(rootDir, srcRel);
3482
3565
  }
3483
3566
  sourcePathCache.set(prodAbsPath, result);
3484
3567
  return result;
@@ -3496,7 +3579,7 @@ async function loadAgentModule(filePath, hasRun, rootDir) {
3496
3579
  const dist = getDevDist();
3497
3580
  if (dist) {
3498
3581
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
3499
- if (sourcePath && fs10.existsSync(sourcePath)) {
3582
+ if (sourcePath && fs11.existsSync(sourcePath)) {
3500
3583
  try {
3501
3584
  await ensureCompiled(sourcePath, rootDir, dist);
3502
3585
  } catch (compileErr) {
@@ -3529,13 +3612,13 @@ async function loadAgentModule(filePath, hasRun, rootDir) {
3529
3612
  }
3530
3613
 
3531
3614
  // src/loader/loadToolModule.ts
3532
- import fs11 from "fs";
3615
+ import fs12 from "fs";
3533
3616
  async function loadToolModule(filePath, functionName, rootDir) {
3534
3617
  if (isDevOnDemandEnabled() && rootDir) {
3535
3618
  const dist = getDevDist();
3536
3619
  if (dist) {
3537
3620
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
3538
- if (sourcePath && fs11.existsSync(sourcePath)) {
3621
+ if (sourcePath && fs12.existsSync(sourcePath)) {
3539
3622
  try {
3540
3623
  await ensureCompiled(sourcePath, rootDir, dist);
3541
3624
  } catch (compileErr) {
@@ -3567,7 +3650,7 @@ async function loadToolModule(filePath, functionName, rootDir) {
3567
3650
  import { existsSync as existsSync2 } from "fs";
3568
3651
 
3569
3652
  // src/cli/generateToolArtifacts.ts
3570
- import path13 from "path";
3653
+ import path14 from "path";
3571
3654
  import { existsSync } from "fs";
3572
3655
 
3573
3656
  // src/ast/extractToolMetadata.ts
@@ -3691,7 +3774,7 @@ function collectToolSchemaSources(tools, rootDir) {
3691
3774
  const toolsByFile = /* @__PURE__ */ new Map();
3692
3775
  for (const tool of tools) {
3693
3776
  if (!tool.inputTypeName) continue;
3694
- const absPath = path13.resolve(rootDir, tool.filePath);
3777
+ const absPath = path14.resolve(rootDir, tool.filePath);
3695
3778
  let list = toolsByFile.get(absPath);
3696
3779
  if (!list) {
3697
3780
  list = [];
@@ -3751,15 +3834,15 @@ function generateToolSchemaFileSource(sources, resolveType, helpersImportPath) {
3751
3834
  }
3752
3835
  async function maybeGenerateHelpers(allSourceCode, distDir) {
3753
3836
  if (!usesCoerceHelpers(allSourceCode)) return;
3754
- const helpersPath = path13.resolve(distDir, HELPERS_FILENAME);
3837
+ const helpersPath = path14.resolve(distDir, HELPERS_FILENAME);
3755
3838
  if (existsSync(helpersPath)) return;
3756
3839
  await atomicWriteFile(helpersPath, generateHelpersFileSource());
3757
3840
  }
3758
3841
  async function generateToolArtifacts(tools, rootDir, dist, options) {
3759
3842
  const metadata = [];
3760
- const programByFile = createPrograms(tools.map((m) => path13.resolve(rootDir, m.filePath)));
3843
+ const programByFile = createPrograms(tools.map((m) => path14.resolve(rootDir, m.filePath)));
3761
3844
  for (const manifest of tools) {
3762
- const absPath = path13.resolve(rootDir, manifest.filePath);
3845
+ const absPath = path14.resolve(rootDir, manifest.filePath);
3763
3846
  const program = programByFile.get(absPath);
3764
3847
  const result = extractToolMetadata(program, absPath, manifest.functionName, {
3765
3848
  name: manifest.name,
@@ -3770,7 +3853,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
3770
3853
  }
3771
3854
  }
3772
3855
  const serialized = serializeTools(metadata, dist);
3773
- const toolsPath = path13.resolve(rootDir, dist, TOOLS_FILE);
3856
+ const toolsPath = path14.resolve(rootDir, dist, TOOLS_FILE);
3774
3857
  await writeToolsModule(serialized, toolsPath);
3775
3858
  if (options?.skipSchema) {
3776
3859
  return metadata;
@@ -3793,7 +3876,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
3793
3876
  }
3794
3877
  const fileEntries = [];
3795
3878
  for (const [filePath, fileSources] of sourcesByFile) {
3796
- const relFile = path13.relative(rootDir, filePath).replace(/\\/g, "/");
3879
+ const relFile = path14.relative(rootDir, filePath).replace(/\\/g, "/");
3797
3880
  const outputPath = getSchemaOutputPath(relFile, dist, rootDir);
3798
3881
  const resolver = resolversByFile.get(filePath);
3799
3882
  let relForDir = relFile;
@@ -3811,7 +3894,7 @@ async function generateToolArtifacts(tools, rootDir, dist, options) {
3811
3894
  fileEntries.push({ outputPath, source });
3812
3895
  }
3813
3896
  const allSourceCode = fileEntries.map((e) => e.source).join("\n");
3814
- const distDir = path13.resolve(rootDir, dist);
3897
+ const distDir = path14.resolve(rootDir, dist);
3815
3898
  await maybeGenerateHelpers(allSourceCode, distDir);
3816
3899
  await Promise.all(
3817
3900
  fileEntries.map(({ outputPath, source }) => writeToolSchemaFile(outputPath, source))
@@ -3925,9 +4008,28 @@ function cors(options = {}) {
3925
4008
  }
3926
4009
 
3927
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
+ }
3928
4030
  function logger(options = {}) {
3929
4031
  return async (ctx, next) => {
3930
- const log = options.log ?? console.log;
4032
+ const log = options.log ?? defaultLog;
3931
4033
  const start = Date.now();
3932
4034
  try {
3933
4035
  const response = await next();
@@ -4022,16 +4124,16 @@ function helmet(options = {}) {
4022
4124
  }
4023
4125
 
4024
4126
  // src/config/loadConfig.ts
4025
- import path14 from "path";
4026
- import fs12 from "fs";
4127
+ import path15 from "path";
4128
+ import fs13 from "fs";
4027
4129
  var CONFIG_PRODUCT_FILE = "faapi-config.js";
4028
4130
  async function loadConfig(rootDir, dist) {
4029
- const configProductPath = path14.resolve(rootDir, dist, CONFIG_PRODUCT_FILE);
4030
- if (fs12.existsSync(configProductPath)) {
4131
+ const configProductPath = path15.resolve(rootDir, dist, CONFIG_PRODUCT_FILE);
4132
+ if (fs13.existsSync(configProductPath)) {
4031
4133
  const module = await importWithCacheBust(configProductPath);
4032
4134
  return module.default ?? {};
4033
4135
  }
4034
- const hasSourceConfig = fs12.existsSync(path14.join(rootDir, "faapi.config.ts")) || fs12.existsSync(path14.join(rootDir, "faapi.config.js"));
4136
+ const hasSourceConfig = fs13.existsSync(path15.join(rootDir, "faapi.config.ts")) || fs13.existsSync(path15.join(rootDir, "faapi.config.js"));
4035
4137
  if (hasSourceConfig) {
4036
4138
  throw new Error(
4037
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`
@@ -4041,8 +4143,8 @@ async function loadConfig(rootDir, dist) {
4041
4143
  }
4042
4144
 
4043
4145
  // src/cli/loadEnv.ts
4044
- import fs13 from "fs";
4045
- import path15 from "path";
4146
+ import fs14 from "fs";
4147
+ import path16 from "path";
4046
4148
  function resolveEnv() {
4047
4149
  return process.env.NODE_ENV || "development";
4048
4150
  }
@@ -4109,9 +4211,9 @@ function loadEnv(rootDir) {
4109
4211
  const files = getEnvFiles(env);
4110
4212
  const merged = {};
4111
4213
  for (const file of files) {
4112
- const filePath = path15.join(rootDir, file);
4113
- if (!fs13.existsSync(filePath)) continue;
4114
- const content = fs13.readFileSync(filePath, "utf-8");
4214
+ const filePath = path16.join(rootDir, file);
4215
+ if (!fs14.existsSync(filePath)) continue;
4216
+ const content = fs14.readFileSync(filePath, "utf-8");
4115
4217
  const parsed = parseEnvFile(content, merged);
4116
4218
  Object.assign(merged, parsed);
4117
4219
  }
@@ -4123,8 +4225,8 @@ function loadEnv(rootDir) {
4123
4225
  }
4124
4226
 
4125
4227
  // src/cli/createAppCore.ts
4126
- import fs18 from "fs";
4127
- import path23 from "path";
4228
+ import fs19 from "fs";
4229
+ import path24 from "path";
4128
4230
  import { PassThrough, Readable as Readable3 } from "stream";
4129
4231
 
4130
4232
  // src/router/sortRoutes.ts
@@ -4177,7 +4279,7 @@ import {
4177
4279
  import { createSecureServer as createHttp2SecureServer } from "http2";
4178
4280
  import { readFileSync } from "fs";
4179
4281
  import { Readable as Readable2 } from "stream";
4180
- import path17 from "path";
4282
+ import path18 from "path";
4181
4283
 
4182
4284
  // src/router/matchRoute.ts
4183
4285
  var httpIndexCache = /* @__PURE__ */ new WeakMap();
@@ -4219,18 +4321,18 @@ function getWsIndex(routes) {
4219
4321
  wsIndexCache.set(routes, index);
4220
4322
  return index;
4221
4323
  }
4222
- function matchRoute(routes, method, path28) {
4324
+ function matchRoute(routes, method, path29) {
4223
4325
  const index = getHttpIndex(routes);
4224
4326
  const upper = method.toUpperCase();
4225
- const hit = matchByMethod(index, upper, path28);
4327
+ const hit = matchByMethod(index, upper, path29);
4226
4328
  if (hit) return hit;
4227
4329
  if (upper === "HEAD") {
4228
- return matchByMethod(index, "GET", path28);
4330
+ return matchByMethod(index, "GET", path29);
4229
4331
  }
4230
4332
  return null;
4231
4333
  }
4232
- function matchByMethod(index, method, path28) {
4233
- const staticHit = index.static.get(`${method}|${path28}`);
4334
+ function matchByMethod(index, method, path29) {
4335
+ const staticHit = index.static.get(`${method}|${path29}`);
4234
4336
  if (staticHit) {
4235
4337
  return { route: staticHit, params: {} };
4236
4338
  }
@@ -4239,31 +4341,31 @@ function matchByMethod(index, method, path28) {
4239
4341
  if (route.method !== method) {
4240
4342
  continue;
4241
4343
  }
4242
- const params = matchSegments(entry.segments, path28, route.paramNames, route.isCatchAll);
4344
+ const params = matchSegments(entry.segments, path29, route.paramNames, route.isCatchAll);
4243
4345
  if (params !== null) {
4244
4346
  return { route, params };
4245
4347
  }
4246
4348
  }
4247
4349
  return null;
4248
4350
  }
4249
- function matchWsRoute(wsRoutes, path28) {
4351
+ function matchWsRoute(wsRoutes, path29) {
4250
4352
  const index = getWsIndex(wsRoutes);
4251
- const staticHit = index.static.get(path28);
4353
+ const staticHit = index.static.get(path29);
4252
4354
  if (staticHit) {
4253
4355
  return { route: staticHit, params: {} };
4254
4356
  }
4255
4357
  for (const route of index.dynamics) {
4256
- const params = matchDynamicPath(route.urlPath, path28, route.paramNames, route.isCatchAll);
4358
+ const params = matchDynamicPath(route.urlPath, path29, route.paramNames, route.isCatchAll);
4257
4359
  if (params !== null) {
4258
4360
  return { route, params };
4259
4361
  }
4260
4362
  }
4261
4363
  return null;
4262
4364
  }
4263
- function findAllowedMethods(routes, path28) {
4365
+ function findAllowedMethods(routes, path29) {
4264
4366
  const index = getHttpIndex(routes);
4265
4367
  const methods = /* @__PURE__ */ new Set();
4266
- const staticMethods = index.methodsByStaticPath.get(path28);
4368
+ const staticMethods = index.methodsByStaticPath.get(path29);
4267
4369
  if (staticMethods) {
4268
4370
  for (const method of staticMethods) {
4269
4371
  methods.add(method);
@@ -4272,7 +4374,7 @@ function findAllowedMethods(routes, path28) {
4272
4374
  for (const entry of index.dynamics) {
4273
4375
  const params = matchSegments(
4274
4376
  entry.segments,
4275
- path28,
4377
+ path29,
4276
4378
  entry.route.paramNames,
4277
4379
  entry.route.isCatchAll
4278
4380
  );
@@ -4285,11 +4387,11 @@ function findAllowedMethods(routes, path28) {
4285
4387
  }
4286
4388
  return Array.from(methods);
4287
4389
  }
4288
- function matchDynamicPath(pattern, path28, paramNames, isCatchAll) {
4289
- return matchSegments(pattern.split("/").filter(Boolean), path28, paramNames, isCatchAll);
4390
+ function matchDynamicPath(pattern, path29, paramNames, isCatchAll) {
4391
+ return matchSegments(pattern.split("/").filter(Boolean), path29, paramNames, isCatchAll);
4290
4392
  }
4291
- function matchSegments(patternSegments, path28, paramNames, isCatchAll) {
4292
- const pathSegments = path28.split("/").filter(Boolean);
4393
+ function matchSegments(patternSegments, path29, paramNames, isCatchAll) {
4394
+ const pathSegments = path29.split("/").filter(Boolean);
4293
4395
  if (isCatchAll) {
4294
4396
  const nonCatchAllCount = patternSegments.length - 1;
4295
4397
  if (pathSegments.length <= nonCatchAllCount) {
@@ -5196,9 +5298,9 @@ async function validateInput(schemaPath, method, inputType, input) {
5196
5298
  function mapZodIssues(error) {
5197
5299
  return error.issues.map((issue) => {
5198
5300
  const code = mapZodCode(issue);
5199
- const path28 = issue.path.map(String).join(".") || "";
5301
+ const path29 = issue.path.map(String).join(".") || "";
5200
5302
  return {
5201
- path: path28,
5303
+ path: path29,
5202
5304
  code,
5203
5305
  expected: issue.expected ?? mapExpectedFromMessage(issue.message),
5204
5306
  received: issue.received ?? mapReceivedFromMessage(issue.message),
@@ -5430,9 +5532,9 @@ function etag(options = {}) {
5430
5532
  }
5431
5533
 
5432
5534
  // src/server/handleWsUpgrade.ts
5433
- import fs14 from "fs";
5535
+ import fs15 from "fs";
5434
5536
  import { WebSocketServer, WebSocket } from "ws";
5435
- import path16 from "path";
5537
+ import path17 from "path";
5436
5538
 
5437
5539
  // src/server/serverUtils.ts
5438
5540
  function nodeHttpToWebHeaders(req) {
@@ -5567,7 +5669,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
5567
5669
  const dist = getDevDist();
5568
5670
  if (dist) {
5569
5671
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
5570
- if (sourcePath && fs14.existsSync(sourcePath)) {
5672
+ if (sourcePath && fs15.existsSync(sourcePath)) {
5571
5673
  await ensureCompiled(sourcePath, rootDir, dist);
5572
5674
  }
5573
5675
  }
@@ -5681,7 +5783,7 @@ function attachWebSocket(options) {
5681
5783
  const finalHandler = async () => {
5682
5784
  let handlers;
5683
5785
  try {
5684
- const absoluteFilePath = path16.resolve(rootDir, route.filePath);
5786
+ const absoluteFilePath = path17.resolve(rootDir, route.filePath);
5685
5787
  handlers = await loadWsHandler(absoluteFilePath, ctx, rootDir);
5686
5788
  } catch (err) {
5687
5789
  const reason = err instanceof Error ? err.message : String(err);
@@ -5934,7 +6036,7 @@ function getRoutePaths(route, rootDir, dist) {
5934
6036
  let cached = routePathCache.get(route);
5935
6037
  if (!cached) {
5936
6038
  cached = {
5937
- absFilePath: path17.resolve(rootDir, route.filePath),
6039
+ absFilePath: path18.resolve(rootDir, route.filePath),
5938
6040
  schemaPath: getRuntimeSchemaPath(route.filePath, dist, rootDir)
5939
6041
  };
5940
6042
  routePathCache.set(route, cached);
@@ -6056,8 +6158,8 @@ function applyPluginWrappers(server, handlerWrappers, upgradeWrappers) {
6056
6158
  }
6057
6159
 
6058
6160
  // src/cli/generateRoutes.ts
6059
- import fs15 from "fs";
6060
- import path18 from "path";
6161
+ import fs16 from "fs";
6162
+ import path19 from "path";
6061
6163
  async function hydrateRoutes(manifest) {
6062
6164
  const hydrateRoute = (serialized) => ({
6063
6165
  method: serialized.method,
@@ -6082,7 +6184,7 @@ async function hydrateRoutes(manifest) {
6082
6184
  }
6083
6185
 
6084
6186
  // src/cli/generateAgentArtifacts.ts
6085
- import path19 from "path";
6187
+ import path20 from "path";
6086
6188
 
6087
6189
  // src/ast/extractAgentMetadata.ts
6088
6190
  import ts10 from "typescript";
@@ -6355,9 +6457,9 @@ function validateAgentList(metadata) {
6355
6457
  }
6356
6458
  async function generateAgentArtifacts(agents, rootDir, dist) {
6357
6459
  const metadata = [];
6358
- const programByFile = createPrograms(agents.map((m) => path19.resolve(rootDir, m.filePath)));
6460
+ const programByFile = createPrograms(agents.map((m) => path20.resolve(rootDir, m.filePath)));
6359
6461
  for (const manifest of agents) {
6360
- const absPath = path19.resolve(rootDir, manifest.filePath);
6462
+ const absPath = path20.resolve(rootDir, manifest.filePath);
6361
6463
  const program = programByFile.get(absPath);
6362
6464
  const result = extractAgentMetadata(program, absPath, {
6363
6465
  name: manifest.name,
@@ -6373,13 +6475,13 @@ async function generateAgentArtifacts(agents, rootDir, dist) {
6373
6475
  }
6374
6476
  validateAgentList(metadata);
6375
6477
  const serialized = serializeAgents(metadata, dist);
6376
- const agentsPath = path19.resolve(rootDir, dist, AGENTS_FILE);
6478
+ const agentsPath = path20.resolve(rootDir, dist, AGENTS_FILE);
6377
6479
  await writeAgentsModule(serialized, agentsPath);
6378
6480
  return metadata;
6379
6481
  }
6380
6482
 
6381
6483
  // src/cli/generateTaskArtifacts.ts
6382
- import path20 from "path";
6484
+ import path21 from "path";
6383
6485
  init_createProgram();
6384
6486
  init_atomicWrite();
6385
6487
  init_generateSchemaFiles();
@@ -6418,7 +6520,7 @@ function collectTaskSchemaSources(tasks, rootDir) {
6418
6520
  const tasksByFile = /* @__PURE__ */ new Map();
6419
6521
  for (const task of tasks) {
6420
6522
  if (!task.inputTypeName) continue;
6421
- const absPath = path20.resolve(rootDir, task.filePath);
6523
+ const absPath = path21.resolve(rootDir, task.filePath);
6422
6524
  let list = tasksByFile.get(absPath);
6423
6525
  if (!list) {
6424
6526
  list = [];
@@ -6475,9 +6577,9 @@ function generateTaskSchemaFileSource(sources, resolveType, helpersImportPath) {
6475
6577
  async function generateTaskArtifacts(manifests, rootDir, dist) {
6476
6578
  const metadata = [];
6477
6579
  if (manifests.length > 0) {
6478
- const programByFile = createPrograms(manifests.map((m) => path20.resolve(rootDir, m.filePath)));
6580
+ const programByFile = createPrograms(manifests.map((m) => path21.resolve(rootDir, m.filePath)));
6479
6581
  for (const manifest of manifests) {
6480
- const absPath = path20.resolve(rootDir, manifest.filePath);
6582
+ const absPath = path21.resolve(rootDir, manifest.filePath);
6481
6583
  const result = extractToolMetadata(programByFile.get(absPath), absPath, "run", {
6482
6584
  name: manifest.name,
6483
6585
  filePath: manifest.filePath
@@ -6488,7 +6590,7 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
6488
6590
  }
6489
6591
  }
6490
6592
  const serialized = serializeTasks(manifests, dist);
6491
- const tasksPath = path20.resolve(rootDir, dist, TASKS_FILE);
6593
+ const tasksPath = path21.resolve(rootDir, dist, TASKS_FILE);
6492
6594
  await writeTasksModule(serialized, tasksPath);
6493
6595
  if (metadata.length === 0) {
6494
6596
  return hydrateTasks(serialized);
@@ -6508,7 +6610,7 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
6508
6610
  }
6509
6611
  const fileEntries = [];
6510
6612
  for (const [filePath, fileSources] of sourcesByFile) {
6511
- const relFile = path20.relative(rootDir, filePath).replace(/\\/g, "/");
6613
+ const relFile = path21.relative(rootDir, filePath).replace(/\\/g, "/");
6512
6614
  const outputPath = getSchemaOutputPath(relFile, dist, rootDir);
6513
6615
  const resolver = resolversByFile.get(filePath);
6514
6616
  let relForDir = relFile;
@@ -6527,7 +6629,7 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
6527
6629
  }
6528
6630
  const allSourceCode = fileEntries.map((e) => e.source).join("\n");
6529
6631
  if (usesCoerceHelpers(allSourceCode)) {
6530
- const helpersPath = path20.resolve(rootDir, dist, HELPERS_FILENAME);
6632
+ const helpersPath = path21.resolve(rootDir, dist, HELPERS_FILENAME);
6531
6633
  const { existsSync: existsSync3 } = await import("fs");
6532
6634
  if (!existsSync3(helpersPath)) {
6533
6635
  await atomicWriteFile(helpersPath, generateHelpersFileSource());
@@ -6559,18 +6661,18 @@ function createIdleTaskDriver() {
6559
6661
  }
6560
6662
 
6561
6663
  // src/cli/loadPlugins.ts
6562
- import path22 from "path";
6563
- import fs17 from "fs";
6664
+ import path23 from "path";
6665
+ import fs18 from "fs";
6564
6666
  import { pathToFileURL as pathToFileURL3 } from "url";
6565
6667
 
6566
6668
  // src/cli/compileConfig.ts
6567
- import path21 from "path";
6568
- import fs16 from "fs";
6669
+ import path22 from "path";
6670
+ import fs17 from "fs";
6569
6671
  async function compileProjectModules(entryPoints, rootDir, dist) {
6570
6672
  const { insideFiles, outsideFiles } = await collectRelativeImports(entryPoints, rootDir);
6571
6673
  const esbuild = await import("esbuild");
6572
6674
  const aliasPlugins = buildAliasPlugins(rootDir);
6573
- const absDist = path21.resolve(rootDir, dist);
6675
+ const absDist = path22.resolve(rootDir, dist);
6574
6676
  await esbuild.build({
6575
6677
  entryPoints: [...entryPoints, ...outsideFiles],
6576
6678
  outdir: absDist,
@@ -6584,7 +6686,7 @@ async function compileProjectModules(entryPoints, rootDir, dist) {
6584
6686
  logLevel: "silent"
6585
6687
  });
6586
6688
  if (insideFiles.length > 0) {
6587
- const appOutbase = path21.resolve(rootDir, "src");
6689
+ const appOutbase = path22.resolve(rootDir, "src");
6588
6690
  await esbuild.build({
6589
6691
  entryPoints: insideFiles,
6590
6692
  outdir: absDist,
@@ -6665,37 +6767,37 @@ async function loadPlugins(declarations, ctx, rootDir, dist) {
6665
6767
  var TS_EXTS = /\.(ts|tsx|mts|cts)$/;
6666
6768
  var JS_EXTS = /\.(js|mjs|cjs|jsx)$/;
6667
6769
  function resolveLocalPluginSource(specifier, baseDir) {
6668
- const base = path22.isAbsolute(specifier) ? specifier : path22.resolve(baseDir, specifier);
6669
- if ((TS_EXTS.test(base) || JS_EXTS.test(base)) && fs17.existsSync(base)) return 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;
6670
6772
  for (const ext of [".ts", ".js"]) {
6671
- if (fs17.existsSync(base + ext)) return base + ext;
6773
+ if (fs18.existsSync(base + ext)) return base + ext;
6672
6774
  }
6673
6775
  for (const indexExt of ["/index.ts", "/index.js"]) {
6674
- if (fs17.existsSync(base + indexExt)) return base + indexExt;
6776
+ if (fs18.existsSync(base + indexExt)) return base + indexExt;
6675
6777
  }
6676
6778
  return null;
6677
6779
  }
6678
6780
  function mirrorProductPath(sourcePath, baseDir, distDir) {
6679
- let rel = path22.relative(baseDir, sourcePath).replace(/\\/g, "/");
6781
+ let rel = path23.relative(baseDir, sourcePath).replace(/\\/g, "/");
6680
6782
  if (rel.startsWith("src/")) rel = rel.slice(4);
6681
- return path22.resolve(distDir, rel.replace(TS_EXTS, ".js"));
6783
+ return path23.resolve(distDir, rel.replace(TS_EXTS, ".js"));
6682
6784
  }
6683
6785
  function isSourceNewer(sourcePath, productPath) {
6684
6786
  try {
6685
- return fs17.statSync(sourcePath).mtimeMs > fs17.statSync(productPath).mtimeMs;
6787
+ return fs18.statSync(sourcePath).mtimeMs > fs18.statSync(productPath).mtimeMs;
6686
6788
  } catch {
6687
6789
  return true;
6688
6790
  }
6689
6791
  }
6690
6792
  async function importPluginModule(specifier, baseDir, dist) {
6691
6793
  const isRelative = specifier.startsWith("./") || specifier.startsWith("../");
6692
- if (!isRelative && !path22.isAbsolute(specifier)) {
6794
+ if (!isRelative && !path23.isAbsolute(specifier)) {
6693
6795
  return import(specifier);
6694
6796
  }
6695
- const distDir = dist ? path22.resolve(baseDir, dist) : null;
6797
+ const distDir = dist ? path23.resolve(baseDir, dist) : null;
6696
6798
  const sourcePath = resolveLocalPluginSource(specifier, baseDir);
6697
6799
  const productPath = sourcePath && distDir ? mirrorProductPath(sourcePath, baseDir, distDir) : null;
6698
- if (productPath !== null && fs17.existsSync(productPath) && (sourcePath === null || !isSourceNewer(sourcePath, productPath))) {
6800
+ if (productPath !== null && fs18.existsSync(productPath) && (sourcePath === null || !isSourceNewer(sourcePath, productPath))) {
6699
6801
  return import(pathToFileURL3(productPath).href);
6700
6802
  }
6701
6803
  if (sourcePath && TS_EXTS.test(sourcePath)) {
@@ -6704,13 +6806,13 @@ async function importPluginModule(specifier, baseDir, dist) {
6704
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.`
6705
6807
  );
6706
6808
  }
6707
- const relFromRoot = path22.relative(baseDir, sourcePath).replace(/\\/g, "/");
6809
+ const relFromRoot = path23.relative(baseDir, sourcePath).replace(/\\/g, "/");
6708
6810
  if (relFromRoot.startsWith("src/")) {
6709
6811
  await ensureCompiled(sourcePath, baseDir, dist);
6710
6812
  } else {
6711
6813
  await compileProjectModules([sourcePath], baseDir, dist);
6712
6814
  }
6713
- if (productPath && fs17.existsSync(productPath)) {
6815
+ if (productPath && fs18.existsSync(productPath)) {
6714
6816
  return import(pathToFileURL3(productPath).href);
6715
6817
  }
6716
6818
  }
@@ -6722,7 +6824,7 @@ async function importPluginModule(specifier, baseDir, dist) {
6722
6824
  `${specifier}/index.ts`,
6723
6825
  `${specifier}.js`,
6724
6826
  `${specifier}/index.js`
6725
- ].map((c) => path22.isAbsolute(c) ? c : path22.join(baseDir, c));
6827
+ ].map((c) => path23.isAbsolute(c) ? c : path23.join(baseDir, c));
6726
6828
  throw new Error(
6727
6829
  `Cannot find local plugin "${specifier}" (resolved from ${baseDir}). Expected one of:
6728
6830
  ${candidates.join("\n ")}
@@ -6753,8 +6855,8 @@ var ROUTES_FILE = "faapi-routes.js";
6753
6855
  var TOOLS_FILE2 = "faapi-tools.js";
6754
6856
  var AGENTS_FILE2 = "faapi-agents.js";
6755
6857
  async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries) {
6756
- const toolsPath = path23.resolve(rootDir, dist, TOOLS_FILE2);
6757
- if (!fs18.existsSync(toolsPath)) {
6858
+ const toolsPath = path24.resolve(rootDir, dist, TOOLS_FILE2);
6859
+ if (!fs19.existsSync(toolsPath)) {
6758
6860
  return [];
6759
6861
  }
6760
6862
  const serialized = await importWithCacheBust(toolsPath);
@@ -6763,8 +6865,8 @@ async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries
6763
6865
  return hydrated;
6764
6866
  }
6765
6867
  async function loadAndHydrateAgents(rootDir, dist, registries = defaultRegistries) {
6766
- const agentsPath = path23.resolve(rootDir, dist, AGENTS_FILE2);
6767
- if (!fs18.existsSync(agentsPath)) {
6868
+ const agentsPath = path24.resolve(rootDir, dist, AGENTS_FILE2);
6869
+ if (!fs19.existsSync(agentsPath)) {
6768
6870
  return [];
6769
6871
  }
6770
6872
  const serialized = await importWithCacheBust(agentsPath);
@@ -6779,8 +6881,8 @@ function getTaskDriverOptions(config) {
6779
6881
  return void 0;
6780
6882
  }
6781
6883
  async function loadAndHydrateTasks(rootDir, dist, registries = defaultRegistries) {
6782
- const tasksPath = path23.resolve(rootDir, dist, TASKS_FILE);
6783
- if (!fs18.existsSync(tasksPath)) {
6884
+ const tasksPath = path24.resolve(rootDir, dist, TASKS_FILE);
6885
+ if (!fs19.existsSync(tasksPath)) {
6784
6886
  return [];
6785
6887
  }
6786
6888
  const serialized = await importWithCacheBust(tasksPath);
@@ -6849,8 +6951,8 @@ function isFaapiConfigKey(key) {
6849
6951
  async function createAppBase(options) {
6850
6952
  const rootDir = options?.rootDir ?? process.cwd();
6851
6953
  const dist = options?.dist ?? process.env.FAAPI_DIST ?? DEFAULT_DIST;
6852
- const routesPath = path23.resolve(rootDir, dist, ROUTES_FILE);
6853
- if (!fs18.existsSync(routesPath)) {
6954
+ const routesPath = path24.resolve(rootDir, dist, ROUTES_FILE);
6955
+ if (!fs19.existsSync(routesPath)) {
6854
6956
  throw new Error(
6855
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`
6856
6958
  );
@@ -7178,21 +7280,21 @@ async function createAppBase(options) {
7178
7280
  }
7179
7281
 
7180
7282
  // src/cli/createDevApp.ts
7181
- import path27 from "path";
7283
+ import path28 from "path";
7182
7284
 
7183
7285
  // src/router/scanRoutes.ts
7184
7286
  import fg3 from "fast-glob";
7185
- import path24 from "path";
7186
- import fs19 from "fs";
7287
+ import path25 from "path";
7288
+ import fs20 from "fs";
7187
7289
 
7188
7290
  // src/router/constants.ts
7189
7291
  var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
7190
7292
  var HTTP_METHOD_SET = new Set(HTTP_METHODS);
7191
7293
 
7192
7294
  // src/utils/normalizePath.ts
7193
- function normalizePath(path28) {
7194
- if (!path28) return "";
7195
- let result = path28.replace(/\\/g, "/");
7295
+ function normalizePath(path29) {
7296
+ if (!path29) return "";
7297
+ let result = path29.replace(/\\/g, "/");
7196
7298
  result = result.replace(/\/+/g, "/");
7197
7299
  result = result.replace(/\/+$/, "");
7198
7300
  if (result && !result.startsWith("/")) {
@@ -7253,34 +7355,34 @@ function extractExportsFromSource(source) {
7253
7355
  return names;
7254
7356
  }
7255
7357
  function collectMiddlewarePaths(routeFilePath, rootDir, dist) {
7256
- const routeDir = path24.dirname(routeFilePath);
7257
- const resolvedRoot = path24.resolve(rootDir);
7358
+ const routeDir = path25.dirname(routeFilePath);
7359
+ const resolvedRoot = path25.resolve(rootDir);
7258
7360
  const paths = [];
7259
- let currentDir = path24.resolve(rootDir, routeDir);
7361
+ let currentDir = path25.resolve(rootDir, routeDir);
7260
7362
  while (true) {
7261
7363
  if (dist) {
7262
- const mwTsPath = path24.join(currentDir, "middlewares.ts");
7263
- const mwJsPath = path24.join(currentDir, "middlewares.js");
7264
- const absTsPath = path24.resolve(rootDir, mwTsPath);
7265
- const absJsPath = path24.resolve(rootDir, mwJsPath);
7266
- const absMwPath = fs19.existsSync(absTsPath) ? absTsPath : fs19.existsSync(absJsPath) ? absJsPath : null;
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;
7267
7369
  if (absMwPath) {
7268
- const relMwPath = path24.relative(rootDir, absMwPath);
7269
- const prodAbsPath = path24.resolve(rootDir, toProdFilePath(relMwPath, dist));
7370
+ const relMwPath = path25.relative(rootDir, absMwPath);
7371
+ const prodAbsPath = path25.resolve(rootDir, toProdFilePath(relMwPath, dist));
7270
7372
  paths.push(prodAbsPath);
7271
7373
  }
7272
7374
  } else {
7273
7375
  for (const ext of [".ts", ".js"]) {
7274
- const mwPath = path24.join(currentDir, `middlewares${ext}`);
7275
- const absMwPath = path24.resolve(rootDir, mwPath);
7276
- if (fs19.existsSync(absMwPath)) {
7376
+ const mwPath = path25.join(currentDir, `middlewares${ext}`);
7377
+ const absMwPath = path25.resolve(rootDir, mwPath);
7378
+ if (fs20.existsSync(absMwPath)) {
7277
7379
  paths.push(absMwPath);
7278
7380
  break;
7279
7381
  }
7280
7382
  }
7281
7383
  }
7282
7384
  if (currentDir === resolvedRoot) break;
7283
- const parentDir = path24.dirname(currentDir);
7385
+ const parentDir = path25.dirname(currentDir);
7284
7386
  if (parentDir === currentDir) break;
7285
7387
  currentDir = parentDir;
7286
7388
  }
@@ -7299,7 +7401,7 @@ async function scanRoutes(rootDir, patterns, dist) {
7299
7401
  const normalizedFile = file.replace(/\\/g, "/");
7300
7402
  const fileName = normalizedFile.split("/").pop();
7301
7403
  if (fileName === "handler.ts" || fileName === "handler.js") {
7302
- const absPath = path24.resolve(rootDir, normalizedFile);
7404
+ const absPath = path25.resolve(rootDir, normalizedFile);
7303
7405
  const urlPath = filePathToUrlPath(normalizedFile);
7304
7406
  const paramNames = extractParamNames(urlPath);
7305
7407
  const isDynamic = paramNames.length > 0;
@@ -7312,7 +7414,7 @@ async function scanRoutes(rootDir, patterns, dist) {
7312
7414
  const mwPaths = collectMiddlewarePaths(normalizedFile, rootDir);
7313
7415
  middlewareBundle = await loadMergedMiddlewares(mwPaths);
7314
7416
  }
7315
- const source = await fs19.promises.readFile(absPath, "utf8").catch(() => "");
7417
+ const source = await fs20.promises.readFile(absPath, "utf8").catch(() => "");
7316
7418
  const exportNames = extractExportsFromSource(source);
7317
7419
  const methods = HTTP_METHODS.filter((m) => exportNames.has(m));
7318
7420
  for (const method of methods) {
@@ -7348,8 +7450,8 @@ async function scanRoutes(rootDir, patterns, dist) {
7348
7450
 
7349
7451
  // src/tools/scanTools.ts
7350
7452
  import fg4 from "fast-glob";
7351
- import path25 from "path";
7352
- import fs20 from "fs";
7453
+ import path26 from "path";
7454
+ import fs21 from "fs";
7353
7455
  var TOOL_PATTERNS = ["src/tools/**/*.ts"];
7354
7456
  var TOOL_EXPORT_RE = new RegExp(
7355
7457
  String.raw`export\s+(?:async\s+)?(?:function\s+|const\s+)([A-Za-z_$][\w$]*)\s*(?:\(|=)`,
@@ -7399,8 +7501,8 @@ async function scanTools(rootDir, patterns) {
7399
7501
  if (fileName !== "handler.ts" && fileName !== "handler.js") {
7400
7502
  continue;
7401
7503
  }
7402
- const absPath = path25.resolve(rootDir, normalizedFile);
7403
- const source = await fs20.promises.readFile(absPath, "utf8").catch(() => "");
7504
+ const absPath = path26.resolve(rootDir, normalizedFile);
7505
+ const source = await fs21.promises.readFile(absPath, "utf8").catch(() => "");
7404
7506
  const exportNames = extractToolExportsFromSource(source);
7405
7507
  const namespace = filePathToToolNamespace(normalizedFile);
7406
7508
  for (const fnName of exportNames) {
@@ -7424,8 +7526,8 @@ async function scanTools(rootDir, patterns) {
7424
7526
 
7425
7527
  // src/agents/scanAgents.ts
7426
7528
  import fg5 from "fast-glob";
7427
- import path26 from "path";
7428
- import fs21 from "fs";
7529
+ import path27 from "path";
7530
+ import fs22 from "fs";
7429
7531
  var DEFAULT_AGENT_PATTERNS = ["src/agents/**/handler.ts"];
7430
7532
  var RUN_EXPORT_RE = /export\s+(?:async\s+)?(?:function\s+|const\s+)run\b/;
7431
7533
  function extractAgentNameFromPath(filePath) {
@@ -7457,8 +7559,8 @@ async function scanAgents(rootDir, patterns) {
7457
7559
  if (fileName !== "handler.ts" && fileName !== "handler.js") {
7458
7560
  continue;
7459
7561
  }
7460
- const absPath = path26.resolve(rootDir, normalizedFile);
7461
- const source = await fs21.promises.readFile(absPath, "utf8").catch(() => "");
7562
+ const absPath = path27.resolve(rootDir, normalizedFile);
7563
+ const source = await fs22.promises.readFile(absPath, "utf8").catch(() => "");
7462
7564
  const { hasRun } = detectAgentExports(source);
7463
7565
  const name = extractAgentNameFromPath(normalizedFile);
7464
7566
  const prevFile = seen.get(name);
@@ -7528,7 +7630,7 @@ async function createDevApp(options) {
7528
7630
  invalidateProgramCache();
7529
7631
  const tasks = await scanTasks(ctx.rootDir, TASK_PATTERNS);
7530
7632
  for (const task of tasks) {
7531
- await ensureCompiled(path27.resolve(ctx.rootDir, task.filePath), ctx.rootDir, ctx.dist);
7633
+ await ensureCompiled(path28.resolve(ctx.rootDir, task.filePath), ctx.rootDir, ctx.dist);
7532
7634
  }
7533
7635
  await generateTaskArtifacts(tasks, ctx.rootDir, ctx.dist);
7534
7636
  ctx.taskQueue.invalidateModules();