@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/cli/index.js CHANGED
@@ -649,9 +649,9 @@ var init_constants = __esm({
649
649
  });
650
650
 
651
651
  // src/utils/normalizePath.ts
652
- function normalizePath(path31) {
653
- if (!path31) return "";
654
- let result = path31.replace(/\\/g, "/");
652
+ function normalizePath(path32) {
653
+ if (!path32) return "";
654
+ let result = path32.replace(/\\/g, "/");
655
655
  result = result.replace(/\/+/g, "/");
656
656
  result = result.replace(/\/+$/, "");
657
657
  if (result && !result.startsWith("/")) {
@@ -4082,7 +4082,7 @@ var init_esm = __esm({
4082
4082
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
4083
4083
  const statMethod = opts.lstat ? lstat : stat;
4084
4084
  if (wantBigintFsStats) {
4085
- this._stat = (path31) => statMethod(path31, { bigint: true });
4085
+ this._stat = (path32) => statMethod(path32, { bigint: true });
4086
4086
  } else {
4087
4087
  this._stat = statMethod;
4088
4088
  }
@@ -4107,8 +4107,8 @@ var init_esm = __esm({
4107
4107
  const par = this.parent;
4108
4108
  const fil = par && par.files;
4109
4109
  if (fil && fil.length > 0) {
4110
- const { path: path31, depth } = par;
4111
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path31));
4110
+ const { path: path32, depth } = par;
4111
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path32));
4112
4112
  const awaited = await Promise.all(slice);
4113
4113
  for (const entry of awaited) {
4114
4114
  if (!entry)
@@ -4148,20 +4148,20 @@ var init_esm = __esm({
4148
4148
  this.reading = false;
4149
4149
  }
4150
4150
  }
4151
- async _exploreDir(path31, depth) {
4151
+ async _exploreDir(path32, depth) {
4152
4152
  let files;
4153
4153
  try {
4154
- files = await readdir(path31, this._rdOptions);
4154
+ files = await readdir(path32, this._rdOptions);
4155
4155
  } catch (error) {
4156
4156
  this._onError(error);
4157
4157
  }
4158
- return { files, depth, path: path31 };
4158
+ return { files, depth, path: path32 };
4159
4159
  }
4160
- async _formatEntry(dirent, path31) {
4160
+ async _formatEntry(dirent, path32) {
4161
4161
  let entry;
4162
4162
  const basename3 = this._isDirent ? dirent.name : dirent;
4163
4163
  try {
4164
- const fullPath = presolve(pjoin(path31, basename3));
4164
+ const fullPath = presolve(pjoin(path32, basename3));
4165
4165
  entry = { path: prelative(this._root, fullPath), fullPath, basename: basename3 };
4166
4166
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
4167
4167
  } catch (err) {
@@ -4222,16 +4222,16 @@ import { watchFile, unwatchFile, watch as fs_watch } from "fs";
4222
4222
  import { open, stat as stat2, lstat as lstat2, realpath as fsrealpath } from "fs/promises";
4223
4223
  import * as sysPath from "path";
4224
4224
  import { type as osType } from "os";
4225
- function createFsWatchInstance(path31, options, listener, errHandler, emitRaw) {
4225
+ function createFsWatchInstance(path32, options, listener, errHandler, emitRaw) {
4226
4226
  const handleEvent = (rawEvent, evPath) => {
4227
- listener(path31);
4228
- emitRaw(rawEvent, evPath, { watchedPath: path31 });
4229
- if (evPath && path31 !== evPath) {
4230
- fsWatchBroadcast(sysPath.resolve(path31, evPath), KEY_LISTENERS, sysPath.join(path31, evPath));
4227
+ listener(path32);
4228
+ emitRaw(rawEvent, evPath, { watchedPath: path32 });
4229
+ if (evPath && path32 !== evPath) {
4230
+ fsWatchBroadcast(sysPath.resolve(path32, evPath), KEY_LISTENERS, sysPath.join(path32, evPath));
4231
4231
  }
4232
4232
  };
4233
4233
  try {
4234
- return fs_watch(path31, {
4234
+ return fs_watch(path32, {
4235
4235
  persistent: options.persistent
4236
4236
  }, handleEvent);
4237
4237
  } catch (error) {
@@ -4576,12 +4576,12 @@ var init_handler = __esm({
4576
4576
  listener(val1, val2, val3);
4577
4577
  });
4578
4578
  };
4579
- setFsWatchListener = (path31, fullPath, options, handlers) => {
4579
+ setFsWatchListener = (path32, fullPath, options, handlers) => {
4580
4580
  const { listener, errHandler, rawEmitter } = handlers;
4581
4581
  let cont = FsWatchInstances.get(fullPath);
4582
4582
  let watcher;
4583
4583
  if (!options.persistent) {
4584
- watcher = createFsWatchInstance(path31, options, listener, errHandler, rawEmitter);
4584
+ watcher = createFsWatchInstance(path32, options, listener, errHandler, rawEmitter);
4585
4585
  if (!watcher)
4586
4586
  return;
4587
4587
  return watcher.close.bind(watcher);
@@ -4592,7 +4592,7 @@ var init_handler = __esm({
4592
4592
  addAndConvert(cont, KEY_RAW, rawEmitter);
4593
4593
  } else {
4594
4594
  watcher = createFsWatchInstance(
4595
- path31,
4595
+ path32,
4596
4596
  options,
4597
4597
  fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
4598
4598
  errHandler,
@@ -4607,7 +4607,7 @@ var init_handler = __esm({
4607
4607
  cont.watcherUnusable = true;
4608
4608
  if (isWindows && error.code === "EPERM") {
4609
4609
  try {
4610
- const fd = await open(path31, "r");
4610
+ const fd = await open(path32, "r");
4611
4611
  await fd.close();
4612
4612
  broadcastErr(error);
4613
4613
  } catch (err) {
@@ -4638,7 +4638,7 @@ var init_handler = __esm({
4638
4638
  };
4639
4639
  };
4640
4640
  FsWatchFileInstances = /* @__PURE__ */ new Map();
4641
- setFsWatchFileListener = (path31, fullPath, options, handlers) => {
4641
+ setFsWatchFileListener = (path32, fullPath, options, handlers) => {
4642
4642
  const { listener, rawEmitter } = handlers;
4643
4643
  let cont = FsWatchFileInstances.get(fullPath);
4644
4644
  const copts = cont && cont.options;
@@ -4660,7 +4660,7 @@ var init_handler = __esm({
4660
4660
  });
4661
4661
  const currmtime = curr.mtimeMs;
4662
4662
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
4663
- foreach(cont.listeners, (listener2) => listener2(path31, curr));
4663
+ foreach(cont.listeners, (listener2) => listener2(path32, curr));
4664
4664
  }
4665
4665
  })
4666
4666
  };
@@ -4688,13 +4688,13 @@ var init_handler = __esm({
4688
4688
  * @param listener on fs change
4689
4689
  * @returns closer for the watcher instance
4690
4690
  */
4691
- _watchWithNodeFs(path31, listener) {
4691
+ _watchWithNodeFs(path32, listener) {
4692
4692
  const opts = this.fsw.options;
4693
- const directory = sysPath.dirname(path31);
4694
- const basename3 = sysPath.basename(path31);
4693
+ const directory = sysPath.dirname(path32);
4694
+ const basename3 = sysPath.basename(path32);
4695
4695
  const parent = this.fsw._getWatchedDir(directory);
4696
4696
  parent.add(basename3);
4697
- const absolutePath = sysPath.resolve(path31);
4697
+ const absolutePath = sysPath.resolve(path32);
4698
4698
  const options = {
4699
4699
  persistent: opts.persistent
4700
4700
  };
@@ -4704,12 +4704,12 @@ var init_handler = __esm({
4704
4704
  if (opts.usePolling) {
4705
4705
  const enableBin = opts.interval !== opts.binaryInterval;
4706
4706
  options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
4707
- closer = setFsWatchFileListener(path31, absolutePath, options, {
4707
+ closer = setFsWatchFileListener(path32, absolutePath, options, {
4708
4708
  listener,
4709
4709
  rawEmitter: this.fsw._emitRaw
4710
4710
  });
4711
4711
  } else {
4712
- closer = setFsWatchListener(path31, absolutePath, options, {
4712
+ closer = setFsWatchListener(path32, absolutePath, options, {
4713
4713
  listener,
4714
4714
  errHandler: this._boundHandleError,
4715
4715
  rawEmitter: this.fsw._emitRaw
@@ -4731,7 +4731,7 @@ var init_handler = __esm({
4731
4731
  let prevStats = stats;
4732
4732
  if (parent.has(basename3))
4733
4733
  return;
4734
- const listener = async (path31, newStats) => {
4734
+ const listener = async (path32, newStats) => {
4735
4735
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
4736
4736
  return;
4737
4737
  if (!newStats || newStats.mtimeMs === 0) {
@@ -4745,11 +4745,11 @@ var init_handler = __esm({
4745
4745
  this.fsw._emit(EV.CHANGE, file, newStats2);
4746
4746
  }
4747
4747
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
4748
- this.fsw._closeFile(path31);
4748
+ this.fsw._closeFile(path32);
4749
4749
  prevStats = newStats2;
4750
4750
  const closer2 = this._watchWithNodeFs(file, listener);
4751
4751
  if (closer2)
4752
- this.fsw._addPathCloser(path31, closer2);
4752
+ this.fsw._addPathCloser(path32, closer2);
4753
4753
  } else {
4754
4754
  prevStats = newStats2;
4755
4755
  }
@@ -4781,7 +4781,7 @@ var init_handler = __esm({
4781
4781
  * @param item basename of this item
4782
4782
  * @returns true if no more processing is needed for this entry.
4783
4783
  */
4784
- async _handleSymlink(entry, directory, path31, item) {
4784
+ async _handleSymlink(entry, directory, path32, item) {
4785
4785
  if (this.fsw.closed) {
4786
4786
  return;
4787
4787
  }
@@ -4791,7 +4791,7 @@ var init_handler = __esm({
4791
4791
  this.fsw._incrReadyCount();
4792
4792
  let linkPath;
4793
4793
  try {
4794
- linkPath = await fsrealpath(path31);
4794
+ linkPath = await fsrealpath(path32);
4795
4795
  } catch (e) {
4796
4796
  this.fsw._emitReady();
4797
4797
  return true;
@@ -4801,12 +4801,12 @@ var init_handler = __esm({
4801
4801
  if (dir.has(item)) {
4802
4802
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
4803
4803
  this.fsw._symlinkPaths.set(full, linkPath);
4804
- this.fsw._emit(EV.CHANGE, path31, entry.stats);
4804
+ this.fsw._emit(EV.CHANGE, path32, entry.stats);
4805
4805
  }
4806
4806
  } else {
4807
4807
  dir.add(item);
4808
4808
  this.fsw._symlinkPaths.set(full, linkPath);
4809
- this.fsw._emit(EV.ADD, path31, entry.stats);
4809
+ this.fsw._emit(EV.ADD, path32, entry.stats);
4810
4810
  }
4811
4811
  this.fsw._emitReady();
4812
4812
  return true;
@@ -4835,9 +4835,9 @@ var init_handler = __esm({
4835
4835
  return;
4836
4836
  }
4837
4837
  const item = entry.path;
4838
- let path31 = sysPath.join(directory, item);
4838
+ let path32 = sysPath.join(directory, item);
4839
4839
  current.add(item);
4840
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path31, item)) {
4840
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path32, item)) {
4841
4841
  return;
4842
4842
  }
4843
4843
  if (this.fsw.closed) {
@@ -4846,8 +4846,8 @@ var init_handler = __esm({
4846
4846
  }
4847
4847
  if (item === target || !target && !previous.has(item)) {
4848
4848
  this.fsw._incrReadyCount();
4849
- path31 = sysPath.join(dir, sysPath.relative(dir, path31));
4850
- this._addToNodeFs(path31, initialAdd, wh, depth + 1);
4849
+ path32 = sysPath.join(dir, sysPath.relative(dir, path32));
4850
+ this._addToNodeFs(path32, initialAdd, wh, depth + 1);
4851
4851
  }
4852
4852
  }).on(EV.ERROR, this._boundHandleError);
4853
4853
  return new Promise((resolve3, reject) => {
@@ -4916,13 +4916,13 @@ var init_handler = __esm({
4916
4916
  * @param depth Child path actually targeted for watch
4917
4917
  * @param target Child path actually targeted for watch
4918
4918
  */
4919
- async _addToNodeFs(path31, initialAdd, priorWh, depth, target) {
4919
+ async _addToNodeFs(path32, initialAdd, priorWh, depth, target) {
4920
4920
  const ready = this.fsw._emitReady;
4921
- if (this.fsw._isIgnored(path31) || this.fsw.closed) {
4921
+ if (this.fsw._isIgnored(path32) || this.fsw.closed) {
4922
4922
  ready();
4923
4923
  return false;
4924
4924
  }
4925
- const wh = this.fsw._getWatchHelpers(path31);
4925
+ const wh = this.fsw._getWatchHelpers(path32);
4926
4926
  if (priorWh) {
4927
4927
  wh.filterPath = (entry) => priorWh.filterPath(entry);
4928
4928
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -4938,8 +4938,8 @@ var init_handler = __esm({
4938
4938
  const follow = this.fsw.options.followSymlinks;
4939
4939
  let closer;
4940
4940
  if (stats.isDirectory()) {
4941
- const absPath = sysPath.resolve(path31);
4942
- const targetPath = follow ? await fsrealpath(path31) : path31;
4941
+ const absPath = sysPath.resolve(path32);
4942
+ const targetPath = follow ? await fsrealpath(path32) : path32;
4943
4943
  if (this.fsw.closed)
4944
4944
  return;
4945
4945
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -4949,29 +4949,29 @@ var init_handler = __esm({
4949
4949
  this.fsw._symlinkPaths.set(absPath, targetPath);
4950
4950
  }
4951
4951
  } else if (stats.isSymbolicLink()) {
4952
- const targetPath = follow ? await fsrealpath(path31) : path31;
4952
+ const targetPath = follow ? await fsrealpath(path32) : path32;
4953
4953
  if (this.fsw.closed)
4954
4954
  return;
4955
4955
  const parent = sysPath.dirname(wh.watchPath);
4956
4956
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
4957
4957
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
4958
- closer = await this._handleDir(parent, stats, initialAdd, depth, path31, wh, targetPath);
4958
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path32, wh, targetPath);
4959
4959
  if (this.fsw.closed)
4960
4960
  return;
4961
4961
  if (targetPath !== void 0) {
4962
- this.fsw._symlinkPaths.set(sysPath.resolve(path31), targetPath);
4962
+ this.fsw._symlinkPaths.set(sysPath.resolve(path32), targetPath);
4963
4963
  }
4964
4964
  } else {
4965
4965
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
4966
4966
  }
4967
4967
  ready();
4968
4968
  if (closer)
4969
- this.fsw._addPathCloser(path31, closer);
4969
+ this.fsw._addPathCloser(path32, closer);
4970
4970
  return false;
4971
4971
  } catch (error) {
4972
4972
  if (this.fsw._handleError(error)) {
4973
4973
  ready();
4974
- return path31;
4974
+ return path32;
4975
4975
  }
4976
4976
  }
4977
4977
  }
@@ -5010,26 +5010,26 @@ function createPattern(matcher) {
5010
5010
  }
5011
5011
  return () => false;
5012
5012
  }
5013
- function normalizePath2(path31) {
5014
- if (typeof path31 !== "string")
5013
+ function normalizePath2(path32) {
5014
+ if (typeof path32 !== "string")
5015
5015
  throw new Error("string expected");
5016
- path31 = sysPath2.normalize(path31);
5017
- path31 = path31.replace(/\\/g, "/");
5016
+ path32 = sysPath2.normalize(path32);
5017
+ path32 = path32.replace(/\\/g, "/");
5018
5018
  let prepend = false;
5019
- if (path31.startsWith("//"))
5019
+ if (path32.startsWith("//"))
5020
5020
  prepend = true;
5021
5021
  const DOUBLE_SLASH_RE2 = /\/\//;
5022
- while (path31.match(DOUBLE_SLASH_RE2))
5023
- path31 = path31.replace(DOUBLE_SLASH_RE2, "/");
5022
+ while (path32.match(DOUBLE_SLASH_RE2))
5023
+ path32 = path32.replace(DOUBLE_SLASH_RE2, "/");
5024
5024
  if (prepend)
5025
- path31 = "/" + path31;
5026
- return path31;
5025
+ path32 = "/" + path32;
5026
+ return path32;
5027
5027
  }
5028
5028
  function matchPatterns(patterns, testString, stats) {
5029
- const path31 = normalizePath2(testString);
5029
+ const path32 = normalizePath2(testString);
5030
5030
  for (let index = 0; index < patterns.length; index++) {
5031
5031
  const pattern = patterns[index];
5032
- if (pattern(path31, stats)) {
5032
+ if (pattern(path32, stats)) {
5033
5033
  return true;
5034
5034
  }
5035
5035
  }
@@ -5090,19 +5090,19 @@ var init_esm2 = __esm({
5090
5090
  }
5091
5091
  return str;
5092
5092
  };
5093
- normalizePathToUnix = (path31) => toUnix(sysPath2.normalize(toUnix(path31)));
5094
- normalizeIgnored = (cwd = "") => (path31) => {
5095
- if (typeof path31 === "string") {
5096
- return normalizePathToUnix(sysPath2.isAbsolute(path31) ? path31 : sysPath2.join(cwd, path31));
5093
+ normalizePathToUnix = (path32) => toUnix(sysPath2.normalize(toUnix(path32)));
5094
+ normalizeIgnored = (cwd = "") => (path32) => {
5095
+ if (typeof path32 === "string") {
5096
+ return normalizePathToUnix(sysPath2.isAbsolute(path32) ? path32 : sysPath2.join(cwd, path32));
5097
5097
  } else {
5098
- return path31;
5098
+ return path32;
5099
5099
  }
5100
5100
  };
5101
- getAbsolutePath = (path31, cwd) => {
5102
- if (sysPath2.isAbsolute(path31)) {
5103
- return path31;
5101
+ getAbsolutePath = (path32, cwd) => {
5102
+ if (sysPath2.isAbsolute(path32)) {
5103
+ return path32;
5104
5104
  }
5105
- return sysPath2.join(cwd, path31);
5105
+ return sysPath2.join(cwd, path32);
5106
5106
  };
5107
5107
  EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
5108
5108
  DirEntry = class {
@@ -5157,10 +5157,10 @@ var init_esm2 = __esm({
5157
5157
  STAT_METHOD_F = "stat";
5158
5158
  STAT_METHOD_L = "lstat";
5159
5159
  WatchHelper = class {
5160
- constructor(path31, follow, fsw) {
5160
+ constructor(path32, follow, fsw) {
5161
5161
  this.fsw = fsw;
5162
- const watchPath = path31;
5163
- this.path = path31 = path31.replace(REPLACER_RE, "");
5162
+ const watchPath = path32;
5163
+ this.path = path32 = path32.replace(REPLACER_RE, "");
5164
5164
  this.watchPath = watchPath;
5165
5165
  this.fullWatchPath = sysPath2.resolve(watchPath);
5166
5166
  this.dirParts = [];
@@ -5282,20 +5282,20 @@ var init_esm2 = __esm({
5282
5282
  this._closePromise = void 0;
5283
5283
  let paths = unifyPaths(paths_);
5284
5284
  if (cwd) {
5285
- paths = paths.map((path31) => {
5286
- const absPath = getAbsolutePath(path31, cwd);
5285
+ paths = paths.map((path32) => {
5286
+ const absPath = getAbsolutePath(path32, cwd);
5287
5287
  return absPath;
5288
5288
  });
5289
5289
  }
5290
- paths.forEach((path31) => {
5291
- this._removeIgnoredPath(path31);
5290
+ paths.forEach((path32) => {
5291
+ this._removeIgnoredPath(path32);
5292
5292
  });
5293
5293
  this._userIgnored = void 0;
5294
5294
  if (!this._readyCount)
5295
5295
  this._readyCount = 0;
5296
5296
  this._readyCount += paths.length;
5297
- Promise.all(paths.map(async (path31) => {
5298
- const res = await this._nodeFsHandler._addToNodeFs(path31, !_internal, void 0, 0, _origAdd);
5297
+ Promise.all(paths.map(async (path32) => {
5298
+ const res = await this._nodeFsHandler._addToNodeFs(path32, !_internal, void 0, 0, _origAdd);
5299
5299
  if (res)
5300
5300
  this._emitReady();
5301
5301
  return res;
@@ -5317,17 +5317,17 @@ var init_esm2 = __esm({
5317
5317
  return this;
5318
5318
  const paths = unifyPaths(paths_);
5319
5319
  const { cwd } = this.options;
5320
- paths.forEach((path31) => {
5321
- if (!sysPath2.isAbsolute(path31) && !this._closers.has(path31)) {
5320
+ paths.forEach((path32) => {
5321
+ if (!sysPath2.isAbsolute(path32) && !this._closers.has(path32)) {
5322
5322
  if (cwd)
5323
- path31 = sysPath2.join(cwd, path31);
5324
- path31 = sysPath2.resolve(path31);
5323
+ path32 = sysPath2.join(cwd, path32);
5324
+ path32 = sysPath2.resolve(path32);
5325
5325
  }
5326
- this._closePath(path31);
5327
- this._addIgnoredPath(path31);
5328
- if (this._watched.has(path31)) {
5326
+ this._closePath(path32);
5327
+ this._addIgnoredPath(path32);
5328
+ if (this._watched.has(path32)) {
5329
5329
  this._addIgnoredPath({
5330
- path: path31,
5330
+ path: path32,
5331
5331
  recursive: true
5332
5332
  });
5333
5333
  }
@@ -5391,38 +5391,38 @@ var init_esm2 = __esm({
5391
5391
  * @param stats arguments to be passed with event
5392
5392
  * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
5393
5393
  */
5394
- async _emit(event, path31, stats) {
5394
+ async _emit(event, path32, stats) {
5395
5395
  if (this.closed)
5396
5396
  return;
5397
5397
  const opts = this.options;
5398
5398
  if (isWindows)
5399
- path31 = sysPath2.normalize(path31);
5399
+ path32 = sysPath2.normalize(path32);
5400
5400
  if (opts.cwd)
5401
- path31 = sysPath2.relative(opts.cwd, path31);
5402
- const args = [path31];
5401
+ path32 = sysPath2.relative(opts.cwd, path32);
5402
+ const args = [path32];
5403
5403
  if (stats != null)
5404
5404
  args.push(stats);
5405
5405
  const awf = opts.awaitWriteFinish;
5406
5406
  let pw;
5407
- if (awf && (pw = this._pendingWrites.get(path31))) {
5407
+ if (awf && (pw = this._pendingWrites.get(path32))) {
5408
5408
  pw.lastChange = /* @__PURE__ */ new Date();
5409
5409
  return this;
5410
5410
  }
5411
5411
  if (opts.atomic) {
5412
5412
  if (event === EVENTS.UNLINK) {
5413
- this._pendingUnlinks.set(path31, [event, ...args]);
5413
+ this._pendingUnlinks.set(path32, [event, ...args]);
5414
5414
  setTimeout(() => {
5415
- this._pendingUnlinks.forEach((entry, path32) => {
5415
+ this._pendingUnlinks.forEach((entry, path33) => {
5416
5416
  this.emit(...entry);
5417
5417
  this.emit(EVENTS.ALL, ...entry);
5418
- this._pendingUnlinks.delete(path32);
5418
+ this._pendingUnlinks.delete(path33);
5419
5419
  });
5420
5420
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
5421
5421
  return this;
5422
5422
  }
5423
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path31)) {
5423
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path32)) {
5424
5424
  event = EVENTS.CHANGE;
5425
- this._pendingUnlinks.delete(path31);
5425
+ this._pendingUnlinks.delete(path32);
5426
5426
  }
5427
5427
  }
5428
5428
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -5440,16 +5440,16 @@ var init_esm2 = __esm({
5440
5440
  this.emitWithAll(event, args);
5441
5441
  }
5442
5442
  };
5443
- this._awaitWriteFinish(path31, awf.stabilityThreshold, event, awfEmit);
5443
+ this._awaitWriteFinish(path32, awf.stabilityThreshold, event, awfEmit);
5444
5444
  return this;
5445
5445
  }
5446
5446
  if (event === EVENTS.CHANGE) {
5447
- const isThrottled = !this._throttle(EVENTS.CHANGE, path31, 50);
5447
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path32, 50);
5448
5448
  if (isThrottled)
5449
5449
  return this;
5450
5450
  }
5451
5451
  if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
5452
- const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path31) : path31;
5452
+ const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path32) : path32;
5453
5453
  let stats2;
5454
5454
  try {
5455
5455
  stats2 = await stat3(fullPath);
@@ -5480,23 +5480,23 @@ var init_esm2 = __esm({
5480
5480
  * @param timeout duration of time to suppress duplicate actions
5481
5481
  * @returns tracking object or false if action should be suppressed
5482
5482
  */
5483
- _throttle(actionType, path31, timeout) {
5483
+ _throttle(actionType, path32, timeout) {
5484
5484
  if (!this._throttled.has(actionType)) {
5485
5485
  this._throttled.set(actionType, /* @__PURE__ */ new Map());
5486
5486
  }
5487
5487
  const action = this._throttled.get(actionType);
5488
5488
  if (!action)
5489
5489
  throw new Error("invalid throttle");
5490
- const actionPath = action.get(path31);
5490
+ const actionPath = action.get(path32);
5491
5491
  if (actionPath) {
5492
5492
  actionPath.count++;
5493
5493
  return false;
5494
5494
  }
5495
5495
  let timeoutObject;
5496
5496
  const clear = () => {
5497
- const item = action.get(path31);
5497
+ const item = action.get(path32);
5498
5498
  const count = item ? item.count : 0;
5499
- action.delete(path31);
5499
+ action.delete(path32);
5500
5500
  clearTimeout(timeoutObject);
5501
5501
  if (item)
5502
5502
  clearTimeout(item.timeoutObject);
@@ -5504,7 +5504,7 @@ var init_esm2 = __esm({
5504
5504
  };
5505
5505
  timeoutObject = setTimeout(clear, timeout);
5506
5506
  const thr = { timeoutObject, clear, count: 0 };
5507
- action.set(path31, thr);
5507
+ action.set(path32, thr);
5508
5508
  return thr;
5509
5509
  }
5510
5510
  _incrReadyCount() {
@@ -5518,44 +5518,44 @@ var init_esm2 = __esm({
5518
5518
  * @param event
5519
5519
  * @param awfEmit Callback to be called when ready for event to be emitted.
5520
5520
  */
5521
- _awaitWriteFinish(path31, threshold, event, awfEmit) {
5521
+ _awaitWriteFinish(path32, threshold, event, awfEmit) {
5522
5522
  const awf = this.options.awaitWriteFinish;
5523
5523
  if (typeof awf !== "object")
5524
5524
  return;
5525
5525
  const pollInterval = awf.pollInterval;
5526
5526
  let timeoutHandler;
5527
- let fullPath = path31;
5528
- if (this.options.cwd && !sysPath2.isAbsolute(path31)) {
5529
- fullPath = sysPath2.join(this.options.cwd, path31);
5527
+ let fullPath = path32;
5528
+ if (this.options.cwd && !sysPath2.isAbsolute(path32)) {
5529
+ fullPath = sysPath2.join(this.options.cwd, path32);
5530
5530
  }
5531
5531
  const now = /* @__PURE__ */ new Date();
5532
5532
  const writes = this._pendingWrites;
5533
5533
  function awaitWriteFinishFn(prevStat) {
5534
5534
  statcb(fullPath, (err, curStat) => {
5535
- if (err || !writes.has(path31)) {
5535
+ if (err || !writes.has(path32)) {
5536
5536
  if (err && err.code !== "ENOENT")
5537
5537
  awfEmit(err);
5538
5538
  return;
5539
5539
  }
5540
5540
  const now2 = Number(/* @__PURE__ */ new Date());
5541
5541
  if (prevStat && curStat.size !== prevStat.size) {
5542
- writes.get(path31).lastChange = now2;
5542
+ writes.get(path32).lastChange = now2;
5543
5543
  }
5544
- const pw = writes.get(path31);
5544
+ const pw = writes.get(path32);
5545
5545
  const df = now2 - pw.lastChange;
5546
5546
  if (df >= threshold) {
5547
- writes.delete(path31);
5547
+ writes.delete(path32);
5548
5548
  awfEmit(void 0, curStat);
5549
5549
  } else {
5550
5550
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
5551
5551
  }
5552
5552
  });
5553
5553
  }
5554
- if (!writes.has(path31)) {
5555
- writes.set(path31, {
5554
+ if (!writes.has(path32)) {
5555
+ writes.set(path32, {
5556
5556
  lastChange: now,
5557
5557
  cancelWait: () => {
5558
- writes.delete(path31);
5558
+ writes.delete(path32);
5559
5559
  clearTimeout(timeoutHandler);
5560
5560
  return event;
5561
5561
  }
@@ -5566,8 +5566,8 @@ var init_esm2 = __esm({
5566
5566
  /**
5567
5567
  * Determines whether user has asked to ignore this path.
5568
5568
  */
5569
- _isIgnored(path31, stats) {
5570
- if (this.options.atomic && DOT_RE.test(path31))
5569
+ _isIgnored(path32, stats) {
5570
+ if (this.options.atomic && DOT_RE.test(path32))
5571
5571
  return true;
5572
5572
  if (!this._userIgnored) {
5573
5573
  const { cwd } = this.options;
@@ -5577,17 +5577,17 @@ var init_esm2 = __esm({
5577
5577
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
5578
5578
  this._userIgnored = anymatch(list, void 0);
5579
5579
  }
5580
- return this._userIgnored(path31, stats);
5580
+ return this._userIgnored(path32, stats);
5581
5581
  }
5582
- _isntIgnored(path31, stat4) {
5583
- return !this._isIgnored(path31, stat4);
5582
+ _isntIgnored(path32, stat4) {
5583
+ return !this._isIgnored(path32, stat4);
5584
5584
  }
5585
5585
  /**
5586
5586
  * Provides a set of common helpers and properties relating to symlink handling.
5587
5587
  * @param path file or directory pattern being watched
5588
5588
  */
5589
- _getWatchHelpers(path31) {
5590
- return new WatchHelper(path31, this.options.followSymlinks, this);
5589
+ _getWatchHelpers(path32) {
5590
+ return new WatchHelper(path32, this.options.followSymlinks, this);
5591
5591
  }
5592
5592
  // Directory helpers
5593
5593
  // -----------------
@@ -5619,63 +5619,63 @@ var init_esm2 = __esm({
5619
5619
  * @param item base path of item/directory
5620
5620
  */
5621
5621
  _remove(directory, item, isDirectory) {
5622
- const path31 = sysPath2.join(directory, item);
5623
- const fullPath = sysPath2.resolve(path31);
5624
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path31) || this._watched.has(fullPath);
5625
- if (!this._throttle("remove", path31, 100))
5622
+ const path32 = sysPath2.join(directory, item);
5623
+ const fullPath = sysPath2.resolve(path32);
5624
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path32) || this._watched.has(fullPath);
5625
+ if (!this._throttle("remove", path32, 100))
5626
5626
  return;
5627
5627
  if (!isDirectory && this._watched.size === 1) {
5628
5628
  this.add(directory, item, true);
5629
5629
  }
5630
- const wp = this._getWatchedDir(path31);
5630
+ const wp = this._getWatchedDir(path32);
5631
5631
  const nestedDirectoryChildren = wp.getChildren();
5632
- nestedDirectoryChildren.forEach((nested) => this._remove(path31, nested));
5632
+ nestedDirectoryChildren.forEach((nested) => this._remove(path32, nested));
5633
5633
  const parent = this._getWatchedDir(directory);
5634
5634
  const wasTracked = parent.has(item);
5635
5635
  parent.remove(item);
5636
5636
  if (this._symlinkPaths.has(fullPath)) {
5637
5637
  this._symlinkPaths.delete(fullPath);
5638
5638
  }
5639
- let relPath = path31;
5639
+ let relPath = path32;
5640
5640
  if (this.options.cwd)
5641
- relPath = sysPath2.relative(this.options.cwd, path31);
5641
+ relPath = sysPath2.relative(this.options.cwd, path32);
5642
5642
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
5643
5643
  const event = this._pendingWrites.get(relPath).cancelWait();
5644
5644
  if (event === EVENTS.ADD)
5645
5645
  return;
5646
5646
  }
5647
- this._watched.delete(path31);
5647
+ this._watched.delete(path32);
5648
5648
  this._watched.delete(fullPath);
5649
5649
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
5650
- if (wasTracked && !this._isIgnored(path31))
5651
- this._emit(eventName, path31);
5652
- this._closePath(path31);
5650
+ if (wasTracked && !this._isIgnored(path32))
5651
+ this._emit(eventName, path32);
5652
+ this._closePath(path32);
5653
5653
  }
5654
5654
  /**
5655
5655
  * Closes all watchers for a path
5656
5656
  */
5657
- _closePath(path31) {
5658
- this._closeFile(path31);
5659
- const dir = sysPath2.dirname(path31);
5660
- this._getWatchedDir(dir).remove(sysPath2.basename(path31));
5657
+ _closePath(path32) {
5658
+ this._closeFile(path32);
5659
+ const dir = sysPath2.dirname(path32);
5660
+ this._getWatchedDir(dir).remove(sysPath2.basename(path32));
5661
5661
  }
5662
5662
  /**
5663
5663
  * Closes only file-specific watchers
5664
5664
  */
5665
- _closeFile(path31) {
5666
- const closers = this._closers.get(path31);
5665
+ _closeFile(path32) {
5666
+ const closers = this._closers.get(path32);
5667
5667
  if (!closers)
5668
5668
  return;
5669
5669
  closers.forEach((closer) => closer());
5670
- this._closers.delete(path31);
5670
+ this._closers.delete(path32);
5671
5671
  }
5672
- _addPathCloser(path31, closer) {
5672
+ _addPathCloser(path32, closer) {
5673
5673
  if (!closer)
5674
5674
  return;
5675
- let list = this._closers.get(path31);
5675
+ let list = this._closers.get(path32);
5676
5676
  if (!list) {
5677
5677
  list = [];
5678
- this._closers.set(path31, list);
5678
+ this._closers.set(path32, list);
5679
5679
  }
5680
5680
  list.push(closer);
5681
5681
  }
@@ -5920,18 +5920,18 @@ function getWsIndex(routes) {
5920
5920
  wsIndexCache.set(routes, index);
5921
5921
  return index;
5922
5922
  }
5923
- function matchRoute(routes, method, path31) {
5923
+ function matchRoute(routes, method, path32) {
5924
5924
  const index = getHttpIndex(routes);
5925
5925
  const upper = method.toUpperCase();
5926
- const hit = matchByMethod(index, upper, path31);
5926
+ const hit = matchByMethod(index, upper, path32);
5927
5927
  if (hit) return hit;
5928
5928
  if (upper === "HEAD") {
5929
- return matchByMethod(index, "GET", path31);
5929
+ return matchByMethod(index, "GET", path32);
5930
5930
  }
5931
5931
  return null;
5932
5932
  }
5933
- function matchByMethod(index, method, path31) {
5934
- const staticHit = index.static.get(`${method}|${path31}`);
5933
+ function matchByMethod(index, method, path32) {
5934
+ const staticHit = index.static.get(`${method}|${path32}`);
5935
5935
  if (staticHit) {
5936
5936
  return { route: staticHit, params: {} };
5937
5937
  }
@@ -5940,31 +5940,31 @@ function matchByMethod(index, method, path31) {
5940
5940
  if (route.method !== method) {
5941
5941
  continue;
5942
5942
  }
5943
- const params = matchSegments(entry.segments, path31, route.paramNames, route.isCatchAll);
5943
+ const params = matchSegments(entry.segments, path32, route.paramNames, route.isCatchAll);
5944
5944
  if (params !== null) {
5945
5945
  return { route, params };
5946
5946
  }
5947
5947
  }
5948
5948
  return null;
5949
5949
  }
5950
- function matchWsRoute(wsRoutes, path31) {
5950
+ function matchWsRoute(wsRoutes, path32) {
5951
5951
  const index = getWsIndex(wsRoutes);
5952
- const staticHit = index.static.get(path31);
5952
+ const staticHit = index.static.get(path32);
5953
5953
  if (staticHit) {
5954
5954
  return { route: staticHit, params: {} };
5955
5955
  }
5956
5956
  for (const route of index.dynamics) {
5957
- const params = matchDynamicPath(route.urlPath, path31, route.paramNames, route.isCatchAll);
5957
+ const params = matchDynamicPath(route.urlPath, path32, route.paramNames, route.isCatchAll);
5958
5958
  if (params !== null) {
5959
5959
  return { route, params };
5960
5960
  }
5961
5961
  }
5962
5962
  return null;
5963
5963
  }
5964
- function findAllowedMethods(routes, path31) {
5964
+ function findAllowedMethods(routes, path32) {
5965
5965
  const index = getHttpIndex(routes);
5966
5966
  const methods = /* @__PURE__ */ new Set();
5967
- const staticMethods = index.methodsByStaticPath.get(path31);
5967
+ const staticMethods = index.methodsByStaticPath.get(path32);
5968
5968
  if (staticMethods) {
5969
5969
  for (const method of staticMethods) {
5970
5970
  methods.add(method);
@@ -5973,7 +5973,7 @@ function findAllowedMethods(routes, path31) {
5973
5973
  for (const entry of index.dynamics) {
5974
5974
  const params = matchSegments(
5975
5975
  entry.segments,
5976
- path31,
5976
+ path32,
5977
5977
  entry.route.paramNames,
5978
5978
  entry.route.isCatchAll
5979
5979
  );
@@ -5986,11 +5986,11 @@ function findAllowedMethods(routes, path31) {
5986
5986
  }
5987
5987
  return Array.from(methods);
5988
5988
  }
5989
- function matchDynamicPath(pattern, path31, paramNames, isCatchAll) {
5990
- return matchSegments(pattern.split("/").filter(Boolean), path31, paramNames, isCatchAll);
5989
+ function matchDynamicPath(pattern, path32, paramNames, isCatchAll) {
5990
+ return matchSegments(pattern.split("/").filter(Boolean), path32, paramNames, isCatchAll);
5991
5991
  }
5992
- function matchSegments(patternSegments, path31, paramNames, isCatchAll) {
5993
- const pathSegments = path31.split("/").filter(Boolean);
5992
+ function matchSegments(patternSegments, path32, paramNames, isCatchAll) {
5993
+ const pathSegments = path32.split("/").filter(Boolean);
5994
5994
  if (isCatchAll) {
5995
5995
  const nonCatchAllCount = patternSegments.length - 1;
5996
5996
  if (pathSegments.length <= nonCatchAllCount) {
@@ -6263,14 +6263,14 @@ var init_httpErrors = __esm({
6263
6263
  issues;
6264
6264
  };
6265
6265
  RouteNotFoundError = class extends FaapiError {
6266
- constructor(path31) {
6267
- super("ROUTE_NOT_FOUND", `Route not found: ${path31}`, 404);
6266
+ constructor(path32) {
6267
+ super("ROUTE_NOT_FOUND", `Route not found: ${path32}`, 404);
6268
6268
  this.name = "RouteNotFoundError";
6269
6269
  }
6270
6270
  };
6271
6271
  MethodNotAllowedError = class extends FaapiError {
6272
- constructor(method, path31, allowedMethods) {
6273
- super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path31}`, 405);
6272
+ constructor(method, path32, allowedMethods) {
6273
+ super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path32}`, 405);
6274
6274
  this.allowedMethods = allowedMethods;
6275
6275
  this.name = "MethodNotAllowedError";
6276
6276
  }
@@ -6388,6 +6388,107 @@ var init_responseFormatter = __esm({
6388
6388
  }
6389
6389
  });
6390
6390
 
6391
+ // src/logger/formatEntry.ts
6392
+ function serializeFieldValue(value) {
6393
+ if (value instanceof Error) {
6394
+ return { name: value.name, message: value.message, stack: value.stack };
6395
+ }
6396
+ return value;
6397
+ }
6398
+ function formatEntry(entry) {
6399
+ let line = `[${entry.time}] ${entry.level.toUpperCase()} `;
6400
+ if (entry.scope) line += `[${entry.scope}] `;
6401
+ line += entry.message;
6402
+ if (entry.fields !== void 0) {
6403
+ const plain = Object.fromEntries(
6404
+ Object.entries(entry.fields).map(([k, v]) => [k, serializeFieldValue(v)])
6405
+ );
6406
+ try {
6407
+ line += ` ${JSON.stringify(plain)}`;
6408
+ } catch (err) {
6409
+ line += ` [unserializable fields: ${err instanceof Error ? err.message : String(err)}]`;
6410
+ }
6411
+ }
6412
+ return line;
6413
+ }
6414
+ var init_formatEntry = __esm({
6415
+ "src/logger/formatEntry.ts"() {
6416
+ "use strict";
6417
+ }
6418
+ });
6419
+
6420
+ // src/logger/fileSink.ts
6421
+ import fs17 from "fs";
6422
+ import path23 from "path";
6423
+ function createFileLogSink(options) {
6424
+ fs17.mkdirSync(options.dir, { recursive: true });
6425
+ const streams = /* @__PURE__ */ new Map();
6426
+ const getStream = (name) => {
6427
+ if (streams.has(name)) return streams.get(name);
6428
+ return void 0;
6429
+ };
6430
+ const openStream = (name) => {
6431
+ const stream = fs17.createWriteStream(path23.join(options.dir, `${name}.log`), { flags: "a" });
6432
+ stream.on("error", () => {
6433
+ });
6434
+ streams.set(name, stream);
6435
+ };
6436
+ const fileNames = options.splitByLevel ? [...LEVEL_FILES] : ["app", "error"];
6437
+ for (const name of fileNames) openStream(name);
6438
+ let pendingCount = 0;
6439
+ let drainWaiters = [];
6440
+ const onWriteDone = () => {
6441
+ pendingCount--;
6442
+ if (pendingCount === 0 && drainWaiters.length > 0) {
6443
+ const waiters = drainWaiters;
6444
+ drainWaiters = [];
6445
+ for (const waiter of waiters) waiter();
6446
+ }
6447
+ };
6448
+ const write = (entry) => {
6449
+ const line = `${formatEntry(entry)}
6450
+ `;
6451
+ const target = options.splitByLevel ? entry.level : "app";
6452
+ const main = getStream(target);
6453
+ if (main) {
6454
+ pendingCount++;
6455
+ main.write(line, onWriteDone);
6456
+ }
6457
+ if (!options.splitByLevel && entry.level === "error") {
6458
+ const dup = getStream("error");
6459
+ if (dup) {
6460
+ pendingCount++;
6461
+ dup.write(line, onWriteDone);
6462
+ }
6463
+ }
6464
+ };
6465
+ const flush = () => new Promise((resolve3) => {
6466
+ if (pendingCount === 0) {
6467
+ resolve3();
6468
+ return;
6469
+ }
6470
+ drainWaiters.push(resolve3);
6471
+ });
6472
+ const close = () => Promise.all(
6473
+ [...streams.values()].map(
6474
+ (stream) => new Promise((resolve3) => {
6475
+ stream.end(() => resolve3());
6476
+ })
6477
+ )
6478
+ ).then(() => {
6479
+ streams.clear();
6480
+ });
6481
+ return { write, flush, close };
6482
+ }
6483
+ var LEVEL_FILES;
6484
+ var init_fileSink = __esm({
6485
+ "src/logger/fileSink.ts"() {
6486
+ "use strict";
6487
+ init_formatEntry();
6488
+ LEVEL_FILES = ["debug", "info", "warn", "error"];
6489
+ }
6490
+ });
6491
+
6391
6492
  // src/logger/logger.ts
6392
6493
  function assertLogLevel(value, source) {
6393
6494
  if (typeof value !== "string" || !VALID_LEVELS.includes(value)) {
@@ -6397,15 +6498,18 @@ function assertLogLevel(value, source) {
6397
6498
  }
6398
6499
  }
6399
6500
  function configureLogging(config) {
6400
- if (config === void 0) {
6401
- globalState.level = null;
6402
- globalState.sink = null;
6403
- globalState.disabled = false;
6404
- return;
6405
- }
6406
6501
  const objectConfig = typeof config === "object" ? config : {};
6502
+ if (objectConfig.sink && objectConfig.dir) {
6503
+ throw new Error(
6504
+ "[faapi] config.log.sink and config.log.dir are mutually exclusive: pick one output pipeline (custom sink OR built-in file logs)."
6505
+ );
6506
+ }
6507
+ void globalState.fileSink?.close();
6407
6508
  globalState.disabled = config === false;
6408
6509
  globalState.sink = objectConfig.sink ?? null;
6510
+ globalState.accessLog = objectConfig.accessLog ?? objectConfig.dir !== void 0;
6511
+ globalState.stdout = objectConfig.stdout ?? true;
6512
+ globalState.fileSink = objectConfig.dir ? createFileLogSink({ dir: objectConfig.dir, splitByLevel: objectConfig.splitByLevel }) : null;
6409
6513
  if (objectConfig.level !== void 0) {
6410
6514
  assertLogLevel(objectConfig.level, "config.log.level");
6411
6515
  globalState.level = objectConfig.level;
@@ -6417,47 +6521,42 @@ function configureLogging(config) {
6417
6521
  }
6418
6522
  }
6419
6523
  function globalThreshold() {
6420
- return globalState.level ?? "info";
6524
+ if (globalState.level) return globalState.level;
6525
+ if (globalState.fileSink) return void 0;
6526
+ return "info";
6527
+ }
6528
+ function belowThreshold(level, threshold) {
6529
+ return threshold !== void 0 && LEVEL_RANK[level] < LEVEL_RANK[threshold];
6421
6530
  }
6422
6531
  function getEffectiveLogLevel() {
6423
6532
  return globalThreshold();
6424
6533
  }
6425
- function serializeFieldValue(value) {
6426
- if (value instanceof Error) {
6427
- return { name: value.name, message: value.message, stack: value.stack };
6428
- }
6429
- return value;
6430
- }
6431
- function formatEntry(entry) {
6432
- let line = `[${entry.time}] ${entry.level.toUpperCase()} `;
6433
- if (entry.scope) line += `[${entry.scope}] `;
6434
- line += entry.message;
6435
- if (entry.fields !== void 0) {
6436
- const plain = Object.fromEntries(
6437
- Object.entries(entry.fields).map(([k, v]) => [k, serializeFieldValue(v)])
6438
- );
6439
- try {
6440
- line += ` ${JSON.stringify(plain)}`;
6441
- } catch (err) {
6442
- line += ` [unserializable fields: ${err instanceof Error ? err.message : String(err)}]`;
6443
- }
6444
- }
6445
- return line;
6446
- }
6447
6534
  function globalDispatch(entry) {
6448
6535
  if (globalState.disabled) return;
6449
- (globalState.sink ?? consoleSink)(entry);
6536
+ if (globalState.sink) {
6537
+ globalState.sink(entry);
6538
+ return;
6539
+ }
6540
+ if (globalState.fileSink) {
6541
+ globalState.fileSink.write(entry);
6542
+ if (globalState.stdout) consoleSink(entry);
6543
+ return;
6544
+ }
6545
+ consoleSink(entry);
6450
6546
  }
6451
6547
  function writeLogEntry(entry) {
6452
- if (LEVEL_RANK[entry.level] < LEVEL_RANK[globalThreshold()]) return;
6548
+ if (belowThreshold(entry.level, globalThreshold())) return;
6453
6549
  globalDispatch(entry);
6454
6550
  }
6551
+ function isAccessLogPiped() {
6552
+ return !globalState.disabled && globalState.accessLog;
6553
+ }
6455
6554
  function createLogger(scope, options) {
6456
6555
  const baseScope = scope;
6457
6556
  const baseFields = options?.fields;
6458
6557
  const write = (level, message, callFields, scopeSuffix) => {
6459
6558
  const threshold = options?.level ?? globalThreshold();
6460
- if (LEVEL_RANK[level] < LEVEL_RANK[threshold]) return;
6559
+ if (belowThreshold(level, threshold)) return;
6461
6560
  const entry = {
6462
6561
  level,
6463
6562
  message,
@@ -6483,16 +6582,17 @@ function createLogger(scope, options) {
6483
6582
  });
6484
6583
  return makeLogger(void 0);
6485
6584
  }
6486
- var LEVEL_RANK, VALID_LEVELS, globalState, CONSOLE_METHOD, consoleSink;
6585
+ var LEVEL_RANK, VALID_LEVELS, globalState, consoleSink, CONSOLE_METHOD;
6487
6586
  var init_logger = __esm({
6488
6587
  "src/logger/logger.ts"() {
6489
6588
  "use strict";
6589
+ init_formatEntry();
6590
+ init_fileSink();
6490
6591
  LEVEL_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
6491
6592
  VALID_LEVELS = ["debug", "info", "warn", "error"];
6492
- globalState = {
6493
- level: null,
6494
- sink: null,
6495
- disabled: false
6593
+ globalState = { level: null, sink: null, fileSink: null, stdout: true, accessLog: false, disabled: false };
6594
+ consoleSink = (entry) => {
6595
+ console[CONSOLE_METHOD[entry.level]](formatEntry(entry));
6496
6596
  };
6497
6597
  CONSOLE_METHOD = {
6498
6598
  debug: "debug",
@@ -6500,9 +6600,6 @@ var init_logger = __esm({
6500
6600
  warn: "warn",
6501
6601
  error: "error"
6502
6602
  };
6503
- consoleSink = (entry) => {
6504
- console[CONSOLE_METHOD[entry.level]](formatEntry(entry));
6505
- };
6506
6603
  }
6507
6604
  });
6508
6605
 
@@ -7444,9 +7541,9 @@ async function validateInput(schemaPath, method, inputType, input) {
7444
7541
  function mapZodIssues(error) {
7445
7542
  return error.issues.map((issue) => {
7446
7543
  const code = mapZodCode(issue);
7447
- const path31 = issue.path.map(String).join(".") || "";
7544
+ const path32 = issue.path.map(String).join(".") || "";
7448
7545
  return {
7449
- path: path31,
7546
+ path: path32,
7450
7547
  code,
7451
7548
  expected: issue.expected ?? mapExpectedFromMessage(issue.message),
7452
7549
  received: issue.received ?? mapReceivedFromMessage(issue.message),
@@ -7844,9 +7941,28 @@ var init_etag = __esm({
7844
7941
  });
7845
7942
 
7846
7943
  // src/middleware/logger.ts
7944
+ function levelForStatus(status) {
7945
+ if (status >= 500) return "error";
7946
+ if (status >= 400) return "warn";
7947
+ return "info";
7948
+ }
7949
+ function defaultLog(entry, text) {
7950
+ if (isAccessLogPiped()) {
7951
+ const logEntry = {
7952
+ level: levelForStatus(entry.status),
7953
+ message: text,
7954
+ time: (/* @__PURE__ */ new Date()).toISOString(),
7955
+ scope: "access",
7956
+ fields: entry
7957
+ };
7958
+ writeLogEntry(logEntry);
7959
+ return;
7960
+ }
7961
+ console.log(entry);
7962
+ }
7847
7963
  function logger(options = {}) {
7848
7964
  return async (ctx, next) => {
7849
- const log = options.log ?? console.log;
7965
+ const log = options.log ?? defaultLog;
7850
7966
  const start = Date.now();
7851
7967
  try {
7852
7968
  const response = await next();
@@ -7880,6 +7996,7 @@ function logger(options = {}) {
7880
7996
  var init_logger2 = __esm({
7881
7997
  "src/middleware/logger.ts"() {
7882
7998
  "use strict";
7999
+ init_logger();
7883
8000
  }
7884
8001
  });
7885
8002
 
@@ -7946,9 +8063,9 @@ var init_wsHandler = __esm({
7946
8063
  });
7947
8064
 
7948
8065
  // src/server/handleWsUpgrade.ts
7949
- import fs17 from "fs";
8066
+ import fs18 from "fs";
7950
8067
  import { WebSocketServer, WebSocket } from "ws";
7951
- import path23 from "path";
8068
+ import path24 from "path";
7952
8069
  function getPathname(req) {
7953
8070
  const url = req.url ?? "/";
7954
8071
  const idx = url.indexOf("?");
@@ -7959,7 +8076,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
7959
8076
  const dist = getDevDist();
7960
8077
  if (dist) {
7961
8078
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
7962
- if (sourcePath && fs17.existsSync(sourcePath)) {
8079
+ if (sourcePath && fs18.existsSync(sourcePath)) {
7963
8080
  await ensureCompiled(sourcePath, rootDir, dist);
7964
8081
  }
7965
8082
  }
@@ -8073,7 +8190,7 @@ function attachWebSocket(options) {
8073
8190
  const finalHandler = async () => {
8074
8191
  let handlers;
8075
8192
  try {
8076
- const absoluteFilePath = path23.resolve(rootDir, route.filePath);
8193
+ const absoluteFilePath = path24.resolve(rootDir, route.filePath);
8077
8194
  handlers = await loadWsHandler(absoluteFilePath, ctx, rootDir);
8078
8195
  } catch (err) {
8079
8196
  const reason = err instanceof Error ? err.message : String(err);
@@ -8149,7 +8266,7 @@ import {
8149
8266
  import { createSecureServer as createHttp2SecureServer } from "http2";
8150
8267
  import { readFileSync } from "fs";
8151
8268
  import { Readable as Readable3 } from "stream";
8152
- import path24 from "path";
8269
+ import path25 from "path";
8153
8270
  function toWebRequest(req, bodyLimit = DEFAULT_BODY_LIMIT, requestSignal) {
8154
8271
  const forwardedProto = req.headers["x-forwarded-proto"];
8155
8272
  const protocol = Array.isArray(forwardedProto) ? forwardedProto[0]?.split(",")[0]?.trim() ?? "http" : forwardedProto?.split(",")[0]?.trim() ?? "http";
@@ -8345,7 +8462,7 @@ function getRoutePaths(route, rootDir, dist) {
8345
8462
  let cached = routePathCache.get(route);
8346
8463
  if (!cached) {
8347
8464
  cached = {
8348
- absFilePath: path24.resolve(rootDir, route.filePath),
8465
+ absFilePath: path25.resolve(rootDir, route.filePath),
8349
8466
  schemaPath: getRuntimeSchemaPath(route.filePath, dist, rootDir)
8350
8467
  };
8351
8468
  routePathCache.set(route, cached);
@@ -8775,7 +8892,7 @@ var LOG_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
8775
8892
  function createTaskLogger(level, scope, fields) {
8776
8893
  function make(suffix) {
8777
8894
  function write(lvl, message, callFields) {
8778
- if (LOG_RANK[lvl] < LOG_RANK[level]) return;
8895
+ if (level !== undefined && LOG_RANK[lvl] < LOG_RANK[level]) return;
8779
8896
  var entry = { level: lvl, message: message, time: new Date().toISOString() };
8780
8897
  var fullScope = suffix === undefined ? scope : scope === undefined ? suffix : scope + ':' + suffix;
8781
8898
  if (fullScope !== undefined) entry.scope = fullScope;
@@ -8804,7 +8921,7 @@ function createTaskLogger(level, scope, fields) {
8804
8921
  });
8805
8922
 
8806
8923
  // src/task/taskQueue.ts
8807
- import path25 from "path";
8924
+ import path26 from "path";
8808
8925
  function createTaskQueue(deps) {
8809
8926
  const { registry, rootDir, driver } = deps;
8810
8927
  const registriesView = deps.registries ?? createEmptyTaskRegistriesView();
@@ -8834,7 +8951,7 @@ function createTaskQueue(deps) {
8834
8951
  }
8835
8952
  const loadTaskModule = deps.loadTaskModule ?? (async (filePath) => await import(filePath));
8836
8953
  const loadPayloadSchema = deps.loadPayloadSchema ?? (async (filePath) => {
8837
- const zodPath = path25.join(path25.dirname(filePath), "zod.js");
8954
+ const zodPath = path26.join(path26.dirname(filePath), "zod.js");
8838
8955
  try {
8839
8956
  const mod = await import(zodPath);
8840
8957
  const schemaKey = Object.keys(mod).find((k) => k.endsWith("Schema"));
@@ -8862,7 +8979,7 @@ function createTaskQueue(deps) {
8862
8979
  const meta = registry.get(name);
8863
8980
  schemaCache.set(
8864
8981
  name,
8865
- await loadPayloadSchema(path25.resolve(rootDir, meta.filePath)).catch(() => void 0)
8982
+ await loadPayloadSchema(path26.resolve(rootDir, meta.filePath)).catch(() => void 0)
8866
8983
  );
8867
8984
  }
8868
8985
  const schema = schemaCache.get(name);
@@ -8898,7 +9015,7 @@ function createTaskQueue(deps) {
8898
9015
  let result;
8899
9016
  if (meta.timeoutMs !== void 0 && meta.timeoutMs > 0) {
8900
9017
  result = await (deps.runIsolated ?? runTaskInWorker)({
8901
- taskModulePath: path25.resolve(rootDir, meta.filePath),
9018
+ taskModulePath: path26.resolve(rootDir, meta.filePath),
8902
9019
  payload: job.payload,
8903
9020
  taskCtx: {
8904
9021
  config: deps.config,
@@ -8923,7 +9040,7 @@ function createTaskQueue(deps) {
8923
9040
  } else {
8924
9041
  let mod = moduleCache2.get(job.name);
8925
9042
  if (!mod) {
8926
- mod = await loadTaskModule(path25.resolve(rootDir, meta.filePath));
9043
+ mod = await loadTaskModule(path26.resolve(rootDir, meta.filePath));
8927
9044
  moduleCache2.set(job.name, mod);
8928
9045
  }
8929
9046
  if (typeof mod.run !== "function") {
@@ -9205,8 +9322,8 @@ var init_cronScheduler = __esm({
9205
9322
  });
9206
9323
 
9207
9324
  // src/cli/loadPlugins.ts
9208
- import path26 from "path";
9209
- import fs18 from "fs";
9325
+ import path27 from "path";
9326
+ import fs19 from "fs";
9210
9327
  import { pathToFileURL as pathToFileURL3 } from "url";
9211
9328
  async function loadPlugins(declarations, ctx, rootDir, dist) {
9212
9329
  const handlerWrappers = [];
@@ -9269,37 +9386,37 @@ async function loadPlugins(declarations, ctx, rootDir, dist) {
9269
9386
  return { handlerWrappers, upgradeWrappers, failures };
9270
9387
  }
9271
9388
  function resolveLocalPluginSource(specifier, baseDir) {
9272
- const base = path26.isAbsolute(specifier) ? specifier : path26.resolve(baseDir, specifier);
9273
- if ((TS_EXTS.test(base) || JS_EXTS.test(base)) && fs18.existsSync(base)) return base;
9389
+ const base = path27.isAbsolute(specifier) ? specifier : path27.resolve(baseDir, specifier);
9390
+ if ((TS_EXTS.test(base) || JS_EXTS.test(base)) && fs19.existsSync(base)) return base;
9274
9391
  for (const ext of [".ts", ".js"]) {
9275
- if (fs18.existsSync(base + ext)) return base + ext;
9392
+ if (fs19.existsSync(base + ext)) return base + ext;
9276
9393
  }
9277
9394
  for (const indexExt of ["/index.ts", "/index.js"]) {
9278
- if (fs18.existsSync(base + indexExt)) return base + indexExt;
9395
+ if (fs19.existsSync(base + indexExt)) return base + indexExt;
9279
9396
  }
9280
9397
  return null;
9281
9398
  }
9282
9399
  function mirrorProductPath(sourcePath, baseDir, distDir) {
9283
- let rel = path26.relative(baseDir, sourcePath).replace(/\\/g, "/");
9400
+ let rel = path27.relative(baseDir, sourcePath).replace(/\\/g, "/");
9284
9401
  if (rel.startsWith("src/")) rel = rel.slice(4);
9285
- return path26.resolve(distDir, rel.replace(TS_EXTS, ".js"));
9402
+ return path27.resolve(distDir, rel.replace(TS_EXTS, ".js"));
9286
9403
  }
9287
9404
  function isSourceNewer(sourcePath, productPath) {
9288
9405
  try {
9289
- return fs18.statSync(sourcePath).mtimeMs > fs18.statSync(productPath).mtimeMs;
9406
+ return fs19.statSync(sourcePath).mtimeMs > fs19.statSync(productPath).mtimeMs;
9290
9407
  } catch {
9291
9408
  return true;
9292
9409
  }
9293
9410
  }
9294
9411
  async function importPluginModule(specifier, baseDir, dist) {
9295
9412
  const isRelative = specifier.startsWith("./") || specifier.startsWith("../");
9296
- if (!isRelative && !path26.isAbsolute(specifier)) {
9413
+ if (!isRelative && !path27.isAbsolute(specifier)) {
9297
9414
  return import(specifier);
9298
9415
  }
9299
- const distDir = dist ? path26.resolve(baseDir, dist) : null;
9416
+ const distDir = dist ? path27.resolve(baseDir, dist) : null;
9300
9417
  const sourcePath = resolveLocalPluginSource(specifier, baseDir);
9301
9418
  const productPath = sourcePath && distDir ? mirrorProductPath(sourcePath, baseDir, distDir) : null;
9302
- if (productPath !== null && fs18.existsSync(productPath) && (sourcePath === null || !isSourceNewer(sourcePath, productPath))) {
9419
+ if (productPath !== null && fs19.existsSync(productPath) && (sourcePath === null || !isSourceNewer(sourcePath, productPath))) {
9303
9420
  return import(pathToFileURL3(productPath).href);
9304
9421
  }
9305
9422
  if (sourcePath && TS_EXTS.test(sourcePath)) {
@@ -9308,13 +9425,13 @@ async function importPluginModule(specifier, baseDir, dist) {
9308
9425
  `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.`
9309
9426
  );
9310
9427
  }
9311
- const relFromRoot = path26.relative(baseDir, sourcePath).replace(/\\/g, "/");
9428
+ const relFromRoot = path27.relative(baseDir, sourcePath).replace(/\\/g, "/");
9312
9429
  if (relFromRoot.startsWith("src/")) {
9313
9430
  await ensureCompiled(sourcePath, baseDir, dist);
9314
9431
  } else {
9315
9432
  await compileProjectModules([sourcePath], baseDir, dist);
9316
9433
  }
9317
- if (productPath && fs18.existsSync(productPath)) {
9434
+ if (productPath && fs19.existsSync(productPath)) {
9318
9435
  return import(pathToFileURL3(productPath).href);
9319
9436
  }
9320
9437
  }
@@ -9326,7 +9443,7 @@ async function importPluginModule(specifier, baseDir, dist) {
9326
9443
  `${specifier}/index.ts`,
9327
9444
  `${specifier}.js`,
9328
9445
  `${specifier}/index.js`
9329
- ].map((c) => path26.isAbsolute(c) ? c : path26.join(baseDir, c));
9446
+ ].map((c) => path27.isAbsolute(c) ? c : path27.join(baseDir, c));
9330
9447
  throw new Error(
9331
9448
  `Cannot find local plugin "${specifier}" (resolved from ${baseDir}). Expected one of:
9332
9449
  ${candidates.join("\n ")}
@@ -9361,12 +9478,12 @@ var init_loadPlugins = __esm({
9361
9478
  });
9362
9479
 
9363
9480
  // src/cli/createAppCore.ts
9364
- import fs19 from "fs";
9365
- import path27 from "path";
9481
+ import fs20 from "fs";
9482
+ import path28 from "path";
9366
9483
  import { PassThrough, Readable as Readable4 } from "stream";
9367
9484
  async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries) {
9368
- const toolsPath = path27.resolve(rootDir, dist, TOOLS_FILE2);
9369
- if (!fs19.existsSync(toolsPath)) {
9485
+ const toolsPath = path28.resolve(rootDir, dist, TOOLS_FILE2);
9486
+ if (!fs20.existsSync(toolsPath)) {
9370
9487
  return [];
9371
9488
  }
9372
9489
  const serialized = await importWithCacheBust(toolsPath);
@@ -9375,8 +9492,8 @@ async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries
9375
9492
  return hydrated;
9376
9493
  }
9377
9494
  async function loadAndHydrateAgents(rootDir, dist, registries = defaultRegistries) {
9378
- const agentsPath = path27.resolve(rootDir, dist, AGENTS_FILE2);
9379
- if (!fs19.existsSync(agentsPath)) {
9495
+ const agentsPath = path28.resolve(rootDir, dist, AGENTS_FILE2);
9496
+ if (!fs20.existsSync(agentsPath)) {
9380
9497
  return [];
9381
9498
  }
9382
9499
  const serialized = await importWithCacheBust(agentsPath);
@@ -9391,8 +9508,8 @@ function getTaskDriverOptions(config) {
9391
9508
  return void 0;
9392
9509
  }
9393
9510
  async function loadAndHydrateTasks(rootDir, dist, registries = defaultRegistries) {
9394
- const tasksPath = path27.resolve(rootDir, dist, TASKS_FILE);
9395
- if (!fs19.existsSync(tasksPath)) {
9511
+ const tasksPath = path28.resolve(rootDir, dist, TASKS_FILE);
9512
+ if (!fs20.existsSync(tasksPath)) {
9396
9513
  return [];
9397
9514
  }
9398
9515
  const serialized = await importWithCacheBust(tasksPath);
@@ -9432,8 +9549,8 @@ function isFaapiConfigKey(key) {
9432
9549
  async function createAppBase(options) {
9433
9550
  const rootDir = options?.rootDir ?? process.cwd();
9434
9551
  const dist = options?.dist ?? process.env.FAAPI_DIST ?? DEFAULT_DIST;
9435
- const routesPath = path27.resolve(rootDir, dist, ROUTES_FILE);
9436
- if (!fs19.existsSync(routesPath)) {
9552
+ const routesPath = path28.resolve(rootDir, dist, ROUTES_FILE);
9553
+ if (!fs20.existsSync(routesPath)) {
9437
9554
  throw new Error(
9438
9555
  `[faapi] ${dist}/${ROUTES_FILE} \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6267\u884C \`faapi build\`\uFF08\u6216 \`faapi dev\`\uFF09\u751F\u6210\u4EA7\u7269\u3002`
9439
9556
  );
@@ -9810,7 +9927,7 @@ var init_createAppCore = __esm({
9810
9927
  });
9811
9928
 
9812
9929
  // src/cli/createDevApp.ts
9813
- import path28 from "path";
9930
+ import path29 from "path";
9814
9931
  async function createDevApp(options) {
9815
9932
  const { app, ctx } = await createAppBase(options);
9816
9933
  const devApp = app;
@@ -9860,7 +9977,7 @@ async function createDevApp(options) {
9860
9977
  invalidateProgramCache();
9861
9978
  const tasks = await scanTasks(ctx.rootDir, TASK_PATTERNS);
9862
9979
  for (const task of tasks) {
9863
- await ensureCompiled(path28.resolve(ctx.rootDir, task.filePath), ctx.rootDir, ctx.dist);
9980
+ await ensureCompiled(path29.resolve(ctx.rootDir, task.filePath), ctx.rootDir, ctx.dist);
9864
9981
  }
9865
9982
  await generateTaskArtifacts(tasks, ctx.rootDir, ctx.dist);
9866
9983
  ctx.taskQueue.invalidateModules();
@@ -9902,7 +10019,7 @@ __export(devCommand_exports, {
9902
10019
  generateTaskArtifactsForDev: () => generateTaskArtifactsForDev,
9903
10020
  generateToolArtifactsForDev: () => generateToolArtifactsForDev
9904
10021
  });
9905
- import path29 from "path";
10022
+ import path30 from "path";
9906
10023
  async function devCommand(options) {
9907
10024
  const rootDir = process.cwd();
9908
10025
  if (!process.env.NODE_ENV) process.env.NODE_ENV = "development";
@@ -9931,7 +10048,7 @@ async function devCommand(options) {
9931
10048
  async function generateRouteArtifacts(rootDir, patterns, dist) {
9932
10049
  const { routes, wsRoutes } = await scanRoutes(rootDir, patterns, dist);
9933
10050
  const sorted = sortRoutes(routes);
9934
- const routesPath = path29.resolve(rootDir, dist, ROUTES_FILE2);
10051
+ const routesPath = path30.resolve(rootDir, dist, ROUTES_FILE2);
9935
10052
  const serialized = serializeRoutes(sorted, wsRoutes, rootDir, dist);
9936
10053
  await writeRoutesModule(serialized, routesPath);
9937
10054
  }
@@ -9946,7 +10063,7 @@ async function generateAgentArtifactsForDev(rootDir, dist) {
9946
10063
  async function generateTaskArtifactsForDev(rootDir, dist) {
9947
10064
  const tasks = await scanTasks(rootDir, TASK_PATTERNS);
9948
10065
  for (const task of tasks) {
9949
- await ensureCompiled(path29.resolve(rootDir, task.filePath), rootDir, dist);
10066
+ await ensureCompiled(path30.resolve(rootDir, task.filePath), rootDir, dist);
9950
10067
  }
9951
10068
  await generateTaskArtifacts(tasks, rootDir, dist);
9952
10069
  }
@@ -9994,15 +10111,15 @@ var buildCommand_exports = {};
9994
10111
  __export(buildCommand_exports, {
9995
10112
  buildCommand: () => buildCommand
9996
10113
  });
9997
- import path30 from "path";
9998
- import fs20 from "fs";
10114
+ import path31 from "path";
10115
+ import fs21 from "fs";
9999
10116
  async function buildCommand(options) {
10000
10117
  const rootDir = options?.rootDir ?? process.cwd();
10001
10118
  const outdir = options?.dist ?? DEFAULT_DIST2;
10002
- const absOut = path30.resolve(rootDir, outdir);
10003
- const realRoot = toRealPath(path30.resolve(rootDir));
10119
+ const absOut = path31.resolve(rootDir, outdir);
10120
+ const realRoot = toRealPath(path31.resolve(rootDir));
10004
10121
  if (isInsideDir(toRealPath(absOut), realRoot)) {
10005
- fs20.rmSync(absOut, { recursive: true, force: true });
10122
+ fs21.rmSync(absOut, { recursive: true, force: true });
10006
10123
  } else {
10007
10124
  console.warn(
10008
10125
  `! Output directory "${outdir}" is outside the project root, skipping clean (stale artifacts may remain)`
@@ -10010,10 +10127,10 @@ async function buildCommand(options) {
10010
10127
  }
10011
10128
  await compileConfig({ rootDir, dist: outdir });
10012
10129
  const _config = await loadConfig(rootDir, outdir);
10013
- const pkgPath = path30.resolve(rootDir, "package.json");
10014
- if (fs20.existsSync(pkgPath)) {
10130
+ const pkgPath = path31.resolve(rootDir, "package.json");
10131
+ if (fs21.existsSync(pkgPath)) {
10015
10132
  try {
10016
- const pkg = JSON.parse(fs20.readFileSync(pkgPath, "utf-8"));
10133
+ const pkg = JSON.parse(fs21.readFileSync(pkgPath, "utf-8"));
10017
10134
  if (pkg.type !== "module") {
10018
10135
  console.warn(
10019
10136
  '! package.json is missing "type": "module" \u2014 build output is ESM and `node dist/main` will fail without it'
@@ -10041,7 +10158,7 @@ async function buildCommand(options) {
10041
10158
  if (localPluginSources.length > 0) {
10042
10159
  console.log("\n[2.5/8] Compiling local plugins...");
10043
10160
  const outside = localPluginSources.filter((p) => {
10044
- const rel = path30.relative(rootDir, p).replace(/\\/g, "/");
10161
+ const rel = path31.relative(rootDir, p).replace(/\\/g, "/");
10045
10162
  return !rel.startsWith("src/");
10046
10163
  });
10047
10164
  if (outside.length > 0) {
@@ -10065,9 +10182,9 @@ async function buildCommand(options) {
10065
10182
  }
10066
10183
  console.log("\n[4/8] Generating schema...");
10067
10184
  await generateSchemaFiles(sorted, rootDir, outdir);
10068
- console.log(` Schema: zod.js files under ${path30.resolve(rootDir, outdir)}`);
10185
+ console.log(` Schema: zod.js files under ${path31.resolve(rootDir, outdir)}`);
10069
10186
  console.log("\n[5/8] Generating routes manifest...");
10070
- const routesPath = path30.resolve(rootDir, outdir, "faapi-routes.js");
10187
+ const routesPath = path31.resolve(rootDir, outdir, "faapi-routes.js");
10071
10188
  const serialized = serializeRoutes(sorted, wsRoutes, rootDir, outdir);
10072
10189
  await writeRoutesModule(serialized, routesPath);
10073
10190
  console.log(` Written to ${routesPath}`);
@@ -10075,19 +10192,19 @@ async function buildCommand(options) {
10075
10192
  const tools = await scanTools(rootDir, TOOL_PATTERNS);
10076
10193
  const toolMeta = await generateToolArtifacts(tools, rootDir, outdir);
10077
10194
  console.log(` Found ${toolMeta.length} tool(s)`);
10078
- console.log(` Tool manifest: ${path30.resolve(rootDir, outdir, "faapi-tools.js")}`);
10195
+ console.log(` Tool manifest: ${path31.resolve(rootDir, outdir, "faapi-tools.js")}`);
10079
10196
  console.log("\n[7/8] Generating agent manifest...");
10080
10197
  const agents = await scanAgents(rootDir, DEFAULT_AGENT_PATTERNS);
10081
10198
  const agentMeta = await generateAgentArtifacts(agents, rootDir, outdir);
10082
10199
  console.log(` Found ${agentMeta.length} agent(s)`);
10083
- console.log(` Agent manifest: ${path30.resolve(rootDir, outdir, "faapi-agents.js")}`);
10200
+ console.log(` Agent manifest: ${path31.resolve(rootDir, outdir, "faapi-agents.js")}`);
10084
10201
  console.log("\n[7.5/8] Generating task manifest and schema...");
10085
10202
  const tasks = await scanTasks(rootDir, TASK_PATTERNS);
10086
10203
  const taskMeta = await generateTaskArtifacts(tasks, rootDir, outdir);
10087
10204
  console.log(` Found ${taskMeta.length} task(s)`);
10088
- console.log(` Task manifest: ${path30.resolve(rootDir, outdir, "faapi-tasks.js")}`);
10205
+ console.log(` Task manifest: ${path31.resolve(rootDir, outdir, "faapi-tasks.js")}`);
10089
10206
  console.log("\n[8/8] Generating entry file...");
10090
- const mainPath = path30.resolve(rootDir, outdir, "main.js");
10207
+ const mainPath = path31.resolve(rootDir, outdir, "main.js");
10091
10208
  const createProdAppArgs = options?.dist && options.dist !== DEFAULT_DIST2 ? `{ dist: ${JSON.stringify(outdir)} }` : "";
10092
10209
  const mainContent = `// \u7531 faapi build \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u52A8\u7F16\u8F91
10093
10210
  import { createProdApp, loadEnv } from '@faapi/faapi';
@@ -10099,7 +10216,7 @@ loadEnv(process.cwd());
10099
10216
  const app = await createProdApp(${createProdAppArgs});
10100
10217
  await app.listen();
10101
10218
  `;
10102
- await fs20.promises.writeFile(mainPath, mainContent, "utf-8");
10219
+ await fs21.promises.writeFile(mainPath, mainContent, "utf-8");
10103
10220
  console.log(` Written to ${mainPath}`);
10104
10221
  console.log("\nfaapi build completed");
10105
10222
  }
@@ -10113,7 +10230,7 @@ function extractLocalPluginSources(declarations, rootDir) {
10113
10230
  else if (Array.isArray(decl)) specifier = decl[0];
10114
10231
  else if ("path" in decl) specifier = decl.path;
10115
10232
  if (!specifier) continue;
10116
- if (!specifier.startsWith("./") && !specifier.startsWith("../") && !path30.isAbsolute(specifier)) {
10233
+ if (!specifier.startsWith("./") && !specifier.startsWith("../") && !path31.isAbsolute(specifier)) {
10117
10234
  continue;
10118
10235
  }
10119
10236
  const source = resolveLocalPluginSource(specifier, rootDir);