@faapi/faapi 6.24.0 → 6.26.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(path34) {
653
- if (!path34) return "";
654
- let result = path34.replace(/\\/g, "/");
652
+ function normalizePath(path35) {
653
+ if (!path35) return "";
654
+ let result = path35.replace(/\\/g, "/");
655
655
  result = result.replace(/\/+/g, "/");
656
656
  result = result.replace(/\/+$/, "");
657
657
  if (result && !result.startsWith("/")) {
@@ -3536,6 +3536,11 @@ async function scanTasks(rootDir, patterns) {
3536
3536
  `[faapi] Task "${name}" timeoutMs ${value} is below the minimum ${MIN_ISOLATED_TIMEOUT_MS}ms (1 minute). Declaring a timeout means this is a long-running task that needs real cancellation \u2014 tasks finishing within a minute do not need one: remove timeoutMs to run in-process (implement your own deadline with Promise.race if needed), or raise it.`
3537
3537
  );
3538
3538
  }
3539
+ if (value > MAX_ISOLATED_TIMEOUT_MS) {
3540
+ throw new Error(
3541
+ `[faapi] Task "${name}" timeoutMs ${value} exceeds the maximum ${MAX_ISOLATED_TIMEOUT_MS}ms (23 hours). The pg-boss driver budgets expire_in from timeoutMs (execution budget preventing mid-run re-delivery), and pg-boss versions before 12.28 assert expire_in strictly below 24h \u2014 the 23h cap keeps every driver and pg-boss version on a single bound. Split the work into a resumable pipeline (persist progress, enqueue the next stage), or use the bullmq driver (Redis has no such cap).`
3542
+ );
3543
+ }
3539
3544
  manifest.timeoutMs = value;
3540
3545
  }
3541
3546
  if (graceMs !== void 0) manifest.graceMs = parseNumericLiteral(graceMs);
@@ -3543,7 +3548,7 @@ async function scanTasks(rootDir, patterns) {
3543
3548
  }
3544
3549
  return tasks.sort((a, b) => a.name.localeCompare(b.name));
3545
3550
  }
3546
- var TASK_PATTERNS, TASK_FILENAME, CRON_RE, NUM_LITERAL, CONCURRENCY_RE, RETRIES_RE, TIMEOUT_MS_RE, GRACE_MS_RE, MIN_ISOLATED_TIMEOUT_MS;
3551
+ var TASK_PATTERNS, TASK_FILENAME, CRON_RE, NUM_LITERAL, CONCURRENCY_RE, RETRIES_RE, TIMEOUT_MS_RE, GRACE_MS_RE, MIN_ISOLATED_TIMEOUT_MS, MAX_ISOLATED_TIMEOUT_MS;
3547
3552
  var init_scanTasks = __esm({
3548
3553
  "src/task/scanTasks.ts"() {
3549
3554
  "use strict";
@@ -3556,6 +3561,7 @@ var init_scanTasks = __esm({
3556
3561
  TIMEOUT_MS_RE = new RegExp(`(?:^|\\n)\\s*timeoutMs:\\s*${NUM_LITERAL}`);
3557
3562
  GRACE_MS_RE = new RegExp(`(?:^|\\n)\\s*graceMs:\\s*${NUM_LITERAL}`);
3558
3563
  MIN_ISOLATED_TIMEOUT_MS = 6e4;
3564
+ MAX_ISOLATED_TIMEOUT_MS = 23 * 60 * 6e4;
3559
3565
  }
3560
3566
  });
3561
3567
 
@@ -4158,7 +4164,7 @@ var init_esm = __esm({
4158
4164
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
4159
4165
  const statMethod = opts.lstat ? lstat : stat;
4160
4166
  if (wantBigintFsStats) {
4161
- this._stat = (path34) => statMethod(path34, { bigint: true });
4167
+ this._stat = (path35) => statMethod(path35, { bigint: true });
4162
4168
  } else {
4163
4169
  this._stat = statMethod;
4164
4170
  }
@@ -4183,8 +4189,8 @@ var init_esm = __esm({
4183
4189
  const par = this.parent;
4184
4190
  const fil = par && par.files;
4185
4191
  if (fil && fil.length > 0) {
4186
- const { path: path34, depth } = par;
4187
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path34));
4192
+ const { path: path35, depth } = par;
4193
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path35));
4188
4194
  const awaited = await Promise.all(slice);
4189
4195
  for (const entry of awaited) {
4190
4196
  if (!entry)
@@ -4224,20 +4230,20 @@ var init_esm = __esm({
4224
4230
  this.reading = false;
4225
4231
  }
4226
4232
  }
4227
- async _exploreDir(path34, depth) {
4233
+ async _exploreDir(path35, depth) {
4228
4234
  let files;
4229
4235
  try {
4230
- files = await readdir(path34, this._rdOptions);
4236
+ files = await readdir(path35, this._rdOptions);
4231
4237
  } catch (error) {
4232
4238
  this._onError(error);
4233
4239
  }
4234
- return { files, depth, path: path34 };
4240
+ return { files, depth, path: path35 };
4235
4241
  }
4236
- async _formatEntry(dirent, path34) {
4242
+ async _formatEntry(dirent, path35) {
4237
4243
  let entry;
4238
4244
  const basename3 = this._isDirent ? dirent.name : dirent;
4239
4245
  try {
4240
- const fullPath = presolve(pjoin(path34, basename3));
4246
+ const fullPath = presolve(pjoin(path35, basename3));
4241
4247
  entry = { path: prelative(this._root, fullPath), fullPath, basename: basename3 };
4242
4248
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
4243
4249
  } catch (err) {
@@ -4298,16 +4304,16 @@ import { watchFile, unwatchFile, watch as fs_watch } from "fs";
4298
4304
  import { open, stat as stat2, lstat as lstat2, realpath as fsrealpath } from "fs/promises";
4299
4305
  import * as sysPath from "path";
4300
4306
  import { type as osType } from "os";
4301
- function createFsWatchInstance(path34, options, listener, errHandler, emitRaw) {
4307
+ function createFsWatchInstance(path35, options, listener, errHandler, emitRaw) {
4302
4308
  const handleEvent = (rawEvent, evPath) => {
4303
- listener(path34);
4304
- emitRaw(rawEvent, evPath, { watchedPath: path34 });
4305
- if (evPath && path34 !== evPath) {
4306
- fsWatchBroadcast(sysPath.resolve(path34, evPath), KEY_LISTENERS, sysPath.join(path34, evPath));
4309
+ listener(path35);
4310
+ emitRaw(rawEvent, evPath, { watchedPath: path35 });
4311
+ if (evPath && path35 !== evPath) {
4312
+ fsWatchBroadcast(sysPath.resolve(path35, evPath), KEY_LISTENERS, sysPath.join(path35, evPath));
4307
4313
  }
4308
4314
  };
4309
4315
  try {
4310
- return fs_watch(path34, {
4316
+ return fs_watch(path35, {
4311
4317
  persistent: options.persistent
4312
4318
  }, handleEvent);
4313
4319
  } catch (error) {
@@ -4652,12 +4658,12 @@ var init_handler = __esm({
4652
4658
  listener(val1, val2, val3);
4653
4659
  });
4654
4660
  };
4655
- setFsWatchListener = (path34, fullPath, options, handlers) => {
4661
+ setFsWatchListener = (path35, fullPath, options, handlers) => {
4656
4662
  const { listener, errHandler, rawEmitter } = handlers;
4657
4663
  let cont = FsWatchInstances.get(fullPath);
4658
4664
  let watcher;
4659
4665
  if (!options.persistent) {
4660
- watcher = createFsWatchInstance(path34, options, listener, errHandler, rawEmitter);
4666
+ watcher = createFsWatchInstance(path35, options, listener, errHandler, rawEmitter);
4661
4667
  if (!watcher)
4662
4668
  return;
4663
4669
  return watcher.close.bind(watcher);
@@ -4668,7 +4674,7 @@ var init_handler = __esm({
4668
4674
  addAndConvert(cont, KEY_RAW, rawEmitter);
4669
4675
  } else {
4670
4676
  watcher = createFsWatchInstance(
4671
- path34,
4677
+ path35,
4672
4678
  options,
4673
4679
  fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
4674
4680
  errHandler,
@@ -4683,7 +4689,7 @@ var init_handler = __esm({
4683
4689
  cont.watcherUnusable = true;
4684
4690
  if (isWindows && error.code === "EPERM") {
4685
4691
  try {
4686
- const fd = await open(path34, "r");
4692
+ const fd = await open(path35, "r");
4687
4693
  await fd.close();
4688
4694
  broadcastErr(error);
4689
4695
  } catch (err) {
@@ -4714,7 +4720,7 @@ var init_handler = __esm({
4714
4720
  };
4715
4721
  };
4716
4722
  FsWatchFileInstances = /* @__PURE__ */ new Map();
4717
- setFsWatchFileListener = (path34, fullPath, options, handlers) => {
4723
+ setFsWatchFileListener = (path35, fullPath, options, handlers) => {
4718
4724
  const { listener, rawEmitter } = handlers;
4719
4725
  let cont = FsWatchFileInstances.get(fullPath);
4720
4726
  const copts = cont && cont.options;
@@ -4736,7 +4742,7 @@ var init_handler = __esm({
4736
4742
  });
4737
4743
  const currmtime = curr.mtimeMs;
4738
4744
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
4739
- foreach(cont.listeners, (listener2) => listener2(path34, curr));
4745
+ foreach(cont.listeners, (listener2) => listener2(path35, curr));
4740
4746
  }
4741
4747
  })
4742
4748
  };
@@ -4764,13 +4770,13 @@ var init_handler = __esm({
4764
4770
  * @param listener on fs change
4765
4771
  * @returns closer for the watcher instance
4766
4772
  */
4767
- _watchWithNodeFs(path34, listener) {
4773
+ _watchWithNodeFs(path35, listener) {
4768
4774
  const opts = this.fsw.options;
4769
- const directory = sysPath.dirname(path34);
4770
- const basename3 = sysPath.basename(path34);
4775
+ const directory = sysPath.dirname(path35);
4776
+ const basename3 = sysPath.basename(path35);
4771
4777
  const parent = this.fsw._getWatchedDir(directory);
4772
4778
  parent.add(basename3);
4773
- const absolutePath = sysPath.resolve(path34);
4779
+ const absolutePath = sysPath.resolve(path35);
4774
4780
  const options = {
4775
4781
  persistent: opts.persistent
4776
4782
  };
@@ -4780,12 +4786,12 @@ var init_handler = __esm({
4780
4786
  if (opts.usePolling) {
4781
4787
  const enableBin = opts.interval !== opts.binaryInterval;
4782
4788
  options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
4783
- closer = setFsWatchFileListener(path34, absolutePath, options, {
4789
+ closer = setFsWatchFileListener(path35, absolutePath, options, {
4784
4790
  listener,
4785
4791
  rawEmitter: this.fsw._emitRaw
4786
4792
  });
4787
4793
  } else {
4788
- closer = setFsWatchListener(path34, absolutePath, options, {
4794
+ closer = setFsWatchListener(path35, absolutePath, options, {
4789
4795
  listener,
4790
4796
  errHandler: this._boundHandleError,
4791
4797
  rawEmitter: this.fsw._emitRaw
@@ -4807,7 +4813,7 @@ var init_handler = __esm({
4807
4813
  let prevStats = stats;
4808
4814
  if (parent.has(basename3))
4809
4815
  return;
4810
- const listener = async (path34, newStats) => {
4816
+ const listener = async (path35, newStats) => {
4811
4817
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
4812
4818
  return;
4813
4819
  if (!newStats || newStats.mtimeMs === 0) {
@@ -4821,11 +4827,11 @@ var init_handler = __esm({
4821
4827
  this.fsw._emit(EV.CHANGE, file, newStats2);
4822
4828
  }
4823
4829
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
4824
- this.fsw._closeFile(path34);
4830
+ this.fsw._closeFile(path35);
4825
4831
  prevStats = newStats2;
4826
4832
  const closer2 = this._watchWithNodeFs(file, listener);
4827
4833
  if (closer2)
4828
- this.fsw._addPathCloser(path34, closer2);
4834
+ this.fsw._addPathCloser(path35, closer2);
4829
4835
  } else {
4830
4836
  prevStats = newStats2;
4831
4837
  }
@@ -4857,7 +4863,7 @@ var init_handler = __esm({
4857
4863
  * @param item basename of this item
4858
4864
  * @returns true if no more processing is needed for this entry.
4859
4865
  */
4860
- async _handleSymlink(entry, directory, path34, item) {
4866
+ async _handleSymlink(entry, directory, path35, item) {
4861
4867
  if (this.fsw.closed) {
4862
4868
  return;
4863
4869
  }
@@ -4867,7 +4873,7 @@ var init_handler = __esm({
4867
4873
  this.fsw._incrReadyCount();
4868
4874
  let linkPath;
4869
4875
  try {
4870
- linkPath = await fsrealpath(path34);
4876
+ linkPath = await fsrealpath(path35);
4871
4877
  } catch (e) {
4872
4878
  this.fsw._emitReady();
4873
4879
  return true;
@@ -4877,12 +4883,12 @@ var init_handler = __esm({
4877
4883
  if (dir.has(item)) {
4878
4884
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
4879
4885
  this.fsw._symlinkPaths.set(full, linkPath);
4880
- this.fsw._emit(EV.CHANGE, path34, entry.stats);
4886
+ this.fsw._emit(EV.CHANGE, path35, entry.stats);
4881
4887
  }
4882
4888
  } else {
4883
4889
  dir.add(item);
4884
4890
  this.fsw._symlinkPaths.set(full, linkPath);
4885
- this.fsw._emit(EV.ADD, path34, entry.stats);
4891
+ this.fsw._emit(EV.ADD, path35, entry.stats);
4886
4892
  }
4887
4893
  this.fsw._emitReady();
4888
4894
  return true;
@@ -4911,9 +4917,9 @@ var init_handler = __esm({
4911
4917
  return;
4912
4918
  }
4913
4919
  const item = entry.path;
4914
- let path34 = sysPath.join(directory, item);
4920
+ let path35 = sysPath.join(directory, item);
4915
4921
  current.add(item);
4916
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path34, item)) {
4922
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path35, item)) {
4917
4923
  return;
4918
4924
  }
4919
4925
  if (this.fsw.closed) {
@@ -4922,8 +4928,8 @@ var init_handler = __esm({
4922
4928
  }
4923
4929
  if (item === target || !target && !previous.has(item)) {
4924
4930
  this.fsw._incrReadyCount();
4925
- path34 = sysPath.join(dir, sysPath.relative(dir, path34));
4926
- this._addToNodeFs(path34, initialAdd, wh, depth + 1);
4931
+ path35 = sysPath.join(dir, sysPath.relative(dir, path35));
4932
+ this._addToNodeFs(path35, initialAdd, wh, depth + 1);
4927
4933
  }
4928
4934
  }).on(EV.ERROR, this._boundHandleError);
4929
4935
  return new Promise((resolve3, reject) => {
@@ -4992,13 +4998,13 @@ var init_handler = __esm({
4992
4998
  * @param depth Child path actually targeted for watch
4993
4999
  * @param target Child path actually targeted for watch
4994
5000
  */
4995
- async _addToNodeFs(path34, initialAdd, priorWh, depth, target) {
5001
+ async _addToNodeFs(path35, initialAdd, priorWh, depth, target) {
4996
5002
  const ready = this.fsw._emitReady;
4997
- if (this.fsw._isIgnored(path34) || this.fsw.closed) {
5003
+ if (this.fsw._isIgnored(path35) || this.fsw.closed) {
4998
5004
  ready();
4999
5005
  return false;
5000
5006
  }
5001
- const wh = this.fsw._getWatchHelpers(path34);
5007
+ const wh = this.fsw._getWatchHelpers(path35);
5002
5008
  if (priorWh) {
5003
5009
  wh.filterPath = (entry) => priorWh.filterPath(entry);
5004
5010
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -5014,8 +5020,8 @@ var init_handler = __esm({
5014
5020
  const follow = this.fsw.options.followSymlinks;
5015
5021
  let closer;
5016
5022
  if (stats.isDirectory()) {
5017
- const absPath = sysPath.resolve(path34);
5018
- const targetPath = follow ? await fsrealpath(path34) : path34;
5023
+ const absPath = sysPath.resolve(path35);
5024
+ const targetPath = follow ? await fsrealpath(path35) : path35;
5019
5025
  if (this.fsw.closed)
5020
5026
  return;
5021
5027
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -5025,29 +5031,29 @@ var init_handler = __esm({
5025
5031
  this.fsw._symlinkPaths.set(absPath, targetPath);
5026
5032
  }
5027
5033
  } else if (stats.isSymbolicLink()) {
5028
- const targetPath = follow ? await fsrealpath(path34) : path34;
5034
+ const targetPath = follow ? await fsrealpath(path35) : path35;
5029
5035
  if (this.fsw.closed)
5030
5036
  return;
5031
5037
  const parent = sysPath.dirname(wh.watchPath);
5032
5038
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
5033
5039
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
5034
- closer = await this._handleDir(parent, stats, initialAdd, depth, path34, wh, targetPath);
5040
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path35, wh, targetPath);
5035
5041
  if (this.fsw.closed)
5036
5042
  return;
5037
5043
  if (targetPath !== void 0) {
5038
- this.fsw._symlinkPaths.set(sysPath.resolve(path34), targetPath);
5044
+ this.fsw._symlinkPaths.set(sysPath.resolve(path35), targetPath);
5039
5045
  }
5040
5046
  } else {
5041
5047
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
5042
5048
  }
5043
5049
  ready();
5044
5050
  if (closer)
5045
- this.fsw._addPathCloser(path34, closer);
5051
+ this.fsw._addPathCloser(path35, closer);
5046
5052
  return false;
5047
5053
  } catch (error) {
5048
5054
  if (this.fsw._handleError(error)) {
5049
5055
  ready();
5050
- return path34;
5056
+ return path35;
5051
5057
  }
5052
5058
  }
5053
5059
  }
@@ -5086,26 +5092,26 @@ function createPattern(matcher) {
5086
5092
  }
5087
5093
  return () => false;
5088
5094
  }
5089
- function normalizePath2(path34) {
5090
- if (typeof path34 !== "string")
5095
+ function normalizePath2(path35) {
5096
+ if (typeof path35 !== "string")
5091
5097
  throw new Error("string expected");
5092
- path34 = sysPath2.normalize(path34);
5093
- path34 = path34.replace(/\\/g, "/");
5098
+ path35 = sysPath2.normalize(path35);
5099
+ path35 = path35.replace(/\\/g, "/");
5094
5100
  let prepend = false;
5095
- if (path34.startsWith("//"))
5101
+ if (path35.startsWith("//"))
5096
5102
  prepend = true;
5097
5103
  const DOUBLE_SLASH_RE2 = /\/\//;
5098
- while (path34.match(DOUBLE_SLASH_RE2))
5099
- path34 = path34.replace(DOUBLE_SLASH_RE2, "/");
5104
+ while (path35.match(DOUBLE_SLASH_RE2))
5105
+ path35 = path35.replace(DOUBLE_SLASH_RE2, "/");
5100
5106
  if (prepend)
5101
- path34 = "/" + path34;
5102
- return path34;
5107
+ path35 = "/" + path35;
5108
+ return path35;
5103
5109
  }
5104
5110
  function matchPatterns(patterns, testString, stats) {
5105
- const path34 = normalizePath2(testString);
5111
+ const path35 = normalizePath2(testString);
5106
5112
  for (let index = 0; index < patterns.length; index++) {
5107
5113
  const pattern = patterns[index];
5108
- if (pattern(path34, stats)) {
5114
+ if (pattern(path35, stats)) {
5109
5115
  return true;
5110
5116
  }
5111
5117
  }
@@ -5166,19 +5172,19 @@ var init_esm2 = __esm({
5166
5172
  }
5167
5173
  return str;
5168
5174
  };
5169
- normalizePathToUnix = (path34) => toUnix(sysPath2.normalize(toUnix(path34)));
5170
- normalizeIgnored = (cwd = "") => (path34) => {
5171
- if (typeof path34 === "string") {
5172
- return normalizePathToUnix(sysPath2.isAbsolute(path34) ? path34 : sysPath2.join(cwd, path34));
5175
+ normalizePathToUnix = (path35) => toUnix(sysPath2.normalize(toUnix(path35)));
5176
+ normalizeIgnored = (cwd = "") => (path35) => {
5177
+ if (typeof path35 === "string") {
5178
+ return normalizePathToUnix(sysPath2.isAbsolute(path35) ? path35 : sysPath2.join(cwd, path35));
5173
5179
  } else {
5174
- return path34;
5180
+ return path35;
5175
5181
  }
5176
5182
  };
5177
- getAbsolutePath = (path34, cwd) => {
5178
- if (sysPath2.isAbsolute(path34)) {
5179
- return path34;
5183
+ getAbsolutePath = (path35, cwd) => {
5184
+ if (sysPath2.isAbsolute(path35)) {
5185
+ return path35;
5180
5186
  }
5181
- return sysPath2.join(cwd, path34);
5187
+ return sysPath2.join(cwd, path35);
5182
5188
  };
5183
5189
  EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
5184
5190
  DirEntry = class {
@@ -5233,10 +5239,10 @@ var init_esm2 = __esm({
5233
5239
  STAT_METHOD_F = "stat";
5234
5240
  STAT_METHOD_L = "lstat";
5235
5241
  WatchHelper = class {
5236
- constructor(path34, follow, fsw) {
5242
+ constructor(path35, follow, fsw) {
5237
5243
  this.fsw = fsw;
5238
- const watchPath = path34;
5239
- this.path = path34 = path34.replace(REPLACER_RE, "");
5244
+ const watchPath = path35;
5245
+ this.path = path35 = path35.replace(REPLACER_RE, "");
5240
5246
  this.watchPath = watchPath;
5241
5247
  this.fullWatchPath = sysPath2.resolve(watchPath);
5242
5248
  this.dirParts = [];
@@ -5358,20 +5364,20 @@ var init_esm2 = __esm({
5358
5364
  this._closePromise = void 0;
5359
5365
  let paths = unifyPaths(paths_);
5360
5366
  if (cwd) {
5361
- paths = paths.map((path34) => {
5362
- const absPath = getAbsolutePath(path34, cwd);
5367
+ paths = paths.map((path35) => {
5368
+ const absPath = getAbsolutePath(path35, cwd);
5363
5369
  return absPath;
5364
5370
  });
5365
5371
  }
5366
- paths.forEach((path34) => {
5367
- this._removeIgnoredPath(path34);
5372
+ paths.forEach((path35) => {
5373
+ this._removeIgnoredPath(path35);
5368
5374
  });
5369
5375
  this._userIgnored = void 0;
5370
5376
  if (!this._readyCount)
5371
5377
  this._readyCount = 0;
5372
5378
  this._readyCount += paths.length;
5373
- Promise.all(paths.map(async (path34) => {
5374
- const res = await this._nodeFsHandler._addToNodeFs(path34, !_internal, void 0, 0, _origAdd);
5379
+ Promise.all(paths.map(async (path35) => {
5380
+ const res = await this._nodeFsHandler._addToNodeFs(path35, !_internal, void 0, 0, _origAdd);
5375
5381
  if (res)
5376
5382
  this._emitReady();
5377
5383
  return res;
@@ -5393,17 +5399,17 @@ var init_esm2 = __esm({
5393
5399
  return this;
5394
5400
  const paths = unifyPaths(paths_);
5395
5401
  const { cwd } = this.options;
5396
- paths.forEach((path34) => {
5397
- if (!sysPath2.isAbsolute(path34) && !this._closers.has(path34)) {
5402
+ paths.forEach((path35) => {
5403
+ if (!sysPath2.isAbsolute(path35) && !this._closers.has(path35)) {
5398
5404
  if (cwd)
5399
- path34 = sysPath2.join(cwd, path34);
5400
- path34 = sysPath2.resolve(path34);
5405
+ path35 = sysPath2.join(cwd, path35);
5406
+ path35 = sysPath2.resolve(path35);
5401
5407
  }
5402
- this._closePath(path34);
5403
- this._addIgnoredPath(path34);
5404
- if (this._watched.has(path34)) {
5408
+ this._closePath(path35);
5409
+ this._addIgnoredPath(path35);
5410
+ if (this._watched.has(path35)) {
5405
5411
  this._addIgnoredPath({
5406
- path: path34,
5412
+ path: path35,
5407
5413
  recursive: true
5408
5414
  });
5409
5415
  }
@@ -5467,38 +5473,38 @@ var init_esm2 = __esm({
5467
5473
  * @param stats arguments to be passed with event
5468
5474
  * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
5469
5475
  */
5470
- async _emit(event, path34, stats) {
5476
+ async _emit(event, path35, stats) {
5471
5477
  if (this.closed)
5472
5478
  return;
5473
5479
  const opts = this.options;
5474
5480
  if (isWindows)
5475
- path34 = sysPath2.normalize(path34);
5481
+ path35 = sysPath2.normalize(path35);
5476
5482
  if (opts.cwd)
5477
- path34 = sysPath2.relative(opts.cwd, path34);
5478
- const args = [path34];
5483
+ path35 = sysPath2.relative(opts.cwd, path35);
5484
+ const args = [path35];
5479
5485
  if (stats != null)
5480
5486
  args.push(stats);
5481
5487
  const awf = opts.awaitWriteFinish;
5482
5488
  let pw;
5483
- if (awf && (pw = this._pendingWrites.get(path34))) {
5489
+ if (awf && (pw = this._pendingWrites.get(path35))) {
5484
5490
  pw.lastChange = /* @__PURE__ */ new Date();
5485
5491
  return this;
5486
5492
  }
5487
5493
  if (opts.atomic) {
5488
5494
  if (event === EVENTS.UNLINK) {
5489
- this._pendingUnlinks.set(path34, [event, ...args]);
5495
+ this._pendingUnlinks.set(path35, [event, ...args]);
5490
5496
  setTimeout(() => {
5491
- this._pendingUnlinks.forEach((entry, path35) => {
5497
+ this._pendingUnlinks.forEach((entry, path36) => {
5492
5498
  this.emit(...entry);
5493
5499
  this.emit(EVENTS.ALL, ...entry);
5494
- this._pendingUnlinks.delete(path35);
5500
+ this._pendingUnlinks.delete(path36);
5495
5501
  });
5496
5502
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
5497
5503
  return this;
5498
5504
  }
5499
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path34)) {
5505
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path35)) {
5500
5506
  event = EVENTS.CHANGE;
5501
- this._pendingUnlinks.delete(path34);
5507
+ this._pendingUnlinks.delete(path35);
5502
5508
  }
5503
5509
  }
5504
5510
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -5516,16 +5522,16 @@ var init_esm2 = __esm({
5516
5522
  this.emitWithAll(event, args);
5517
5523
  }
5518
5524
  };
5519
- this._awaitWriteFinish(path34, awf.stabilityThreshold, event, awfEmit);
5525
+ this._awaitWriteFinish(path35, awf.stabilityThreshold, event, awfEmit);
5520
5526
  return this;
5521
5527
  }
5522
5528
  if (event === EVENTS.CHANGE) {
5523
- const isThrottled = !this._throttle(EVENTS.CHANGE, path34, 50);
5529
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path35, 50);
5524
5530
  if (isThrottled)
5525
5531
  return this;
5526
5532
  }
5527
5533
  if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
5528
- const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path34) : path34;
5534
+ const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path35) : path35;
5529
5535
  let stats2;
5530
5536
  try {
5531
5537
  stats2 = await stat3(fullPath);
@@ -5556,23 +5562,23 @@ var init_esm2 = __esm({
5556
5562
  * @param timeout duration of time to suppress duplicate actions
5557
5563
  * @returns tracking object or false if action should be suppressed
5558
5564
  */
5559
- _throttle(actionType, path34, timeout) {
5565
+ _throttle(actionType, path35, timeout) {
5560
5566
  if (!this._throttled.has(actionType)) {
5561
5567
  this._throttled.set(actionType, /* @__PURE__ */ new Map());
5562
5568
  }
5563
5569
  const action = this._throttled.get(actionType);
5564
5570
  if (!action)
5565
5571
  throw new Error("invalid throttle");
5566
- const actionPath = action.get(path34);
5572
+ const actionPath = action.get(path35);
5567
5573
  if (actionPath) {
5568
5574
  actionPath.count++;
5569
5575
  return false;
5570
5576
  }
5571
5577
  let timeoutObject;
5572
5578
  const clear = () => {
5573
- const item = action.get(path34);
5579
+ const item = action.get(path35);
5574
5580
  const count = item ? item.count : 0;
5575
- action.delete(path34);
5581
+ action.delete(path35);
5576
5582
  clearTimeout(timeoutObject);
5577
5583
  if (item)
5578
5584
  clearTimeout(item.timeoutObject);
@@ -5580,7 +5586,7 @@ var init_esm2 = __esm({
5580
5586
  };
5581
5587
  timeoutObject = setTimeout(clear, timeout);
5582
5588
  const thr = { timeoutObject, clear, count: 0 };
5583
- action.set(path34, thr);
5589
+ action.set(path35, thr);
5584
5590
  return thr;
5585
5591
  }
5586
5592
  _incrReadyCount() {
@@ -5594,44 +5600,44 @@ var init_esm2 = __esm({
5594
5600
  * @param event
5595
5601
  * @param awfEmit Callback to be called when ready for event to be emitted.
5596
5602
  */
5597
- _awaitWriteFinish(path34, threshold, event, awfEmit) {
5603
+ _awaitWriteFinish(path35, threshold, event, awfEmit) {
5598
5604
  const awf = this.options.awaitWriteFinish;
5599
5605
  if (typeof awf !== "object")
5600
5606
  return;
5601
5607
  const pollInterval = awf.pollInterval;
5602
5608
  let timeoutHandler;
5603
- let fullPath = path34;
5604
- if (this.options.cwd && !sysPath2.isAbsolute(path34)) {
5605
- fullPath = sysPath2.join(this.options.cwd, path34);
5609
+ let fullPath = path35;
5610
+ if (this.options.cwd && !sysPath2.isAbsolute(path35)) {
5611
+ fullPath = sysPath2.join(this.options.cwd, path35);
5606
5612
  }
5607
5613
  const now = /* @__PURE__ */ new Date();
5608
5614
  const writes = this._pendingWrites;
5609
5615
  function awaitWriteFinishFn(prevStat) {
5610
5616
  statcb(fullPath, (err, curStat) => {
5611
- if (err || !writes.has(path34)) {
5617
+ if (err || !writes.has(path35)) {
5612
5618
  if (err && err.code !== "ENOENT")
5613
5619
  awfEmit(err);
5614
5620
  return;
5615
5621
  }
5616
5622
  const now2 = Number(/* @__PURE__ */ new Date());
5617
5623
  if (prevStat && curStat.size !== prevStat.size) {
5618
- writes.get(path34).lastChange = now2;
5624
+ writes.get(path35).lastChange = now2;
5619
5625
  }
5620
- const pw = writes.get(path34);
5626
+ const pw = writes.get(path35);
5621
5627
  const df = now2 - pw.lastChange;
5622
5628
  if (df >= threshold) {
5623
- writes.delete(path34);
5629
+ writes.delete(path35);
5624
5630
  awfEmit(void 0, curStat);
5625
5631
  } else {
5626
5632
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
5627
5633
  }
5628
5634
  });
5629
5635
  }
5630
- if (!writes.has(path34)) {
5631
- writes.set(path34, {
5636
+ if (!writes.has(path35)) {
5637
+ writes.set(path35, {
5632
5638
  lastChange: now,
5633
5639
  cancelWait: () => {
5634
- writes.delete(path34);
5640
+ writes.delete(path35);
5635
5641
  clearTimeout(timeoutHandler);
5636
5642
  return event;
5637
5643
  }
@@ -5642,8 +5648,8 @@ var init_esm2 = __esm({
5642
5648
  /**
5643
5649
  * Determines whether user has asked to ignore this path.
5644
5650
  */
5645
- _isIgnored(path34, stats) {
5646
- if (this.options.atomic && DOT_RE.test(path34))
5651
+ _isIgnored(path35, stats) {
5652
+ if (this.options.atomic && DOT_RE.test(path35))
5647
5653
  return true;
5648
5654
  if (!this._userIgnored) {
5649
5655
  const { cwd } = this.options;
@@ -5653,17 +5659,17 @@ var init_esm2 = __esm({
5653
5659
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
5654
5660
  this._userIgnored = anymatch(list, void 0);
5655
5661
  }
5656
- return this._userIgnored(path34, stats);
5662
+ return this._userIgnored(path35, stats);
5657
5663
  }
5658
- _isntIgnored(path34, stat4) {
5659
- return !this._isIgnored(path34, stat4);
5664
+ _isntIgnored(path35, stat4) {
5665
+ return !this._isIgnored(path35, stat4);
5660
5666
  }
5661
5667
  /**
5662
5668
  * Provides a set of common helpers and properties relating to symlink handling.
5663
5669
  * @param path file or directory pattern being watched
5664
5670
  */
5665
- _getWatchHelpers(path34) {
5666
- return new WatchHelper(path34, this.options.followSymlinks, this);
5671
+ _getWatchHelpers(path35) {
5672
+ return new WatchHelper(path35, this.options.followSymlinks, this);
5667
5673
  }
5668
5674
  // Directory helpers
5669
5675
  // -----------------
@@ -5695,63 +5701,63 @@ var init_esm2 = __esm({
5695
5701
  * @param item base path of item/directory
5696
5702
  */
5697
5703
  _remove(directory, item, isDirectory) {
5698
- const path34 = sysPath2.join(directory, item);
5699
- const fullPath = sysPath2.resolve(path34);
5700
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path34) || this._watched.has(fullPath);
5701
- if (!this._throttle("remove", path34, 100))
5704
+ const path35 = sysPath2.join(directory, item);
5705
+ const fullPath = sysPath2.resolve(path35);
5706
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path35) || this._watched.has(fullPath);
5707
+ if (!this._throttle("remove", path35, 100))
5702
5708
  return;
5703
5709
  if (!isDirectory && this._watched.size === 1) {
5704
5710
  this.add(directory, item, true);
5705
5711
  }
5706
- const wp = this._getWatchedDir(path34);
5712
+ const wp = this._getWatchedDir(path35);
5707
5713
  const nestedDirectoryChildren = wp.getChildren();
5708
- nestedDirectoryChildren.forEach((nested) => this._remove(path34, nested));
5714
+ nestedDirectoryChildren.forEach((nested) => this._remove(path35, nested));
5709
5715
  const parent = this._getWatchedDir(directory);
5710
5716
  const wasTracked = parent.has(item);
5711
5717
  parent.remove(item);
5712
5718
  if (this._symlinkPaths.has(fullPath)) {
5713
5719
  this._symlinkPaths.delete(fullPath);
5714
5720
  }
5715
- let relPath = path34;
5721
+ let relPath = path35;
5716
5722
  if (this.options.cwd)
5717
- relPath = sysPath2.relative(this.options.cwd, path34);
5723
+ relPath = sysPath2.relative(this.options.cwd, path35);
5718
5724
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
5719
5725
  const event = this._pendingWrites.get(relPath).cancelWait();
5720
5726
  if (event === EVENTS.ADD)
5721
5727
  return;
5722
5728
  }
5723
- this._watched.delete(path34);
5729
+ this._watched.delete(path35);
5724
5730
  this._watched.delete(fullPath);
5725
5731
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
5726
- if (wasTracked && !this._isIgnored(path34))
5727
- this._emit(eventName, path34);
5728
- this._closePath(path34);
5732
+ if (wasTracked && !this._isIgnored(path35))
5733
+ this._emit(eventName, path35);
5734
+ this._closePath(path35);
5729
5735
  }
5730
5736
  /**
5731
5737
  * Closes all watchers for a path
5732
5738
  */
5733
- _closePath(path34) {
5734
- this._closeFile(path34);
5735
- const dir = sysPath2.dirname(path34);
5736
- this._getWatchedDir(dir).remove(sysPath2.basename(path34));
5739
+ _closePath(path35) {
5740
+ this._closeFile(path35);
5741
+ const dir = sysPath2.dirname(path35);
5742
+ this._getWatchedDir(dir).remove(sysPath2.basename(path35));
5737
5743
  }
5738
5744
  /**
5739
5745
  * Closes only file-specific watchers
5740
5746
  */
5741
- _closeFile(path34) {
5742
- const closers = this._closers.get(path34);
5747
+ _closeFile(path35) {
5748
+ const closers = this._closers.get(path35);
5743
5749
  if (!closers)
5744
5750
  return;
5745
5751
  closers.forEach((closer) => closer());
5746
- this._closers.delete(path34);
5752
+ this._closers.delete(path35);
5747
5753
  }
5748
- _addPathCloser(path34, closer) {
5754
+ _addPathCloser(path35, closer) {
5749
5755
  if (!closer)
5750
5756
  return;
5751
- let list = this._closers.get(path34);
5757
+ let list = this._closers.get(path35);
5752
5758
  if (!list) {
5753
5759
  list = [];
5754
- this._closers.set(path34, list);
5760
+ this._closers.set(path35, list);
5755
5761
  }
5756
5762
  list.push(closer);
5757
5763
  }
@@ -6080,25 +6086,25 @@ function getWsIndex(routes) {
6080
6086
  wsIndexCache.set(routes, index);
6081
6087
  return index;
6082
6088
  }
6083
- function matchRoute(routes, method, path34) {
6089
+ function matchRoute(routes, method, path35) {
6084
6090
  const index = getHttpIndex(routes);
6085
6091
  const upper = method.toUpperCase();
6086
- const hit = matchByMethod(index, upper, path34);
6092
+ const hit = matchByMethod(index, upper, path35);
6087
6093
  if (hit) return hit;
6088
6094
  if (upper === "HEAD") {
6089
- return matchByMethod(index, "GET", path34);
6095
+ return matchByMethod(index, "GET", path35);
6090
6096
  }
6091
6097
  return null;
6092
6098
  }
6093
- function matchByMethod(index, method, path34) {
6094
- const staticHit = index.static.get(`${method}|${path34}`);
6099
+ function matchByMethod(index, method, path35) {
6100
+ const staticHit = index.static.get(`${method}|${path35}`);
6095
6101
  if (staticHit) {
6096
6102
  return { route: staticHit, params: {} };
6097
6103
  }
6098
6104
  if (index.dynamics.length === 0) {
6099
6105
  return null;
6100
6106
  }
6101
- const pathSegments = path34.split("/").filter(Boolean);
6107
+ const pathSegments = path35.split("/").filter(Boolean);
6102
6108
  for (const entry of index.dynamics) {
6103
6109
  const route = entry.route;
6104
6110
  if (route.method !== method) {
@@ -6111,31 +6117,31 @@ function matchByMethod(index, method, path34) {
6111
6117
  }
6112
6118
  return null;
6113
6119
  }
6114
- function matchWsRoute(wsRoutes, path34) {
6120
+ function matchWsRoute(wsRoutes, path35) {
6115
6121
  const index = getWsIndex(wsRoutes);
6116
- const staticHit = index.static.get(path34);
6122
+ const staticHit = index.static.get(path35);
6117
6123
  if (staticHit) {
6118
6124
  return { route: staticHit, params: {} };
6119
6125
  }
6120
6126
  for (const route of index.dynamics) {
6121
- const params = matchDynamicPath(route.urlPath, path34, route.paramNames, route.isCatchAll);
6127
+ const params = matchDynamicPath(route.urlPath, path35, route.paramNames, route.isCatchAll);
6122
6128
  if (params !== null) {
6123
6129
  return { route, params };
6124
6130
  }
6125
6131
  }
6126
6132
  return null;
6127
6133
  }
6128
- function findAllowedMethods(routes, path34) {
6134
+ function findAllowedMethods(routes, path35) {
6129
6135
  const index = getHttpIndex(routes);
6130
6136
  const methods = /* @__PURE__ */ new Set();
6131
- const staticMethods = index.methodsByStaticPath.get(path34);
6137
+ const staticMethods = index.methodsByStaticPath.get(path35);
6132
6138
  if (staticMethods) {
6133
6139
  for (const method of staticMethods) {
6134
6140
  methods.add(method);
6135
6141
  }
6136
6142
  }
6137
6143
  if (index.dynamics.length > 0) {
6138
- const pathSegments = path34.split("/").filter(Boolean);
6144
+ const pathSegments = path35.split("/").filter(Boolean);
6139
6145
  for (const entry of index.dynamics) {
6140
6146
  const params = matchSegments(
6141
6147
  entry.segments,
@@ -6153,10 +6159,10 @@ function findAllowedMethods(routes, path34) {
6153
6159
  }
6154
6160
  return Array.from(methods);
6155
6161
  }
6156
- function matchDynamicPath(pattern, path34, paramNames, isCatchAll) {
6162
+ function matchDynamicPath(pattern, path35, paramNames, isCatchAll) {
6157
6163
  return matchSegments(
6158
6164
  pattern.split("/").filter(Boolean),
6159
- path34.split("/").filter(Boolean),
6165
+ path35.split("/").filter(Boolean),
6160
6166
  paramNames,
6161
6167
  isCatchAll
6162
6168
  );
@@ -6635,14 +6641,14 @@ var init_httpErrors = __esm({
6635
6641
  issues;
6636
6642
  };
6637
6643
  RouteNotFoundError = class extends FaapiError {
6638
- constructor(path34) {
6639
- super("ROUTE_NOT_FOUND", `Route not found: ${path34}`, 404);
6644
+ constructor(path35) {
6645
+ super("ROUTE_NOT_FOUND", `Route not found: ${path35}`, 404);
6640
6646
  this.name = "RouteNotFoundError";
6641
6647
  }
6642
6648
  };
6643
6649
  MethodNotAllowedError = class extends FaapiError {
6644
- constructor(method, path34, allowedMethods) {
6645
- super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path34}`, 405);
6650
+ constructor(method, path35, allowedMethods) {
6651
+ super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path35}`, 405);
6646
6652
  this.allowedMethods = allowedMethods;
6647
6653
  this.name = "MethodNotAllowedError";
6648
6654
  }
@@ -7026,6 +7032,24 @@ var init_queryToObject = __esm({
7026
7032
  }
7027
7033
  });
7028
7034
 
7035
+ // src/utils/readResource.ts
7036
+ import path25 from "path";
7037
+ import fs19 from "fs/promises";
7038
+ function setActiveResourcesDir(dir) {
7039
+ if (dir === null) {
7040
+ delete globalThis[ACTIVE_RESOURCES_DIR_KEY];
7041
+ } else {
7042
+ globalThis[ACTIVE_RESOURCES_DIR_KEY] = dir;
7043
+ }
7044
+ }
7045
+ var ACTIVE_RESOURCES_DIR_KEY;
7046
+ var init_readResource = __esm({
7047
+ "src/utils/readResource.ts"() {
7048
+ "use strict";
7049
+ ACTIVE_RESOURCES_DIR_KEY = /* @__PURE__ */ Symbol.for("faapi.resources.dir");
7050
+ }
7051
+ });
7052
+
7029
7053
  // src/runtime/createContext.ts
7030
7054
  function resolveRequestId(request) {
7031
7055
  const header = request.headers.get("x-request-id");
@@ -7996,9 +8020,9 @@ async function validateInput(schemaPath, method, inputType, input) {
7996
8020
  function mapZodIssues(error) {
7997
8021
  return error.issues.map((issue) => {
7998
8022
  const code = mapZodCode(issue);
7999
- const path34 = issue.path.map(String).join(".") || "";
8023
+ const path35 = issue.path.map(String).join(".") || "";
8000
8024
  return {
8001
- path: path34,
8025
+ path: path35,
8002
8026
  code,
8003
8027
  expected: issue.expected ?? mapExpectedFromMessage(issue.message),
8004
8028
  received: issue.received ?? mapReceivedFromMessage(issue.message),
@@ -8522,9 +8546,9 @@ var init_wsHandler = __esm({
8522
8546
  });
8523
8547
 
8524
8548
  // src/server/handleWsUpgrade.ts
8525
- import fs19 from "fs";
8549
+ import fs20 from "fs";
8526
8550
  import { WebSocketServer, WebSocket } from "ws";
8527
- import path25 from "path";
8551
+ import path26 from "path";
8528
8552
  function getPathname(req) {
8529
8553
  const url = req.url ?? "/";
8530
8554
  const idx = url.indexOf("?");
@@ -8535,7 +8559,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
8535
8559
  const dist = getDevDist();
8536
8560
  if (dist) {
8537
8561
  const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
8538
- if (sourcePath && fs19.existsSync(sourcePath)) {
8562
+ if (sourcePath && fs20.existsSync(sourcePath)) {
8539
8563
  await ensureCompiled(sourcePath, rootDir, dist);
8540
8564
  }
8541
8565
  }
@@ -8677,7 +8701,7 @@ function attachWebSocket(options) {
8677
8701
  let upgraded = false;
8678
8702
  const finalHandler = async () => {
8679
8703
  const schemaPath = getRuntimeSchemaPath(route.filePath, dist, rootDir);
8680
- if (fs19.existsSync(schemaPath)) {
8704
+ if (fs20.existsSync(schemaPath)) {
8681
8705
  if (isDevOnDemandEnabled()) {
8682
8706
  const devDist = getDevDist();
8683
8707
  if (devDist) {
@@ -8716,7 +8740,7 @@ function attachWebSocket(options) {
8716
8740
  }
8717
8741
  let handlers;
8718
8742
  try {
8719
- const absoluteFilePath = path25.resolve(rootDir, route.filePath);
8743
+ const absoluteFilePath = path26.resolve(rootDir, route.filePath);
8720
8744
  handlers = await loadWsHandler(absoluteFilePath, ctx, rootDir);
8721
8745
  } catch (err) {
8722
8746
  const reason = err instanceof Error ? err.message : String(err);
@@ -8797,7 +8821,7 @@ import {
8797
8821
  import { createSecureServer as createHttp2SecureServer } from "http2";
8798
8822
  import { readFileSync } from "fs";
8799
8823
  import { Readable as Readable3 } from "stream";
8800
- import path26 from "path";
8824
+ import path27 from "path";
8801
8825
  function toWebRequest(req, bodyLimit = DEFAULT_BODY_LIMIT, requestSignal) {
8802
8826
  const forwardedProto = req.headers["x-forwarded-proto"];
8803
8827
  const protocol = Array.isArray(forwardedProto) ? forwardedProto[0]?.split(",")[0]?.trim() ?? "http" : forwardedProto?.split(",")[0]?.trim() ?? "http";
@@ -9003,7 +9027,7 @@ function getRoutePaths(route, rootDir, dist) {
9003
9027
  let cached = routePathCache.get(route);
9004
9028
  if (!cached) {
9005
9029
  cached = {
9006
- absFilePath: path26.resolve(rootDir, route.filePath),
9030
+ absFilePath: path27.resolve(rootDir, route.filePath),
9007
9031
  schemaPath: getRuntimeSchemaPath(route.filePath, dist, rootDir)
9008
9032
  };
9009
9033
  routePathCache.set(route, cached);
@@ -9258,8 +9282,15 @@ var init_startServer = __esm({
9258
9282
  });
9259
9283
 
9260
9284
  // src/task/taskWorker.ts
9285
+ import { existsSync as existsSync3 } from "fs";
9261
9286
  import { Worker } from "worker_threads";
9262
- import { pathToFileURL as pathToFileURL2 } from "url";
9287
+ import { fileURLToPath, pathToFileURL as pathToFileURL2 } from "url";
9288
+ function resolveWorkerEntryUrl() {
9289
+ if (workerEntryUrl) return workerEntryUrl;
9290
+ const js = new URL("./workerEntry.js", import.meta.url);
9291
+ workerEntryUrl = existsSync3(fileURLToPath(js)) ? js : new URL("./workerEntry.ts", import.meta.url);
9292
+ return workerEntryUrl;
9293
+ }
9263
9294
  function safeConfig(config) {
9264
9295
  if (config === void 0 || config === null) return config;
9265
9296
  try {
@@ -9273,55 +9304,6 @@ function safeConfig(config) {
9273
9304
  return void 0;
9274
9305
  }
9275
9306
  }
9276
- function buildWrapperSource(moduleUrl) {
9277
- return `
9278
- import { parentPort } from 'node:worker_threads';
9279
- import * as mod from '${moduleUrl}';
9280
-
9281
- ${BUILD_VIEW_SOURCE}
9282
-
9283
- ${SERIALIZE_ERROR_SOURCE}
9284
-
9285
- ${BUILD_LOGGER_SOURCE}
9286
-
9287
- const run = mod.run;
9288
- if (typeof run !== 'function') {
9289
- parentPort.postMessage({
9290
- type: 'error',
9291
- error: { name: 'Error', message: 'Task module has no run export', stack: undefined, props: {} },
9292
- });
9293
- } else {
9294
- let controller = null;
9295
- parentPort.on('message', async (msg) => {
9296
- if (msg?.type === 'abort') {
9297
- controller?.abort(new Error(msg.reason));
9298
- return;
9299
- }
9300
- if (msg?.type !== 'run') return;
9301
- controller = new AbortController();
9302
- const { payload, taskCtx } = msg;
9303
- try {
9304
- const registries = buildRegistriesView(msg.registries);
9305
- const progress = (value) => parentPort.postMessage({ type: 'progress', value });
9306
- const taskLog = msg.log ? createTaskLogger(msg.log.level, msg.log.scope, msg.log.fields) : undefined;
9307
- const result = await run(payload, { ...taskCtx, signal: controller.signal, registries, progress, log: taskLog });
9308
- parentPort.postMessage({ type: 'done', result });
9309
- } catch (err) {
9310
- const serialized = serializeError(err);
9311
- try {
9312
- parentPort.postMessage({ type: 'error', error: serialized });
9313
- } catch (_) {
9314
- // props \u542B\u4E0D\u53EF\u514B\u9686\u503C\uFF08\u51FD\u6570\u7B49\uFF09\u65F6\u4E22\u5F03 props\uFF0C\u4FDD\u5E95 name/message/stack
9315
- parentPort.postMessage({
9316
- type: 'error',
9317
- error: { name: serialized.name, message: serialized.message, stack: serialized.stack, props: {} },
9318
- });
9319
- }
9320
- }
9321
- });
9322
- }
9323
- `;
9324
- }
9325
9307
  function reviveError(payload) {
9326
9308
  const err = new Error(payload?.message ?? "task worker error");
9327
9309
  if (payload?.name !== void 0) err.name = payload.name;
@@ -9342,13 +9324,12 @@ async function runTaskInWorker(options) {
9342
9324
  );
9343
9325
  }
9344
9326
  const moduleUrl = pathToFileURL2(taskModulePath).href;
9345
- const wrapperUrl = new URL(
9346
- `data:text/javascript,${encodeURIComponent(buildWrapperSource(moduleUrl))}`
9347
- );
9348
9327
  return new Promise((resolve3, reject) => {
9349
9328
  let worker;
9350
9329
  try {
9351
- worker = new Worker(wrapperUrl);
9330
+ worker = new Worker(resolveWorkerEntryUrl(), {
9331
+ workerData: { moduleUrl, resourcesDir: taskCtx.resourcesDir }
9332
+ });
9352
9333
  } catch (err) {
9353
9334
  reject(err);
9354
9335
  return;
@@ -9453,7 +9434,7 @@ async function runTaskInWorker(options) {
9453
9434
  }
9454
9435
  });
9455
9436
  }
9456
- var KILL_GRACE_MS, TaskCancelledError, BUILD_VIEW_SOURCE, SERIALIZE_ERROR_SOURCE, BUILD_LOGGER_SOURCE;
9437
+ var workerEntryUrl, KILL_GRACE_MS, TaskCancelledError;
9457
9438
  var init_taskWorker = __esm({
9458
9439
  "src/task/taskWorker.ts"() {
9459
9440
  "use strict";
@@ -9464,109 +9445,11 @@ var init_taskWorker = __esm({
9464
9445
  this.name = "TaskCancelledError";
9465
9446
  }
9466
9447
  };
9467
- BUILD_VIEW_SOURCE = `
9468
- function buildRegistriesView(snapshot) {
9469
- var agents = new Map(((snapshot && snapshot.agents) || []).map(function (a) { return [a.name, a]; }));
9470
- var tools = new Map(((snapshot && snapshot.tools) || []).map(function (t) { return [t.name, t]; }));
9471
- var skills = new Map(((snapshot && snapshot.skills) || []).map(function (s) { return [s.name, s]; }));
9472
- return {
9473
- agent: {
9474
- getAgent: function (name) { return agents.get(name); },
9475
- getAgentEntry: function (name) { return agents.get(name); },
9476
- listAgents: function () { return Array.from(agents.values()); },
9477
- asTool: function (name) {
9478
- var agent = agents.get(name);
9479
- if (!agent) return undefined;
9480
- return {
9481
- kind: 'agent',
9482
- name: 'agent.' + agent.name,
9483
- agentName: agent.name,
9484
- description: agent.description,
9485
- metadata: agent,
9486
- };
9487
- },
9488
- resolveAgentTools: function (name) {
9489
- var agent = agents.get(name);
9490
- var result = new Map();
9491
- if (agent && agent.tools) {
9492
- agent.tools.forEach(function (toolName) {
9493
- var resolved = tools.get(toolName);
9494
- if (resolved) result.set(resolved.name, resolved);
9495
- });
9496
- }
9497
- return Array.from(result.values());
9498
- },
9499
- resolveSubAgents: function (name) {
9500
- var agent = agents.get(name);
9501
- var result = [];
9502
- if (agent && agent.agents) {
9503
- agent.agents.forEach(function (subName) {
9504
- var sub = agents.get(subName);
9505
- if (sub) result.push(sub);
9506
- });
9507
- }
9508
- return result;
9509
- },
9510
- },
9511
- tool: {
9512
- get: function (name) { return tools.get(name); },
9513
- list: function () { return Array.from(tools.values()); },
9514
- },
9515
- skill: {
9516
- get: function (name) { return skills.get(name); },
9517
- list: function () { return Array.from(skills.values()); },
9518
- },
9519
- };
9520
- }
9521
- `;
9522
- SERIALIZE_ERROR_SOURCE = `
9523
- function serializeError(err) {
9524
- if (err instanceof Error) {
9525
- var props = {};
9526
- var keys = Object.keys(err);
9527
- for (var i = 0; i < keys.length; i++) {
9528
- props[keys[i]] = err[keys[i]];
9529
- }
9530
- return { name: err.name, message: err.message, stack: err.stack, props: props };
9531
- }
9532
- return { name: 'Error', message: String(err), stack: undefined, props: {} };
9533
- }
9534
- `;
9535
- BUILD_LOGGER_SOURCE = `
9536
- var LOG_RANK = { debug: 0, info: 1, warn: 2, error: 3 };
9537
- function createTaskLogger(level, scope, fields) {
9538
- function make(suffix) {
9539
- function write(lvl, message, callFields) {
9540
- if (level !== undefined && LOG_RANK[lvl] < LOG_RANK[level]) return;
9541
- var entry = { level: lvl, message: message, time: new Date().toISOString() };
9542
- var fullScope = suffix === undefined ? scope : scope === undefined ? suffix : scope + ':' + suffix;
9543
- if (fullScope !== undefined) entry.scope = fullScope;
9544
- if (fields !== undefined || callFields !== undefined) {
9545
- entry.fields = Object.assign({}, fields, callFields);
9546
- }
9547
- try {
9548
- parentPort.postMessage({ type: 'log', entry: entry });
9549
- } catch (_) {
9550
- entry.fields = { warning: 'log fields not cloneable across worker boundary, dropped' };
9551
- parentPort.postMessage({ type: 'log', entry: entry });
9552
- }
9553
- }
9554
- return {
9555
- debug: function (m, f) { write('debug', m, f); },
9556
- info: function (m, f) { write('info', m, f); },
9557
- warn: function (m, f) { write('warn', m, f); },
9558
- error: function (m, f) { write('error', m, f); },
9559
- child: function (cs) { return make(suffix === undefined ? cs : suffix + ':' + cs); },
9560
- };
9561
- }
9562
- return make(undefined);
9563
- }
9564
- `;
9565
9448
  }
9566
9449
  });
9567
9450
 
9568
9451
  // src/task/taskQueue.ts
9569
- import path27 from "path";
9452
+ import path28 from "path";
9570
9453
  function createTaskQueue(deps) {
9571
9454
  const { registry, rootDir, driver } = deps;
9572
9455
  const registriesView = deps.registries ?? createEmptyTaskRegistriesView();
@@ -9596,7 +9479,7 @@ function createTaskQueue(deps) {
9596
9479
  }
9597
9480
  const loadTaskModule = deps.loadTaskModule ?? (async (filePath) => await import(filePath));
9598
9481
  const loadPayloadSchema = deps.loadPayloadSchema ?? (async (filePath) => {
9599
- const zodPath = path27.join(path27.dirname(filePath), "zod.js");
9482
+ const zodPath = path28.join(path28.dirname(filePath), "zod.js");
9600
9483
  try {
9601
9484
  const mod = await import(zodPath);
9602
9485
  const schemaKey = Object.keys(mod).find((k) => k.endsWith("Schema"));
@@ -9624,7 +9507,7 @@ function createTaskQueue(deps) {
9624
9507
  const meta = registry.get(name);
9625
9508
  schemaCache.set(
9626
9509
  name,
9627
- await loadPayloadSchema(path27.resolve(rootDir, meta.filePath)).catch(() => void 0)
9510
+ await loadPayloadSchema(path28.resolve(rootDir, meta.filePath)).catch(() => void 0)
9628
9511
  );
9629
9512
  }
9630
9513
  const schema = schemaCache.get(name);
@@ -9660,7 +9543,7 @@ function createTaskQueue(deps) {
9660
9543
  let result;
9661
9544
  if (meta.timeoutMs !== void 0 && meta.timeoutMs > 0) {
9662
9545
  result = await (deps.runIsolated ?? runTaskInWorker)({
9663
- taskModulePath: path27.resolve(rootDir, meta.filePath),
9546
+ taskModulePath: path28.resolve(rootDir, meta.filePath),
9664
9547
  payload: job.payload,
9665
9548
  taskCtx: {
9666
9549
  config: deps.config,
@@ -9686,7 +9569,7 @@ function createTaskQueue(deps) {
9686
9569
  } else {
9687
9570
  let mod = moduleCache2.get(job.name);
9688
9571
  if (!mod) {
9689
- mod = await loadTaskModule(path27.resolve(rootDir, meta.filePath));
9572
+ mod = await loadTaskModule(path28.resolve(rootDir, meta.filePath));
9690
9573
  moduleCache2.set(job.name, mod);
9691
9574
  }
9692
9575
  if (typeof mod.run !== "function") {
@@ -9976,8 +9859,8 @@ var init_cronScheduler = __esm({
9976
9859
  });
9977
9860
 
9978
9861
  // src/cli/loadPlugins.ts
9979
- import path28 from "path";
9980
- import fs20 from "fs";
9862
+ import path29 from "path";
9863
+ import fs21 from "fs";
9981
9864
  import { pathToFileURL as pathToFileURL3 } from "url";
9982
9865
  async function loadPlugins(declarations, ctx, rootDir, dist) {
9983
9866
  const handlerWrappers = [];
@@ -10040,30 +9923,30 @@ async function loadPlugins(declarations, ctx, rootDir, dist) {
10040
9923
  return { handlerWrappers, upgradeWrappers, failures };
10041
9924
  }
10042
9925
  function resolveLocalPluginSource(specifier, baseDir) {
10043
- const base = path28.isAbsolute(specifier) ? specifier : path28.resolve(baseDir, specifier);
10044
- if ((TS_EXTS.test(base) || JS_EXTS.test(base)) && fs20.existsSync(base)) return base;
9926
+ const base = path29.isAbsolute(specifier) ? specifier : path29.resolve(baseDir, specifier);
9927
+ if ((TS_EXTS.test(base) || JS_EXTS.test(base)) && fs21.existsSync(base)) return base;
10045
9928
  for (const ext of [".ts", ".js"]) {
10046
- if (fs20.existsSync(base + ext)) return base + ext;
9929
+ if (fs21.existsSync(base + ext)) return base + ext;
10047
9930
  }
10048
9931
  for (const indexExt of ["/index.ts", "/index.js"]) {
10049
- if (fs20.existsSync(base + indexExt)) return base + indexExt;
9932
+ if (fs21.existsSync(base + indexExt)) return base + indexExt;
10050
9933
  }
10051
9934
  return null;
10052
9935
  }
10053
9936
  function mirrorProductPath(sourcePath, baseDir, distDir) {
10054
- let rel = path28.relative(baseDir, sourcePath).replace(/\\/g, "/");
9937
+ let rel = path29.relative(baseDir, sourcePath).replace(/\\/g, "/");
10055
9938
  if (rel.startsWith("src/")) rel = rel.slice(4);
10056
- return path28.resolve(distDir, rel.replace(TS_EXTS, ".js"));
9939
+ return path29.resolve(distDir, rel.replace(TS_EXTS, ".js"));
10057
9940
  }
10058
9941
  async function importPluginModule(specifier, baseDir, dist) {
10059
9942
  const isRelative = specifier.startsWith("./") || specifier.startsWith("../");
10060
- if (!isRelative && !path28.isAbsolute(specifier)) {
9943
+ if (!isRelative && !path29.isAbsolute(specifier)) {
10061
9944
  return import(specifier);
10062
9945
  }
10063
- const distDir = dist ? path28.resolve(baseDir, dist) : null;
9946
+ const distDir = dist ? path29.resolve(baseDir, dist) : null;
10064
9947
  const sourcePath = resolveLocalPluginSource(specifier, baseDir);
10065
9948
  const productPath = sourcePath && distDir ? mirrorProductPath(sourcePath, baseDir, distDir) : null;
10066
- if (productPath !== null && fs20.existsSync(productPath) && (sourcePath === null || isProductFresh(sourcePath, productPath))) {
9949
+ if (productPath !== null && fs21.existsSync(productPath) && (sourcePath === null || isProductFresh(sourcePath, productPath))) {
10067
9950
  return import(pathToFileURL3(productPath).href);
10068
9951
  }
10069
9952
  if (sourcePath && TS_EXTS.test(sourcePath)) {
@@ -10072,13 +9955,13 @@ async function importPluginModule(specifier, baseDir, dist) {
10072
9955
  `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.`
10073
9956
  );
10074
9957
  }
10075
- const relFromRoot = path28.relative(baseDir, sourcePath).replace(/\\/g, "/");
9958
+ const relFromRoot = path29.relative(baseDir, sourcePath).replace(/\\/g, "/");
10076
9959
  if (relFromRoot.startsWith("src/")) {
10077
9960
  await ensureCompiled(sourcePath, baseDir, dist);
10078
9961
  } else {
10079
9962
  await compileProjectModules([sourcePath], baseDir, dist);
10080
9963
  }
10081
- if (productPath && fs20.existsSync(productPath)) {
9964
+ if (productPath && fs21.existsSync(productPath)) {
10082
9965
  return import(pathToFileURL3(productPath).href);
10083
9966
  }
10084
9967
  }
@@ -10090,7 +9973,7 @@ async function importPluginModule(specifier, baseDir, dist) {
10090
9973
  `${specifier}/index.ts`,
10091
9974
  `${specifier}.js`,
10092
9975
  `${specifier}/index.js`
10093
- ].map((c) => path28.isAbsolute(c) ? c : path28.join(baseDir, c));
9976
+ ].map((c) => path29.isAbsolute(c) ? c : path29.join(baseDir, c));
10094
9977
  throw new Error(
10095
9978
  `Cannot find local plugin "${specifier}" (resolved from ${baseDir}). Expected one of:
10096
9979
  ${candidates.join("\n ")}
@@ -10125,11 +10008,11 @@ var init_loadPlugins = __esm({
10125
10008
  });
10126
10009
 
10127
10010
  // src/cli/manifestLoader.ts
10128
- import fs21 from "fs";
10129
- import path29 from "path";
10011
+ import fs22 from "fs";
10012
+ import path30 from "path";
10130
10013
  async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries) {
10131
- const toolsPath = path29.resolve(rootDir, dist, TOOLS_FILE2);
10132
- if (!fs21.existsSync(toolsPath)) {
10014
+ const toolsPath = path30.resolve(rootDir, dist, TOOLS_FILE2);
10015
+ if (!fs22.existsSync(toolsPath)) {
10133
10016
  return [];
10134
10017
  }
10135
10018
  const serialized = await importWithCacheBust(toolsPath);
@@ -10138,8 +10021,8 @@ async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries
10138
10021
  return hydrated;
10139
10022
  }
10140
10023
  async function loadAndHydrateAgents(rootDir, dist, registries = defaultRegistries) {
10141
- const agentsPath = path29.resolve(rootDir, dist, AGENTS_FILE2);
10142
- if (!fs21.existsSync(agentsPath)) {
10024
+ const agentsPath = path30.resolve(rootDir, dist, AGENTS_FILE2);
10025
+ if (!fs22.existsSync(agentsPath)) {
10143
10026
  return [];
10144
10027
  }
10145
10028
  const serialized = await importWithCacheBust(agentsPath);
@@ -10154,8 +10037,8 @@ function getTaskDriverOptions(config) {
10154
10037
  return void 0;
10155
10038
  }
10156
10039
  async function loadAndHydrateTasks(rootDir, dist, registries = defaultRegistries) {
10157
- const tasksPath = path29.resolve(rootDir, dist, TASKS_FILE);
10158
- if (!fs21.existsSync(tasksPath)) {
10040
+ const tasksPath = path30.resolve(rootDir, dist, TASKS_FILE);
10041
+ if (!fs22.existsSync(tasksPath)) {
10159
10042
  return [];
10160
10043
  }
10161
10044
  const serialized = await importWithCacheBust(tasksPath);
@@ -10302,8 +10185,8 @@ var init_injectMock = __esm({
10302
10185
  });
10303
10186
 
10304
10187
  // src/cli/createAppCore.ts
10305
- import fs22 from "fs";
10306
- import path30 from "path";
10188
+ import fs23 from "fs";
10189
+ import path31 from "path";
10307
10190
  function isFaapiConfigKey(key) {
10308
10191
  return FAAPI_CONFIG_KEYS.has(key);
10309
10192
  }
@@ -10341,11 +10224,17 @@ function logStartupSummary(routes, wsRoutes, tools, agents, taskMetas, p) {
10341
10224
  }
10342
10225
  }
10343
10226
  async function createAppBase(options) {
10227
+ if (getCurrentApp()) {
10228
+ throw new Error(
10229
+ "[faapi] createApp: an app is already alive in this process \u2014 faapi supports a single app per process. Close it first (`await app.close()`) or run the second app in a separate process."
10230
+ );
10231
+ }
10344
10232
  const rootDir = options?.rootDir ?? process.cwd();
10345
10233
  const dist = options?.dist ?? process.env.FAAPI_DIST ?? DEFAULT_DIST;
10346
10234
  const resourcesDir = resolveResourcesDir(rootDir, dist);
10347
- const routesPath = path30.resolve(rootDir, dist, ROUTES_FILE);
10348
- if (!fs22.existsSync(routesPath)) {
10235
+ setActiveResourcesDir(resourcesDir);
10236
+ const routesPath = path31.resolve(rootDir, dist, ROUTES_FILE);
10237
+ if (!fs23.existsSync(routesPath)) {
10349
10238
  throw new Error(
10350
10239
  `[faapi] ${dist}/${ROUTES_FILE} \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6267\u884C \`faapi build\`\uFF08\u6216 \`faapi dev\`\uFF09\u751F\u6210\u4EA7\u7269\u3002`
10351
10240
  );
@@ -10510,6 +10399,7 @@ async function createAppBase(options) {
10510
10399
  registries.task.clear();
10511
10400
  registries.agentHandle.clear();
10512
10401
  registries.taskHandle.clear();
10402
+ setActiveResourcesDir(null);
10513
10403
  if (!server.listening) {
10514
10404
  app.server = null;
10515
10405
  if (getCurrentApp() === app) setCurrentApp(null);
@@ -10584,6 +10474,7 @@ var init_createAppCore = __esm({
10584
10474
  init_appSingleton();
10585
10475
  init_injectMock();
10586
10476
  init_copyResources();
10477
+ init_readResource();
10587
10478
  init_manifestLoader();
10588
10479
  DEFAULT_DIST = "dist";
10589
10480
  DEFAULT_PORT = 3e3;
@@ -10609,7 +10500,7 @@ var init_createAppCore = __esm({
10609
10500
  });
10610
10501
 
10611
10502
  // src/cli/createDevApp.ts
10612
- import path31 from "path";
10503
+ import path32 from "path";
10613
10504
  async function createDevApp(options) {
10614
10505
  const { app, ctx } = await createAppBase(options);
10615
10506
  const devApp = app;
@@ -10659,7 +10550,7 @@ async function createDevApp(options) {
10659
10550
  if (!suppressProgramInvalidation) invalidateProgramCache();
10660
10551
  const tasks = await scanTasks(ctx.rootDir, TASK_PATTERNS);
10661
10552
  for (const task of tasks) {
10662
- await ensureCompiled(path31.resolve(ctx.rootDir, task.filePath), ctx.rootDir, ctx.dist);
10553
+ await ensureCompiled(path32.resolve(ctx.rootDir, task.filePath), ctx.rootDir, ctx.dist);
10663
10554
  }
10664
10555
  await generateTaskArtifacts(tasks, ctx.rootDir, ctx.dist);
10665
10556
  ctx.taskQueue.invalidateModules();
@@ -10716,7 +10607,7 @@ __export(devCommand_exports, {
10716
10607
  generateTaskArtifactsForDev: () => generateTaskArtifactsForDev,
10717
10608
  generateToolArtifactsForDev: () => generateToolArtifactsForDev
10718
10609
  });
10719
- import path32 from "path";
10610
+ import path33 from "path";
10720
10611
  async function devCommand(options) {
10721
10612
  const rootDir = process.cwd();
10722
10613
  if (!process.env.NODE_ENV) process.env.NODE_ENV = "development";
@@ -10740,7 +10631,7 @@ async function devCommand(options) {
10740
10631
  console.log("- Copying resources...");
10741
10632
  const copied = await copyResources(rootDir, devDist);
10742
10633
  if (copied)
10743
- console.log(` Copied src/resources \u2192 ${path32.resolve(rootDir, devDist, "resources")}`);
10634
+ console.log(` Copied src/resources \u2192 ${path33.resolve(rootDir, devDist, "resources")}`);
10744
10635
  console.log("- Starting dev app...");
10745
10636
  const app = await createDevApp({ rootDir, port: options?.port });
10746
10637
  await app.listen();
@@ -10749,7 +10640,7 @@ async function devCommand(options) {
10749
10640
  async function generateRouteArtifacts(rootDir, patterns, dist) {
10750
10641
  const { routes, wsRoutes } = await scanRoutes(rootDir, patterns, dist);
10751
10642
  const sorted = sortRoutes(routes);
10752
- const routesPath = path32.resolve(rootDir, dist, ROUTES_FILE2);
10643
+ const routesPath = path33.resolve(rootDir, dist, ROUTES_FILE2);
10753
10644
  const serialized = serializeRoutes(sorted, wsRoutes, rootDir, dist);
10754
10645
  await writeRoutesModule(serialized, routesPath);
10755
10646
  }
@@ -10764,7 +10655,7 @@ async function generateAgentArtifactsForDev(rootDir, dist) {
10764
10655
  async function generateTaskArtifactsForDev(rootDir, dist) {
10765
10656
  const tasks = await scanTasks(rootDir, TASK_PATTERNS);
10766
10657
  for (const task of tasks) {
10767
- await ensureCompiled(path32.resolve(rootDir, task.filePath), rootDir, dist);
10658
+ await ensureCompiled(path33.resolve(rootDir, task.filePath), rootDir, dist);
10768
10659
  }
10769
10660
  await generateTaskArtifacts(tasks, rootDir, dist);
10770
10661
  }
@@ -10813,15 +10704,15 @@ var buildCommand_exports = {};
10813
10704
  __export(buildCommand_exports, {
10814
10705
  buildCommand: () => buildCommand
10815
10706
  });
10816
- import path33 from "path";
10817
- import fs23 from "fs";
10707
+ import path34 from "path";
10708
+ import fs24 from "fs";
10818
10709
  async function buildCommand(options) {
10819
10710
  const rootDir = options?.rootDir ?? process.cwd();
10820
10711
  const outdir = options?.dist ?? DEFAULT_DIST2;
10821
- const absOut = path33.resolve(rootDir, outdir);
10822
- const realRoot = toRealPath(path33.resolve(rootDir));
10712
+ const absOut = path34.resolve(rootDir, outdir);
10713
+ const realRoot = toRealPath(path34.resolve(rootDir));
10823
10714
  if (isInsideDir(toRealPath(absOut), realRoot)) {
10824
- fs23.rmSync(absOut, { recursive: true, force: true });
10715
+ fs24.rmSync(absOut, { recursive: true, force: true });
10825
10716
  } else {
10826
10717
  console.warn(
10827
10718
  `! Output directory "${outdir}" is outside the project root, skipping clean (stale artifacts may remain)`
@@ -10829,10 +10720,10 @@ async function buildCommand(options) {
10829
10720
  }
10830
10721
  await compileConfig({ rootDir, dist: outdir });
10831
10722
  const _config = await loadConfig(rootDir, outdir);
10832
- const pkgPath = path33.resolve(rootDir, "package.json");
10833
- if (fs23.existsSync(pkgPath)) {
10723
+ const pkgPath = path34.resolve(rootDir, "package.json");
10724
+ if (fs24.existsSync(pkgPath)) {
10834
10725
  try {
10835
- const pkg = JSON.parse(fs23.readFileSync(pkgPath, "utf-8"));
10726
+ const pkg = JSON.parse(fs24.readFileSync(pkgPath, "utf-8"));
10836
10727
  if (pkg.type !== "module") {
10837
10728
  console.warn(
10838
10729
  '! package.json is missing "type": "module" \u2014 build output is ESM and `node dist/main` will fail without it'
@@ -10860,7 +10751,7 @@ async function buildCommand(options) {
10860
10751
  if (localPluginSources.length > 0) {
10861
10752
  console.log("\n[2.5/9] Compiling local plugins...");
10862
10753
  const outside = localPluginSources.filter((p) => {
10863
- const rel = path33.relative(rootDir, p).replace(/\\/g, "/");
10754
+ const rel = path34.relative(rootDir, p).replace(/\\/g, "/");
10864
10755
  return !rel.startsWith("src/");
10865
10756
  });
10866
10757
  if (outside.length > 0) {
@@ -10875,9 +10766,9 @@ async function buildCommand(options) {
10875
10766
  reportRouteConflicts(sorted);
10876
10767
  console.log("\n[4/9] Generating schema...");
10877
10768
  await generateSchemaFiles(sorted, rootDir, outdir, wsRoutes);
10878
- console.log(` Schema: zod.js files under ${path33.resolve(rootDir, outdir)}`);
10769
+ console.log(` Schema: zod.js files under ${path34.resolve(rootDir, outdir)}`);
10879
10770
  console.log("\n[5/9] Generating routes manifest...");
10880
- const routesPath = path33.resolve(rootDir, outdir, "faapi-routes.js");
10771
+ const routesPath = path34.resolve(rootDir, outdir, "faapi-routes.js");
10881
10772
  const serialized = serializeRoutes(sorted, wsRoutes, rootDir, outdir);
10882
10773
  await writeRoutesModule(serialized, routesPath);
10883
10774
  console.log(` Written to ${routesPath}`);
@@ -10885,24 +10776,24 @@ async function buildCommand(options) {
10885
10776
  const tools = await scanTools(rootDir, TOOL_PATTERNS);
10886
10777
  const toolMeta = await generateToolArtifacts(tools, rootDir, outdir);
10887
10778
  console.log(` Found ${toolMeta.length} tool(s)`);
10888
- console.log(` Tool manifest: ${path33.resolve(rootDir, outdir, "faapi-tools.js")}`);
10779
+ console.log(` Tool manifest: ${path34.resolve(rootDir, outdir, "faapi-tools.js")}`);
10889
10780
  console.log("\n[7/9] Generating agent manifest...");
10890
10781
  const agents = await scanAgents(rootDir, DEFAULT_AGENT_PATTERNS);
10891
10782
  const agentMeta = await generateAgentArtifacts(agents, rootDir, outdir);
10892
10783
  console.log(` Found ${agentMeta.length} agent(s)`);
10893
- console.log(` Agent manifest: ${path33.resolve(rootDir, outdir, "faapi-agents.js")}`);
10784
+ console.log(` Agent manifest: ${path34.resolve(rootDir, outdir, "faapi-agents.js")}`);
10894
10785
  console.log("\n[7.5/9] Generating task manifest and schema...");
10895
10786
  const tasks = await scanTasks(rootDir, TASK_PATTERNS);
10896
10787
  const taskMeta = await generateTaskArtifacts(tasks, rootDir, outdir);
10897
10788
  console.log(` Found ${taskMeta.length} task(s)`);
10898
- console.log(` Task manifest: ${path33.resolve(rootDir, outdir, "faapi-tasks.js")}`);
10789
+ console.log(` Task manifest: ${path34.resolve(rootDir, outdir, "faapi-tasks.js")}`);
10899
10790
  console.log("\n[8/9] Copying resources...");
10900
10791
  const resourcesCopied = await copyResources(rootDir, outdir);
10901
10792
  if (resourcesCopied) {
10902
- console.log(` Copied src/resources \u2192 ${path33.resolve(rootDir, outdir, "resources")}`);
10793
+ console.log(` Copied src/resources \u2192 ${path34.resolve(rootDir, outdir, "resources")}`);
10903
10794
  }
10904
10795
  console.log("\n[9/9] Generating entry file...");
10905
- const mainPath = path33.resolve(rootDir, outdir, "main.js");
10796
+ const mainPath = path34.resolve(rootDir, outdir, "main.js");
10906
10797
  const createProdAppArgs = options?.dist && options.dist !== DEFAULT_DIST2 ? `{ dist: ${JSON.stringify(outdir)} }` : "";
10907
10798
  const mainContent = `// \u7531 faapi build \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u52A8\u7F16\u8F91
10908
10799
  import { createProdApp, loadEnv } from '@faapi/faapi';
@@ -10914,7 +10805,7 @@ loadEnv(process.cwd());
10914
10805
  const app = await createProdApp(${createProdAppArgs});
10915
10806
  await app.listen();
10916
10807
  `;
10917
- await fs23.promises.writeFile(mainPath, mainContent, "utf-8");
10808
+ await fs24.promises.writeFile(mainPath, mainContent, "utf-8");
10918
10809
  console.log(` Written to ${mainPath}`);
10919
10810
  console.log("\nfaapi build completed");
10920
10811
  }
@@ -10928,7 +10819,7 @@ function extractLocalPluginSources(declarations, rootDir) {
10928
10819
  else if (Array.isArray(decl)) specifier = decl[0];
10929
10820
  else if ("path" in decl) specifier = decl.path;
10930
10821
  if (!specifier) continue;
10931
- if (!specifier.startsWith("./") && !specifier.startsWith("../") && !path33.isAbsolute(specifier)) {
10822
+ if (!specifier.startsWith("./") && !specifier.startsWith("../") && !path34.isAbsolute(specifier)) {
10932
10823
  continue;
10933
10824
  }
10934
10825
  const source = resolveLocalPluginSource(specifier, rootDir);