@faapi/faapi 0.0.0-canary.f5b23c6 → 1.0.0-canary.4f644f8

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
@@ -235,7 +235,7 @@ async function compileDevRoutes(options) {
235
235
  const plugins = buildAliasPlugins(rootDir);
236
236
  const esbuild = await import("esbuild");
237
237
  const outbase = path3.resolve(rootDir, APP_DIR2);
238
- await esbuild.build({
238
+ const result = await esbuild.build({
239
239
  entryPoints,
240
240
  outdir: absDist,
241
241
  outbase,
@@ -245,8 +245,19 @@ async function compileDevRoutes(options) {
245
245
  sourcemap: true,
246
246
  packages: "external",
247
247
  plugins,
248
- logLevel
248
+ logLevel,
249
+ write: false
249
250
  });
251
+ if (result.outputFiles) {
252
+ await Promise.all(
253
+ result.outputFiles.map(async (file) => {
254
+ await fs3.promises.mkdir(path3.dirname(file.path), { recursive: true });
255
+ const tmp = `${file.path}.tmp-${process.pid}-${Math.random().toString(36).slice(2)}`;
256
+ await fs3.promises.writeFile(tmp, file.contents);
257
+ await fs3.promises.rename(tmp, file.path);
258
+ })
259
+ );
260
+ }
250
261
  return { compiledFiles: entryPoints };
251
262
  }
252
263
  var APP_DIR2;
@@ -258,35 +269,6 @@ var init_compileDevRoutes = __esm({
258
269
  }
259
270
  });
260
271
 
261
- // src/config/deepMerge.ts
262
- function deepMerge(base, override) {
263
- const result = { ...base };
264
- for (const key of Object.keys(override)) {
265
- const baseVal = base[key];
266
- const overVal = override[key];
267
- if (baseVal instanceof Date || overVal instanceof Date || baseVal instanceof RegExp || overVal instanceof RegExp || baseVal instanceof Map || overVal instanceof Map || baseVal instanceof Set || overVal instanceof Set) {
268
- result[key] = overVal;
269
- continue;
270
- }
271
- if (baseVal !== null && overVal !== null && typeof baseVal === "object" && typeof overVal === "object" && !Array.isArray(baseVal) && !Array.isArray(overVal) && !(baseVal instanceof Function) && !(overVal instanceof Function)) {
272
- result[key] = deepMerge(
273
- baseVal,
274
- overVal
275
- );
276
- } else {
277
- result[key] = overVal;
278
- }
279
- }
280
- return result;
281
- }
282
- var DEEP_MERGE_SOURCE;
283
- var init_deepMerge = __esm({
284
- "src/config/deepMerge.ts"() {
285
- "use strict";
286
- DEEP_MERGE_SOURCE = `const deepMerge = ${deepMerge.toString()};`;
287
- }
288
- });
289
-
290
272
  // src/cli/compileConfig.ts
291
273
  import path4 from "path";
292
274
  import fs4 from "fs";
@@ -301,9 +283,6 @@ function isInsideDir2(filePath, dir) {
301
283
  const rel = path4.relative(dir, filePath);
302
284
  return rel !== "" && !rel.startsWith("..") && !path4.isAbsolute(rel);
303
285
  }
304
- function getEnv() {
305
- return process.env.FAAPI_ENV || process.env.NODE_ENV || "development";
306
- }
307
286
  function findBaseConfig(rootDir) {
308
287
  for (const f of BASE_CONFIG_FILES) {
309
288
  if (fs4.existsSync(path4.join(rootDir, f))) {
@@ -312,15 +291,6 @@ function findBaseConfig(rootDir) {
312
291
  }
313
292
  return null;
314
293
  }
315
- function findEnvConfig(rootDir, env) {
316
- for (const ext of ENV_CONFIG_EXTS) {
317
- const f = `faapi.config.${env}${ext}`;
318
- if (fs4.existsSync(path4.join(rootDir, f))) {
319
- return f;
320
- }
321
- }
322
- return null;
323
- }
324
294
  function toProdExtension2(filePath) {
325
295
  if (filePath.endsWith(".ts")) return filePath.slice(0, -3) + ".js";
326
296
  if (filePath.endsWith(".tsx")) return filePath.slice(0, -4) + ".js";
@@ -394,14 +364,9 @@ async function compileConfig(options) {
394
364
  if (!baseConfigName) {
395
365
  return { generated: false, outputFile: "" };
396
366
  }
397
- const env = getEnv();
398
- const envConfigName = findEnvConfig(rootDir, env);
399
367
  const absDist = path4.resolve(rootDir, dist);
400
368
  await fs4.promises.mkdir(absDist, { recursive: true });
401
369
  const configEntryPoints = [path4.resolve(rootDir, baseConfigName)];
402
- if (envConfigName) {
403
- configEntryPoints.push(path4.resolve(rootDir, envConfigName));
404
- }
405
370
  const { appDirFiles, nonAppDirFiles } = await collectRelativeImports(configEntryPoints, rootDir);
406
371
  const esbuild = await import("esbuild");
407
372
  const aliasPlugins = buildAliasPlugins(rootDir);
@@ -434,16 +399,8 @@ async function compileConfig(options) {
434
399
  });
435
400
  }
436
401
  const baseImport = `import base from './${toProdImport(baseConfigName)}';`;
437
- const imports = [baseImport];
438
- let exportDefault;
439
- if (envConfigName) {
440
- const envImport = `import env from './${toProdImport(envConfigName)}';`;
441
- imports.push(envImport);
442
- exportDefault = "export default deepMerge(base, env);";
443
- } else {
444
- exportDefault = "export default base;";
445
- }
446
- const entryCode = [...imports, DEEP_MERGE_SOURCE, exportDefault].join("\n");
402
+ const exportDefault = "export default base;";
403
+ const entryCode = [baseImport, exportDefault].join("\n");
447
404
  const outputFile = path4.resolve(absDist, "faapi-config.js");
448
405
  await esbuild.build({
449
406
  stdin: { contents: entryCode, resolveDir: absDist, loader: "ts" },
@@ -459,14 +416,12 @@ async function compileConfig(options) {
459
416
  });
460
417
  return { generated: true, outputFile };
461
418
  }
462
- var BASE_CONFIG_FILES, ENV_CONFIG_EXTS, SPEC_RE;
419
+ var BASE_CONFIG_FILES, SPEC_RE;
463
420
  var init_compileConfig = __esm({
464
421
  "src/cli/compileConfig.ts"() {
465
422
  "use strict";
466
- init_deepMerge();
467
423
  init_aliasPlugin();
468
424
  BASE_CONFIG_FILES = ["faapi.config.ts", "faapi.config.js"];
469
- ENV_CONFIG_EXTS = [".ts", ".js"];
470
425
  SPEC_RE = /(\bfrom\s*|import\s*\(\s*)(['"])([^'"]+)\2/g;
471
426
  }
472
427
  });
@@ -1859,7 +1814,7 @@ function toProdFilePath(filePath, dist) {
1859
1814
  const jsPath = rel.replace(/\.ts$/, ".js");
1860
1815
  return jsPath.startsWith(`${dist}/`) ? jsPath : `${dist}/${jsPath}`;
1861
1816
  }
1862
- function serializeRoutes(routes, wsRoutes, rootDir, dist = ".faapi/build") {
1817
+ function serializeRoutes(routes, wsRoutes, rootDir, dist = "dist") {
1863
1818
  const serialize = (route) => {
1864
1819
  const middlewarePaths = extractMiddlewarePaths(route.filePath, rootDir, dist);
1865
1820
  const serialized = {
@@ -1981,9 +1936,9 @@ var init_constants = __esm({
1981
1936
  });
1982
1937
 
1983
1938
  // src/utils/normalizePath.ts
1984
- function normalizePath(path17) {
1985
- if (!path17) return "";
1986
- let result = path17.replace(/\\/g, "/");
1939
+ function normalizePath(path18) {
1940
+ if (!path18) return "";
1941
+ let result = path18.replace(/\\/g, "/");
1987
1942
  result = result.replace(/\/+/g, "/");
1988
1943
  result = result.replace(/\/+$/, "");
1989
1944
  if (result && !result.startsWith("/")) {
@@ -2236,6 +2191,92 @@ var init_loadConfig = __esm({
2236
2191
  }
2237
2192
  });
2238
2193
 
2194
+ // src/cli/loadEnv.ts
2195
+ import fs9 from "fs";
2196
+ import path10 from "path";
2197
+ function resolveEnv() {
2198
+ return process.env.NODE_ENV || "development";
2199
+ }
2200
+ function getEnvFiles(env) {
2201
+ return [".env", ".env.local", `.env.${env}`, `.env.${env}.local`];
2202
+ }
2203
+ function parseEnvFile(content, fileVars) {
2204
+ const result = {};
2205
+ const lines = content.replace(/\r\n/g, "\n").split("\n");
2206
+ for (const line of lines) {
2207
+ const trimmed = line.trim();
2208
+ if (!trimmed || trimmed.startsWith("#")) continue;
2209
+ const match = /^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(trimmed);
2210
+ if (!match) continue;
2211
+ const [, key, rawValue] = match;
2212
+ const value = parseValue(rawValue, { ...fileVars, ...result });
2213
+ result[key] = value;
2214
+ }
2215
+ return result;
2216
+ }
2217
+ function parseValue(raw, env) {
2218
+ if (raw === "") return "";
2219
+ if (raw[0] === "'") {
2220
+ const end = raw.indexOf("'", 1);
2221
+ return end === -1 ? raw.slice(1) : raw.slice(1, end);
2222
+ }
2223
+ if (raw[0] === '"') {
2224
+ const match = /^"((?:\\.|[^"\\])*)"/.exec(raw);
2225
+ const inner = match ? match[1] : raw.slice(1);
2226
+ return expandEscapesAndVars(inner, env);
2227
+ }
2228
+ const commentMatch = /^(.*?)(\s+#.*)$/.exec(raw);
2229
+ const value = commentMatch ? commentMatch[1] : raw;
2230
+ return value.trim();
2231
+ }
2232
+ function expandEscapesAndVars(str, env) {
2233
+ const escaped = str.replace(/\\(.)/g, (_, ch) => {
2234
+ switch (ch) {
2235
+ case "n":
2236
+ return "\n";
2237
+ case "r":
2238
+ return "\r";
2239
+ case "t":
2240
+ return " ";
2241
+ case "\\":
2242
+ return "\\";
2243
+ case '"':
2244
+ return '"';
2245
+ default:
2246
+ return ch;
2247
+ }
2248
+ });
2249
+ return escaped.replace(
2250
+ /\$\{([A-Za-z_][A-Za-z0-9_]*)\}|\$([A-Za-z_][A-Za-z0-9_]*)/g,
2251
+ (_, braced, plain) => {
2252
+ const varName = braced || plain;
2253
+ return env[varName] ?? process.env[varName] ?? "";
2254
+ }
2255
+ );
2256
+ }
2257
+ function loadEnv(rootDir) {
2258
+ const env = resolveEnv();
2259
+ const files = getEnvFiles(env);
2260
+ const merged = {};
2261
+ for (const file of files) {
2262
+ const filePath = path10.join(rootDir, file);
2263
+ if (!fs9.existsSync(filePath)) continue;
2264
+ const content = fs9.readFileSync(filePath, "utf-8");
2265
+ const parsed = parseEnvFile(content, merged);
2266
+ Object.assign(merged, parsed);
2267
+ }
2268
+ for (const [key, value] of Object.entries(merged)) {
2269
+ if (process.env[key] === void 0) {
2270
+ process.env[key] = value;
2271
+ }
2272
+ }
2273
+ }
2274
+ var init_loadEnv = __esm({
2275
+ "src/cli/loadEnv.ts"() {
2276
+ "use strict";
2277
+ }
2278
+ });
2279
+
2239
2280
  // ../../node_modules/.pnpm/readdirp@4.1.2/node_modules/readdirp/esm/index.js
2240
2281
  import { stat, lstat, readdir, realpath } from "fs/promises";
2241
2282
  import { Readable } from "stream";
@@ -2326,7 +2367,7 @@ var init_esm = __esm({
2326
2367
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
2327
2368
  const statMethod = opts.lstat ? lstat : stat;
2328
2369
  if (wantBigintFsStats) {
2329
- this._stat = (path17) => statMethod(path17, { bigint: true });
2370
+ this._stat = (path18) => statMethod(path18, { bigint: true });
2330
2371
  } else {
2331
2372
  this._stat = statMethod;
2332
2373
  }
@@ -2351,8 +2392,8 @@ var init_esm = __esm({
2351
2392
  const par = this.parent;
2352
2393
  const fil = par && par.files;
2353
2394
  if (fil && fil.length > 0) {
2354
- const { path: path17, depth } = par;
2355
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path17));
2395
+ const { path: path18, depth } = par;
2396
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path18));
2356
2397
  const awaited = await Promise.all(slice);
2357
2398
  for (const entry of awaited) {
2358
2399
  if (!entry)
@@ -2392,20 +2433,20 @@ var init_esm = __esm({
2392
2433
  this.reading = false;
2393
2434
  }
2394
2435
  }
2395
- async _exploreDir(path17, depth) {
2436
+ async _exploreDir(path18, depth) {
2396
2437
  let files;
2397
2438
  try {
2398
- files = await readdir(path17, this._rdOptions);
2439
+ files = await readdir(path18, this._rdOptions);
2399
2440
  } catch (error) {
2400
2441
  this._onError(error);
2401
2442
  }
2402
- return { files, depth, path: path17 };
2443
+ return { files, depth, path: path18 };
2403
2444
  }
2404
- async _formatEntry(dirent, path17) {
2445
+ async _formatEntry(dirent, path18) {
2405
2446
  let entry;
2406
2447
  const basename3 = this._isDirent ? dirent.name : dirent;
2407
2448
  try {
2408
- const fullPath = presolve(pjoin(path17, basename3));
2449
+ const fullPath = presolve(pjoin(path18, basename3));
2409
2450
  entry = { path: prelative(this._root, fullPath), fullPath, basename: basename3 };
2410
2451
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
2411
2452
  } catch (err) {
@@ -2466,16 +2507,16 @@ import { watchFile, unwatchFile, watch as fs_watch } from "fs";
2466
2507
  import { open, stat as stat2, lstat as lstat2, realpath as fsrealpath } from "fs/promises";
2467
2508
  import * as sysPath from "path";
2468
2509
  import { type as osType } from "os";
2469
- function createFsWatchInstance(path17, options, listener, errHandler, emitRaw) {
2510
+ function createFsWatchInstance(path18, options, listener, errHandler, emitRaw) {
2470
2511
  const handleEvent = (rawEvent, evPath) => {
2471
- listener(path17);
2472
- emitRaw(rawEvent, evPath, { watchedPath: path17 });
2473
- if (evPath && path17 !== evPath) {
2474
- fsWatchBroadcast(sysPath.resolve(path17, evPath), KEY_LISTENERS, sysPath.join(path17, evPath));
2512
+ listener(path18);
2513
+ emitRaw(rawEvent, evPath, { watchedPath: path18 });
2514
+ if (evPath && path18 !== evPath) {
2515
+ fsWatchBroadcast(sysPath.resolve(path18, evPath), KEY_LISTENERS, sysPath.join(path18, evPath));
2475
2516
  }
2476
2517
  };
2477
2518
  try {
2478
- return fs_watch(path17, {
2519
+ return fs_watch(path18, {
2479
2520
  persistent: options.persistent
2480
2521
  }, handleEvent);
2481
2522
  } catch (error) {
@@ -2820,12 +2861,12 @@ var init_handler = __esm({
2820
2861
  listener(val1, val2, val3);
2821
2862
  });
2822
2863
  };
2823
- setFsWatchListener = (path17, fullPath, options, handlers) => {
2864
+ setFsWatchListener = (path18, fullPath, options, handlers) => {
2824
2865
  const { listener, errHandler, rawEmitter } = handlers;
2825
2866
  let cont = FsWatchInstances.get(fullPath);
2826
2867
  let watcher;
2827
2868
  if (!options.persistent) {
2828
- watcher = createFsWatchInstance(path17, options, listener, errHandler, rawEmitter);
2869
+ watcher = createFsWatchInstance(path18, options, listener, errHandler, rawEmitter);
2829
2870
  if (!watcher)
2830
2871
  return;
2831
2872
  return watcher.close.bind(watcher);
@@ -2836,7 +2877,7 @@ var init_handler = __esm({
2836
2877
  addAndConvert(cont, KEY_RAW, rawEmitter);
2837
2878
  } else {
2838
2879
  watcher = createFsWatchInstance(
2839
- path17,
2880
+ path18,
2840
2881
  options,
2841
2882
  fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
2842
2883
  errHandler,
@@ -2851,7 +2892,7 @@ var init_handler = __esm({
2851
2892
  cont.watcherUnusable = true;
2852
2893
  if (isWindows && error.code === "EPERM") {
2853
2894
  try {
2854
- const fd = await open(path17, "r");
2895
+ const fd = await open(path18, "r");
2855
2896
  await fd.close();
2856
2897
  broadcastErr(error);
2857
2898
  } catch (err) {
@@ -2882,7 +2923,7 @@ var init_handler = __esm({
2882
2923
  };
2883
2924
  };
2884
2925
  FsWatchFileInstances = /* @__PURE__ */ new Map();
2885
- setFsWatchFileListener = (path17, fullPath, options, handlers) => {
2926
+ setFsWatchFileListener = (path18, fullPath, options, handlers) => {
2886
2927
  const { listener, rawEmitter } = handlers;
2887
2928
  let cont = FsWatchFileInstances.get(fullPath);
2888
2929
  const copts = cont && cont.options;
@@ -2904,7 +2945,7 @@ var init_handler = __esm({
2904
2945
  });
2905
2946
  const currmtime = curr.mtimeMs;
2906
2947
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
2907
- foreach(cont.listeners, (listener2) => listener2(path17, curr));
2948
+ foreach(cont.listeners, (listener2) => listener2(path18, curr));
2908
2949
  }
2909
2950
  })
2910
2951
  };
@@ -2932,13 +2973,13 @@ var init_handler = __esm({
2932
2973
  * @param listener on fs change
2933
2974
  * @returns closer for the watcher instance
2934
2975
  */
2935
- _watchWithNodeFs(path17, listener) {
2976
+ _watchWithNodeFs(path18, listener) {
2936
2977
  const opts = this.fsw.options;
2937
- const directory = sysPath.dirname(path17);
2938
- const basename3 = sysPath.basename(path17);
2978
+ const directory = sysPath.dirname(path18);
2979
+ const basename3 = sysPath.basename(path18);
2939
2980
  const parent = this.fsw._getWatchedDir(directory);
2940
2981
  parent.add(basename3);
2941
- const absolutePath = sysPath.resolve(path17);
2982
+ const absolutePath = sysPath.resolve(path18);
2942
2983
  const options = {
2943
2984
  persistent: opts.persistent
2944
2985
  };
@@ -2948,12 +2989,12 @@ var init_handler = __esm({
2948
2989
  if (opts.usePolling) {
2949
2990
  const enableBin = opts.interval !== opts.binaryInterval;
2950
2991
  options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
2951
- closer = setFsWatchFileListener(path17, absolutePath, options, {
2992
+ closer = setFsWatchFileListener(path18, absolutePath, options, {
2952
2993
  listener,
2953
2994
  rawEmitter: this.fsw._emitRaw
2954
2995
  });
2955
2996
  } else {
2956
- closer = setFsWatchListener(path17, absolutePath, options, {
2997
+ closer = setFsWatchListener(path18, absolutePath, options, {
2957
2998
  listener,
2958
2999
  errHandler: this._boundHandleError,
2959
3000
  rawEmitter: this.fsw._emitRaw
@@ -2975,7 +3016,7 @@ var init_handler = __esm({
2975
3016
  let prevStats = stats;
2976
3017
  if (parent.has(basename3))
2977
3018
  return;
2978
- const listener = async (path17, newStats) => {
3019
+ const listener = async (path18, newStats) => {
2979
3020
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
2980
3021
  return;
2981
3022
  if (!newStats || newStats.mtimeMs === 0) {
@@ -2989,11 +3030,11 @@ var init_handler = __esm({
2989
3030
  this.fsw._emit(EV.CHANGE, file, newStats2);
2990
3031
  }
2991
3032
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
2992
- this.fsw._closeFile(path17);
3033
+ this.fsw._closeFile(path18);
2993
3034
  prevStats = newStats2;
2994
3035
  const closer2 = this._watchWithNodeFs(file, listener);
2995
3036
  if (closer2)
2996
- this.fsw._addPathCloser(path17, closer2);
3037
+ this.fsw._addPathCloser(path18, closer2);
2997
3038
  } else {
2998
3039
  prevStats = newStats2;
2999
3040
  }
@@ -3025,7 +3066,7 @@ var init_handler = __esm({
3025
3066
  * @param item basename of this item
3026
3067
  * @returns true if no more processing is needed for this entry.
3027
3068
  */
3028
- async _handleSymlink(entry, directory, path17, item) {
3069
+ async _handleSymlink(entry, directory, path18, item) {
3029
3070
  if (this.fsw.closed) {
3030
3071
  return;
3031
3072
  }
@@ -3035,7 +3076,7 @@ var init_handler = __esm({
3035
3076
  this.fsw._incrReadyCount();
3036
3077
  let linkPath;
3037
3078
  try {
3038
- linkPath = await fsrealpath(path17);
3079
+ linkPath = await fsrealpath(path18);
3039
3080
  } catch (e) {
3040
3081
  this.fsw._emitReady();
3041
3082
  return true;
@@ -3045,12 +3086,12 @@ var init_handler = __esm({
3045
3086
  if (dir.has(item)) {
3046
3087
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
3047
3088
  this.fsw._symlinkPaths.set(full, linkPath);
3048
- this.fsw._emit(EV.CHANGE, path17, entry.stats);
3089
+ this.fsw._emit(EV.CHANGE, path18, entry.stats);
3049
3090
  }
3050
3091
  } else {
3051
3092
  dir.add(item);
3052
3093
  this.fsw._symlinkPaths.set(full, linkPath);
3053
- this.fsw._emit(EV.ADD, path17, entry.stats);
3094
+ this.fsw._emit(EV.ADD, path18, entry.stats);
3054
3095
  }
3055
3096
  this.fsw._emitReady();
3056
3097
  return true;
@@ -3079,9 +3120,9 @@ var init_handler = __esm({
3079
3120
  return;
3080
3121
  }
3081
3122
  const item = entry.path;
3082
- let path17 = sysPath.join(directory, item);
3123
+ let path18 = sysPath.join(directory, item);
3083
3124
  current.add(item);
3084
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path17, item)) {
3125
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path18, item)) {
3085
3126
  return;
3086
3127
  }
3087
3128
  if (this.fsw.closed) {
@@ -3090,8 +3131,8 @@ var init_handler = __esm({
3090
3131
  }
3091
3132
  if (item === target || !target && !previous.has(item)) {
3092
3133
  this.fsw._incrReadyCount();
3093
- path17 = sysPath.join(dir, sysPath.relative(dir, path17));
3094
- this._addToNodeFs(path17, initialAdd, wh, depth + 1);
3134
+ path18 = sysPath.join(dir, sysPath.relative(dir, path18));
3135
+ this._addToNodeFs(path18, initialAdd, wh, depth + 1);
3095
3136
  }
3096
3137
  }).on(EV.ERROR, this._boundHandleError);
3097
3138
  return new Promise((resolve3, reject) => {
@@ -3160,13 +3201,13 @@ var init_handler = __esm({
3160
3201
  * @param depth Child path actually targeted for watch
3161
3202
  * @param target Child path actually targeted for watch
3162
3203
  */
3163
- async _addToNodeFs(path17, initialAdd, priorWh, depth, target) {
3204
+ async _addToNodeFs(path18, initialAdd, priorWh, depth, target) {
3164
3205
  const ready = this.fsw._emitReady;
3165
- if (this.fsw._isIgnored(path17) || this.fsw.closed) {
3206
+ if (this.fsw._isIgnored(path18) || this.fsw.closed) {
3166
3207
  ready();
3167
3208
  return false;
3168
3209
  }
3169
- const wh = this.fsw._getWatchHelpers(path17);
3210
+ const wh = this.fsw._getWatchHelpers(path18);
3170
3211
  if (priorWh) {
3171
3212
  wh.filterPath = (entry) => priorWh.filterPath(entry);
3172
3213
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -3182,8 +3223,8 @@ var init_handler = __esm({
3182
3223
  const follow = this.fsw.options.followSymlinks;
3183
3224
  let closer;
3184
3225
  if (stats.isDirectory()) {
3185
- const absPath = sysPath.resolve(path17);
3186
- const targetPath = follow ? await fsrealpath(path17) : path17;
3226
+ const absPath = sysPath.resolve(path18);
3227
+ const targetPath = follow ? await fsrealpath(path18) : path18;
3187
3228
  if (this.fsw.closed)
3188
3229
  return;
3189
3230
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -3193,29 +3234,29 @@ var init_handler = __esm({
3193
3234
  this.fsw._symlinkPaths.set(absPath, targetPath);
3194
3235
  }
3195
3236
  } else if (stats.isSymbolicLink()) {
3196
- const targetPath = follow ? await fsrealpath(path17) : path17;
3237
+ const targetPath = follow ? await fsrealpath(path18) : path18;
3197
3238
  if (this.fsw.closed)
3198
3239
  return;
3199
3240
  const parent = sysPath.dirname(wh.watchPath);
3200
3241
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
3201
3242
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
3202
- closer = await this._handleDir(parent, stats, initialAdd, depth, path17, wh, targetPath);
3243
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path18, wh, targetPath);
3203
3244
  if (this.fsw.closed)
3204
3245
  return;
3205
3246
  if (targetPath !== void 0) {
3206
- this.fsw._symlinkPaths.set(sysPath.resolve(path17), targetPath);
3247
+ this.fsw._symlinkPaths.set(sysPath.resolve(path18), targetPath);
3207
3248
  }
3208
3249
  } else {
3209
3250
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
3210
3251
  }
3211
3252
  ready();
3212
3253
  if (closer)
3213
- this.fsw._addPathCloser(path17, closer);
3254
+ this.fsw._addPathCloser(path18, closer);
3214
3255
  return false;
3215
3256
  } catch (error) {
3216
3257
  if (this.fsw._handleError(error)) {
3217
3258
  ready();
3218
- return path17;
3259
+ return path18;
3219
3260
  }
3220
3261
  }
3221
3262
  }
@@ -3254,26 +3295,26 @@ function createPattern(matcher) {
3254
3295
  }
3255
3296
  return () => false;
3256
3297
  }
3257
- function normalizePath2(path17) {
3258
- if (typeof path17 !== "string")
3298
+ function normalizePath2(path18) {
3299
+ if (typeof path18 !== "string")
3259
3300
  throw new Error("string expected");
3260
- path17 = sysPath2.normalize(path17);
3261
- path17 = path17.replace(/\\/g, "/");
3301
+ path18 = sysPath2.normalize(path18);
3302
+ path18 = path18.replace(/\\/g, "/");
3262
3303
  let prepend = false;
3263
- if (path17.startsWith("//"))
3304
+ if (path18.startsWith("//"))
3264
3305
  prepend = true;
3265
3306
  const DOUBLE_SLASH_RE2 = /\/\//;
3266
- while (path17.match(DOUBLE_SLASH_RE2))
3267
- path17 = path17.replace(DOUBLE_SLASH_RE2, "/");
3307
+ while (path18.match(DOUBLE_SLASH_RE2))
3308
+ path18 = path18.replace(DOUBLE_SLASH_RE2, "/");
3268
3309
  if (prepend)
3269
- path17 = "/" + path17;
3270
- return path17;
3310
+ path18 = "/" + path18;
3311
+ return path18;
3271
3312
  }
3272
3313
  function matchPatterns(patterns, testString, stats) {
3273
- const path17 = normalizePath2(testString);
3314
+ const path18 = normalizePath2(testString);
3274
3315
  for (let index = 0; index < patterns.length; index++) {
3275
3316
  const pattern = patterns[index];
3276
- if (pattern(path17, stats)) {
3317
+ if (pattern(path18, stats)) {
3277
3318
  return true;
3278
3319
  }
3279
3320
  }
@@ -3334,19 +3375,19 @@ var init_esm2 = __esm({
3334
3375
  }
3335
3376
  return str;
3336
3377
  };
3337
- normalizePathToUnix = (path17) => toUnix(sysPath2.normalize(toUnix(path17)));
3338
- normalizeIgnored = (cwd = "") => (path17) => {
3339
- if (typeof path17 === "string") {
3340
- return normalizePathToUnix(sysPath2.isAbsolute(path17) ? path17 : sysPath2.join(cwd, path17));
3378
+ normalizePathToUnix = (path18) => toUnix(sysPath2.normalize(toUnix(path18)));
3379
+ normalizeIgnored = (cwd = "") => (path18) => {
3380
+ if (typeof path18 === "string") {
3381
+ return normalizePathToUnix(sysPath2.isAbsolute(path18) ? path18 : sysPath2.join(cwd, path18));
3341
3382
  } else {
3342
- return path17;
3383
+ return path18;
3343
3384
  }
3344
3385
  };
3345
- getAbsolutePath = (path17, cwd) => {
3346
- if (sysPath2.isAbsolute(path17)) {
3347
- return path17;
3386
+ getAbsolutePath = (path18, cwd) => {
3387
+ if (sysPath2.isAbsolute(path18)) {
3388
+ return path18;
3348
3389
  }
3349
- return sysPath2.join(cwd, path17);
3390
+ return sysPath2.join(cwd, path18);
3350
3391
  };
3351
3392
  EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
3352
3393
  DirEntry = class {
@@ -3401,10 +3442,10 @@ var init_esm2 = __esm({
3401
3442
  STAT_METHOD_F = "stat";
3402
3443
  STAT_METHOD_L = "lstat";
3403
3444
  WatchHelper = class {
3404
- constructor(path17, follow, fsw) {
3445
+ constructor(path18, follow, fsw) {
3405
3446
  this.fsw = fsw;
3406
- const watchPath = path17;
3407
- this.path = path17 = path17.replace(REPLACER_RE, "");
3447
+ const watchPath = path18;
3448
+ this.path = path18 = path18.replace(REPLACER_RE, "");
3408
3449
  this.watchPath = watchPath;
3409
3450
  this.fullWatchPath = sysPath2.resolve(watchPath);
3410
3451
  this.dirParts = [];
@@ -3526,20 +3567,20 @@ var init_esm2 = __esm({
3526
3567
  this._closePromise = void 0;
3527
3568
  let paths = unifyPaths(paths_);
3528
3569
  if (cwd) {
3529
- paths = paths.map((path17) => {
3530
- const absPath = getAbsolutePath(path17, cwd);
3570
+ paths = paths.map((path18) => {
3571
+ const absPath = getAbsolutePath(path18, cwd);
3531
3572
  return absPath;
3532
3573
  });
3533
3574
  }
3534
- paths.forEach((path17) => {
3535
- this._removeIgnoredPath(path17);
3575
+ paths.forEach((path18) => {
3576
+ this._removeIgnoredPath(path18);
3536
3577
  });
3537
3578
  this._userIgnored = void 0;
3538
3579
  if (!this._readyCount)
3539
3580
  this._readyCount = 0;
3540
3581
  this._readyCount += paths.length;
3541
- Promise.all(paths.map(async (path17) => {
3542
- const res = await this._nodeFsHandler._addToNodeFs(path17, !_internal, void 0, 0, _origAdd);
3582
+ Promise.all(paths.map(async (path18) => {
3583
+ const res = await this._nodeFsHandler._addToNodeFs(path18, !_internal, void 0, 0, _origAdd);
3543
3584
  if (res)
3544
3585
  this._emitReady();
3545
3586
  return res;
@@ -3561,17 +3602,17 @@ var init_esm2 = __esm({
3561
3602
  return this;
3562
3603
  const paths = unifyPaths(paths_);
3563
3604
  const { cwd } = this.options;
3564
- paths.forEach((path17) => {
3565
- if (!sysPath2.isAbsolute(path17) && !this._closers.has(path17)) {
3605
+ paths.forEach((path18) => {
3606
+ if (!sysPath2.isAbsolute(path18) && !this._closers.has(path18)) {
3566
3607
  if (cwd)
3567
- path17 = sysPath2.join(cwd, path17);
3568
- path17 = sysPath2.resolve(path17);
3608
+ path18 = sysPath2.join(cwd, path18);
3609
+ path18 = sysPath2.resolve(path18);
3569
3610
  }
3570
- this._closePath(path17);
3571
- this._addIgnoredPath(path17);
3572
- if (this._watched.has(path17)) {
3611
+ this._closePath(path18);
3612
+ this._addIgnoredPath(path18);
3613
+ if (this._watched.has(path18)) {
3573
3614
  this._addIgnoredPath({
3574
- path: path17,
3615
+ path: path18,
3575
3616
  recursive: true
3576
3617
  });
3577
3618
  }
@@ -3635,38 +3676,38 @@ var init_esm2 = __esm({
3635
3676
  * @param stats arguments to be passed with event
3636
3677
  * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
3637
3678
  */
3638
- async _emit(event, path17, stats) {
3679
+ async _emit(event, path18, stats) {
3639
3680
  if (this.closed)
3640
3681
  return;
3641
3682
  const opts = this.options;
3642
3683
  if (isWindows)
3643
- path17 = sysPath2.normalize(path17);
3684
+ path18 = sysPath2.normalize(path18);
3644
3685
  if (opts.cwd)
3645
- path17 = sysPath2.relative(opts.cwd, path17);
3646
- const args = [path17];
3686
+ path18 = sysPath2.relative(opts.cwd, path18);
3687
+ const args = [path18];
3647
3688
  if (stats != null)
3648
3689
  args.push(stats);
3649
3690
  const awf = opts.awaitWriteFinish;
3650
3691
  let pw;
3651
- if (awf && (pw = this._pendingWrites.get(path17))) {
3692
+ if (awf && (pw = this._pendingWrites.get(path18))) {
3652
3693
  pw.lastChange = /* @__PURE__ */ new Date();
3653
3694
  return this;
3654
3695
  }
3655
3696
  if (opts.atomic) {
3656
3697
  if (event === EVENTS.UNLINK) {
3657
- this._pendingUnlinks.set(path17, [event, ...args]);
3698
+ this._pendingUnlinks.set(path18, [event, ...args]);
3658
3699
  setTimeout(() => {
3659
- this._pendingUnlinks.forEach((entry, path18) => {
3700
+ this._pendingUnlinks.forEach((entry, path19) => {
3660
3701
  this.emit(...entry);
3661
3702
  this.emit(EVENTS.ALL, ...entry);
3662
- this._pendingUnlinks.delete(path18);
3703
+ this._pendingUnlinks.delete(path19);
3663
3704
  });
3664
3705
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
3665
3706
  return this;
3666
3707
  }
3667
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path17)) {
3708
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path18)) {
3668
3709
  event = EVENTS.CHANGE;
3669
- this._pendingUnlinks.delete(path17);
3710
+ this._pendingUnlinks.delete(path18);
3670
3711
  }
3671
3712
  }
3672
3713
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -3684,16 +3725,16 @@ var init_esm2 = __esm({
3684
3725
  this.emitWithAll(event, args);
3685
3726
  }
3686
3727
  };
3687
- this._awaitWriteFinish(path17, awf.stabilityThreshold, event, awfEmit);
3728
+ this._awaitWriteFinish(path18, awf.stabilityThreshold, event, awfEmit);
3688
3729
  return this;
3689
3730
  }
3690
3731
  if (event === EVENTS.CHANGE) {
3691
- const isThrottled = !this._throttle(EVENTS.CHANGE, path17, 50);
3732
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path18, 50);
3692
3733
  if (isThrottled)
3693
3734
  return this;
3694
3735
  }
3695
3736
  if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
3696
- const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path17) : path17;
3737
+ const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path18) : path18;
3697
3738
  let stats2;
3698
3739
  try {
3699
3740
  stats2 = await stat3(fullPath);
@@ -3724,23 +3765,23 @@ var init_esm2 = __esm({
3724
3765
  * @param timeout duration of time to suppress duplicate actions
3725
3766
  * @returns tracking object or false if action should be suppressed
3726
3767
  */
3727
- _throttle(actionType, path17, timeout) {
3768
+ _throttle(actionType, path18, timeout) {
3728
3769
  if (!this._throttled.has(actionType)) {
3729
3770
  this._throttled.set(actionType, /* @__PURE__ */ new Map());
3730
3771
  }
3731
3772
  const action = this._throttled.get(actionType);
3732
3773
  if (!action)
3733
3774
  throw new Error("invalid throttle");
3734
- const actionPath = action.get(path17);
3775
+ const actionPath = action.get(path18);
3735
3776
  if (actionPath) {
3736
3777
  actionPath.count++;
3737
3778
  return false;
3738
3779
  }
3739
3780
  let timeoutObject;
3740
3781
  const clear = () => {
3741
- const item = action.get(path17);
3782
+ const item = action.get(path18);
3742
3783
  const count = item ? item.count : 0;
3743
- action.delete(path17);
3784
+ action.delete(path18);
3744
3785
  clearTimeout(timeoutObject);
3745
3786
  if (item)
3746
3787
  clearTimeout(item.timeoutObject);
@@ -3748,7 +3789,7 @@ var init_esm2 = __esm({
3748
3789
  };
3749
3790
  timeoutObject = setTimeout(clear, timeout);
3750
3791
  const thr = { timeoutObject, clear, count: 0 };
3751
- action.set(path17, thr);
3792
+ action.set(path18, thr);
3752
3793
  return thr;
3753
3794
  }
3754
3795
  _incrReadyCount() {
@@ -3762,44 +3803,44 @@ var init_esm2 = __esm({
3762
3803
  * @param event
3763
3804
  * @param awfEmit Callback to be called when ready for event to be emitted.
3764
3805
  */
3765
- _awaitWriteFinish(path17, threshold, event, awfEmit) {
3806
+ _awaitWriteFinish(path18, threshold, event, awfEmit) {
3766
3807
  const awf = this.options.awaitWriteFinish;
3767
3808
  if (typeof awf !== "object")
3768
3809
  return;
3769
3810
  const pollInterval = awf.pollInterval;
3770
3811
  let timeoutHandler;
3771
- let fullPath = path17;
3772
- if (this.options.cwd && !sysPath2.isAbsolute(path17)) {
3773
- fullPath = sysPath2.join(this.options.cwd, path17);
3812
+ let fullPath = path18;
3813
+ if (this.options.cwd && !sysPath2.isAbsolute(path18)) {
3814
+ fullPath = sysPath2.join(this.options.cwd, path18);
3774
3815
  }
3775
3816
  const now = /* @__PURE__ */ new Date();
3776
3817
  const writes = this._pendingWrites;
3777
3818
  function awaitWriteFinishFn(prevStat) {
3778
3819
  statcb(fullPath, (err, curStat) => {
3779
- if (err || !writes.has(path17)) {
3820
+ if (err || !writes.has(path18)) {
3780
3821
  if (err && err.code !== "ENOENT")
3781
3822
  awfEmit(err);
3782
3823
  return;
3783
3824
  }
3784
3825
  const now2 = Number(/* @__PURE__ */ new Date());
3785
3826
  if (prevStat && curStat.size !== prevStat.size) {
3786
- writes.get(path17).lastChange = now2;
3827
+ writes.get(path18).lastChange = now2;
3787
3828
  }
3788
- const pw = writes.get(path17);
3829
+ const pw = writes.get(path18);
3789
3830
  const df = now2 - pw.lastChange;
3790
3831
  if (df >= threshold) {
3791
- writes.delete(path17);
3832
+ writes.delete(path18);
3792
3833
  awfEmit(void 0, curStat);
3793
3834
  } else {
3794
3835
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
3795
3836
  }
3796
3837
  });
3797
3838
  }
3798
- if (!writes.has(path17)) {
3799
- writes.set(path17, {
3839
+ if (!writes.has(path18)) {
3840
+ writes.set(path18, {
3800
3841
  lastChange: now,
3801
3842
  cancelWait: () => {
3802
- writes.delete(path17);
3843
+ writes.delete(path18);
3803
3844
  clearTimeout(timeoutHandler);
3804
3845
  return event;
3805
3846
  }
@@ -3810,8 +3851,8 @@ var init_esm2 = __esm({
3810
3851
  /**
3811
3852
  * Determines whether user has asked to ignore this path.
3812
3853
  */
3813
- _isIgnored(path17, stats) {
3814
- if (this.options.atomic && DOT_RE.test(path17))
3854
+ _isIgnored(path18, stats) {
3855
+ if (this.options.atomic && DOT_RE.test(path18))
3815
3856
  return true;
3816
3857
  if (!this._userIgnored) {
3817
3858
  const { cwd } = this.options;
@@ -3821,17 +3862,17 @@ var init_esm2 = __esm({
3821
3862
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
3822
3863
  this._userIgnored = anymatch(list, void 0);
3823
3864
  }
3824
- return this._userIgnored(path17, stats);
3865
+ return this._userIgnored(path18, stats);
3825
3866
  }
3826
- _isntIgnored(path17, stat4) {
3827
- return !this._isIgnored(path17, stat4);
3867
+ _isntIgnored(path18, stat4) {
3868
+ return !this._isIgnored(path18, stat4);
3828
3869
  }
3829
3870
  /**
3830
3871
  * Provides a set of common helpers and properties relating to symlink handling.
3831
3872
  * @param path file or directory pattern being watched
3832
3873
  */
3833
- _getWatchHelpers(path17) {
3834
- return new WatchHelper(path17, this.options.followSymlinks, this);
3874
+ _getWatchHelpers(path18) {
3875
+ return new WatchHelper(path18, this.options.followSymlinks, this);
3835
3876
  }
3836
3877
  // Directory helpers
3837
3878
  // -----------------
@@ -3863,63 +3904,63 @@ var init_esm2 = __esm({
3863
3904
  * @param item base path of item/directory
3864
3905
  */
3865
3906
  _remove(directory, item, isDirectory) {
3866
- const path17 = sysPath2.join(directory, item);
3867
- const fullPath = sysPath2.resolve(path17);
3868
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path17) || this._watched.has(fullPath);
3869
- if (!this._throttle("remove", path17, 100))
3907
+ const path18 = sysPath2.join(directory, item);
3908
+ const fullPath = sysPath2.resolve(path18);
3909
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path18) || this._watched.has(fullPath);
3910
+ if (!this._throttle("remove", path18, 100))
3870
3911
  return;
3871
3912
  if (!isDirectory && this._watched.size === 1) {
3872
3913
  this.add(directory, item, true);
3873
3914
  }
3874
- const wp = this._getWatchedDir(path17);
3915
+ const wp = this._getWatchedDir(path18);
3875
3916
  const nestedDirectoryChildren = wp.getChildren();
3876
- nestedDirectoryChildren.forEach((nested) => this._remove(path17, nested));
3917
+ nestedDirectoryChildren.forEach((nested) => this._remove(path18, nested));
3877
3918
  const parent = this._getWatchedDir(directory);
3878
3919
  const wasTracked = parent.has(item);
3879
3920
  parent.remove(item);
3880
3921
  if (this._symlinkPaths.has(fullPath)) {
3881
3922
  this._symlinkPaths.delete(fullPath);
3882
3923
  }
3883
- let relPath = path17;
3924
+ let relPath = path18;
3884
3925
  if (this.options.cwd)
3885
- relPath = sysPath2.relative(this.options.cwd, path17);
3926
+ relPath = sysPath2.relative(this.options.cwd, path18);
3886
3927
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
3887
3928
  const event = this._pendingWrites.get(relPath).cancelWait();
3888
3929
  if (event === EVENTS.ADD)
3889
3930
  return;
3890
3931
  }
3891
- this._watched.delete(path17);
3932
+ this._watched.delete(path18);
3892
3933
  this._watched.delete(fullPath);
3893
3934
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
3894
- if (wasTracked && !this._isIgnored(path17))
3895
- this._emit(eventName, path17);
3896
- this._closePath(path17);
3935
+ if (wasTracked && !this._isIgnored(path18))
3936
+ this._emit(eventName, path18);
3937
+ this._closePath(path18);
3897
3938
  }
3898
3939
  /**
3899
3940
  * Closes all watchers for a path
3900
3941
  */
3901
- _closePath(path17) {
3902
- this._closeFile(path17);
3903
- const dir = sysPath2.dirname(path17);
3904
- this._getWatchedDir(dir).remove(sysPath2.basename(path17));
3942
+ _closePath(path18) {
3943
+ this._closeFile(path18);
3944
+ const dir = sysPath2.dirname(path18);
3945
+ this._getWatchedDir(dir).remove(sysPath2.basename(path18));
3905
3946
  }
3906
3947
  /**
3907
3948
  * Closes only file-specific watchers
3908
3949
  */
3909
- _closeFile(path17) {
3910
- const closers = this._closers.get(path17);
3950
+ _closeFile(path18) {
3951
+ const closers = this._closers.get(path18);
3911
3952
  if (!closers)
3912
3953
  return;
3913
3954
  closers.forEach((closer) => closer());
3914
- this._closers.delete(path17);
3955
+ this._closers.delete(path18);
3915
3956
  }
3916
- _addPathCloser(path17, closer) {
3957
+ _addPathCloser(path18, closer) {
3917
3958
  if (!closer)
3918
3959
  return;
3919
- let list = this._closers.get(path17);
3960
+ let list = this._closers.get(path18);
3920
3961
  if (!list) {
3921
3962
  list = [];
3922
- this._closers.set(path17, list);
3963
+ this._closers.set(path18, list);
3923
3964
  }
3924
3965
  list.push(closer);
3925
3966
  }
@@ -3946,7 +3987,7 @@ var init_esm2 = __esm({
3946
3987
  });
3947
3988
 
3948
3989
  // src/cli/watcher.ts
3949
- import path10 from "path";
3990
+ import path11 from "path";
3950
3991
  function startWatcher(options) {
3951
3992
  const { rootDir, app, devDist } = options;
3952
3993
  let rebuildTimer = null;
@@ -3979,12 +4020,7 @@ function startWatcher(options) {
3979
4020
  void rebuildRoutes();
3980
4021
  }, 100);
3981
4022
  }
3982
- const CONFIG_FILES = [
3983
- "faapi.config.ts",
3984
- "faapi.config.js",
3985
- "faapi.config.production.ts",
3986
- "faapi.config.production.js"
3987
- ];
4023
+ const CONFIG_FILES = ["faapi.config.ts", "faapi.config.js"];
3988
4024
  const watchPaths = ["src", ...CONFIG_FILES];
3989
4025
  const watcher = esm_default.watch(watchPaths, {
3990
4026
  cwd: rootDir,
@@ -3999,11 +4035,11 @@ function startWatcher(options) {
3999
4035
  }
4000
4036
  });
4001
4037
  watcher.on("add", (file) => {
4002
- pendingFiles.add(path10.resolve(rootDir, file));
4038
+ pendingFiles.add(path11.resolve(rootDir, file));
4003
4039
  scheduleRebuild();
4004
4040
  });
4005
4041
  watcher.on("change", (file) => {
4006
- pendingFiles.add(path10.resolve(rootDir, file));
4042
+ pendingFiles.add(path11.resolve(rootDir, file));
4007
4043
  scheduleRebuild();
4008
4044
  });
4009
4045
  watcher.on("unlink", () => {
@@ -4060,42 +4096,42 @@ var init_detectRouteConflicts = __esm({
4060
4096
  });
4061
4097
 
4062
4098
  // src/router/matchRoute.ts
4063
- function matchRoute(routes, method, path17) {
4099
+ function matchRoute(routes, method, path18) {
4064
4100
  for (const route of routes) {
4065
4101
  if (route.method !== method) {
4066
4102
  continue;
4067
4103
  }
4068
4104
  if (!route.isDynamic) {
4069
- if (route.urlPath === path17) {
4105
+ if (route.urlPath === path18) {
4070
4106
  return { route, params: {} };
4071
4107
  }
4072
4108
  continue;
4073
4109
  }
4074
- const params = matchDynamicPath(route.urlPath, path17, route.paramNames, route.isCatchAll);
4110
+ const params = matchDynamicPath(route.urlPath, path18, route.paramNames, route.isCatchAll);
4075
4111
  if (params !== null) {
4076
4112
  return { route, params };
4077
4113
  }
4078
4114
  }
4079
4115
  return null;
4080
4116
  }
4081
- function matchWsRoute(wsRoutes, path17) {
4117
+ function matchWsRoute(wsRoutes, path18) {
4082
4118
  for (const route of wsRoutes) {
4083
4119
  if (!route.isDynamic) {
4084
- if (route.urlPath === path17) {
4120
+ if (route.urlPath === path18) {
4085
4121
  return { route, params: {} };
4086
4122
  }
4087
4123
  continue;
4088
4124
  }
4089
- const params = matchDynamicPath(route.urlPath, path17, route.paramNames, route.isCatchAll);
4125
+ const params = matchDynamicPath(route.urlPath, path18, route.paramNames, route.isCatchAll);
4090
4126
  if (params !== null) {
4091
4127
  return { route, params };
4092
4128
  }
4093
4129
  }
4094
4130
  return null;
4095
4131
  }
4096
- function matchDynamicPath(pattern, path17, paramNames, isCatchAll) {
4132
+ function matchDynamicPath(pattern, path18, paramNames, isCatchAll) {
4097
4133
  const patternSegments = pattern.split("/").filter(Boolean);
4098
- const pathSegments = path17.split("/").filter(Boolean);
4134
+ const pathSegments = path18.split("/").filter(Boolean);
4099
4135
  if (isCatchAll) {
4100
4136
  const nonCatchAllCount = patternSegments.length - 1;
4101
4137
  if (pathSegments.length <= nonCatchAllCount) {
@@ -4267,6 +4303,11 @@ function createSseWriter() {
4267
4303
  const text = encodeSseEvent(event);
4268
4304
  controller.enqueue(encoder.encode(text));
4269
4305
  },
4306
+ sendRaw(chunk) {
4307
+ if (closed || !controller) return;
4308
+ const bytes = typeof chunk === "string" ? encoder.encode(chunk) : chunk;
4309
+ controller.enqueue(bytes);
4310
+ },
4270
4311
  sendError(error) {
4271
4312
  if (closed || !controller) return;
4272
4313
  const message = error instanceof Error ? error.message : String(error);
@@ -4517,14 +4558,14 @@ var init_httpErrors = __esm({
4517
4558
  issues;
4518
4559
  };
4519
4560
  RouteNotFoundError = class extends FaapiError {
4520
- constructor(path17) {
4521
- super("ROUTE_NOT_FOUND", `Route not found: ${path17}`, 404);
4561
+ constructor(path18) {
4562
+ super("ROUTE_NOT_FOUND", `Route not found: ${path18}`, 404);
4522
4563
  this.name = "RouteNotFoundError";
4523
4564
  }
4524
4565
  };
4525
4566
  MethodNotAllowedError = class extends FaapiError {
4526
- constructor(method, path17, allowedMethods) {
4527
- super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path17}`, 405);
4567
+ constructor(method, path18, allowedMethods) {
4568
+ super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path18}`, 405);
4528
4569
  this.allowedMethods = allowedMethods;
4529
4570
  this.name = "MethodNotAllowedError";
4530
4571
  }
@@ -4926,9 +4967,9 @@ async function validateInput(schemaPath, method, inputType, input) {
4926
4967
  function mapZodIssues(error) {
4927
4968
  return error.issues.map((issue) => {
4928
4969
  const code = mapZodCode(issue.code, issue.message);
4929
- const path17 = issue.path.map(String).join(".") || "";
4970
+ const path18 = issue.path.map(String).join(".") || "";
4930
4971
  return {
4931
- path: path17,
4972
+ path: path18,
4932
4973
  code,
4933
4974
  expected: issue.expected ?? mapExpectedFromMessage(issue.message),
4934
4975
  received: issue.received ?? mapReceivedFromMessage(issue.message),
@@ -5287,7 +5328,7 @@ var init_wsHandler = __esm({
5287
5328
 
5288
5329
  // src/server/handleWsUpgrade.ts
5289
5330
  import { WebSocketServer, WebSocket } from "ws";
5290
- import path11 from "path";
5331
+ import path12 from "path";
5291
5332
  function getPathname(req) {
5292
5333
  const url = req.url ?? "/";
5293
5334
  const idx = url.indexOf("?");
@@ -5369,7 +5410,7 @@ function attachWebSocket(options) {
5369
5410
  const finalHandler = async () => {
5370
5411
  let handlers;
5371
5412
  try {
5372
- const absoluteFilePath = path11.resolve(rootDir, route.filePath);
5413
+ const absoluteFilePath = path12.resolve(rootDir, route.filePath);
5373
5414
  handlers = await loadWsHandler(absoluteFilePath, ctx);
5374
5415
  } catch (err) {
5375
5416
  const reason = err instanceof Error ? err.message : String(err);
@@ -5433,7 +5474,7 @@ import {
5433
5474
  import { createSecureServer as createHttp2SecureServer } from "http2";
5434
5475
  import { readFileSync } from "fs";
5435
5476
  import { Readable as Readable3 } from "stream";
5436
- import path12 from "path";
5477
+ import path13 from "path";
5437
5478
  function toWebRequest(req, bodyLimit = DEFAULT_BODY_LIMIT) {
5438
5479
  const forwardedProto = req.headers["x-forwarded-proto"];
5439
5480
  const protocol = Array.isArray(forwardedProto) ? forwardedProto[0]?.split(",")[0]?.trim() ?? "http" : forwardedProto?.split(",")[0]?.trim() ?? "http";
@@ -5477,15 +5518,15 @@ function limitStreamSize(stream, maxSize) {
5477
5518
  }
5478
5519
  });
5479
5520
  }
5480
- function findAllowedMethods(routes, path17) {
5521
+ function findAllowedMethods(routes, path18) {
5481
5522
  const methods = /* @__PURE__ */ new Set();
5482
5523
  for (const route of routes) {
5483
- if (route.urlPath === path17) {
5524
+ if (route.urlPath === path18) {
5484
5525
  methods.add(route.method);
5485
5526
  continue;
5486
5527
  }
5487
5528
  if (route.isDynamic) {
5488
- const params = matchDynamicPath(route.urlPath, path17, route.paramNames, route.isCatchAll);
5529
+ const params = matchDynamicPath(route.urlPath, path18, route.paramNames, route.isCatchAll);
5489
5530
  if (params !== null) {
5490
5531
  methods.add(route.method);
5491
5532
  }
@@ -5571,7 +5612,7 @@ async function handleRequest(routes, rootDir, dist, req, res, configMiddlewares,
5571
5612
  }
5572
5613
  ctx.params = match.params;
5573
5614
  const { route } = match;
5574
- const absoluteFilePath = path12.resolve(rootDir, route.filePath);
5615
+ const absoluteFilePath = path13.resolve(rootDir, route.filePath);
5575
5616
  const routeModule = await loadRouteModule(absoluteFilePath, route.method);
5576
5617
  const input = await resolveInput(route.method, request);
5577
5618
  const inputType = getInputTypeForMethod(route.method);
@@ -5737,8 +5778,8 @@ var init_loadPlugins = __esm({
5737
5778
  });
5738
5779
 
5739
5780
  // src/cli/createAppCore.ts
5740
- import fs9 from "fs";
5741
- import path13 from "path";
5781
+ import fs10 from "fs";
5782
+ import path14 from "path";
5742
5783
  import { PassThrough } from "stream";
5743
5784
  function isFaapiConfigKey(key) {
5744
5785
  return FAAPI_CONFIG_KEYS.has(key);
@@ -5746,8 +5787,8 @@ function isFaapiConfigKey(key) {
5746
5787
  async function createAppBase(options) {
5747
5788
  const rootDir = options?.rootDir ?? process.cwd();
5748
5789
  const dist = options?.dist ?? process.env.FAAPI_DIST ?? DEFAULT_DIST;
5749
- const routesPath = path13.resolve(rootDir, dist, ROUTES_FILE);
5750
- if (!fs9.existsSync(routesPath)) {
5790
+ const routesPath = path14.resolve(rootDir, dist, ROUTES_FILE);
5791
+ if (!fs10.existsSync(routesPath)) {
5751
5792
  throw new Error(
5752
5793
  `[faapi] ${dist}/${ROUTES_FILE} \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6267\u884C \`faapi build\`\uFF08\u6216 \`faapi dev\`\uFF09\u751F\u6210\u4EA7\u7269\u3002`
5753
5794
  );
@@ -5959,7 +6000,7 @@ var init_createAppCore = __esm({
5959
6000
  init_generateRoutes();
5960
6001
  init_loadPlugins();
5961
6002
  init_importWithCacheBust();
5962
- DEFAULT_DIST = ".faapi/build";
6003
+ DEFAULT_DIST = "dist";
5963
6004
  DEFAULT_PORT = 3e3;
5964
6005
  ROUTES_FILE = "faapi-routes.js";
5965
6006
  PATTERNS = ["src/api/**/*.ts"];
@@ -6014,13 +6055,13 @@ __export(devCommand_exports, {
6014
6055
  devCommand: () => devCommand,
6015
6056
  generateRouteArtifacts: () => generateRouteArtifacts
6016
6057
  });
6017
- import path14 from "path";
6058
+ import path15 from "path";
6018
6059
  async function devCommand(options) {
6019
6060
  const rootDir = process.cwd();
6020
- const rootDist = options?.dist ?? DEFAULT_DEV_ROOT_DIST;
6021
- const devDist = path14.join(rootDist, "dev");
6022
- process.env.FAAPI_DIST = devDist;
6023
6061
  if (!process.env.NODE_ENV) process.env.NODE_ENV = "development";
6062
+ loadEnv(rootDir);
6063
+ const devDist = DEV_DIST;
6064
+ process.env.FAAPI_DIST = devDist;
6024
6065
  console.log("- Development mode");
6025
6066
  console.log("- Compiling config...");
6026
6067
  await compileConfig({ rootDir, dist: devDist });
@@ -6037,12 +6078,12 @@ async function devCommand(options) {
6037
6078
  async function generateRouteArtifacts(rootDir, patterns, dist) {
6038
6079
  const { routes, wsRoutes } = await scanRoutes(rootDir, patterns, dist);
6039
6080
  const sorted = sortRoutes(routes);
6040
- const routesPath = path14.resolve(rootDir, dist, ROUTES_FILE2);
6081
+ const routesPath = path15.resolve(rootDir, dist, ROUTES_FILE2);
6041
6082
  const serialized = serializeRoutes(sorted, wsRoutes, rootDir, dist);
6042
6083
  await writeRoutesModule(serialized, routesPath);
6043
6084
  await generateSchemaFiles(sorted, rootDir, dist);
6044
6085
  }
6045
- var DEFAULT_DEV_ROOT_DIST, ROUTES_FILE2, PATTERNS2;
6086
+ var DEV_DIST, ROUTES_FILE2, PATTERNS2;
6046
6087
  var init_devCommand = __esm({
6047
6088
  "src/cli/devCommand.ts"() {
6048
6089
  "use strict";
@@ -6053,17 +6094,18 @@ var init_devCommand = __esm({
6053
6094
  init_scanRoutes();
6054
6095
  init_sortRoutes();
6055
6096
  init_loadConfig();
6097
+ init_loadEnv();
6056
6098
  init_watcher();
6057
6099
  init_createDevApp();
6058
- DEFAULT_DEV_ROOT_DIST = ".faapi";
6100
+ DEV_DIST = ".faapi";
6059
6101
  ROUTES_FILE2 = "faapi-routes.js";
6060
6102
  PATTERNS2 = ["src/api/**/*.ts"];
6061
6103
  }
6062
6104
  });
6063
6105
 
6064
6106
  // src/cli/compileBuildRoutes.ts
6065
- import path15 from "path";
6066
- import fs10 from "fs";
6107
+ import path16 from "path";
6108
+ import fs11 from "fs";
6067
6109
  import fg3 from "fast-glob";
6068
6110
  async function compileBuildRoutes(options) {
6069
6111
  const { rootDir, dist, files, logLevel = "silent" } = options;
@@ -6076,11 +6118,11 @@ async function compileBuildRoutes(options) {
6076
6118
  if (entryPoints.length === 0) {
6077
6119
  return { compiledFiles: [] };
6078
6120
  }
6079
- const absDist = path15.resolve(rootDir, dist);
6080
- await fs10.promises.mkdir(absDist, { recursive: true });
6121
+ const absDist = path16.resolve(rootDir, dist);
6122
+ await fs11.promises.mkdir(absDist, { recursive: true });
6081
6123
  const plugins = buildAliasPlugins(rootDir);
6082
6124
  const esbuild = await import("esbuild");
6083
- const outbase = path15.resolve(rootDir, APP_DIR4);
6125
+ const outbase = path16.resolve(rootDir, APP_DIR4);
6084
6126
  await esbuild.build({
6085
6127
  entryPoints,
6086
6128
  outdir: absDist,
@@ -6111,12 +6153,11 @@ var buildCommand_exports = {};
6111
6153
  __export(buildCommand_exports, {
6112
6154
  buildCommand: () => buildCommand
6113
6155
  });
6114
- import path16 from "path";
6115
- import fs11 from "fs";
6156
+ import path17 from "path";
6157
+ import fs12 from "fs";
6116
6158
  async function buildCommand(options) {
6117
6159
  const rootDir = options?.rootDir ?? process.cwd();
6118
- const rootDist = options?.dist ?? DEFAULT_BUILD_ROOT_DIST;
6119
- const outdir = path16.join(rootDist, "build");
6160
+ const outdir = options?.dist ?? DEFAULT_DIST2;
6120
6161
  await compileConfig({ rootDir, dist: outdir });
6121
6162
  const _config = await loadConfig(rootDir, outdir);
6122
6163
  console.log("faapi build started");
@@ -6157,27 +6198,30 @@ async function buildCommand(options) {
6157
6198
  }
6158
6199
  console.log("\n[4/6] Generating schema...");
6159
6200
  await generateSchemaFiles(sorted, rootDir, outdir);
6160
- console.log(` Schema: zod.js files under ${path16.resolve(rootDir, outdir)}`);
6201
+ console.log(` Schema: zod.js files under ${path17.resolve(rootDir, outdir)}`);
6161
6202
  console.log("\n[5/6] Generating routes manifest...");
6162
- const routesPath = path16.resolve(rootDir, outdir, "faapi-routes.js");
6203
+ const routesPath = path17.resolve(rootDir, outdir, "faapi-routes.js");
6163
6204
  const serialized = serializeRoutes(sorted, wsRoutes, rootDir, outdir);
6164
6205
  await writeRoutesModule(serialized, routesPath);
6165
6206
  console.log(` Written to ${routesPath}`);
6166
6207
  console.log("\n[6/6] Generating entry file...");
6167
- const mainPath = path16.resolve(rootDir, outdir, "main.js");
6168
- const createProdAppArgs = options?.dist && options.dist !== DEFAULT_BUILD_ROOT_DIST ? `{ dist: '${outdir}' }` : "";
6169
- const listenArgs = options?.port ? String(options.port) : "";
6208
+ const mainPath = path17.resolve(rootDir, outdir, "main.js");
6209
+ const createProdAppArgs = options?.dist && options.dist !== DEFAULT_DIST2 ? `{ dist: '${outdir}' }` : "";
6170
6210
  const mainContent = `// \u7531 faapi build \u81EA\u52A8\u751F\u6210\uFF0C\u8BF7\u52FF\u624B\u52A8\u7F16\u8F91
6171
- import { createProdApp } from '@faapi/faapi';
6211
+ import { createProdApp, loadEnv } from '@faapi/faapi';
6212
+
6213
+ // \u515C\u5E95 NODE_ENV\uFF08\u672A\u663E\u5F0F\u8BBE\u7F6E\u65F6\uFF09+ \u52A0\u8F7D .env \u7CFB\u5217\u6587\u4EF6\u5230 process.env
6214
+ if (!process.env.NODE_ENV) process.env.NODE_ENV = 'production';
6215
+ loadEnv(process.cwd());
6172
6216
 
6173
6217
  const app = await createProdApp(${createProdAppArgs});
6174
- await app.listen(${listenArgs});
6218
+ await app.listen();
6175
6219
  `;
6176
- await fs11.promises.writeFile(mainPath, mainContent, "utf-8");
6220
+ await fs12.promises.writeFile(mainPath, mainContent, "utf-8");
6177
6221
  console.log(` Written to ${mainPath}`);
6178
6222
  console.log("\nfaapi build completed");
6179
6223
  }
6180
- var DEFAULT_BUILD_ROOT_DIST, PATTERNS3;
6224
+ var DEFAULT_DIST2, PATTERNS3;
6181
6225
  var init_buildCommand = __esm({
6182
6226
  "src/cli/buildCommand.ts"() {
6183
6227
  "use strict";
@@ -6189,7 +6233,7 @@ var init_buildCommand = __esm({
6189
6233
  init_compileBuildRoutes();
6190
6234
  init_compileConfig();
6191
6235
  init_loadConfig();
6192
- DEFAULT_BUILD_ROOT_DIST = ".faapi";
6236
+ DEFAULT_DIST2 = "dist";
6193
6237
  PATTERNS3 = ["src/api/**/*.ts"];
6194
6238
  }
6195
6239
  });
@@ -6781,11 +6825,11 @@ var cac = (name = "") => new CAC(name);
6781
6825
 
6782
6826
  // src/cli/index.ts
6783
6827
  var cli = cac("faapi");
6784
- cli.command("").alias("dev").option("--port <number>", "\u670D\u52A1\u7AEF\u53E3\uFF08\u9ED8\u8BA4 3000\uFF09").option("--dist <dir>", "\u4EA7\u7269\u6839\u76EE\u5F55\uFF08\u9ED8\u8BA4 .faapi\uFF0Cdev \u4EA7\u7269\u8F93\u51FA\u5230 <dist>/dev\uFF09").action(async (options) => {
6828
+ cli.command("").alias("dev").option("--port <number>", "\u670D\u52A1\u7AEF\u53E3\uFF08\u9ED8\u8BA4 3000\uFF09").action(async (options) => {
6785
6829
  const { devCommand: devCommand2 } = await Promise.resolve().then(() => (init_devCommand(), devCommand_exports));
6786
6830
  await devCommand2(options);
6787
6831
  });
6788
- cli.command("build", "Build for production").option("--port <number>", "prod \u670D\u52A1\u7AEF\u53E3\uFF0C\u5199\u5165 <dist>/build/main.js").option("--dist <dir>", "\u4EA7\u7269\u6839\u76EE\u5F55\uFF08\u9ED8\u8BA4 .faapi\uFF0Cprod \u4EA7\u7269\u8F93\u51FA\u5230 <dist>/build\uFF09").action(async (options) => {
6832
+ cli.command("build", "Build for production").option("--dist <dir>", "\u4EA7\u7269\u8F93\u51FA\u76EE\u5F55\uFF0C\u9ED8\u8BA4 dist").action(async (options) => {
6789
6833
  const { buildCommand: buildCommand2 } = await Promise.resolve().then(() => (init_buildCommand(), buildCommand_exports));
6790
6834
  await buildCommand2(options);
6791
6835
  });