@lolyjs/core 0.2.0-alpha.26 → 0.2.0-alpha.28

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.cjs CHANGED
@@ -9866,7 +9866,7 @@ var require_built3 = __commonJS({
9866
9866
  });
9867
9867
 
9868
9868
  // modules/cli/index.ts
9869
- var import_path32 = __toESM(require("path"));
9869
+ var import_path34 = __toESM(require("path"));
9870
9870
  var import_process = __toESM(require("process"));
9871
9871
 
9872
9872
  // modules/router/loader-pages.ts
@@ -9878,10 +9878,17 @@ var PAGE_FILE_REGEX = /^page\.(tsx|ts|jsx|js)$/;
9878
9878
  var LAYOUT_FILE_BASENAME = "layout";
9879
9879
 
9880
9880
  // modules/router/path.ts
9881
+ function isRouteGroup(dirName) {
9882
+ return dirName.startsWith("(") && dirName.endsWith(")");
9883
+ }
9881
9884
  function buildRoutePathFromDir(relDir) {
9882
9885
  if (!relDir || relDir === ".") return "/";
9883
9886
  const clean = relDir.replace(/\\/g, "/");
9884
- return "/" + clean;
9887
+ const segments = clean.split("/").filter((seg) => {
9888
+ return !isRouteGroup(seg);
9889
+ });
9890
+ if (segments.length === 0) return "/";
9891
+ return "/" + segments.join("/");
9885
9892
  }
9886
9893
  function buildRegexFromRoutePath(routePath) {
9887
9894
  const segments = routePath.split("/").filter(Boolean);
@@ -10097,13 +10104,17 @@ function validateRoutes(routes, appDir) {
10097
10104
  }
10098
10105
  for (const [pattern, duplicateRoutes] of routePatterns.entries()) {
10099
10106
  if (duplicateRoutes.length > 1) {
10100
- const files = duplicateRoutes.map(
10101
- (r) => r.pageFile ? import_path3.default.relative(appDir, r.pageFile) : "unknown"
10102
- ).join(", ");
10107
+ const files = duplicateRoutes.map((r) => {
10108
+ const relPath = r.pageFile ? import_path3.default.relative(appDir, r.pageFile) : "unknown";
10109
+ const segments = relPath.split(import_path3.default.sep);
10110
+ const hasRouteGroup = segments.some((seg) => isRouteGroup(seg));
10111
+ return hasRouteGroup ? `${relPath} (inside route group)` : relPath;
10112
+ }).join(", ");
10103
10113
  errors.push(
10104
10114
  `Duplicate route pattern "${pattern}" found in multiple files:
10105
10115
  ${files}
10106
- \u{1F4A1} Suggestion: Ensure each route has a unique path pattern`
10116
+ \u{1F4A1} Suggestion: Route groups (directories in parentheses) don't appear in URLs.
10117
+ Ensure each route has a unique path pattern after route groups are ignored.`
10107
10118
  );
10108
10119
  }
10109
10120
  }
@@ -10380,12 +10391,13 @@ function loadApiRoutes(appDir) {
10380
10391
 
10381
10392
  // modules/router/matcher.ts
10382
10393
  function matchRoute(routes, urlPath) {
10394
+ const normalizedPath = urlPath.replace(/\/$/, "") || "/";
10383
10395
  for (const route of routes) {
10384
- const match = route.regex.exec(urlPath);
10396
+ const match = route.regex.exec(normalizedPath);
10385
10397
  if (!match) continue;
10386
10398
  const params = {};
10387
10399
  route.paramNames.forEach((name, idx) => {
10388
- params[name] = match[idx + 1];
10400
+ params[name] = decodeURIComponent(match[idx + 1] || "");
10389
10401
  });
10390
10402
  return { route, params };
10391
10403
  }
@@ -11395,34 +11407,504 @@ function loadErrorRouteFromFilesystem(appDir) {
11395
11407
  };
11396
11408
  }
11397
11409
 
11410
+ // modules/router/rewrites.ts
11411
+ function parseRewritePattern(pattern) {
11412
+ const cleanPattern = pattern.replace(/^\/+|\/+$/g, "") || "";
11413
+ if (!cleanPattern) {
11414
+ return {
11415
+ regex: /^\/?$/,
11416
+ paramNames: []
11417
+ };
11418
+ }
11419
+ const segments = cleanPattern.split("/").filter(Boolean);
11420
+ const paramNames = [];
11421
+ const regexParts = [];
11422
+ for (let i = 0; i < segments.length; i++) {
11423
+ const seg = segments[i];
11424
+ if (seg === "*") {
11425
+ if (i !== segments.length - 1) {
11426
+ throw new Error(
11427
+ `Catch-all "*" in "${pattern}" must be the last segment.`
11428
+ );
11429
+ }
11430
+ regexParts.push("(.+)");
11431
+ continue;
11432
+ }
11433
+ if (seg.endsWith("*") && seg.startsWith(":")) {
11434
+ const paramName = seg.slice(1, -1);
11435
+ if (i !== segments.length - 1) {
11436
+ throw new Error(
11437
+ `Catch-all segment "${seg}" in "${pattern}" must be the last segment.`
11438
+ );
11439
+ }
11440
+ paramNames.push(paramName);
11441
+ regexParts.push("(.+)");
11442
+ continue;
11443
+ }
11444
+ if (seg.startsWith(":") && seg.length > 1) {
11445
+ const paramName = seg.slice(1);
11446
+ paramNames.push(paramName);
11447
+ regexParts.push("([^/]+)");
11448
+ continue;
11449
+ }
11450
+ const escaped = seg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
11451
+ regexParts.push(escaped);
11452
+ }
11453
+ const regexSource = "^/?" + regexParts.join("/") + "/?$";
11454
+ const regex = new RegExp(regexSource);
11455
+ return { regex, paramNames };
11456
+ }
11457
+ function extractHostParams(hostPattern, actualHost) {
11458
+ const regexPattern = hostPattern.replace(/:([^.]+)/g, "([^.]+)").replace(/\./g, "\\.").replace(/\*/g, ".*");
11459
+ const regex = new RegExp(`^${regexPattern}$`);
11460
+ const match = regex.exec(actualHost);
11461
+ if (!match) return null;
11462
+ const paramNames = [];
11463
+ const paramPattern = /:([^.]+)/g;
11464
+ let paramMatch;
11465
+ while ((paramMatch = paramPattern.exec(hostPattern)) !== null) {
11466
+ paramNames.push(paramMatch[1]);
11467
+ }
11468
+ const params = {};
11469
+ paramNames.forEach((name, idx) => {
11470
+ params[name] = match[idx + 1] || "";
11471
+ });
11472
+ return params;
11473
+ }
11474
+ function evaluateRewriteConditions(conditions, req) {
11475
+ const extractedParams = {};
11476
+ for (const condition of conditions) {
11477
+ switch (condition.type) {
11478
+ case "host": {
11479
+ const hostWithPort = req.get("host") || req.hostname || req.get("x-forwarded-host")?.split(",")[0] || "";
11480
+ const host = hostWithPort.split(":")[0];
11481
+ if (process.env.NODE_ENV === "development") {
11482
+ console.log("[rewrites] Host matching:", {
11483
+ pattern: condition.value,
11484
+ actualHost: host,
11485
+ hostWithPort,
11486
+ reqHost: req.get("host"),
11487
+ reqHostname: req.hostname
11488
+ });
11489
+ }
11490
+ const hostParams = extractHostParams(condition.value, host);
11491
+ if (!hostParams) {
11492
+ if (process.env.NODE_ENV === "development") {
11493
+ console.log("[rewrites] Host params extraction failed:", {
11494
+ pattern: condition.value,
11495
+ actualHost: host
11496
+ });
11497
+ }
11498
+ return { matches: false, params: {} };
11499
+ }
11500
+ Object.assign(extractedParams, hostParams);
11501
+ break;
11502
+ }
11503
+ case "header": {
11504
+ if (!condition.key) {
11505
+ return { matches: false, params: {} };
11506
+ }
11507
+ const headerValue = req.get(condition.key.toLowerCase());
11508
+ if (!headerValue || headerValue !== condition.value) {
11509
+ return { matches: false, params: {} };
11510
+ }
11511
+ break;
11512
+ }
11513
+ case "cookie": {
11514
+ if (!condition.key) {
11515
+ return { matches: false, params: {} };
11516
+ }
11517
+ const cookieValue = req.cookies?.[condition.key];
11518
+ if (!cookieValue || cookieValue !== condition.value) {
11519
+ return { matches: false, params: {} };
11520
+ }
11521
+ break;
11522
+ }
11523
+ case "query": {
11524
+ if (!condition.key) {
11525
+ return { matches: false, params: {} };
11526
+ }
11527
+ const queryValue = req.query[condition.key];
11528
+ if (!queryValue || String(queryValue) !== condition.value) {
11529
+ return { matches: false, params: {} };
11530
+ }
11531
+ break;
11532
+ }
11533
+ default:
11534
+ return { matches: false, params: {} };
11535
+ }
11536
+ }
11537
+ return { matches: true, params: extractedParams };
11538
+ }
11539
+ function replaceDestinationParams(destination, params) {
11540
+ let result = destination;
11541
+ for (const [key, value] of Object.entries(params)) {
11542
+ const pattern = new RegExp(`:${key}(?:\\*)?`, "g");
11543
+ result = result.replace(pattern, value);
11544
+ }
11545
+ return result;
11546
+ }
11547
+ async function processRewrites(urlPath, compiledRewrites, req) {
11548
+ const normalizedPath = urlPath.replace(/\/$/, "") || "/";
11549
+ if (normalizedPath.startsWith("/static/") || // Static assets (client.js, client.css, etc.)
11550
+ normalizedPath.startsWith("/__fw/") || // Framework internal routes (hot reload, etc.)
11551
+ normalizedPath === "/favicon.ico" || // Favicon
11552
+ normalizedPath.startsWith("/wss/")) {
11553
+ if (process.env.NODE_ENV === "development") {
11554
+ console.log("[rewrites] Skipping rewrite for system route:", normalizedPath);
11555
+ }
11556
+ return null;
11557
+ }
11558
+ if (process.env.NODE_ENV === "development") {
11559
+ console.log("[rewrites] Processing rewrites:", {
11560
+ urlPath,
11561
+ normalizedPath,
11562
+ host: req.get("host"),
11563
+ hostname: req.hostname,
11564
+ compiledRewritesCount: compiledRewrites.length
11565
+ });
11566
+ }
11567
+ for (const rewrite of compiledRewrites) {
11568
+ let conditionParams = {};
11569
+ if (rewrite.has && rewrite.has.length > 0) {
11570
+ const conditionResult = evaluateRewriteConditions(rewrite.has, req);
11571
+ if (!conditionResult.matches) {
11572
+ if (process.env.NODE_ENV === "development") {
11573
+ console.log("[rewrites] Condition not matched:", {
11574
+ source: rewrite.source,
11575
+ conditions: rewrite.has
11576
+ });
11577
+ }
11578
+ continue;
11579
+ }
11580
+ conditionParams = conditionResult.params;
11581
+ if (process.env.NODE_ENV === "development") {
11582
+ console.log("[rewrites] Condition matched:", {
11583
+ source: rewrite.source,
11584
+ conditionParams
11585
+ });
11586
+ }
11587
+ }
11588
+ const sourceMatch = rewrite.sourceRegex.exec(normalizedPath);
11589
+ if (!sourceMatch) {
11590
+ if (process.env.NODE_ENV === "development") {
11591
+ console.log("[rewrites] Source pattern not matched:", {
11592
+ source: rewrite.source,
11593
+ normalizedPath,
11594
+ sourceRegex: rewrite.sourceRegex.toString()
11595
+ });
11596
+ }
11597
+ continue;
11598
+ }
11599
+ if (process.env.NODE_ENV === "development") {
11600
+ console.log("[rewrites] Source pattern matched:", {
11601
+ source: rewrite.source,
11602
+ normalizedPath,
11603
+ match: sourceMatch[0]
11604
+ });
11605
+ }
11606
+ const sourceParams = {};
11607
+ rewrite.sourceParamNames.forEach((name, idx) => {
11608
+ sourceParams[name] = decodeURIComponent(sourceMatch[idx + 1] || "");
11609
+ });
11610
+ const allParams = { ...sourceParams, ...conditionParams };
11611
+ let destination;
11612
+ if (typeof rewrite.destination === "function") {
11613
+ destination = await rewrite.destination(allParams, req);
11614
+ } else {
11615
+ destination = replaceDestinationParams(rewrite.destination, allParams);
11616
+ }
11617
+ const normalizedDestination = destination.replace(/\/+/g, "/").replace(/^([^/])/, "/$1").replace(/\/$/, "") || "/";
11618
+ if (process.env.NODE_ENV === "development") {
11619
+ console.log("[rewrites] Rewrite successful:", {
11620
+ originalPath: urlPath,
11621
+ rewrittenPath: normalizedDestination,
11622
+ allParams
11623
+ });
11624
+ }
11625
+ return {
11626
+ rewrittenPath: normalizedDestination,
11627
+ extractedParams: allParams
11628
+ };
11629
+ }
11630
+ return null;
11631
+ }
11632
+ function validateRewrites(rules) {
11633
+ for (const rule of rules) {
11634
+ if (typeof rule.destination === "string") {
11635
+ if (rule.source === rule.destination) {
11636
+ console.warn(
11637
+ `[framework][rewrites] Rewrite rule has identical source and destination: "${rule.source}". This may cause issues.`
11638
+ );
11639
+ }
11640
+ }
11641
+ }
11642
+ const sources = /* @__PURE__ */ new Set();
11643
+ for (const rule of rules) {
11644
+ if (sources.has(rule.source)) {
11645
+ console.warn(
11646
+ `[framework][rewrites] Duplicate rewrite source pattern: "${rule.source}". Only the first match will be used.`
11647
+ );
11648
+ }
11649
+ sources.add(rule.source);
11650
+ }
11651
+ }
11652
+ function compileRewriteRules(rules) {
11653
+ validateRewrites(rules);
11654
+ return rules.map((rule) => {
11655
+ const { regex, paramNames } = parseRewritePattern(rule.source);
11656
+ let hostRegex;
11657
+ let hostParamNames;
11658
+ if (rule.has) {
11659
+ const hostCondition = rule.has.find((c) => c.type === "host");
11660
+ if (hostCondition) {
11661
+ const hostPattern = hostCondition.value;
11662
+ const hostRegexPattern = hostPattern.replace(/:([^.]+)/g, "([^.]+)").replace(/\./g, "\\.").replace(/\*/g, ".*");
11663
+ hostRegex = new RegExp(`^${hostRegexPattern}$`);
11664
+ hostParamNames = [];
11665
+ const paramPattern = /:([^.]+)/g;
11666
+ let paramMatch;
11667
+ while ((paramMatch = paramPattern.exec(hostPattern)) !== null) {
11668
+ hostParamNames.push(paramMatch[1]);
11669
+ }
11670
+ }
11671
+ }
11672
+ return {
11673
+ source: rule.source,
11674
+ sourceRegex: regex,
11675
+ sourceParamNames: paramNames,
11676
+ destination: rule.destination,
11677
+ has: rule.has,
11678
+ hostRegex,
11679
+ hostParamNames
11680
+ };
11681
+ });
11682
+ }
11683
+
11684
+ // modules/router/rewrites-loader.ts
11685
+ var import_fs10 = __toESM(require("fs"));
11686
+ var import_path12 = __toESM(require("path"));
11687
+ var FilesystemRewriteLoader = class {
11688
+ // Maximum cache age in ms (1 second fallback)
11689
+ constructor(projectRoot) {
11690
+ this.projectRoot = projectRoot;
11691
+ this.cache = null;
11692
+ this.cacheMaxAge = 1e3;
11693
+ }
11694
+ /**
11695
+ * Invalidates the cache, forcing a reload on next access.
11696
+ */
11697
+ invalidateCache() {
11698
+ this.cache = null;
11699
+ }
11700
+ /**
11701
+ * Finds the rewrites config file.
11702
+ * Looks for rewrites.config.ts, rewrites.config.js, or rewrites.config.json
11703
+ */
11704
+ findRewritesConfig() {
11705
+ const candidates = [
11706
+ import_path12.default.join(this.projectRoot, "rewrites.config.ts"),
11707
+ import_path12.default.join(this.projectRoot, "rewrites.config.js"),
11708
+ import_path12.default.join(this.projectRoot, "rewrites.config.json")
11709
+ ];
11710
+ for (const candidate of candidates) {
11711
+ if (import_fs10.default.existsSync(candidate)) {
11712
+ return candidate;
11713
+ }
11714
+ }
11715
+ return null;
11716
+ }
11717
+ /**
11718
+ * Checks if the rewrites config file has changed.
11719
+ */
11720
+ hasConfigChanged(configPath) {
11721
+ if (!this.cache || !this.cache.fileStats) {
11722
+ return true;
11723
+ }
11724
+ if (!import_fs10.default.existsSync(configPath)) {
11725
+ return this.cache.rewrites.length > 0;
11726
+ }
11727
+ const stats = import_fs10.default.statSync(configPath);
11728
+ const cachedStats = this.cache.fileStats;
11729
+ return stats.mtimeMs !== cachedStats.mtime || stats.size !== cachedStats.size;
11730
+ }
11731
+ /**
11732
+ * Loads rewrites from a config file.
11733
+ */
11734
+ async loadRewritesFromFile(configPath) {
11735
+ const ext = import_path12.default.extname(configPath);
11736
+ if (ext === ".json") {
11737
+ const content = import_fs10.default.readFileSync(configPath, "utf-8");
11738
+ const config2 = JSON.parse(content);
11739
+ return Array.isArray(config2) ? config2 : [];
11740
+ }
11741
+ delete require.cache[require.resolve(configPath)];
11742
+ const mod = require(configPath);
11743
+ const config = mod.default || mod;
11744
+ if (typeof config === "function") {
11745
+ return await config();
11746
+ }
11747
+ if (Array.isArray(config)) {
11748
+ return config;
11749
+ }
11750
+ throw new Error(
11751
+ `Invalid rewrites config in ${configPath}. Expected array or function returning array.`
11752
+ );
11753
+ }
11754
+ /**
11755
+ * Checks if cache is still valid, invalidates if config changed.
11756
+ */
11757
+ ensureCacheValid() {
11758
+ if (!this.cache) {
11759
+ return;
11760
+ }
11761
+ const now = Date.now();
11762
+ if (now - this.cache.timestamp > this.cacheMaxAge) {
11763
+ const configPath = this.findRewritesConfig();
11764
+ if (configPath && this.hasConfigChanged(configPath)) {
11765
+ this.cache = null;
11766
+ } else {
11767
+ this.cache.timestamp = now;
11768
+ }
11769
+ }
11770
+ }
11771
+ async loadRewrites() {
11772
+ this.ensureCacheValid();
11773
+ const configPath = this.findRewritesConfig();
11774
+ if (!configPath) {
11775
+ if (this.cache && this.cache.rewrites.length === 0) {
11776
+ return this.cache.rewrites;
11777
+ }
11778
+ this.cache = {
11779
+ rewrites: [],
11780
+ fileStats: null,
11781
+ timestamp: Date.now()
11782
+ };
11783
+ return [];
11784
+ }
11785
+ if (!this.cache || this.hasConfigChanged(configPath)) {
11786
+ const rules = await this.loadRewritesFromFile(configPath);
11787
+ const compiled = compileRewriteRules(rules);
11788
+ const stats = import_fs10.default.statSync(configPath);
11789
+ const fileStats = {
11790
+ mtime: stats.mtimeMs,
11791
+ size: stats.size
11792
+ };
11793
+ this.cache = {
11794
+ rewrites: compiled,
11795
+ fileStats,
11796
+ timestamp: Date.now()
11797
+ };
11798
+ }
11799
+ return this.cache.rewrites;
11800
+ }
11801
+ };
11802
+ var ManifestRewriteLoader = class {
11803
+ constructor(projectRoot) {
11804
+ this.cache = null;
11805
+ this.manifestPath = import_path12.default.join(projectRoot, ".loly", "rewrites-manifest.json");
11806
+ }
11807
+ /**
11808
+ * Reads the rewrites manifest from disk.
11809
+ */
11810
+ readManifest() {
11811
+ if (!import_fs10.default.existsSync(this.manifestPath)) {
11812
+ return null;
11813
+ }
11814
+ try {
11815
+ const content = import_fs10.default.readFileSync(this.manifestPath, "utf-8");
11816
+ return JSON.parse(content);
11817
+ } catch (error) {
11818
+ console.warn(
11819
+ `Failed to read rewrites manifest from ${this.manifestPath}:`,
11820
+ error
11821
+ );
11822
+ return null;
11823
+ }
11824
+ }
11825
+ async loadRewrites() {
11826
+ if (this.cache) {
11827
+ return this.cache;
11828
+ }
11829
+ const manifest = this.readManifest();
11830
+ if (!manifest || !manifest.rewrites) {
11831
+ this.cache = [];
11832
+ return [];
11833
+ }
11834
+ const compiled = compileRewriteRules(manifest.rewrites);
11835
+ this.cache = compiled;
11836
+ return compiled;
11837
+ }
11838
+ };
11839
+ function createRewriteLoader(projectRoot, isDev) {
11840
+ if (isDev) {
11841
+ return new FilesystemRewriteLoader(projectRoot);
11842
+ } else {
11843
+ return new ManifestRewriteLoader(projectRoot);
11844
+ }
11845
+ }
11846
+
11847
+ // modules/router/rewrites-manifest.ts
11848
+ var import_fs11 = __toESM(require("fs"));
11849
+ var import_path13 = __toESM(require("path"));
11850
+ init_globals();
11851
+ async function writeRewritesManifest(projectRoot) {
11852
+ const buildDir = import_path13.default.join(projectRoot, BUILD_FOLDER_NAME);
11853
+ if (!import_fs11.default.existsSync(buildDir)) {
11854
+ import_fs11.default.mkdirSync(buildDir, { recursive: true });
11855
+ }
11856
+ const manifestPath = import_path13.default.join(buildDir, "rewrites-manifest.json");
11857
+ const loader = createRewriteLoader(projectRoot, true);
11858
+ const compiledRewrites = await loader.loadRewrites();
11859
+ const serializableRules = [];
11860
+ for (const compiled of compiledRewrites) {
11861
+ if (typeof compiled.destination === "string") {
11862
+ serializableRules.push({
11863
+ source: compiled.source,
11864
+ destination: compiled.destination,
11865
+ has: compiled.has
11866
+ });
11867
+ } else {
11868
+ console.warn(
11869
+ `[framework][build] Rewrite with source "${compiled.source}" has a function destination and will not be included in the manifest. Only static rewrites are supported in production builds.`
11870
+ );
11871
+ }
11872
+ }
11873
+ const manifest = {
11874
+ version: 1,
11875
+ rewrites: serializableRules
11876
+ };
11877
+ import_fs11.default.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
11878
+ }
11879
+
11398
11880
  // modules/build/bundler/client.ts
11399
11881
  var import_core2 = require("@rspack/core");
11400
11882
 
11401
11883
  // modules/build/config/client.ts
11402
- var import_path13 = __toESM(require("path"));
11403
- var import_fs11 = __toESM(require("fs"));
11884
+ var import_path15 = __toESM(require("path"));
11885
+ var import_fs13 = __toESM(require("fs"));
11404
11886
  var import_core = require("@rspack/core");
11405
11887
 
11406
11888
  // modules/build/utils/index.ts
11407
- var import_fs10 = __toESM(require("fs"));
11408
- var import_path12 = __toESM(require("path"));
11889
+ var import_fs12 = __toESM(require("fs"));
11890
+ var import_path14 = __toESM(require("path"));
11409
11891
  function ensureDir(dir) {
11410
- import_fs10.default.mkdirSync(dir, { recursive: true });
11892
+ import_fs12.default.mkdirSync(dir, { recursive: true });
11411
11893
  }
11412
11894
  function loadAliasesFromTsconfig(projectRoot) {
11413
- const tsconfigPath = import_path12.default.join(projectRoot, "tsconfig.json");
11895
+ const tsconfigPath = import_path14.default.join(projectRoot, "tsconfig.json");
11414
11896
  const aliases = {};
11415
- if (!import_fs10.default.existsSync(tsconfigPath)) {
11416
- aliases["@app"] = import_path12.default.resolve(projectRoot, "app");
11897
+ if (!import_fs12.default.existsSync(tsconfigPath)) {
11898
+ aliases["@app"] = import_path14.default.resolve(projectRoot, "app");
11417
11899
  return aliases;
11418
11900
  }
11419
11901
  let tsconfig;
11420
11902
  try {
11421
- tsconfig = JSON.parse(import_fs10.default.readFileSync(tsconfigPath, "utf-8"));
11903
+ tsconfig = JSON.parse(import_fs12.default.readFileSync(tsconfigPath, "utf-8"));
11422
11904
  } catch (err) {
11423
11905
  console.warn("\u26A0\uFE0F [framework] Could not read tsconfig.json:", err instanceof Error ? err.message : String(err));
11424
11906
  console.warn("\u{1F4A1} Using default path aliases. For custom aliases, ensure tsconfig.json is valid.");
11425
- aliases["@app"] = import_path12.default.resolve(projectRoot, "app");
11907
+ aliases["@app"] = import_path14.default.resolve(projectRoot, "app");
11426
11908
  return aliases;
11427
11909
  }
11428
11910
  const compilerOptions = tsconfig.compilerOptions ?? {};
@@ -11433,40 +11915,40 @@ function loadAliasesFromTsconfig(projectRoot) {
11433
11915
  const aliasKey = aliasPattern.replace(/\/\*$/, "");
11434
11916
  const firstTarget = targets[0];
11435
11917
  const targetPath = firstTarget.replace(/\/\*$/, "");
11436
- const resolved = import_path12.default.resolve(projectRoot, baseUrl, targetPath);
11918
+ const resolved = import_path14.default.resolve(projectRoot, baseUrl, targetPath);
11437
11919
  aliases[aliasKey] = resolved;
11438
11920
  }
11439
11921
  if (!aliases["@app"]) {
11440
- aliases["@app"] = import_path12.default.resolve(projectRoot, "app");
11922
+ aliases["@app"] = import_path14.default.resolve(projectRoot, "app");
11441
11923
  }
11442
11924
  return aliases;
11443
11925
  }
11444
11926
  function copyDirRecursive(srcDir, destDir) {
11445
- if (!import_fs10.default.existsSync(srcDir)) return;
11927
+ if (!import_fs12.default.existsSync(srcDir)) return;
11446
11928
  ensureDir(destDir);
11447
- const entries = import_fs10.default.readdirSync(srcDir, { withFileTypes: true });
11929
+ const entries = import_fs12.default.readdirSync(srcDir, { withFileTypes: true });
11448
11930
  for (const entry of entries) {
11449
- const srcPath = import_path12.default.join(srcDir, entry.name);
11450
- const destPath = import_path12.default.join(destDir, entry.name);
11931
+ const srcPath = import_path14.default.join(srcDir, entry.name);
11932
+ const destPath = import_path14.default.join(destDir, entry.name);
11451
11933
  if (entry.isDirectory()) {
11452
11934
  copyDirRecursive(srcPath, destPath);
11453
11935
  } else if (entry.isFile()) {
11454
- import_fs10.default.copyFileSync(srcPath, destPath);
11936
+ import_fs12.default.copyFileSync(srcPath, destPath);
11455
11937
  }
11456
11938
  }
11457
11939
  }
11458
11940
  function copyStaticAssets(projectRoot, outDir) {
11459
- const assetsSrc = import_path12.default.join(projectRoot, "assets");
11460
- const assetsDest = import_path12.default.join(outDir, "assets");
11941
+ const assetsSrc = import_path14.default.join(projectRoot, "assets");
11942
+ const assetsDest = import_path14.default.join(outDir, "assets");
11461
11943
  copyDirRecursive(assetsSrc, assetsDest);
11462
- const publicDir = import_path12.default.join(projectRoot, "public");
11944
+ const publicDir = import_path14.default.join(projectRoot, "public");
11463
11945
  const candidates = ["favicon.ico", "favicon.png"];
11464
11946
  for (const name of candidates) {
11465
- const fromPublic = import_path12.default.join(publicDir, name);
11466
- if (import_fs10.default.existsSync(fromPublic)) {
11467
- const dest = import_path12.default.join(outDir, name);
11468
- ensureDir(import_path12.default.dirname(dest));
11469
- import_fs10.default.copyFileSync(fromPublic, dest);
11947
+ const fromPublic = import_path14.default.join(publicDir, name);
11948
+ if (import_fs12.default.existsSync(fromPublic)) {
11949
+ const dest = import_path14.default.join(outDir, name);
11950
+ ensureDir(import_path14.default.dirname(dest));
11951
+ import_fs12.default.copyFileSync(fromPublic, dest);
11470
11952
  break;
11471
11953
  }
11472
11954
  }
@@ -11476,10 +11958,10 @@ function getFaviconInfo(projectRoot, staticDir = "public", isDev = false) {
11476
11958
  { name: "favicon.ico", type: "image/x-icon" },
11477
11959
  { name: "favicon.png", type: "image/png" }
11478
11960
  ];
11479
- const publicDir = import_path12.default.join(projectRoot, staticDir);
11961
+ const publicDir = import_path14.default.join(projectRoot, staticDir);
11480
11962
  for (const candidate of candidates) {
11481
- const publicPath = import_path12.default.join(publicDir, candidate.name);
11482
- if (import_fs10.default.existsSync(publicPath)) {
11963
+ const publicPath = import_path14.default.join(publicDir, candidate.name);
11964
+ if (import_fs12.default.existsSync(publicPath)) {
11483
11965
  return {
11484
11966
  path: `/${candidate.name}`,
11485
11967
  // Served at root from public/
@@ -11497,10 +11979,10 @@ function generateAssetManifest(outDir, stats) {
11497
11979
  },
11498
11980
  chunks: {}
11499
11981
  };
11500
- if (!import_fs10.default.existsSync(outDir)) {
11982
+ if (!import_fs12.default.existsSync(outDir)) {
11501
11983
  return manifest;
11502
11984
  }
11503
- const files = import_fs10.default.readdirSync(outDir);
11985
+ const files = import_fs12.default.readdirSync(outDir);
11504
11986
  if (stats) {
11505
11987
  try {
11506
11988
  const statsJson = stats.toJson({
@@ -11629,12 +12111,12 @@ function generateAssetManifest(outDir, stats) {
11629
12111
  }
11630
12112
  function loadAssetManifest(projectRoot) {
11631
12113
  const { BUILD_FOLDER_NAME: BUILD_FOLDER_NAME2 } = (init_globals(), __toCommonJS(globals_exports));
11632
- const manifestPath = import_path12.default.join(projectRoot, BUILD_FOLDER_NAME2, "asset-manifest.json");
11633
- if (!import_fs10.default.existsSync(manifestPath)) {
12114
+ const manifestPath = import_path14.default.join(projectRoot, BUILD_FOLDER_NAME2, "asset-manifest.json");
12115
+ if (!import_fs12.default.existsSync(manifestPath)) {
11634
12116
  return null;
11635
12117
  }
11636
12118
  try {
11637
- const manifest = JSON.parse(import_fs10.default.readFileSync(manifestPath, "utf-8"));
12119
+ const manifest = JSON.parse(import_fs12.default.readFileSync(manifestPath, "utf-8"));
11638
12120
  return manifest;
11639
12121
  } catch (err) {
11640
12122
  return null;
@@ -11657,11 +12139,11 @@ function getClientCssPath(projectRoot) {
11657
12139
  var import_dotenv = __toESM(require("dotenv"));
11658
12140
  init_globals();
11659
12141
  function createClientConfig(projectRoot, mode) {
11660
- const buildDir = import_path13.default.join(projectRoot, BUILD_FOLDER_NAME);
11661
- const clientEntry = import_path13.default.join(buildDir, "boostrap.ts");
11662
- const outDir = import_path13.default.join(buildDir, "client");
11663
- const envPath2 = import_path13.default.join(projectRoot, ".env");
11664
- if (import_fs11.default.existsSync(envPath2)) {
12142
+ const buildDir = import_path15.default.join(projectRoot, BUILD_FOLDER_NAME);
12143
+ const clientEntry = import_path15.default.join(buildDir, "boostrap.ts");
12144
+ const outDir = import_path15.default.join(buildDir, "client");
12145
+ const envPath2 = import_path15.default.join(projectRoot, ".env");
12146
+ if (import_fs13.default.existsSync(envPath2)) {
11665
12147
  import_dotenv.default.config({ path: envPath2 });
11666
12148
  }
11667
12149
  const publicEnv = {};
@@ -11781,8 +12263,8 @@ function createClientConfig(projectRoot, mode) {
11781
12263
  }
11782
12264
 
11783
12265
  // modules/build/bundler/client.ts
11784
- var import_path14 = __toESM(require("path"));
11785
- var import_fs12 = __toESM(require("fs"));
12266
+ var import_path16 = __toESM(require("path"));
12267
+ var import_fs14 = __toESM(require("fs"));
11786
12268
  init_globals();
11787
12269
  function startClientBundler(projectRoot, mode = "development") {
11788
12270
  const { config, outDir } = createClientConfig(projectRoot, mode);
@@ -11892,18 +12374,18 @@ function buildClientBundle(projectRoot) {
11892
12374
  }
11893
12375
  copyStaticAssets(projectRoot, outDir);
11894
12376
  const assetManifest = generateAssetManifest(outDir, stats);
11895
- const manifestPath = import_path14.default.join(projectRoot, BUILD_FOLDER_NAME, "asset-manifest.json");
11896
- import_fs12.default.writeFileSync(manifestPath, JSON.stringify(assetManifest, null, 2), "utf-8");
12377
+ const manifestPath = import_path16.default.join(projectRoot, BUILD_FOLDER_NAME, "asset-manifest.json");
12378
+ import_fs14.default.writeFileSync(manifestPath, JSON.stringify(assetManifest, null, 2), "utf-8");
11897
12379
  resolve3({ outDir });
11898
12380
  });
11899
12381
  });
11900
12382
  }
11901
12383
 
11902
12384
  // modules/build/ssg/builder.ts
11903
- var import_path22 = __toESM(require("path"));
12385
+ var import_path24 = __toESM(require("path"));
11904
12386
 
11905
12387
  // modules/build/ssg/path.ts
11906
- var import_path15 = __toESM(require("path"));
12388
+ var import_path17 = __toESM(require("path"));
11907
12389
  function buildPathFromPattern(pattern, params) {
11908
12390
  const segments = pattern.split("/").filter(Boolean);
11909
12391
  const parts = [];
@@ -11932,12 +12414,12 @@ function buildPathFromPattern(pattern, params) {
11932
12414
  }
11933
12415
  function pathToOutDir(baseDir, urlPath) {
11934
12416
  const clean = urlPath === "/" ? "" : urlPath.replace(/^\/+/, "");
11935
- return import_path15.default.join(baseDir, clean);
12417
+ return import_path17.default.join(baseDir, clean);
11936
12418
  }
11937
12419
 
11938
12420
  // modules/build/ssg/renderer.ts
11939
- var import_fs14 = __toESM(require("fs"));
11940
- var import_path20 = __toESM(require("path"));
12421
+ var import_fs16 = __toESM(require("fs"));
12422
+ var import_path22 = __toESM(require("path"));
11941
12423
  var import_server2 = require("react-dom/server");
11942
12424
 
11943
12425
  // modules/rendering/createDocumentTree/index.ts
@@ -12360,7 +12842,7 @@ init_globals();
12360
12842
  var import_server = require("react-dom/server");
12361
12843
 
12362
12844
  // modules/server/handlers/middleware.ts
12363
- var import_path16 = __toESM(require("path"));
12845
+ var import_path18 = __toESM(require("path"));
12364
12846
 
12365
12847
  // modules/logger/index.ts
12366
12848
  var import_pino = __toESM(require("pino"));
@@ -12492,12 +12974,12 @@ var DEFAULT_IGNORED_PATHS = [
12492
12974
  /^\/sockjs-node/
12493
12975
  // Hot reload websocket
12494
12976
  ];
12495
- function shouldIgnorePath(path29, ignoredPaths) {
12977
+ function shouldIgnorePath(path31, ignoredPaths) {
12496
12978
  return ignoredPaths.some((pattern) => {
12497
12979
  if (typeof pattern === "string") {
12498
- return path29 === pattern || path29.startsWith(pattern);
12980
+ return path31 === pattern || path31.startsWith(pattern);
12499
12981
  }
12500
- return pattern.test(path29);
12982
+ return pattern.test(path31);
12501
12983
  });
12502
12984
  }
12503
12985
  function requestLoggerMiddleware(options = {}) {
@@ -12559,7 +13041,7 @@ async function runRouteMiddlewares(route, ctx) {
12559
13041
  );
12560
13042
  } catch (error) {
12561
13043
  const reqLogger = getRequestLogger(ctx.req);
12562
- const relativePath = route.pageFile ? import_path16.default.relative(process.cwd(), route.pageFile) : route.pattern;
13044
+ const relativePath = route.pageFile ? import_path18.default.relative(process.cwd(), route.pageFile) : route.pattern;
12563
13045
  reqLogger.error("Route middleware failed", error instanceof Error ? error : new Error(String(error)), {
12564
13046
  route: route.pattern,
12565
13047
  middlewareIndex: i,
@@ -12574,7 +13056,7 @@ async function runRouteMiddlewares(route, ctx) {
12574
13056
  }
12575
13057
 
12576
13058
  // modules/server/handlers/server-hook.ts
12577
- var import_path17 = __toESM(require("path"));
13059
+ var import_path19 = __toESM(require("path"));
12578
13060
  function createServerHookErrorMessage(error, hookType, routePattern, filePath) {
12579
13061
  const errorMessage = error instanceof Error ? error.message : String(error);
12580
13062
  const errorStack = error instanceof Error ? error.stack : void 0;
@@ -12583,7 +13065,7 @@ function createServerHookErrorMessage(error, hookType, routePattern, filePath) {
12583
13065
  message += `Route: ${routePattern}
12584
13066
  `;
12585
13067
  if (filePath) {
12586
- const relativePath = import_path17.default.relative(process.cwd(), filePath);
13068
+ const relativePath = import_path19.default.relative(process.cwd(), filePath);
12587
13069
  message += `File: ${relativePath}
12588
13070
  `;
12589
13071
  }
@@ -12644,7 +13126,9 @@ function handleDataResponse(res, loaderResult, theme, layoutProps, pageProps, er
12644
13126
  // Combined props for backward compatibility
12645
13127
  props: loaderResult.props ?? {},
12646
13128
  metadata: loaderResult.metadata ?? null,
12647
- theme: loaderResult.theme ?? theme ?? null
13129
+ theme: loaderResult.theme ?? theme ?? null,
13130
+ // Include pathname if provided (for rewrites - client needs to know the rewritten path)
13131
+ ...loaderResult.pathname ? { pathname: loaderResult.pathname } : {}
12648
13132
  };
12649
13133
  if (layoutProps !== void 0 && layoutProps !== null) {
12650
13134
  response.layoutProps = layoutProps;
@@ -12676,24 +13160,24 @@ function handleNotFound(res, urlPath) {
12676
13160
  }
12677
13161
 
12678
13162
  // modules/server/handlers/ssg.ts
12679
- var import_fs13 = __toESM(require("fs"));
12680
- var import_path18 = __toESM(require("path"));
13163
+ var import_fs15 = __toESM(require("fs"));
13164
+ var import_path20 = __toESM(require("path"));
12681
13165
  var logger2 = createModuleLogger("ssg");
12682
13166
  function getSsgDirForPath(baseDir, urlPath) {
12683
13167
  const clean = urlPath === "/" ? "" : urlPath.replace(/^\/+/, "");
12684
- return import_path18.default.join(baseDir, clean);
13168
+ return import_path20.default.join(baseDir, clean);
12685
13169
  }
12686
13170
  function getSsgHtmlPath(baseDir, urlPath) {
12687
13171
  const dir = getSsgDirForPath(baseDir, urlPath);
12688
- return import_path18.default.join(dir, "index.html");
13172
+ return import_path20.default.join(dir, "index.html");
12689
13173
  }
12690
13174
  function getSsgDataPath(baseDir, urlPath) {
12691
13175
  const dir = getSsgDirForPath(baseDir, urlPath);
12692
- return import_path18.default.join(dir, "data.json");
13176
+ return import_path20.default.join(dir, "data.json");
12693
13177
  }
12694
13178
  function tryServeSsgHtml(res, ssgOutDir, urlPath) {
12695
13179
  const ssgHtmlPath = getSsgHtmlPath(ssgOutDir, urlPath);
12696
- if (!import_fs13.default.existsSync(ssgHtmlPath)) {
13180
+ if (!import_fs15.default.existsSync(ssgHtmlPath)) {
12697
13181
  return false;
12698
13182
  }
12699
13183
  logger2.info("Serving SSG HTML", { urlPath, ssgHtmlPath });
@@ -12703,17 +13187,17 @@ function tryServeSsgHtml(res, ssgOutDir, urlPath) {
12703
13187
  );
12704
13188
  res.statusCode = 200;
12705
13189
  res.setHeader("Content-Type", "text/html; charset=utf-8");
12706
- const stream = import_fs13.default.createReadStream(ssgHtmlPath, { encoding: "utf-8" });
13190
+ const stream = import_fs15.default.createReadStream(ssgHtmlPath, { encoding: "utf-8" });
12707
13191
  stream.pipe(res);
12708
13192
  return true;
12709
13193
  }
12710
13194
  function tryServeSsgData(res, ssgOutDir, urlPath) {
12711
13195
  const ssgDataPath = getSsgDataPath(ssgOutDir, urlPath);
12712
- if (!import_fs13.default.existsSync(ssgDataPath)) {
13196
+ if (!import_fs15.default.existsSync(ssgDataPath)) {
12713
13197
  return false;
12714
13198
  }
12715
13199
  try {
12716
- const raw = import_fs13.default.readFileSync(ssgDataPath, "utf-8");
13200
+ const raw = import_fs15.default.readFileSync(ssgDataPath, "utf-8");
12717
13201
  res.setHeader("Content-Type", "application/json; charset=utf-8");
12718
13202
  res.status(200).end(raw);
12719
13203
  return true;
@@ -12779,7 +13263,7 @@ function sanitizeQuery(query) {
12779
13263
  }
12780
13264
 
12781
13265
  // modules/server/handlers/pages.ts
12782
- var import_path19 = __toESM(require("path"));
13266
+ var import_path21 = __toESM(require("path"));
12783
13267
  function mergeMetadata(base, override) {
12784
13268
  if (!base && !override) return null;
12785
13269
  if (!base) return override;
@@ -12846,8 +13330,43 @@ async function handlePageRequestInternal(options) {
12846
13330
  ssgOutDir,
12847
13331
  theme,
12848
13332
  projectRoot,
12849
- config
13333
+ config,
13334
+ rewriteLoader
12850
13335
  } = options;
13336
+ let finalUrlPath = urlPath;
13337
+ let extractedParams = {};
13338
+ if (rewriteLoader) {
13339
+ try {
13340
+ const compiledRewrites = await rewriteLoader.loadRewrites();
13341
+ const rewriteResult = await processRewrites(urlPath, compiledRewrites, req);
13342
+ if (rewriteResult) {
13343
+ finalUrlPath = rewriteResult.rewrittenPath;
13344
+ extractedParams = rewriteResult.extractedParams;
13345
+ finalUrlPath = finalUrlPath.replace(/\/+/g, "/").replace(/^([^/])/, "/$1").replace(/\/$/, "") || "/";
13346
+ if (env === "dev") {
13347
+ const reqLogger2 = getRequestLogger(req);
13348
+ reqLogger2.debug("Rewrite applied", {
13349
+ originalPath: urlPath,
13350
+ rewrittenPath: finalUrlPath,
13351
+ extractedParams,
13352
+ host: req.get("host")
13353
+ });
13354
+ }
13355
+ Object.assign(req.query, extractedParams);
13356
+ if (!req.locals) {
13357
+ req.locals = {};
13358
+ }
13359
+ Object.assign(req.locals, extractedParams);
13360
+ }
13361
+ } catch (error) {
13362
+ const reqLogger2 = getRequestLogger(req);
13363
+ reqLogger2.error("Error processing rewrites", error, {
13364
+ urlPath,
13365
+ host: req.get("host")
13366
+ });
13367
+ }
13368
+ }
13369
+ finalUrlPath = finalUrlPath.replace(/\/$/, "") || "/";
12851
13370
  const clientJsPath = env === "dev" ? "/static/client.js" : projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
12852
13371
  const clientCssPath = env === "dev" ? "/static/client.css" : projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
12853
13372
  const assetManifest = env === "prod" && projectRoot ? loadAssetManifest(projectRoot) : null;
@@ -12856,18 +13375,43 @@ async function handlePageRequestInternal(options) {
12856
13375
  const skipLayoutHooks = isDataReq && req.headers["x-skip-layout-hooks"] === "true";
12857
13376
  if (env === "prod" && ssgOutDir) {
12858
13377
  if (isDataReq) {
12859
- if (tryServeSsgData(res, ssgOutDir, urlPath)) {
13378
+ if (tryServeSsgData(res, ssgOutDir, finalUrlPath)) {
12860
13379
  return;
12861
13380
  }
12862
13381
  } else {
12863
- if (tryServeSsgHtml(res, ssgOutDir, urlPath)) {
13382
+ if (tryServeSsgHtml(res, ssgOutDir, finalUrlPath)) {
12864
13383
  return;
12865
13384
  }
12866
13385
  }
12867
13386
  }
12868
- const matched = matchRoute(routes, urlPath);
13387
+ const matched = matchRoute(routes, finalUrlPath);
13388
+ if (env === "dev") {
13389
+ const reqLogger2 = getRequestLogger(req);
13390
+ if (finalUrlPath !== urlPath) {
13391
+ reqLogger2.debug("Route matching after rewrite", {
13392
+ originalPath: urlPath,
13393
+ rewrittenPath: finalUrlPath,
13394
+ matched: !!matched,
13395
+ matchedRoute: matched?.route.pattern,
13396
+ matchedParams: matched?.params,
13397
+ availableRoutes: routes.slice(0, 10).map((r) => r.pattern)
13398
+ // Show first 10 routes
13399
+ });
13400
+ } else if (!matched) {
13401
+ reqLogger2.debug("No route match found", {
13402
+ path: finalUrlPath,
13403
+ availableRoutes: routes.slice(0, 10).map((r) => r.pattern)
13404
+ });
13405
+ }
13406
+ }
12869
13407
  const routerData = buildRouterData(req);
12870
13408
  if (!matched) {
13409
+ if (isDataReq) {
13410
+ res.statusCode = 404;
13411
+ res.setHeader("Content-Type", "application/json; charset=utf-8");
13412
+ res.end(JSON.stringify({ notFound: true, pathname: finalUrlPath }));
13413
+ return;
13414
+ }
12871
13415
  if (notFoundPage) {
12872
13416
  const ctx2 = {
12873
13417
  req,
@@ -12891,7 +13435,7 @@ async function handlePageRequestInternal(options) {
12891
13435
  } catch (error) {
12892
13436
  const reqLogger2 = getRequestLogger(req);
12893
13437
  const layoutFile = notFoundPage.layoutFiles[i];
12894
- const relativeLayoutPath = layoutFile ? import_path19.default.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
13438
+ const relativeLayoutPath = layoutFile ? import_path21.default.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
12895
13439
  reqLogger2.error("Layout middleware failed for not-found page", error instanceof Error ? error : new Error(String(error)), {
12896
13440
  layoutIndex: i,
12897
13441
  layoutFile: relativeLayoutPath
@@ -12912,7 +13456,7 @@ async function handlePageRequestInternal(options) {
12912
13456
  } catch (error) {
12913
13457
  const reqLogger2 = getRequestLogger(req);
12914
13458
  const layoutFile = notFoundPage.layoutFiles[i];
12915
- const relativeLayoutPath = layoutFile ? import_path19.default.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
13459
+ const relativeLayoutPath = layoutFile ? import_path21.default.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
12916
13460
  reqLogger2.warn("Layout server hook failed for not-found page", {
12917
13461
  error: error instanceof Error ? error.message : String(error),
12918
13462
  stack: error instanceof Error ? error.stack : void 0,
@@ -12946,7 +13490,7 @@ async function handlePageRequestInternal(options) {
12946
13490
  );
12947
13491
  return;
12948
13492
  }
12949
- const initialData2 = buildInitialData(urlPath, {}, combinedLoaderResult2);
13493
+ const initialData2 = buildInitialData(finalUrlPath, {}, combinedLoaderResult2);
12950
13494
  const appTree2 = buildAppTree(notFoundPage, {}, initialData2.props);
12951
13495
  initialData2.notFound = true;
12952
13496
  const nonce2 = res.locals.nonce || void 0;
@@ -13032,7 +13576,7 @@ async function handlePageRequestInternal(options) {
13032
13576
  );
13033
13577
  } catch (error) {
13034
13578
  const layoutFile = route.layoutFiles[i];
13035
- const relativeLayoutPath = layoutFile ? import_path19.default.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
13579
+ const relativeLayoutPath = layoutFile ? import_path21.default.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
13036
13580
  reqLogger.error("Layout middleware failed", error instanceof Error ? error : new Error(String(error)), {
13037
13581
  route: route.pattern,
13038
13582
  layoutIndex: i,
@@ -13056,7 +13600,7 @@ async function handlePageRequestInternal(options) {
13056
13600
  }
13057
13601
  } catch (error) {
13058
13602
  const layoutFile = route.layoutFiles[i];
13059
- const relativeLayoutPath = layoutFile ? import_path19.default.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
13603
+ const relativeLayoutPath = layoutFile ? import_path21.default.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
13060
13604
  reqLogger.warn("Layout server hook failed", {
13061
13605
  error: error instanceof Error ? error.message : String(error),
13062
13606
  stack: error instanceof Error ? error.stack : void 0,
@@ -13076,7 +13620,7 @@ async function handlePageRequestInternal(options) {
13076
13620
  loaderResult.theme = theme;
13077
13621
  }
13078
13622
  } catch (error) {
13079
- const relativePagePath = route.pageFile ? import_path19.default.relative(projectRoot || process.cwd(), route.pageFile) : "unknown";
13623
+ const relativePagePath = route.pageFile ? import_path21.default.relative(projectRoot || process.cwd(), route.pageFile) : "unknown";
13080
13624
  reqLogger.error("Page server hook failed", {
13081
13625
  error: error instanceof Error ? error.message : String(error),
13082
13626
  stack: error instanceof Error ? error.stack : void 0,
@@ -13123,7 +13667,9 @@ async function handlePageRequestInternal(options) {
13123
13667
  const combinedLoaderResult = {
13124
13668
  ...loaderResult,
13125
13669
  props: combinedProps,
13126
- metadata: combinedMetadata
13670
+ metadata: combinedMetadata,
13671
+ pathname: finalUrlPath
13672
+ // Include rewritten pathname for client-side matching
13127
13673
  };
13128
13674
  if (isDataReq) {
13129
13675
  const pagePropsOnly = loaderResult.props || {};
@@ -13148,7 +13694,7 @@ async function handlePageRequestInternal(options) {
13148
13694
  }
13149
13695
  return;
13150
13696
  }
13151
- const initialData = buildInitialData(urlPath, params, combinedLoaderResult);
13697
+ const initialData = buildInitialData(finalUrlPath, params, combinedLoaderResult);
13152
13698
  const appTree = buildAppTree(route, params, initialData.props);
13153
13699
  const chunkName = routeChunks[route.pattern];
13154
13700
  let chunkHref = null;
@@ -13253,7 +13799,7 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
13253
13799
  );
13254
13800
  } catch (error2) {
13255
13801
  const layoutFile = errorPage.layoutFiles[i];
13256
- const relativeLayoutPath = layoutFile ? import_path19.default.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
13802
+ const relativeLayoutPath = layoutFile ? import_path21.default.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
13257
13803
  reqLogger.error("Layout middleware failed for error page", error2 instanceof Error ? error2 : new Error(String(error2)), {
13258
13804
  layoutIndex: i,
13259
13805
  layoutFile: relativeLayoutPath
@@ -13273,7 +13819,7 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
13273
13819
  }
13274
13820
  } catch (err) {
13275
13821
  const layoutFile = errorPage.layoutFiles[i];
13276
- const relativeLayoutPath = layoutFile ? import_path19.default.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
13822
+ const relativeLayoutPath = layoutFile ? import_path21.default.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
13277
13823
  reqLogger.warn("Layout server hook failed for error page", {
13278
13824
  error: err instanceof Error ? err.message : String(err),
13279
13825
  stack: err instanceof Error ? err.stack : void 0,
@@ -13510,16 +14056,16 @@ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params,
13510
14056
  const html = "<!DOCTYPE html>" + (0, import_server2.renderToString)(documentTree);
13511
14057
  const dir = pathToOutDir(ssgOutDir, urlPath);
13512
14058
  ensureDir(dir);
13513
- const htmlFile = import_path20.default.join(dir, "index.html");
13514
- const dataFile = import_path20.default.join(dir, "data.json");
13515
- import_fs14.default.writeFileSync(htmlFile, html, "utf-8");
13516
- import_fs14.default.writeFileSync(dataFile, JSON.stringify(initialData, null, 2), "utf-8");
14059
+ const htmlFile = import_path22.default.join(dir, "index.html");
14060
+ const dataFile = import_path22.default.join(dir, "data.json");
14061
+ import_fs16.default.writeFileSync(htmlFile, html, "utf-8");
14062
+ import_fs16.default.writeFileSync(dataFile, JSON.stringify(initialData, null, 2), "utf-8");
13517
14063
  }
13518
14064
 
13519
14065
  // modules/build/ssg/builder.ts
13520
14066
  init_globals();
13521
14067
  async function buildStaticPages(projectRoot, routes, config) {
13522
- const ssgOutDir = import_path22.default.join(projectRoot, BUILD_FOLDER_NAME, "ssg");
14068
+ const ssgOutDir = import_path24.default.join(projectRoot, BUILD_FOLDER_NAME, "ssg");
13523
14069
  ensureDir(ssgOutDir);
13524
14070
  for (const route of routes) {
13525
14071
  if (route.dynamic !== "force-static") continue;
@@ -13574,27 +14120,27 @@ async function buildStaticPages(projectRoot, routes, config) {
13574
14120
  }
13575
14121
 
13576
14122
  // modules/build/bundler/server.ts
13577
- var import_path25 = __toESM(require("path"));
13578
- var import_fs16 = __toESM(require("fs"));
14123
+ var import_path27 = __toESM(require("path"));
14124
+ var import_fs18 = __toESM(require("fs"));
13579
14125
  var import_esbuild = __toESM(require("esbuild"));
13580
14126
 
13581
14127
  // modules/server/utils/server-dir.ts
13582
- var import_fs15 = __toESM(require("fs"));
13583
- var import_path24 = __toESM(require("path"));
14128
+ var import_fs17 = __toESM(require("fs"));
14129
+ var import_path26 = __toESM(require("path"));
13584
14130
  init_globals();
13585
14131
  var getServerFile = async (projectRoot, fileName) => {
13586
- const fileTS = import_path24.default.join(projectRoot, `${fileName}.ts`);
13587
- const fileJS = import_path24.default.join(projectRoot, BUILD_FOLDER_NAME, "server", `${fileName}.js`);
14132
+ const fileTS = import_path26.default.join(projectRoot, `${fileName}.ts`);
14133
+ const fileJS = import_path26.default.join(projectRoot, BUILD_FOLDER_NAME, "server", `${fileName}.js`);
13588
14134
  const isDev = process.env.NODE_ENV === "development";
13589
14135
  let mod = null;
13590
14136
  if (isDev) {
13591
- if (!import_fs15.default.existsSync(fileTS)) {
14137
+ if (!import_fs17.default.existsSync(fileTS)) {
13592
14138
  return null;
13593
14139
  }
13594
14140
  require("tsx/cjs");
13595
14141
  mod = require(fileTS);
13596
14142
  } else {
13597
- if (!import_fs15.default.existsSync(fileJS)) {
14143
+ if (!import_fs17.default.existsSync(fileJS)) {
13598
14144
  return null;
13599
14145
  }
13600
14146
  mod = require(fileJS);
@@ -13776,29 +14322,29 @@ init_globals();
13776
14322
  var SERVER_FILES = [INIT_FILE_NAME, CONFIG_FILE_NAME];
13777
14323
  function createPathAliasPlugin(projectRoot, outDir) {
13778
14324
  const aliases = loadAliasesFromTsconfig(projectRoot);
13779
- const tsconfigPath = import_path25.default.join(projectRoot, "tsconfig.json");
14325
+ const tsconfigPath = import_path27.default.join(projectRoot, "tsconfig.json");
13780
14326
  let baseUrl = ".";
13781
- if (import_fs16.default.existsSync(tsconfigPath)) {
14327
+ if (import_fs18.default.existsSync(tsconfigPath)) {
13782
14328
  try {
13783
- const tsconfig = JSON.parse(import_fs16.default.readFileSync(tsconfigPath, "utf-8"));
14329
+ const tsconfig = JSON.parse(import_fs18.default.readFileSync(tsconfigPath, "utf-8"));
13784
14330
  baseUrl = tsconfig.compilerOptions?.baseUrl ?? ".";
13785
14331
  } catch {
13786
14332
  }
13787
14333
  }
13788
14334
  function resolveAliasToRelative(importPath, sourceFile) {
13789
- if (importPath.startsWith(".") || importPath.startsWith("/") || import_path25.default.isAbsolute(importPath) || importPath.includes("node_modules")) {
14335
+ if (importPath.startsWith(".") || importPath.startsWith("/") || import_path27.default.isAbsolute(importPath) || importPath.includes("node_modules")) {
13790
14336
  return null;
13791
14337
  }
13792
14338
  for (const [aliasKey, aliasPath] of Object.entries(aliases)) {
13793
14339
  if (importPath.startsWith(aliasKey + "/") || importPath === aliasKey) {
13794
14340
  const restPath = importPath.startsWith(aliasKey + "/") ? importPath.slice(aliasKey.length + 1) : "";
13795
- const resolvedPath = restPath ? import_path25.default.join(aliasPath, restPath) : aliasPath;
14341
+ const resolvedPath = restPath ? import_path27.default.join(aliasPath, restPath) : aliasPath;
13796
14342
  let actualPath = null;
13797
14343
  const extensions = [".ts", ".tsx", ".js", ".jsx", ".json"];
13798
- if (import_fs16.default.existsSync(resolvedPath) && import_fs16.default.statSync(resolvedPath).isDirectory()) {
14344
+ if (import_fs18.default.existsSync(resolvedPath) && import_fs18.default.statSync(resolvedPath).isDirectory()) {
13799
14345
  for (const ext of extensions) {
13800
- const indexPath = import_path25.default.join(resolvedPath, `index${ext}`);
13801
- if (import_fs16.default.existsSync(indexPath)) {
14346
+ const indexPath = import_path27.default.join(resolvedPath, `index${ext}`);
14347
+ if (import_fs18.default.existsSync(indexPath)) {
13802
14348
  actualPath = indexPath;
13803
14349
  break;
13804
14350
  }
@@ -13806,20 +14352,20 @@ function createPathAliasPlugin(projectRoot, outDir) {
13806
14352
  } else {
13807
14353
  for (const ext of extensions) {
13808
14354
  const filePath = resolvedPath + ext;
13809
- if (import_fs16.default.existsSync(filePath)) {
14355
+ if (import_fs18.default.existsSync(filePath)) {
13810
14356
  actualPath = filePath;
13811
14357
  break;
13812
14358
  }
13813
14359
  }
13814
- if (!actualPath && import_fs16.default.existsSync(resolvedPath)) {
14360
+ if (!actualPath && import_fs18.default.existsSync(resolvedPath)) {
13815
14361
  actualPath = resolvedPath;
13816
14362
  }
13817
14363
  }
13818
14364
  if (actualPath) {
13819
- const relativePath = import_path25.default.relative(outDir, actualPath);
14365
+ const relativePath = import_path27.default.relative(outDir, actualPath);
13820
14366
  const normalizedPath = relativePath.replace(/\\/g, "/");
13821
14367
  const finalPath = normalizedPath.startsWith(".") ? normalizedPath : `./${normalizedPath}`;
13822
- const ext = import_path25.default.extname(finalPath);
14368
+ const ext = import_path27.default.extname(finalPath);
13823
14369
  const pathWithoutExt = ext === ".json" ? finalPath : finalPath.slice(0, -ext.length);
13824
14370
  return pathWithoutExt;
13825
14371
  }
@@ -13831,13 +14377,13 @@ function createPathAliasPlugin(projectRoot, outDir) {
13831
14377
  name: "path-alias-resolver",
13832
14378
  setup(build) {
13833
14379
  build.onLoad({ filter: /\.(ts|tsx|js|jsx)$/ }, (args) => {
13834
- const fileName = import_path25.default.basename(args.path);
14380
+ const fileName = import_path27.default.basename(args.path);
13835
14381
  const isServerFile = SERVER_FILES.some((f) => fileName === `${f}.ts` || fileName === `${f}.tsx` || fileName === `${f}.js` || fileName === `${f}.jsx`);
13836
- const isInProjectRoot = import_path25.default.dirname(args.path) === projectRoot;
14382
+ const isInProjectRoot = import_path27.default.dirname(args.path) === projectRoot;
13837
14383
  if (!isServerFile || !isInProjectRoot) {
13838
14384
  return null;
13839
14385
  }
13840
- const contents = import_fs16.default.readFileSync(args.path, "utf-8");
14386
+ const contents = import_fs18.default.readFileSync(args.path, "utf-8");
13841
14387
  let transformed = contents;
13842
14388
  const aliasPatterns = Object.keys(aliases).sort((a, b) => b.length - a.length);
13843
14389
  for (const aliasKey of aliasPatterns) {
@@ -13857,7 +14403,7 @@ function createPathAliasPlugin(projectRoot, outDir) {
13857
14403
  }
13858
14404
  return {
13859
14405
  contents: transformed,
13860
- loader: import_path25.default.extname(args.path).slice(1)
14406
+ loader: import_path27.default.extname(args.path).slice(1)
13861
14407
  };
13862
14408
  });
13863
14409
  build.onResolve({ filter: /.*/ }, (args) => {
@@ -13876,9 +14422,9 @@ function createPathAliasPlugin(projectRoot, outDir) {
13876
14422
  function collectAppSources(appDir) {
13877
14423
  const entries = [];
13878
14424
  function walk(dir) {
13879
- const items = import_fs16.default.readdirSync(dir, { withFileTypes: true });
14425
+ const items = import_fs18.default.readdirSync(dir, { withFileTypes: true });
13880
14426
  for (const item of items) {
13881
- const full = import_path25.default.join(dir, item.name);
14427
+ const full = import_path27.default.join(dir, item.name);
13882
14428
  if (item.isDirectory()) {
13883
14429
  walk(full);
13884
14430
  continue;
@@ -13895,7 +14441,7 @@ function collectAppSources(appDir) {
13895
14441
  return entries;
13896
14442
  }
13897
14443
  async function buildServerApp(projectRoot, appDir) {
13898
- const outDir = import_path25.default.join(projectRoot, BUILD_FOLDER_NAME, "server");
14444
+ const outDir = import_path27.default.join(projectRoot, BUILD_FOLDER_NAME, "server");
13899
14445
  const entryPoints = collectAppSources(appDir);
13900
14446
  ensureDir(outDir);
13901
14447
  if (entryPoints.length === 0) {
@@ -13913,14 +14459,14 @@ async function buildServerApp(projectRoot, appDir) {
13913
14459
  bundle: true,
13914
14460
  splitting: false,
13915
14461
  logLevel: "info",
13916
- tsconfig: import_path25.default.join(projectRoot, "tsconfig.json"),
14462
+ tsconfig: import_path27.default.join(projectRoot, "tsconfig.json"),
13917
14463
  packages: "external"
13918
14464
  });
13919
14465
  const pathAliasPlugin = createPathAliasPlugin(projectRoot, outDir);
13920
14466
  for (const fileName of SERVER_FILES) {
13921
- const initTS = import_path25.default.join(projectRoot, `${fileName}.ts`);
13922
- const initJS = import_path25.default.join(outDir, `${fileName}.js`);
13923
- if (import_fs16.default.existsSync(initTS)) {
14467
+ const initTS = import_path27.default.join(projectRoot, `${fileName}.ts`);
14468
+ const initJS = import_path27.default.join(outDir, `${fileName}.js`);
14469
+ if (import_fs18.default.existsSync(initTS)) {
13924
14470
  await import_esbuild.default.build({
13925
14471
  entryPoints: [initTS],
13926
14472
  outfile: initJS,
@@ -13931,7 +14477,7 @@ async function buildServerApp(projectRoot, appDir) {
13931
14477
  sourcemap: true,
13932
14478
  bundle: false,
13933
14479
  logLevel: "info",
13934
- tsconfig: import_path25.default.join(projectRoot, "tsconfig.json"),
14480
+ tsconfig: import_path27.default.join(projectRoot, "tsconfig.json"),
13935
14481
  plugins: [pathAliasPlugin]
13936
14482
  });
13937
14483
  }
@@ -13943,8 +14489,8 @@ async function buildServerApp(projectRoot, appDir) {
13943
14489
  init_globals();
13944
14490
 
13945
14491
  // src/config.ts
13946
- var import_path26 = __toESM(require("path"));
13947
- var import_fs17 = __toESM(require("fs"));
14492
+ var import_path28 = __toESM(require("path"));
14493
+ var import_fs19 = __toESM(require("fs"));
13948
14494
  init_globals();
13949
14495
  var DEFAULT_CONFIG2 = {
13950
14496
  directories: {
@@ -14011,8 +14557,8 @@ function validateConfig(config, projectRoot) {
14011
14557
  if (!config.directories.app || typeof config.directories.app !== "string") {
14012
14558
  errors.push("config.directories.app must be a non-empty string");
14013
14559
  } else {
14014
- const appDir = import_path26.default.join(projectRoot, config.directories.app);
14015
- if (!import_fs17.default.existsSync(appDir) && process.env.NODE_ENV !== "test") {
14560
+ const appDir = import_path28.default.join(projectRoot, config.directories.app);
14561
+ if (!import_fs19.default.existsSync(appDir) && process.env.NODE_ENV !== "test") {
14016
14562
  errors.push(
14017
14563
  `App directory not found: ${config.directories.app}
14018
14564
  Expected at: ${appDir}
@@ -14116,17 +14662,17 @@ function validateConfig(config, projectRoot) {
14116
14662
  }
14117
14663
  function loadConfig(projectRoot) {
14118
14664
  const configFiles = [
14119
- import_path26.default.join(projectRoot, "loly.config.ts"),
14120
- import_path26.default.join(projectRoot, "loly.config.js"),
14121
- import_path26.default.join(projectRoot, "loly.config.json")
14665
+ import_path28.default.join(projectRoot, "loly.config.ts"),
14666
+ import_path28.default.join(projectRoot, "loly.config.js"),
14667
+ import_path28.default.join(projectRoot, "loly.config.json")
14122
14668
  ];
14123
14669
  let userConfig = {};
14124
14670
  let loadedConfigFile = null;
14125
14671
  for (const configFile of configFiles) {
14126
- if (import_fs17.default.existsSync(configFile)) {
14672
+ if (import_fs19.default.existsSync(configFile)) {
14127
14673
  try {
14128
14674
  if (configFile.endsWith(".json")) {
14129
- const content = import_fs17.default.readFileSync(configFile, "utf-8");
14675
+ const content = import_fs19.default.readFileSync(configFile, "utf-8");
14130
14676
  userConfig = JSON.parse(content);
14131
14677
  } else {
14132
14678
  if (process.env.NODE_ENV === "development") {
@@ -14135,12 +14681,12 @@ function loadConfig(projectRoot) {
14135
14681
  const mod = require(configFile);
14136
14682
  userConfig = typeof mod.default === "function" ? mod.default(process.env.NODE_ENV) : mod.default || mod.config || mod;
14137
14683
  }
14138
- loadedConfigFile = import_path26.default.relative(projectRoot, configFile);
14684
+ loadedConfigFile = import_path28.default.relative(projectRoot, configFile);
14139
14685
  break;
14140
14686
  } catch (error) {
14141
14687
  const errorMessage = error instanceof Error ? error.message : String(error);
14142
14688
  throw new ConfigValidationError(
14143
- `Failed to load configuration from ${import_path26.default.relative(projectRoot, configFile)}:
14689
+ `Failed to load configuration from ${import_path28.default.relative(projectRoot, configFile)}:
14144
14690
  ${errorMessage}
14145
14691
  \u{1F4A1} Suggestion: Check that your config file exports a valid configuration object`
14146
14692
  );
@@ -14164,13 +14710,13 @@ ${error.message}`;
14164
14710
  return config;
14165
14711
  }
14166
14712
  function getAppDir(projectRoot, config) {
14167
- return import_path26.default.resolve(projectRoot, config.directories.app);
14713
+ return import_path28.default.resolve(projectRoot, config.directories.app);
14168
14714
  }
14169
14715
  function getBuildDir(projectRoot, config) {
14170
- return import_path26.default.join(projectRoot, config.directories.build);
14716
+ return import_path28.default.join(projectRoot, config.directories.build);
14171
14717
  }
14172
14718
  function getStaticDir(projectRoot, config) {
14173
- return import_path26.default.resolve(projectRoot, config.directories.static);
14719
+ return import_path28.default.resolve(projectRoot, config.directories.static);
14174
14720
  }
14175
14721
 
14176
14722
  // modules/build/index.ts
@@ -14215,6 +14761,7 @@ async function buildApp(options = {}) {
14215
14761
  });
14216
14762
  writeClientBoostrapManifest(projectRoot);
14217
14763
  writeClientRoutesManifest(routes, projectRoot);
14764
+ await writeRewritesManifest(projectRoot);
14218
14765
  await buildClientBundle(projectRoot);
14219
14766
  await buildStaticPages(projectRoot, routes, config);
14220
14767
  delete process.env.LOLY_BUILD;
@@ -14222,16 +14769,16 @@ async function buildApp(options = {}) {
14222
14769
  }
14223
14770
 
14224
14771
  // src/server.ts
14225
- var import_fs21 = __toESM(require("fs"));
14226
- var import_path31 = __toESM(require("path"));
14772
+ var import_fs23 = __toESM(require("fs"));
14773
+ var import_path33 = __toESM(require("path"));
14227
14774
 
14228
14775
  // modules/server/setup.ts
14229
14776
  var import_express = __toESM(require("express"));
14230
- var import_path29 = __toESM(require("path"));
14231
- var import_fs20 = __toESM(require("fs"));
14777
+ var import_path31 = __toESM(require("path"));
14778
+ var import_fs22 = __toESM(require("fs"));
14232
14779
 
14233
14780
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
14234
- var import_fs19 = require("fs");
14781
+ var import_fs21 = require("fs");
14235
14782
  var import_promises3 = require("fs/promises");
14236
14783
  var import_events = require("events");
14237
14784
  var sysPath2 = __toESM(require("path"), 1);
@@ -14306,7 +14853,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
14306
14853
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
14307
14854
  const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
14308
14855
  if (wantBigintFsStats) {
14309
- this._stat = (path29) => statMethod(path29, { bigint: true });
14856
+ this._stat = (path31) => statMethod(path31, { bigint: true });
14310
14857
  } else {
14311
14858
  this._stat = statMethod;
14312
14859
  }
@@ -14331,8 +14878,8 @@ var ReaddirpStream = class extends import_node_stream.Readable {
14331
14878
  const par = this.parent;
14332
14879
  const fil = par && par.files;
14333
14880
  if (fil && fil.length > 0) {
14334
- const { path: path29, depth } = par;
14335
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path29));
14881
+ const { path: path31, depth } = par;
14882
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path31));
14336
14883
  const awaited = await Promise.all(slice);
14337
14884
  for (const entry of awaited) {
14338
14885
  if (!entry)
@@ -14372,20 +14919,20 @@ var ReaddirpStream = class extends import_node_stream.Readable {
14372
14919
  this.reading = false;
14373
14920
  }
14374
14921
  }
14375
- async _exploreDir(path29, depth) {
14922
+ async _exploreDir(path31, depth) {
14376
14923
  let files;
14377
14924
  try {
14378
- files = await (0, import_promises.readdir)(path29, this._rdOptions);
14925
+ files = await (0, import_promises.readdir)(path31, this._rdOptions);
14379
14926
  } catch (error) {
14380
14927
  this._onError(error);
14381
14928
  }
14382
- return { files, depth, path: path29 };
14929
+ return { files, depth, path: path31 };
14383
14930
  }
14384
- async _formatEntry(dirent, path29) {
14931
+ async _formatEntry(dirent, path31) {
14385
14932
  let entry;
14386
14933
  const basename3 = this._isDirent ? dirent.name : dirent;
14387
14934
  try {
14388
- const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path29, basename3));
14935
+ const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path31, basename3));
14389
14936
  entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename3 };
14390
14937
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
14391
14938
  } catch (err) {
@@ -14456,7 +15003,7 @@ function readdirp(root, options = {}) {
14456
15003
  }
14457
15004
 
14458
15005
  // ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/handler.js
14459
- var import_fs18 = require("fs");
15006
+ var import_fs20 = require("fs");
14460
15007
  var import_promises2 = require("fs/promises");
14461
15008
  var sysPath = __toESM(require("path"), 1);
14462
15009
  var import_os = require("os");
@@ -14785,16 +15332,16 @@ var delFromSet = (main, prop, item) => {
14785
15332
  };
14786
15333
  var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
14787
15334
  var FsWatchInstances = /* @__PURE__ */ new Map();
14788
- function createFsWatchInstance(path29, options, listener, errHandler, emitRaw) {
15335
+ function createFsWatchInstance(path31, options, listener, errHandler, emitRaw) {
14789
15336
  const handleEvent = (rawEvent, evPath) => {
14790
- listener(path29);
14791
- emitRaw(rawEvent, evPath, { watchedPath: path29 });
14792
- if (evPath && path29 !== evPath) {
14793
- fsWatchBroadcast(sysPath.resolve(path29, evPath), KEY_LISTENERS, sysPath.join(path29, evPath));
15337
+ listener(path31);
15338
+ emitRaw(rawEvent, evPath, { watchedPath: path31 });
15339
+ if (evPath && path31 !== evPath) {
15340
+ fsWatchBroadcast(sysPath.resolve(path31, evPath), KEY_LISTENERS, sysPath.join(path31, evPath));
14794
15341
  }
14795
15342
  };
14796
15343
  try {
14797
- return (0, import_fs18.watch)(path29, {
15344
+ return (0, import_fs20.watch)(path31, {
14798
15345
  persistent: options.persistent
14799
15346
  }, handleEvent);
14800
15347
  } catch (error) {
@@ -14810,12 +15357,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
14810
15357
  listener(val1, val2, val3);
14811
15358
  });
14812
15359
  };
14813
- var setFsWatchListener = (path29, fullPath, options, handlers) => {
15360
+ var setFsWatchListener = (path31, fullPath, options, handlers) => {
14814
15361
  const { listener, errHandler, rawEmitter } = handlers;
14815
15362
  let cont = FsWatchInstances.get(fullPath);
14816
15363
  let watcher;
14817
15364
  if (!options.persistent) {
14818
- watcher = createFsWatchInstance(path29, options, listener, errHandler, rawEmitter);
15365
+ watcher = createFsWatchInstance(path31, options, listener, errHandler, rawEmitter);
14819
15366
  if (!watcher)
14820
15367
  return;
14821
15368
  return watcher.close.bind(watcher);
@@ -14826,7 +15373,7 @@ var setFsWatchListener = (path29, fullPath, options, handlers) => {
14826
15373
  addAndConvert(cont, KEY_RAW, rawEmitter);
14827
15374
  } else {
14828
15375
  watcher = createFsWatchInstance(
14829
- path29,
15376
+ path31,
14830
15377
  options,
14831
15378
  fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
14832
15379
  errHandler,
@@ -14841,7 +15388,7 @@ var setFsWatchListener = (path29, fullPath, options, handlers) => {
14841
15388
  cont.watcherUnusable = true;
14842
15389
  if (isWindows && error.code === "EPERM") {
14843
15390
  try {
14844
- const fd = await (0, import_promises2.open)(path29, "r");
15391
+ const fd = await (0, import_promises2.open)(path31, "r");
14845
15392
  await fd.close();
14846
15393
  broadcastErr(error);
14847
15394
  } catch (err) {
@@ -14872,12 +15419,12 @@ var setFsWatchListener = (path29, fullPath, options, handlers) => {
14872
15419
  };
14873
15420
  };
14874
15421
  var FsWatchFileInstances = /* @__PURE__ */ new Map();
14875
- var setFsWatchFileListener = (path29, fullPath, options, handlers) => {
15422
+ var setFsWatchFileListener = (path31, fullPath, options, handlers) => {
14876
15423
  const { listener, rawEmitter } = handlers;
14877
15424
  let cont = FsWatchFileInstances.get(fullPath);
14878
15425
  const copts = cont && cont.options;
14879
15426
  if (copts && (copts.persistent < options.persistent || copts.interval > options.interval)) {
14880
- (0, import_fs18.unwatchFile)(fullPath);
15427
+ (0, import_fs20.unwatchFile)(fullPath);
14881
15428
  cont = void 0;
14882
15429
  }
14883
15430
  if (cont) {
@@ -14888,13 +15435,13 @@ var setFsWatchFileListener = (path29, fullPath, options, handlers) => {
14888
15435
  listeners: listener,
14889
15436
  rawEmitters: rawEmitter,
14890
15437
  options,
14891
- watcher: (0, import_fs18.watchFile)(fullPath, options, (curr, prev) => {
15438
+ watcher: (0, import_fs20.watchFile)(fullPath, options, (curr, prev) => {
14892
15439
  foreach(cont.rawEmitters, (rawEmitter2) => {
14893
15440
  rawEmitter2(EV.CHANGE, fullPath, { curr, prev });
14894
15441
  });
14895
15442
  const currmtime = curr.mtimeMs;
14896
15443
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
14897
- foreach(cont.listeners, (listener2) => listener2(path29, curr));
15444
+ foreach(cont.listeners, (listener2) => listener2(path31, curr));
14898
15445
  }
14899
15446
  })
14900
15447
  };
@@ -14905,7 +15452,7 @@ var setFsWatchFileListener = (path29, fullPath, options, handlers) => {
14905
15452
  delFromSet(cont, KEY_RAW, rawEmitter);
14906
15453
  if (isEmptySet(cont.listeners)) {
14907
15454
  FsWatchFileInstances.delete(fullPath);
14908
- (0, import_fs18.unwatchFile)(fullPath);
15455
+ (0, import_fs20.unwatchFile)(fullPath);
14909
15456
  cont.options = cont.watcher = void 0;
14910
15457
  Object.freeze(cont);
14911
15458
  }
@@ -14922,13 +15469,13 @@ var NodeFsHandler = class {
14922
15469
  * @param listener on fs change
14923
15470
  * @returns closer for the watcher instance
14924
15471
  */
14925
- _watchWithNodeFs(path29, listener) {
15472
+ _watchWithNodeFs(path31, listener) {
14926
15473
  const opts = this.fsw.options;
14927
- const directory = sysPath.dirname(path29);
14928
- const basename3 = sysPath.basename(path29);
15474
+ const directory = sysPath.dirname(path31);
15475
+ const basename3 = sysPath.basename(path31);
14929
15476
  const parent = this.fsw._getWatchedDir(directory);
14930
15477
  parent.add(basename3);
14931
- const absolutePath = sysPath.resolve(path29);
15478
+ const absolutePath = sysPath.resolve(path31);
14932
15479
  const options = {
14933
15480
  persistent: opts.persistent
14934
15481
  };
@@ -14938,12 +15485,12 @@ var NodeFsHandler = class {
14938
15485
  if (opts.usePolling) {
14939
15486
  const enableBin = opts.interval !== opts.binaryInterval;
14940
15487
  options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
14941
- closer = setFsWatchFileListener(path29, absolutePath, options, {
15488
+ closer = setFsWatchFileListener(path31, absolutePath, options, {
14942
15489
  listener,
14943
15490
  rawEmitter: this.fsw._emitRaw
14944
15491
  });
14945
15492
  } else {
14946
- closer = setFsWatchListener(path29, absolutePath, options, {
15493
+ closer = setFsWatchListener(path31, absolutePath, options, {
14947
15494
  listener,
14948
15495
  errHandler: this._boundHandleError,
14949
15496
  rawEmitter: this.fsw._emitRaw
@@ -14965,7 +15512,7 @@ var NodeFsHandler = class {
14965
15512
  let prevStats = stats;
14966
15513
  if (parent.has(basename3))
14967
15514
  return;
14968
- const listener = async (path29, newStats) => {
15515
+ const listener = async (path31, newStats) => {
14969
15516
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
14970
15517
  return;
14971
15518
  if (!newStats || newStats.mtimeMs === 0) {
@@ -14979,11 +15526,11 @@ var NodeFsHandler = class {
14979
15526
  this.fsw._emit(EV.CHANGE, file, newStats2);
14980
15527
  }
14981
15528
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
14982
- this.fsw._closeFile(path29);
15529
+ this.fsw._closeFile(path31);
14983
15530
  prevStats = newStats2;
14984
15531
  const closer2 = this._watchWithNodeFs(file, listener);
14985
15532
  if (closer2)
14986
- this.fsw._addPathCloser(path29, closer2);
15533
+ this.fsw._addPathCloser(path31, closer2);
14987
15534
  } else {
14988
15535
  prevStats = newStats2;
14989
15536
  }
@@ -15015,7 +15562,7 @@ var NodeFsHandler = class {
15015
15562
  * @param item basename of this item
15016
15563
  * @returns true if no more processing is needed for this entry.
15017
15564
  */
15018
- async _handleSymlink(entry, directory, path29, item) {
15565
+ async _handleSymlink(entry, directory, path31, item) {
15019
15566
  if (this.fsw.closed) {
15020
15567
  return;
15021
15568
  }
@@ -15025,7 +15572,7 @@ var NodeFsHandler = class {
15025
15572
  this.fsw._incrReadyCount();
15026
15573
  let linkPath;
15027
15574
  try {
15028
- linkPath = await (0, import_promises2.realpath)(path29);
15575
+ linkPath = await (0, import_promises2.realpath)(path31);
15029
15576
  } catch (e) {
15030
15577
  this.fsw._emitReady();
15031
15578
  return true;
@@ -15035,12 +15582,12 @@ var NodeFsHandler = class {
15035
15582
  if (dir.has(item)) {
15036
15583
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
15037
15584
  this.fsw._symlinkPaths.set(full, linkPath);
15038
- this.fsw._emit(EV.CHANGE, path29, entry.stats);
15585
+ this.fsw._emit(EV.CHANGE, path31, entry.stats);
15039
15586
  }
15040
15587
  } else {
15041
15588
  dir.add(item);
15042
15589
  this.fsw._symlinkPaths.set(full, linkPath);
15043
- this.fsw._emit(EV.ADD, path29, entry.stats);
15590
+ this.fsw._emit(EV.ADD, path31, entry.stats);
15044
15591
  }
15045
15592
  this.fsw._emitReady();
15046
15593
  return true;
@@ -15069,9 +15616,9 @@ var NodeFsHandler = class {
15069
15616
  return;
15070
15617
  }
15071
15618
  const item = entry.path;
15072
- let path29 = sysPath.join(directory, item);
15619
+ let path31 = sysPath.join(directory, item);
15073
15620
  current.add(item);
15074
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path29, item)) {
15621
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path31, item)) {
15075
15622
  return;
15076
15623
  }
15077
15624
  if (this.fsw.closed) {
@@ -15080,8 +15627,8 @@ var NodeFsHandler = class {
15080
15627
  }
15081
15628
  if (item === target || !target && !previous.has(item)) {
15082
15629
  this.fsw._incrReadyCount();
15083
- path29 = sysPath.join(dir, sysPath.relative(dir, path29));
15084
- this._addToNodeFs(path29, initialAdd, wh, depth + 1);
15630
+ path31 = sysPath.join(dir, sysPath.relative(dir, path31));
15631
+ this._addToNodeFs(path31, initialAdd, wh, depth + 1);
15085
15632
  }
15086
15633
  }).on(EV.ERROR, this._boundHandleError);
15087
15634
  return new Promise((resolve3, reject) => {
@@ -15150,13 +15697,13 @@ var NodeFsHandler = class {
15150
15697
  * @param depth Child path actually targeted for watch
15151
15698
  * @param target Child path actually targeted for watch
15152
15699
  */
15153
- async _addToNodeFs(path29, initialAdd, priorWh, depth, target) {
15700
+ async _addToNodeFs(path31, initialAdd, priorWh, depth, target) {
15154
15701
  const ready = this.fsw._emitReady;
15155
- if (this.fsw._isIgnored(path29) || this.fsw.closed) {
15702
+ if (this.fsw._isIgnored(path31) || this.fsw.closed) {
15156
15703
  ready();
15157
15704
  return false;
15158
15705
  }
15159
- const wh = this.fsw._getWatchHelpers(path29);
15706
+ const wh = this.fsw._getWatchHelpers(path31);
15160
15707
  if (priorWh) {
15161
15708
  wh.filterPath = (entry) => priorWh.filterPath(entry);
15162
15709
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -15172,8 +15719,8 @@ var NodeFsHandler = class {
15172
15719
  const follow = this.fsw.options.followSymlinks;
15173
15720
  let closer;
15174
15721
  if (stats.isDirectory()) {
15175
- const absPath = sysPath.resolve(path29);
15176
- const targetPath = follow ? await (0, import_promises2.realpath)(path29) : path29;
15722
+ const absPath = sysPath.resolve(path31);
15723
+ const targetPath = follow ? await (0, import_promises2.realpath)(path31) : path31;
15177
15724
  if (this.fsw.closed)
15178
15725
  return;
15179
15726
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -15183,29 +15730,29 @@ var NodeFsHandler = class {
15183
15730
  this.fsw._symlinkPaths.set(absPath, targetPath);
15184
15731
  }
15185
15732
  } else if (stats.isSymbolicLink()) {
15186
- const targetPath = follow ? await (0, import_promises2.realpath)(path29) : path29;
15733
+ const targetPath = follow ? await (0, import_promises2.realpath)(path31) : path31;
15187
15734
  if (this.fsw.closed)
15188
15735
  return;
15189
15736
  const parent = sysPath.dirname(wh.watchPath);
15190
15737
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
15191
15738
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
15192
- closer = await this._handleDir(parent, stats, initialAdd, depth, path29, wh, targetPath);
15739
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path31, wh, targetPath);
15193
15740
  if (this.fsw.closed)
15194
15741
  return;
15195
15742
  if (targetPath !== void 0) {
15196
- this.fsw._symlinkPaths.set(sysPath.resolve(path29), targetPath);
15743
+ this.fsw._symlinkPaths.set(sysPath.resolve(path31), targetPath);
15197
15744
  }
15198
15745
  } else {
15199
15746
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
15200
15747
  }
15201
15748
  ready();
15202
15749
  if (closer)
15203
- this.fsw._addPathCloser(path29, closer);
15750
+ this.fsw._addPathCloser(path31, closer);
15204
15751
  return false;
15205
15752
  } catch (error) {
15206
15753
  if (this.fsw._handleError(error)) {
15207
15754
  ready();
15208
- return path29;
15755
+ return path31;
15209
15756
  }
15210
15757
  }
15211
15758
  }
@@ -15248,26 +15795,26 @@ function createPattern(matcher) {
15248
15795
  }
15249
15796
  return () => false;
15250
15797
  }
15251
- function normalizePath(path29) {
15252
- if (typeof path29 !== "string")
15798
+ function normalizePath(path31) {
15799
+ if (typeof path31 !== "string")
15253
15800
  throw new Error("string expected");
15254
- path29 = sysPath2.normalize(path29);
15255
- path29 = path29.replace(/\\/g, "/");
15801
+ path31 = sysPath2.normalize(path31);
15802
+ path31 = path31.replace(/\\/g, "/");
15256
15803
  let prepend = false;
15257
- if (path29.startsWith("//"))
15804
+ if (path31.startsWith("//"))
15258
15805
  prepend = true;
15259
15806
  const DOUBLE_SLASH_RE2 = /\/\//;
15260
- while (path29.match(DOUBLE_SLASH_RE2))
15261
- path29 = path29.replace(DOUBLE_SLASH_RE2, "/");
15807
+ while (path31.match(DOUBLE_SLASH_RE2))
15808
+ path31 = path31.replace(DOUBLE_SLASH_RE2, "/");
15262
15809
  if (prepend)
15263
- path29 = "/" + path29;
15264
- return path29;
15810
+ path31 = "/" + path31;
15811
+ return path31;
15265
15812
  }
15266
15813
  function matchPatterns(patterns, testString, stats) {
15267
- const path29 = normalizePath(testString);
15814
+ const path31 = normalizePath(testString);
15268
15815
  for (let index = 0; index < patterns.length; index++) {
15269
15816
  const pattern = patterns[index];
15270
- if (pattern(path29, stats)) {
15817
+ if (pattern(path31, stats)) {
15271
15818
  return true;
15272
15819
  }
15273
15820
  }
@@ -15307,19 +15854,19 @@ var toUnix = (string) => {
15307
15854
  }
15308
15855
  return str;
15309
15856
  };
15310
- var normalizePathToUnix = (path29) => toUnix(sysPath2.normalize(toUnix(path29)));
15311
- var normalizeIgnored = (cwd = "") => (path29) => {
15312
- if (typeof path29 === "string") {
15313
- return normalizePathToUnix(sysPath2.isAbsolute(path29) ? path29 : sysPath2.join(cwd, path29));
15857
+ var normalizePathToUnix = (path31) => toUnix(sysPath2.normalize(toUnix(path31)));
15858
+ var normalizeIgnored = (cwd = "") => (path31) => {
15859
+ if (typeof path31 === "string") {
15860
+ return normalizePathToUnix(sysPath2.isAbsolute(path31) ? path31 : sysPath2.join(cwd, path31));
15314
15861
  } else {
15315
- return path29;
15862
+ return path31;
15316
15863
  }
15317
15864
  };
15318
- var getAbsolutePath = (path29, cwd) => {
15319
- if (sysPath2.isAbsolute(path29)) {
15320
- return path29;
15865
+ var getAbsolutePath = (path31, cwd) => {
15866
+ if (sysPath2.isAbsolute(path31)) {
15867
+ return path31;
15321
15868
  }
15322
- return sysPath2.join(cwd, path29);
15869
+ return sysPath2.join(cwd, path31);
15323
15870
  };
15324
15871
  var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
15325
15872
  var DirEntry = class {
@@ -15374,10 +15921,10 @@ var DirEntry = class {
15374
15921
  var STAT_METHOD_F = "stat";
15375
15922
  var STAT_METHOD_L = "lstat";
15376
15923
  var WatchHelper = class {
15377
- constructor(path29, follow, fsw) {
15924
+ constructor(path31, follow, fsw) {
15378
15925
  this.fsw = fsw;
15379
- const watchPath = path29;
15380
- this.path = path29 = path29.replace(REPLACER_RE, "");
15926
+ const watchPath = path31;
15927
+ this.path = path31 = path31.replace(REPLACER_RE, "");
15381
15928
  this.watchPath = watchPath;
15382
15929
  this.fullWatchPath = sysPath2.resolve(watchPath);
15383
15930
  this.dirParts = [];
@@ -15499,20 +16046,20 @@ var FSWatcher = class extends import_events.EventEmitter {
15499
16046
  this._closePromise = void 0;
15500
16047
  let paths = unifyPaths(paths_);
15501
16048
  if (cwd) {
15502
- paths = paths.map((path29) => {
15503
- const absPath = getAbsolutePath(path29, cwd);
16049
+ paths = paths.map((path31) => {
16050
+ const absPath = getAbsolutePath(path31, cwd);
15504
16051
  return absPath;
15505
16052
  });
15506
16053
  }
15507
- paths.forEach((path29) => {
15508
- this._removeIgnoredPath(path29);
16054
+ paths.forEach((path31) => {
16055
+ this._removeIgnoredPath(path31);
15509
16056
  });
15510
16057
  this._userIgnored = void 0;
15511
16058
  if (!this._readyCount)
15512
16059
  this._readyCount = 0;
15513
16060
  this._readyCount += paths.length;
15514
- Promise.all(paths.map(async (path29) => {
15515
- const res = await this._nodeFsHandler._addToNodeFs(path29, !_internal, void 0, 0, _origAdd);
16061
+ Promise.all(paths.map(async (path31) => {
16062
+ const res = await this._nodeFsHandler._addToNodeFs(path31, !_internal, void 0, 0, _origAdd);
15516
16063
  if (res)
15517
16064
  this._emitReady();
15518
16065
  return res;
@@ -15534,17 +16081,17 @@ var FSWatcher = class extends import_events.EventEmitter {
15534
16081
  return this;
15535
16082
  const paths = unifyPaths(paths_);
15536
16083
  const { cwd } = this.options;
15537
- paths.forEach((path29) => {
15538
- if (!sysPath2.isAbsolute(path29) && !this._closers.has(path29)) {
16084
+ paths.forEach((path31) => {
16085
+ if (!sysPath2.isAbsolute(path31) && !this._closers.has(path31)) {
15539
16086
  if (cwd)
15540
- path29 = sysPath2.join(cwd, path29);
15541
- path29 = sysPath2.resolve(path29);
16087
+ path31 = sysPath2.join(cwd, path31);
16088
+ path31 = sysPath2.resolve(path31);
15542
16089
  }
15543
- this._closePath(path29);
15544
- this._addIgnoredPath(path29);
15545
- if (this._watched.has(path29)) {
16090
+ this._closePath(path31);
16091
+ this._addIgnoredPath(path31);
16092
+ if (this._watched.has(path31)) {
15546
16093
  this._addIgnoredPath({
15547
- path: path29,
16094
+ path: path31,
15548
16095
  recursive: true
15549
16096
  });
15550
16097
  }
@@ -15608,38 +16155,38 @@ var FSWatcher = class extends import_events.EventEmitter {
15608
16155
  * @param stats arguments to be passed with event
15609
16156
  * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
15610
16157
  */
15611
- async _emit(event, path29, stats) {
16158
+ async _emit(event, path31, stats) {
15612
16159
  if (this.closed)
15613
16160
  return;
15614
16161
  const opts = this.options;
15615
16162
  if (isWindows)
15616
- path29 = sysPath2.normalize(path29);
16163
+ path31 = sysPath2.normalize(path31);
15617
16164
  if (opts.cwd)
15618
- path29 = sysPath2.relative(opts.cwd, path29);
15619
- const args = [path29];
16165
+ path31 = sysPath2.relative(opts.cwd, path31);
16166
+ const args = [path31];
15620
16167
  if (stats != null)
15621
16168
  args.push(stats);
15622
16169
  const awf = opts.awaitWriteFinish;
15623
16170
  let pw;
15624
- if (awf && (pw = this._pendingWrites.get(path29))) {
16171
+ if (awf && (pw = this._pendingWrites.get(path31))) {
15625
16172
  pw.lastChange = /* @__PURE__ */ new Date();
15626
16173
  return this;
15627
16174
  }
15628
16175
  if (opts.atomic) {
15629
16176
  if (event === EVENTS.UNLINK) {
15630
- this._pendingUnlinks.set(path29, [event, ...args]);
16177
+ this._pendingUnlinks.set(path31, [event, ...args]);
15631
16178
  setTimeout(() => {
15632
- this._pendingUnlinks.forEach((entry, path30) => {
16179
+ this._pendingUnlinks.forEach((entry, path32) => {
15633
16180
  this.emit(...entry);
15634
16181
  this.emit(EVENTS.ALL, ...entry);
15635
- this._pendingUnlinks.delete(path30);
16182
+ this._pendingUnlinks.delete(path32);
15636
16183
  });
15637
16184
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
15638
16185
  return this;
15639
16186
  }
15640
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path29)) {
16187
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path31)) {
15641
16188
  event = EVENTS.CHANGE;
15642
- this._pendingUnlinks.delete(path29);
16189
+ this._pendingUnlinks.delete(path31);
15643
16190
  }
15644
16191
  }
15645
16192
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -15657,16 +16204,16 @@ var FSWatcher = class extends import_events.EventEmitter {
15657
16204
  this.emitWithAll(event, args);
15658
16205
  }
15659
16206
  };
15660
- this._awaitWriteFinish(path29, awf.stabilityThreshold, event, awfEmit);
16207
+ this._awaitWriteFinish(path31, awf.stabilityThreshold, event, awfEmit);
15661
16208
  return this;
15662
16209
  }
15663
16210
  if (event === EVENTS.CHANGE) {
15664
- const isThrottled = !this._throttle(EVENTS.CHANGE, path29, 50);
16211
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path31, 50);
15665
16212
  if (isThrottled)
15666
16213
  return this;
15667
16214
  }
15668
16215
  if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
15669
- const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path29) : path29;
16216
+ const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path31) : path31;
15670
16217
  let stats2;
15671
16218
  try {
15672
16219
  stats2 = await (0, import_promises3.stat)(fullPath);
@@ -15697,23 +16244,23 @@ var FSWatcher = class extends import_events.EventEmitter {
15697
16244
  * @param timeout duration of time to suppress duplicate actions
15698
16245
  * @returns tracking object or false if action should be suppressed
15699
16246
  */
15700
- _throttle(actionType, path29, timeout) {
16247
+ _throttle(actionType, path31, timeout) {
15701
16248
  if (!this._throttled.has(actionType)) {
15702
16249
  this._throttled.set(actionType, /* @__PURE__ */ new Map());
15703
16250
  }
15704
16251
  const action = this._throttled.get(actionType);
15705
16252
  if (!action)
15706
16253
  throw new Error("invalid throttle");
15707
- const actionPath = action.get(path29);
16254
+ const actionPath = action.get(path31);
15708
16255
  if (actionPath) {
15709
16256
  actionPath.count++;
15710
16257
  return false;
15711
16258
  }
15712
16259
  let timeoutObject;
15713
16260
  const clear = () => {
15714
- const item = action.get(path29);
16261
+ const item = action.get(path31);
15715
16262
  const count = item ? item.count : 0;
15716
- action.delete(path29);
16263
+ action.delete(path31);
15717
16264
  clearTimeout(timeoutObject);
15718
16265
  if (item)
15719
16266
  clearTimeout(item.timeoutObject);
@@ -15721,7 +16268,7 @@ var FSWatcher = class extends import_events.EventEmitter {
15721
16268
  };
15722
16269
  timeoutObject = setTimeout(clear, timeout);
15723
16270
  const thr = { timeoutObject, clear, count: 0 };
15724
- action.set(path29, thr);
16271
+ action.set(path31, thr);
15725
16272
  return thr;
15726
16273
  }
15727
16274
  _incrReadyCount() {
@@ -15735,44 +16282,44 @@ var FSWatcher = class extends import_events.EventEmitter {
15735
16282
  * @param event
15736
16283
  * @param awfEmit Callback to be called when ready for event to be emitted.
15737
16284
  */
15738
- _awaitWriteFinish(path29, threshold, event, awfEmit) {
16285
+ _awaitWriteFinish(path31, threshold, event, awfEmit) {
15739
16286
  const awf = this.options.awaitWriteFinish;
15740
16287
  if (typeof awf !== "object")
15741
16288
  return;
15742
16289
  const pollInterval = awf.pollInterval;
15743
16290
  let timeoutHandler;
15744
- let fullPath = path29;
15745
- if (this.options.cwd && !sysPath2.isAbsolute(path29)) {
15746
- fullPath = sysPath2.join(this.options.cwd, path29);
16291
+ let fullPath = path31;
16292
+ if (this.options.cwd && !sysPath2.isAbsolute(path31)) {
16293
+ fullPath = sysPath2.join(this.options.cwd, path31);
15747
16294
  }
15748
16295
  const now = /* @__PURE__ */ new Date();
15749
16296
  const writes = this._pendingWrites;
15750
16297
  function awaitWriteFinishFn(prevStat) {
15751
- (0, import_fs19.stat)(fullPath, (err, curStat) => {
15752
- if (err || !writes.has(path29)) {
16298
+ (0, import_fs21.stat)(fullPath, (err, curStat) => {
16299
+ if (err || !writes.has(path31)) {
15753
16300
  if (err && err.code !== "ENOENT")
15754
16301
  awfEmit(err);
15755
16302
  return;
15756
16303
  }
15757
16304
  const now2 = Number(/* @__PURE__ */ new Date());
15758
16305
  if (prevStat && curStat.size !== prevStat.size) {
15759
- writes.get(path29).lastChange = now2;
16306
+ writes.get(path31).lastChange = now2;
15760
16307
  }
15761
- const pw = writes.get(path29);
16308
+ const pw = writes.get(path31);
15762
16309
  const df = now2 - pw.lastChange;
15763
16310
  if (df >= threshold) {
15764
- writes.delete(path29);
16311
+ writes.delete(path31);
15765
16312
  awfEmit(void 0, curStat);
15766
16313
  } else {
15767
16314
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
15768
16315
  }
15769
16316
  });
15770
16317
  }
15771
- if (!writes.has(path29)) {
15772
- writes.set(path29, {
16318
+ if (!writes.has(path31)) {
16319
+ writes.set(path31, {
15773
16320
  lastChange: now,
15774
16321
  cancelWait: () => {
15775
- writes.delete(path29);
16322
+ writes.delete(path31);
15776
16323
  clearTimeout(timeoutHandler);
15777
16324
  return event;
15778
16325
  }
@@ -15783,8 +16330,8 @@ var FSWatcher = class extends import_events.EventEmitter {
15783
16330
  /**
15784
16331
  * Determines whether user has asked to ignore this path.
15785
16332
  */
15786
- _isIgnored(path29, stats) {
15787
- if (this.options.atomic && DOT_RE.test(path29))
16333
+ _isIgnored(path31, stats) {
16334
+ if (this.options.atomic && DOT_RE.test(path31))
15788
16335
  return true;
15789
16336
  if (!this._userIgnored) {
15790
16337
  const { cwd } = this.options;
@@ -15794,17 +16341,17 @@ var FSWatcher = class extends import_events.EventEmitter {
15794
16341
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
15795
16342
  this._userIgnored = anymatch(list, void 0);
15796
16343
  }
15797
- return this._userIgnored(path29, stats);
16344
+ return this._userIgnored(path31, stats);
15798
16345
  }
15799
- _isntIgnored(path29, stat4) {
15800
- return !this._isIgnored(path29, stat4);
16346
+ _isntIgnored(path31, stat4) {
16347
+ return !this._isIgnored(path31, stat4);
15801
16348
  }
15802
16349
  /**
15803
16350
  * Provides a set of common helpers and properties relating to symlink handling.
15804
16351
  * @param path file or directory pattern being watched
15805
16352
  */
15806
- _getWatchHelpers(path29) {
15807
- return new WatchHelper(path29, this.options.followSymlinks, this);
16353
+ _getWatchHelpers(path31) {
16354
+ return new WatchHelper(path31, this.options.followSymlinks, this);
15808
16355
  }
15809
16356
  // Directory helpers
15810
16357
  // -----------------
@@ -15836,63 +16383,63 @@ var FSWatcher = class extends import_events.EventEmitter {
15836
16383
  * @param item base path of item/directory
15837
16384
  */
15838
16385
  _remove(directory, item, isDirectory) {
15839
- const path29 = sysPath2.join(directory, item);
15840
- const fullPath = sysPath2.resolve(path29);
15841
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path29) || this._watched.has(fullPath);
15842
- if (!this._throttle("remove", path29, 100))
16386
+ const path31 = sysPath2.join(directory, item);
16387
+ const fullPath = sysPath2.resolve(path31);
16388
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path31) || this._watched.has(fullPath);
16389
+ if (!this._throttle("remove", path31, 100))
15843
16390
  return;
15844
16391
  if (!isDirectory && this._watched.size === 1) {
15845
16392
  this.add(directory, item, true);
15846
16393
  }
15847
- const wp = this._getWatchedDir(path29);
16394
+ const wp = this._getWatchedDir(path31);
15848
16395
  const nestedDirectoryChildren = wp.getChildren();
15849
- nestedDirectoryChildren.forEach((nested) => this._remove(path29, nested));
16396
+ nestedDirectoryChildren.forEach((nested) => this._remove(path31, nested));
15850
16397
  const parent = this._getWatchedDir(directory);
15851
16398
  const wasTracked = parent.has(item);
15852
16399
  parent.remove(item);
15853
16400
  if (this._symlinkPaths.has(fullPath)) {
15854
16401
  this._symlinkPaths.delete(fullPath);
15855
16402
  }
15856
- let relPath = path29;
16403
+ let relPath = path31;
15857
16404
  if (this.options.cwd)
15858
- relPath = sysPath2.relative(this.options.cwd, path29);
16405
+ relPath = sysPath2.relative(this.options.cwd, path31);
15859
16406
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
15860
16407
  const event = this._pendingWrites.get(relPath).cancelWait();
15861
16408
  if (event === EVENTS.ADD)
15862
16409
  return;
15863
16410
  }
15864
- this._watched.delete(path29);
16411
+ this._watched.delete(path31);
15865
16412
  this._watched.delete(fullPath);
15866
16413
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
15867
- if (wasTracked && !this._isIgnored(path29))
15868
- this._emit(eventName, path29);
15869
- this._closePath(path29);
16414
+ if (wasTracked && !this._isIgnored(path31))
16415
+ this._emit(eventName, path31);
16416
+ this._closePath(path31);
15870
16417
  }
15871
16418
  /**
15872
16419
  * Closes all watchers for a path
15873
16420
  */
15874
- _closePath(path29) {
15875
- this._closeFile(path29);
15876
- const dir = sysPath2.dirname(path29);
15877
- this._getWatchedDir(dir).remove(sysPath2.basename(path29));
16421
+ _closePath(path31) {
16422
+ this._closeFile(path31);
16423
+ const dir = sysPath2.dirname(path31);
16424
+ this._getWatchedDir(dir).remove(sysPath2.basename(path31));
15878
16425
  }
15879
16426
  /**
15880
16427
  * Closes only file-specific watchers
15881
16428
  */
15882
- _closeFile(path29) {
15883
- const closers = this._closers.get(path29);
16429
+ _closeFile(path31) {
16430
+ const closers = this._closers.get(path31);
15884
16431
  if (!closers)
15885
16432
  return;
15886
16433
  closers.forEach((closer) => closer());
15887
- this._closers.delete(path29);
16434
+ this._closers.delete(path31);
15888
16435
  }
15889
- _addPathCloser(path29, closer) {
16436
+ _addPathCloser(path31, closer) {
15890
16437
  if (!closer)
15891
16438
  return;
15892
- let list = this._closers.get(path29);
16439
+ let list = this._closers.get(path31);
15893
16440
  if (!list) {
15894
16441
  list = [];
15895
- this._closers.set(path29, list);
16442
+ this._closers.set(path31, list);
15896
16443
  }
15897
16444
  list.push(closer);
15898
16445
  }
@@ -15922,7 +16469,7 @@ function watch(paths, options = {}) {
15922
16469
  var esm_default = { watch, FSWatcher };
15923
16470
 
15924
16471
  // modules/dev/hot-reload-client/index.ts
15925
- var import_path27 = __toESM(require("path"));
16472
+ var import_path29 = __toESM(require("path"));
15926
16473
  init_globals();
15927
16474
  function setupHotReload({
15928
16475
  app,
@@ -15964,7 +16511,7 @@ function setupHotReload({
15964
16511
  });
15965
16512
  });
15966
16513
  console.log(`[hot-reload-server] \u2705 SSE endpoint registered at ${route}`);
15967
- const resolvedProjectRoot = projectRoot ? import_path27.default.resolve(projectRoot) : import_path27.default.dirname(import_path27.default.resolve(appDir));
16514
+ const resolvedProjectRoot = projectRoot ? import_path29.default.resolve(projectRoot) : import_path29.default.dirname(import_path29.default.resolve(appDir));
15968
16515
  const watcher = esm_default.watch(resolvedProjectRoot, {
15969
16516
  ignoreInitial: true,
15970
16517
  ignored: [
@@ -16004,11 +16551,11 @@ function setupHotReload({
16004
16551
  let broadcastTimeout = null;
16005
16552
  const BROADCAST_DEBOUNCE_MS = 300;
16006
16553
  async function broadcastReload(reason, filePath) {
16007
- const normalizedPath = import_path27.default.normalize(filePath);
16554
+ const normalizedPath = import_path29.default.normalize(filePath);
16008
16555
  if (normalizedPath.includes(BUILD_FOLDER_NAME) || normalizedPath.includes(".loly") || normalizedPath.endsWith(".map") || normalizedPath.endsWith(".log") || normalizedPath.includes("route-chunks.json") || normalizedPath.includes("routes-client.ts") || normalizedPath.includes("/client/route-")) {
16009
16556
  return;
16010
16557
  }
16011
- const rel = import_path27.default.relative(appDir, filePath);
16558
+ const rel = import_path29.default.relative(appDir, filePath);
16012
16559
  console.log(`[hot-reload] ${reason}: ${rel}`);
16013
16560
  if (broadcastTimeout) {
16014
16561
  clearTimeout(broadcastTimeout);
@@ -16058,9 +16605,9 @@ data: reload:${rel}
16058
16605
  }
16059
16606
 
16060
16607
  // modules/dev/hot-reload-server/index.ts
16061
- var import_path28 = __toESM(require("path"));
16608
+ var import_path30 = __toESM(require("path"));
16062
16609
  function clearAppRequireCache(appDir) {
16063
- const appDirNormalized = import_path28.default.resolve(appDir);
16610
+ const appDirNormalized = import_path30.default.resolve(appDir);
16064
16611
  for (const id of Object.keys(require.cache)) {
16065
16612
  if (id.startsWith(appDirNormalized)) {
16066
16613
  delete require.cache[id];
@@ -16073,7 +16620,7 @@ init_globals();
16073
16620
  function setupStaticFiles(app, projectRoot, config) {
16074
16621
  if (!config) return;
16075
16622
  const staticDir = getStaticDir(projectRoot, config);
16076
- if (import_fs20.default.existsSync(staticDir)) {
16623
+ if (import_fs22.default.existsSync(staticDir)) {
16077
16624
  app.use(
16078
16625
  import_express.default.static(staticDir, {
16079
16626
  // In production, add caching headers for better performance
@@ -16099,7 +16646,7 @@ function setupServer(app, options) {
16099
16646
  var getRoutes = getRoutes2;
16100
16647
  const { outDir, waitForBuild } = startClientBundler(projectRoot, "development");
16101
16648
  const onFileChange = async (filePath) => {
16102
- const rel = import_path29.default.relative(appDir, filePath);
16649
+ const rel = import_path31.default.relative(appDir, filePath);
16103
16650
  const isPageFile = filePath.includes("page.tsx") || filePath.includes("page.ts") || filePath.includes("layout.tsx") || filePath.includes("layout.ts") || filePath.includes("_not-found") || filePath.includes("_error");
16104
16651
  const isTsFile = filePath.endsWith(".ts") || filePath.endsWith(".tsx");
16105
16652
  if (isTsFile) {
@@ -16135,8 +16682,8 @@ function setupServer(app, options) {
16135
16682
  const wssRoutes = routeLoader.loadWssRoutes();
16136
16683
  const notFoundPage = routeLoader.loadNotFoundRoute();
16137
16684
  const errorPage = routeLoader.loadErrorRoute();
16138
- const buildDir = config ? getBuildDir(projectRoot, config) : import_path29.default.join(projectRoot, BUILD_FOLDER_NAME);
16139
- const clientOutDir = import_path29.default.join(buildDir, "client");
16685
+ const buildDir = config ? getBuildDir(projectRoot, config) : import_path31.default.join(projectRoot, BUILD_FOLDER_NAME);
16686
+ const clientOutDir = import_path31.default.join(buildDir, "client");
16140
16687
  app.use(
16141
16688
  "/static",
16142
16689
  import_express.default.static(clientOutDir, {
@@ -16263,11 +16810,11 @@ function createStrictRateLimiterFromConfig(config) {
16263
16810
  }
16264
16811
 
16265
16812
  // modules/server/middleware/auto-rate-limit.ts
16266
- function matchesStrictPattern(path29, patterns) {
16813
+ function matchesStrictPattern(path31, patterns) {
16267
16814
  for (const pattern of patterns) {
16268
16815
  const regexPattern = pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/\//g, "\\/");
16269
16816
  const regex = new RegExp(`^${regexPattern}$`);
16270
- if (regex.test(path29)) {
16817
+ if (regex.test(path31)) {
16271
16818
  return true;
16272
16819
  }
16273
16820
  }
@@ -16302,8 +16849,31 @@ function getAutoRateLimiter(route, strictPatterns = [], rateLimitConfig) {
16302
16849
 
16303
16850
  // modules/server/handlers/api.ts
16304
16851
  async function handleApiRequest(options) {
16305
- const { apiRoutes, urlPath, req, res, env = "dev" } = options;
16306
- const matched = matchApiRoute(apiRoutes, urlPath);
16852
+ const { apiRoutes, urlPath, req, res, env = "dev", rewriteLoader } = options;
16853
+ let finalUrlPath = urlPath;
16854
+ let extractedParams = {};
16855
+ if (rewriteLoader) {
16856
+ try {
16857
+ const compiledRewrites = await rewriteLoader.loadRewrites();
16858
+ const rewriteResult = await processRewrites(urlPath, compiledRewrites, req);
16859
+ if (rewriteResult) {
16860
+ finalUrlPath = rewriteResult.rewrittenPath;
16861
+ extractedParams = rewriteResult.extractedParams;
16862
+ Object.assign(req.query, extractedParams);
16863
+ if (!req.locals) {
16864
+ req.locals = {};
16865
+ }
16866
+ Object.assign(req.locals, extractedParams);
16867
+ }
16868
+ } catch (error) {
16869
+ const reqLogger = getRequestLogger(req);
16870
+ reqLogger.error("Error processing rewrites", error, {
16871
+ urlPath
16872
+ });
16873
+ }
16874
+ }
16875
+ finalUrlPath = finalUrlPath.replace(/\/$/, "") || "/";
16876
+ const matched = matchApiRoute(apiRoutes, finalUrlPath);
16307
16877
  if (!matched) {
16308
16878
  res.status(404).json({ error: "Not Found" });
16309
16879
  return;
@@ -16324,9 +16894,13 @@ async function handleApiRequest(options) {
16324
16894
  Response: (body = {}, status = 200) => res.status(status).json(body),
16325
16895
  NotFound: (body = {}) => res.status(404).json(body),
16326
16896
  params: sanitizedParams,
16327
- pathname: urlPath,
16897
+ pathname: finalUrlPath,
16898
+ // Use rewritten path
16328
16899
  locals: {}
16329
16900
  };
16901
+ if (extractedParams && Object.keys(extractedParams).length > 0) {
16902
+ Object.assign(ctx.locals, extractedParams);
16903
+ }
16330
16904
  req.query = sanitizedQuery;
16331
16905
  try {
16332
16906
  const autoRateLimiter = getAutoRateLimiter(
@@ -16405,7 +16979,19 @@ async function handleApiRequest(options) {
16405
16979
 
16406
16980
  // modules/server/routes.ts
16407
16981
  init_globals();
16408
- var import_path30 = __toESM(require("path"));
16982
+ var import_path32 = __toESM(require("path"));
16983
+ var cachedRewriteLoader = null;
16984
+ var cachedProjectRoot = null;
16985
+ var cachedIsDev = null;
16986
+ function getRewriteLoader(projectRoot, isDev) {
16987
+ if (cachedRewriteLoader && cachedProjectRoot === projectRoot && cachedIsDev === isDev) {
16988
+ return cachedRewriteLoader;
16989
+ }
16990
+ cachedRewriteLoader = createRewriteLoader(projectRoot, isDev);
16991
+ cachedProjectRoot = projectRoot;
16992
+ cachedIsDev = isDev;
16993
+ return cachedRewriteLoader;
16994
+ }
16409
16995
  function setupRoutes(options) {
16410
16996
  const {
16411
16997
  app,
@@ -16420,8 +17006,9 @@ function setupRoutes(options) {
16420
17006
  config
16421
17007
  } = options;
16422
17008
  const routeChunks = routeLoader.loadRouteChunks();
16423
- const ssgOutDir = import_path30.default.join(
16424
- config ? getBuildDir(projectRoot, config) : import_path30.default.join(projectRoot, BUILD_FOLDER_NAME),
17009
+ const rewriteLoader = getRewriteLoader(projectRoot, isDev);
17010
+ const ssgOutDir = import_path32.default.join(
17011
+ config ? getBuildDir(projectRoot, config) : import_path32.default.join(projectRoot, BUILD_FOLDER_NAME),
16425
17012
  "ssg"
16426
17013
  );
16427
17014
  app.all("/api/*", async (req, res) => {
@@ -16436,7 +17023,8 @@ function setupRoutes(options) {
16436
17023
  res,
16437
17024
  env: isDev ? "dev" : "prod",
16438
17025
  strictRateLimitPatterns: strictPatterns,
16439
- rateLimitConfig
17026
+ rateLimitConfig,
17027
+ rewriteLoader
16440
17028
  });
16441
17029
  });
16442
17030
  app.get("*", async (req, res) => {
@@ -16459,7 +17047,8 @@ function setupRoutes(options) {
16459
17047
  ssgOutDir,
16460
17048
  theme: req.cookies?.theme || "light",
16461
17049
  projectRoot,
16462
- config
17050
+ config,
17051
+ rewriteLoader
16463
17052
  });
16464
17053
  });
16465
17054
  }
@@ -17648,8 +18237,8 @@ var setupApplication = async ({
17648
18237
 
17649
18238
  // src/server.ts
17650
18239
  var import_dotenv2 = __toESM(require("dotenv"));
17651
- var envPath = import_path31.default.join(process.cwd(), ".env");
17652
- if (import_fs21.default.existsSync(envPath)) {
18240
+ var envPath = import_path33.default.join(process.cwd(), ".env");
18241
+ if (import_fs23.default.existsSync(envPath)) {
17653
18242
  import_dotenv2.default.config({ path: envPath });
17654
18243
  } else {
17655
18244
  import_dotenv2.default.config();
@@ -17670,8 +18259,8 @@ async function startServer(options = {}) {
17670
18259
  }
17671
18260
  const port = options.port ?? (process.env.PORT ? parseInt(process.env.PORT, 10) : void 0) ?? config.server.port;
17672
18261
  const host = process.env.HOST ?? (!isDev ? "0.0.0.0" : void 0) ?? config.server.host;
17673
- const appDir = options.appDir ?? (isDev ? getAppDir(projectRoot, config) : import_path31.default.join(getBuildDir(projectRoot, config), "server"));
17674
- if (!isDev && !import_fs21.default.existsSync(appDir)) {
18262
+ const appDir = options.appDir ?? (isDev ? getAppDir(projectRoot, config) : import_path33.default.join(getBuildDir(projectRoot, config), "server"));
18263
+ if (!isDev && !import_fs23.default.existsSync(appDir)) {
17675
18264
  logger4.error("Compiled directory not found", void 0, {
17676
18265
  buildDir: config.directories.build,
17677
18266
  appDir,
@@ -17867,7 +18456,7 @@ async function run() {
17867
18456
  }
17868
18457
  const args = parseArgs(argv.slice(1));
17869
18458
  const projectRoot = import_process.default.cwd();
17870
- const appDir = import_path32.default.resolve(projectRoot, args.appDir || "app");
18459
+ const appDir = import_path34.default.resolve(projectRoot, args.appDir || "app");
17871
18460
  const port = typeof args.port === "string" && args.port.trim().length > 0 ? Number(args.port) : 3e3;
17872
18461
  switch (command) {
17873
18462
  case "dev": {