@lolyjs/core 0.2.0-alpha.27 → 0.2.0-alpha.29
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/README.md +321 -0
- package/dist/cli.cjs +904 -315
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +898 -309
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +916 -316
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +38 -3
- package/dist/index.d.ts +38 -3
- package/dist/index.js +910 -310
- package/dist/index.js.map +1 -1
- package/dist/{index.types-DMOO-uvF.d.mts → index.types-B9j4OQft.d.mts} +1 -0
- package/dist/{index.types-DMOO-uvF.d.ts → index.types-B9j4OQft.d.ts} +1 -0
- package/dist/react/cache.cjs.map +1 -1
- package/dist/react/cache.d.mts +3 -1
- package/dist/react/cache.d.ts +3 -1
- package/dist/react/cache.js.map +1 -1
- package/dist/react/components.cjs +1 -4
- package/dist/react/components.cjs.map +1 -1
- package/dist/react/components.js +1 -4
- package/dist/react/components.js.map +1 -1
- package/dist/runtime.cjs +16 -5
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +16 -5
- package/dist/runtime.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -9871,7 +9871,7 @@ var require_built3 = __commonJS({
|
|
|
9871
9871
|
});
|
|
9872
9872
|
|
|
9873
9873
|
// modules/cli/index.ts
|
|
9874
|
-
import
|
|
9874
|
+
import path30 from "path";
|
|
9875
9875
|
import process2 from "process";
|
|
9876
9876
|
|
|
9877
9877
|
// modules/router/loader-pages.ts
|
|
@@ -9883,10 +9883,17 @@ var PAGE_FILE_REGEX = /^page\.(tsx|ts|jsx|js)$/;
|
|
|
9883
9883
|
var LAYOUT_FILE_BASENAME = "layout";
|
|
9884
9884
|
|
|
9885
9885
|
// modules/router/path.ts
|
|
9886
|
+
function isRouteGroup(dirName) {
|
|
9887
|
+
return dirName.startsWith("(") && dirName.endsWith(")");
|
|
9888
|
+
}
|
|
9886
9889
|
function buildRoutePathFromDir(relDir) {
|
|
9887
9890
|
if (!relDir || relDir === ".") return "/";
|
|
9888
9891
|
const clean = relDir.replace(/\\/g, "/");
|
|
9889
|
-
|
|
9892
|
+
const segments = clean.split("/").filter((seg) => {
|
|
9893
|
+
return !isRouteGroup(seg);
|
|
9894
|
+
});
|
|
9895
|
+
if (segments.length === 0) return "/";
|
|
9896
|
+
return "/" + segments.join("/");
|
|
9890
9897
|
}
|
|
9891
9898
|
function buildRegexFromRoutePath(routePath) {
|
|
9892
9899
|
const segments = routePath.split("/").filter(Boolean);
|
|
@@ -10102,13 +10109,17 @@ function validateRoutes(routes, appDir) {
|
|
|
10102
10109
|
}
|
|
10103
10110
|
for (const [pattern, duplicateRoutes] of routePatterns.entries()) {
|
|
10104
10111
|
if (duplicateRoutes.length > 1) {
|
|
10105
|
-
const files = duplicateRoutes.map(
|
|
10106
|
-
|
|
10107
|
-
|
|
10112
|
+
const files = duplicateRoutes.map((r) => {
|
|
10113
|
+
const relPath = r.pageFile ? path3.relative(appDir, r.pageFile) : "unknown";
|
|
10114
|
+
const segments = relPath.split(path3.sep);
|
|
10115
|
+
const hasRouteGroup = segments.some((seg) => isRouteGroup(seg));
|
|
10116
|
+
return hasRouteGroup ? `${relPath} (inside route group)` : relPath;
|
|
10117
|
+
}).join(", ");
|
|
10108
10118
|
errors.push(
|
|
10109
10119
|
`Duplicate route pattern "${pattern}" found in multiple files:
|
|
10110
10120
|
${files}
|
|
10111
|
-
\u{1F4A1} Suggestion:
|
|
10121
|
+
\u{1F4A1} Suggestion: Route groups (directories in parentheses) don't appear in URLs.
|
|
10122
|
+
Ensure each route has a unique path pattern after route groups are ignored.`
|
|
10112
10123
|
);
|
|
10113
10124
|
}
|
|
10114
10125
|
}
|
|
@@ -10385,12 +10396,13 @@ function loadApiRoutes(appDir) {
|
|
|
10385
10396
|
|
|
10386
10397
|
// modules/router/matcher.ts
|
|
10387
10398
|
function matchRoute(routes, urlPath) {
|
|
10399
|
+
const normalizedPath = urlPath.replace(/\/$/, "") || "/";
|
|
10388
10400
|
for (const route of routes) {
|
|
10389
|
-
const match = route.regex.exec(
|
|
10401
|
+
const match = route.regex.exec(normalizedPath);
|
|
10390
10402
|
if (!match) continue;
|
|
10391
10403
|
const params = {};
|
|
10392
10404
|
route.paramNames.forEach((name, idx) => {
|
|
10393
|
-
params[name] = match[idx + 1];
|
|
10405
|
+
params[name] = decodeURIComponent(match[idx + 1] || "");
|
|
10394
10406
|
});
|
|
10395
10407
|
return { route, params };
|
|
10396
10408
|
}
|
|
@@ -11400,34 +11412,504 @@ function loadErrorRouteFromFilesystem(appDir) {
|
|
|
11400
11412
|
};
|
|
11401
11413
|
}
|
|
11402
11414
|
|
|
11415
|
+
// modules/router/rewrites.ts
|
|
11416
|
+
function parseRewritePattern(pattern) {
|
|
11417
|
+
const cleanPattern = pattern.replace(/^\/+|\/+$/g, "") || "";
|
|
11418
|
+
if (!cleanPattern) {
|
|
11419
|
+
return {
|
|
11420
|
+
regex: /^\/?$/,
|
|
11421
|
+
paramNames: []
|
|
11422
|
+
};
|
|
11423
|
+
}
|
|
11424
|
+
const segments = cleanPattern.split("/").filter(Boolean);
|
|
11425
|
+
const paramNames = [];
|
|
11426
|
+
const regexParts = [];
|
|
11427
|
+
for (let i = 0; i < segments.length; i++) {
|
|
11428
|
+
const seg = segments[i];
|
|
11429
|
+
if (seg === "*") {
|
|
11430
|
+
if (i !== segments.length - 1) {
|
|
11431
|
+
throw new Error(
|
|
11432
|
+
`Catch-all "*" in "${pattern}" must be the last segment.`
|
|
11433
|
+
);
|
|
11434
|
+
}
|
|
11435
|
+
regexParts.push("(.+)");
|
|
11436
|
+
continue;
|
|
11437
|
+
}
|
|
11438
|
+
if (seg.endsWith("*") && seg.startsWith(":")) {
|
|
11439
|
+
const paramName = seg.slice(1, -1);
|
|
11440
|
+
if (i !== segments.length - 1) {
|
|
11441
|
+
throw new Error(
|
|
11442
|
+
`Catch-all segment "${seg}" in "${pattern}" must be the last segment.`
|
|
11443
|
+
);
|
|
11444
|
+
}
|
|
11445
|
+
paramNames.push(paramName);
|
|
11446
|
+
regexParts.push("(.+)");
|
|
11447
|
+
continue;
|
|
11448
|
+
}
|
|
11449
|
+
if (seg.startsWith(":") && seg.length > 1) {
|
|
11450
|
+
const paramName = seg.slice(1);
|
|
11451
|
+
paramNames.push(paramName);
|
|
11452
|
+
regexParts.push("([^/]+)");
|
|
11453
|
+
continue;
|
|
11454
|
+
}
|
|
11455
|
+
const escaped = seg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
11456
|
+
regexParts.push(escaped);
|
|
11457
|
+
}
|
|
11458
|
+
const regexSource = "^/?" + regexParts.join("/") + "/?$";
|
|
11459
|
+
const regex = new RegExp(regexSource);
|
|
11460
|
+
return { regex, paramNames };
|
|
11461
|
+
}
|
|
11462
|
+
function extractHostParams(hostPattern, actualHost) {
|
|
11463
|
+
const regexPattern = hostPattern.replace(/:([^.]+)/g, "([^.]+)").replace(/\./g, "\\.").replace(/\*/g, ".*");
|
|
11464
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
11465
|
+
const match = regex.exec(actualHost);
|
|
11466
|
+
if (!match) return null;
|
|
11467
|
+
const paramNames = [];
|
|
11468
|
+
const paramPattern = /:([^.]+)/g;
|
|
11469
|
+
let paramMatch;
|
|
11470
|
+
while ((paramMatch = paramPattern.exec(hostPattern)) !== null) {
|
|
11471
|
+
paramNames.push(paramMatch[1]);
|
|
11472
|
+
}
|
|
11473
|
+
const params = {};
|
|
11474
|
+
paramNames.forEach((name, idx) => {
|
|
11475
|
+
params[name] = match[idx + 1] || "";
|
|
11476
|
+
});
|
|
11477
|
+
return params;
|
|
11478
|
+
}
|
|
11479
|
+
function evaluateRewriteConditions(conditions, req) {
|
|
11480
|
+
const extractedParams = {};
|
|
11481
|
+
for (const condition of conditions) {
|
|
11482
|
+
switch (condition.type) {
|
|
11483
|
+
case "host": {
|
|
11484
|
+
const hostWithPort = req.get("host") || req.hostname || req.get("x-forwarded-host")?.split(",")[0] || "";
|
|
11485
|
+
const host = hostWithPort.split(":")[0];
|
|
11486
|
+
if (process.env.NODE_ENV === "development") {
|
|
11487
|
+
console.log("[rewrites] Host matching:", {
|
|
11488
|
+
pattern: condition.value,
|
|
11489
|
+
actualHost: host,
|
|
11490
|
+
hostWithPort,
|
|
11491
|
+
reqHost: req.get("host"),
|
|
11492
|
+
reqHostname: req.hostname
|
|
11493
|
+
});
|
|
11494
|
+
}
|
|
11495
|
+
const hostParams = extractHostParams(condition.value, host);
|
|
11496
|
+
if (!hostParams) {
|
|
11497
|
+
if (process.env.NODE_ENV === "development") {
|
|
11498
|
+
console.log("[rewrites] Host params extraction failed:", {
|
|
11499
|
+
pattern: condition.value,
|
|
11500
|
+
actualHost: host
|
|
11501
|
+
});
|
|
11502
|
+
}
|
|
11503
|
+
return { matches: false, params: {} };
|
|
11504
|
+
}
|
|
11505
|
+
Object.assign(extractedParams, hostParams);
|
|
11506
|
+
break;
|
|
11507
|
+
}
|
|
11508
|
+
case "header": {
|
|
11509
|
+
if (!condition.key) {
|
|
11510
|
+
return { matches: false, params: {} };
|
|
11511
|
+
}
|
|
11512
|
+
const headerValue = req.get(condition.key.toLowerCase());
|
|
11513
|
+
if (!headerValue || headerValue !== condition.value) {
|
|
11514
|
+
return { matches: false, params: {} };
|
|
11515
|
+
}
|
|
11516
|
+
break;
|
|
11517
|
+
}
|
|
11518
|
+
case "cookie": {
|
|
11519
|
+
if (!condition.key) {
|
|
11520
|
+
return { matches: false, params: {} };
|
|
11521
|
+
}
|
|
11522
|
+
const cookieValue = req.cookies?.[condition.key];
|
|
11523
|
+
if (!cookieValue || cookieValue !== condition.value) {
|
|
11524
|
+
return { matches: false, params: {} };
|
|
11525
|
+
}
|
|
11526
|
+
break;
|
|
11527
|
+
}
|
|
11528
|
+
case "query": {
|
|
11529
|
+
if (!condition.key) {
|
|
11530
|
+
return { matches: false, params: {} };
|
|
11531
|
+
}
|
|
11532
|
+
const queryValue = req.query[condition.key];
|
|
11533
|
+
if (!queryValue || String(queryValue) !== condition.value) {
|
|
11534
|
+
return { matches: false, params: {} };
|
|
11535
|
+
}
|
|
11536
|
+
break;
|
|
11537
|
+
}
|
|
11538
|
+
default:
|
|
11539
|
+
return { matches: false, params: {} };
|
|
11540
|
+
}
|
|
11541
|
+
}
|
|
11542
|
+
return { matches: true, params: extractedParams };
|
|
11543
|
+
}
|
|
11544
|
+
function replaceDestinationParams(destination, params) {
|
|
11545
|
+
let result = destination;
|
|
11546
|
+
for (const [key, value] of Object.entries(params)) {
|
|
11547
|
+
const pattern = new RegExp(`:${key}(?:\\*)?`, "g");
|
|
11548
|
+
result = result.replace(pattern, value);
|
|
11549
|
+
}
|
|
11550
|
+
return result;
|
|
11551
|
+
}
|
|
11552
|
+
async function processRewrites(urlPath, compiledRewrites, req) {
|
|
11553
|
+
const normalizedPath = urlPath.replace(/\/$/, "") || "/";
|
|
11554
|
+
if (normalizedPath.startsWith("/static/") || // Static assets (client.js, client.css, etc.)
|
|
11555
|
+
normalizedPath.startsWith("/__fw/") || // Framework internal routes (hot reload, etc.)
|
|
11556
|
+
normalizedPath === "/favicon.ico" || // Favicon
|
|
11557
|
+
normalizedPath.startsWith("/wss/")) {
|
|
11558
|
+
if (process.env.NODE_ENV === "development") {
|
|
11559
|
+
console.log("[rewrites] Skipping rewrite for system route:", normalizedPath);
|
|
11560
|
+
}
|
|
11561
|
+
return null;
|
|
11562
|
+
}
|
|
11563
|
+
if (process.env.NODE_ENV === "development") {
|
|
11564
|
+
console.log("[rewrites] Processing rewrites:", {
|
|
11565
|
+
urlPath,
|
|
11566
|
+
normalizedPath,
|
|
11567
|
+
host: req.get("host"),
|
|
11568
|
+
hostname: req.hostname,
|
|
11569
|
+
compiledRewritesCount: compiledRewrites.length
|
|
11570
|
+
});
|
|
11571
|
+
}
|
|
11572
|
+
for (const rewrite of compiledRewrites) {
|
|
11573
|
+
let conditionParams = {};
|
|
11574
|
+
if (rewrite.has && rewrite.has.length > 0) {
|
|
11575
|
+
const conditionResult = evaluateRewriteConditions(rewrite.has, req);
|
|
11576
|
+
if (!conditionResult.matches) {
|
|
11577
|
+
if (process.env.NODE_ENV === "development") {
|
|
11578
|
+
console.log("[rewrites] Condition not matched:", {
|
|
11579
|
+
source: rewrite.source,
|
|
11580
|
+
conditions: rewrite.has
|
|
11581
|
+
});
|
|
11582
|
+
}
|
|
11583
|
+
continue;
|
|
11584
|
+
}
|
|
11585
|
+
conditionParams = conditionResult.params;
|
|
11586
|
+
if (process.env.NODE_ENV === "development") {
|
|
11587
|
+
console.log("[rewrites] Condition matched:", {
|
|
11588
|
+
source: rewrite.source,
|
|
11589
|
+
conditionParams
|
|
11590
|
+
});
|
|
11591
|
+
}
|
|
11592
|
+
}
|
|
11593
|
+
const sourceMatch = rewrite.sourceRegex.exec(normalizedPath);
|
|
11594
|
+
if (!sourceMatch) {
|
|
11595
|
+
if (process.env.NODE_ENV === "development") {
|
|
11596
|
+
console.log("[rewrites] Source pattern not matched:", {
|
|
11597
|
+
source: rewrite.source,
|
|
11598
|
+
normalizedPath,
|
|
11599
|
+
sourceRegex: rewrite.sourceRegex.toString()
|
|
11600
|
+
});
|
|
11601
|
+
}
|
|
11602
|
+
continue;
|
|
11603
|
+
}
|
|
11604
|
+
if (process.env.NODE_ENV === "development") {
|
|
11605
|
+
console.log("[rewrites] Source pattern matched:", {
|
|
11606
|
+
source: rewrite.source,
|
|
11607
|
+
normalizedPath,
|
|
11608
|
+
match: sourceMatch[0]
|
|
11609
|
+
});
|
|
11610
|
+
}
|
|
11611
|
+
const sourceParams = {};
|
|
11612
|
+
rewrite.sourceParamNames.forEach((name, idx) => {
|
|
11613
|
+
sourceParams[name] = decodeURIComponent(sourceMatch[idx + 1] || "");
|
|
11614
|
+
});
|
|
11615
|
+
const allParams = { ...sourceParams, ...conditionParams };
|
|
11616
|
+
let destination;
|
|
11617
|
+
if (typeof rewrite.destination === "function") {
|
|
11618
|
+
destination = await rewrite.destination(allParams, req);
|
|
11619
|
+
} else {
|
|
11620
|
+
destination = replaceDestinationParams(rewrite.destination, allParams);
|
|
11621
|
+
}
|
|
11622
|
+
const normalizedDestination = destination.replace(/\/+/g, "/").replace(/^([^/])/, "/$1").replace(/\/$/, "") || "/";
|
|
11623
|
+
if (process.env.NODE_ENV === "development") {
|
|
11624
|
+
console.log("[rewrites] Rewrite successful:", {
|
|
11625
|
+
originalPath: urlPath,
|
|
11626
|
+
rewrittenPath: normalizedDestination,
|
|
11627
|
+
allParams
|
|
11628
|
+
});
|
|
11629
|
+
}
|
|
11630
|
+
return {
|
|
11631
|
+
rewrittenPath: normalizedDestination,
|
|
11632
|
+
extractedParams: allParams
|
|
11633
|
+
};
|
|
11634
|
+
}
|
|
11635
|
+
return null;
|
|
11636
|
+
}
|
|
11637
|
+
function validateRewrites(rules) {
|
|
11638
|
+
for (const rule of rules) {
|
|
11639
|
+
if (typeof rule.destination === "string") {
|
|
11640
|
+
if (rule.source === rule.destination) {
|
|
11641
|
+
console.warn(
|
|
11642
|
+
`[framework][rewrites] Rewrite rule has identical source and destination: "${rule.source}". This may cause issues.`
|
|
11643
|
+
);
|
|
11644
|
+
}
|
|
11645
|
+
}
|
|
11646
|
+
}
|
|
11647
|
+
const sources = /* @__PURE__ */ new Set();
|
|
11648
|
+
for (const rule of rules) {
|
|
11649
|
+
if (sources.has(rule.source)) {
|
|
11650
|
+
console.warn(
|
|
11651
|
+
`[framework][rewrites] Duplicate rewrite source pattern: "${rule.source}". Only the first match will be used.`
|
|
11652
|
+
);
|
|
11653
|
+
}
|
|
11654
|
+
sources.add(rule.source);
|
|
11655
|
+
}
|
|
11656
|
+
}
|
|
11657
|
+
function compileRewriteRules(rules) {
|
|
11658
|
+
validateRewrites(rules);
|
|
11659
|
+
return rules.map((rule) => {
|
|
11660
|
+
const { regex, paramNames } = parseRewritePattern(rule.source);
|
|
11661
|
+
let hostRegex;
|
|
11662
|
+
let hostParamNames;
|
|
11663
|
+
if (rule.has) {
|
|
11664
|
+
const hostCondition = rule.has.find((c) => c.type === "host");
|
|
11665
|
+
if (hostCondition) {
|
|
11666
|
+
const hostPattern = hostCondition.value;
|
|
11667
|
+
const hostRegexPattern = hostPattern.replace(/:([^.]+)/g, "([^.]+)").replace(/\./g, "\\.").replace(/\*/g, ".*");
|
|
11668
|
+
hostRegex = new RegExp(`^${hostRegexPattern}$`);
|
|
11669
|
+
hostParamNames = [];
|
|
11670
|
+
const paramPattern = /:([^.]+)/g;
|
|
11671
|
+
let paramMatch;
|
|
11672
|
+
while ((paramMatch = paramPattern.exec(hostPattern)) !== null) {
|
|
11673
|
+
hostParamNames.push(paramMatch[1]);
|
|
11674
|
+
}
|
|
11675
|
+
}
|
|
11676
|
+
}
|
|
11677
|
+
return {
|
|
11678
|
+
source: rule.source,
|
|
11679
|
+
sourceRegex: regex,
|
|
11680
|
+
sourceParamNames: paramNames,
|
|
11681
|
+
destination: rule.destination,
|
|
11682
|
+
has: rule.has,
|
|
11683
|
+
hostRegex,
|
|
11684
|
+
hostParamNames
|
|
11685
|
+
};
|
|
11686
|
+
});
|
|
11687
|
+
}
|
|
11688
|
+
|
|
11689
|
+
// modules/router/rewrites-loader.ts
|
|
11690
|
+
import fs10 from "fs";
|
|
11691
|
+
import path10 from "path";
|
|
11692
|
+
var FilesystemRewriteLoader = class {
|
|
11693
|
+
// Maximum cache age in ms (1 second fallback)
|
|
11694
|
+
constructor(projectRoot) {
|
|
11695
|
+
this.projectRoot = projectRoot;
|
|
11696
|
+
this.cache = null;
|
|
11697
|
+
this.cacheMaxAge = 1e3;
|
|
11698
|
+
}
|
|
11699
|
+
/**
|
|
11700
|
+
* Invalidates the cache, forcing a reload on next access.
|
|
11701
|
+
*/
|
|
11702
|
+
invalidateCache() {
|
|
11703
|
+
this.cache = null;
|
|
11704
|
+
}
|
|
11705
|
+
/**
|
|
11706
|
+
* Finds the rewrites config file.
|
|
11707
|
+
* Looks for rewrites.config.ts, rewrites.config.js, or rewrites.config.json
|
|
11708
|
+
*/
|
|
11709
|
+
findRewritesConfig() {
|
|
11710
|
+
const candidates = [
|
|
11711
|
+
path10.join(this.projectRoot, "rewrites.config.ts"),
|
|
11712
|
+
path10.join(this.projectRoot, "rewrites.config.js"),
|
|
11713
|
+
path10.join(this.projectRoot, "rewrites.config.json")
|
|
11714
|
+
];
|
|
11715
|
+
for (const candidate of candidates) {
|
|
11716
|
+
if (fs10.existsSync(candidate)) {
|
|
11717
|
+
return candidate;
|
|
11718
|
+
}
|
|
11719
|
+
}
|
|
11720
|
+
return null;
|
|
11721
|
+
}
|
|
11722
|
+
/**
|
|
11723
|
+
* Checks if the rewrites config file has changed.
|
|
11724
|
+
*/
|
|
11725
|
+
hasConfigChanged(configPath) {
|
|
11726
|
+
if (!this.cache || !this.cache.fileStats) {
|
|
11727
|
+
return true;
|
|
11728
|
+
}
|
|
11729
|
+
if (!fs10.existsSync(configPath)) {
|
|
11730
|
+
return this.cache.rewrites.length > 0;
|
|
11731
|
+
}
|
|
11732
|
+
const stats = fs10.statSync(configPath);
|
|
11733
|
+
const cachedStats = this.cache.fileStats;
|
|
11734
|
+
return stats.mtimeMs !== cachedStats.mtime || stats.size !== cachedStats.size;
|
|
11735
|
+
}
|
|
11736
|
+
/**
|
|
11737
|
+
* Loads rewrites from a config file.
|
|
11738
|
+
*/
|
|
11739
|
+
async loadRewritesFromFile(configPath) {
|
|
11740
|
+
const ext = path10.extname(configPath);
|
|
11741
|
+
if (ext === ".json") {
|
|
11742
|
+
const content = fs10.readFileSync(configPath, "utf-8");
|
|
11743
|
+
const config2 = JSON.parse(content);
|
|
11744
|
+
return Array.isArray(config2) ? config2 : [];
|
|
11745
|
+
}
|
|
11746
|
+
delete __require.cache[__require.resolve(configPath)];
|
|
11747
|
+
const mod = __require(configPath);
|
|
11748
|
+
const config = mod.default || mod;
|
|
11749
|
+
if (typeof config === "function") {
|
|
11750
|
+
return await config();
|
|
11751
|
+
}
|
|
11752
|
+
if (Array.isArray(config)) {
|
|
11753
|
+
return config;
|
|
11754
|
+
}
|
|
11755
|
+
throw new Error(
|
|
11756
|
+
`Invalid rewrites config in ${configPath}. Expected array or function returning array.`
|
|
11757
|
+
);
|
|
11758
|
+
}
|
|
11759
|
+
/**
|
|
11760
|
+
* Checks if cache is still valid, invalidates if config changed.
|
|
11761
|
+
*/
|
|
11762
|
+
ensureCacheValid() {
|
|
11763
|
+
if (!this.cache) {
|
|
11764
|
+
return;
|
|
11765
|
+
}
|
|
11766
|
+
const now = Date.now();
|
|
11767
|
+
if (now - this.cache.timestamp > this.cacheMaxAge) {
|
|
11768
|
+
const configPath = this.findRewritesConfig();
|
|
11769
|
+
if (configPath && this.hasConfigChanged(configPath)) {
|
|
11770
|
+
this.cache = null;
|
|
11771
|
+
} else {
|
|
11772
|
+
this.cache.timestamp = now;
|
|
11773
|
+
}
|
|
11774
|
+
}
|
|
11775
|
+
}
|
|
11776
|
+
async loadRewrites() {
|
|
11777
|
+
this.ensureCacheValid();
|
|
11778
|
+
const configPath = this.findRewritesConfig();
|
|
11779
|
+
if (!configPath) {
|
|
11780
|
+
if (this.cache && this.cache.rewrites.length === 0) {
|
|
11781
|
+
return this.cache.rewrites;
|
|
11782
|
+
}
|
|
11783
|
+
this.cache = {
|
|
11784
|
+
rewrites: [],
|
|
11785
|
+
fileStats: null,
|
|
11786
|
+
timestamp: Date.now()
|
|
11787
|
+
};
|
|
11788
|
+
return [];
|
|
11789
|
+
}
|
|
11790
|
+
if (!this.cache || this.hasConfigChanged(configPath)) {
|
|
11791
|
+
const rules = await this.loadRewritesFromFile(configPath);
|
|
11792
|
+
const compiled = compileRewriteRules(rules);
|
|
11793
|
+
const stats = fs10.statSync(configPath);
|
|
11794
|
+
const fileStats = {
|
|
11795
|
+
mtime: stats.mtimeMs,
|
|
11796
|
+
size: stats.size
|
|
11797
|
+
};
|
|
11798
|
+
this.cache = {
|
|
11799
|
+
rewrites: compiled,
|
|
11800
|
+
fileStats,
|
|
11801
|
+
timestamp: Date.now()
|
|
11802
|
+
};
|
|
11803
|
+
}
|
|
11804
|
+
return this.cache.rewrites;
|
|
11805
|
+
}
|
|
11806
|
+
};
|
|
11807
|
+
var ManifestRewriteLoader = class {
|
|
11808
|
+
constructor(projectRoot) {
|
|
11809
|
+
this.cache = null;
|
|
11810
|
+
this.manifestPath = path10.join(projectRoot, ".loly", "rewrites-manifest.json");
|
|
11811
|
+
}
|
|
11812
|
+
/**
|
|
11813
|
+
* Reads the rewrites manifest from disk.
|
|
11814
|
+
*/
|
|
11815
|
+
readManifest() {
|
|
11816
|
+
if (!fs10.existsSync(this.manifestPath)) {
|
|
11817
|
+
return null;
|
|
11818
|
+
}
|
|
11819
|
+
try {
|
|
11820
|
+
const content = fs10.readFileSync(this.manifestPath, "utf-8");
|
|
11821
|
+
return JSON.parse(content);
|
|
11822
|
+
} catch (error) {
|
|
11823
|
+
console.warn(
|
|
11824
|
+
`Failed to read rewrites manifest from ${this.manifestPath}:`,
|
|
11825
|
+
error
|
|
11826
|
+
);
|
|
11827
|
+
return null;
|
|
11828
|
+
}
|
|
11829
|
+
}
|
|
11830
|
+
async loadRewrites() {
|
|
11831
|
+
if (this.cache) {
|
|
11832
|
+
return this.cache;
|
|
11833
|
+
}
|
|
11834
|
+
const manifest = this.readManifest();
|
|
11835
|
+
if (!manifest || !manifest.rewrites) {
|
|
11836
|
+
this.cache = [];
|
|
11837
|
+
return [];
|
|
11838
|
+
}
|
|
11839
|
+
const compiled = compileRewriteRules(manifest.rewrites);
|
|
11840
|
+
this.cache = compiled;
|
|
11841
|
+
return compiled;
|
|
11842
|
+
}
|
|
11843
|
+
};
|
|
11844
|
+
function createRewriteLoader(projectRoot, isDev) {
|
|
11845
|
+
if (isDev) {
|
|
11846
|
+
return new FilesystemRewriteLoader(projectRoot);
|
|
11847
|
+
} else {
|
|
11848
|
+
return new ManifestRewriteLoader(projectRoot);
|
|
11849
|
+
}
|
|
11850
|
+
}
|
|
11851
|
+
|
|
11852
|
+
// modules/router/rewrites-manifest.ts
|
|
11853
|
+
import fs11 from "fs";
|
|
11854
|
+
import path11 from "path";
|
|
11855
|
+
init_globals();
|
|
11856
|
+
async function writeRewritesManifest(projectRoot) {
|
|
11857
|
+
const buildDir = path11.join(projectRoot, BUILD_FOLDER_NAME);
|
|
11858
|
+
if (!fs11.existsSync(buildDir)) {
|
|
11859
|
+
fs11.mkdirSync(buildDir, { recursive: true });
|
|
11860
|
+
}
|
|
11861
|
+
const manifestPath = path11.join(buildDir, "rewrites-manifest.json");
|
|
11862
|
+
const loader = createRewriteLoader(projectRoot, true);
|
|
11863
|
+
const compiledRewrites = await loader.loadRewrites();
|
|
11864
|
+
const serializableRules = [];
|
|
11865
|
+
for (const compiled of compiledRewrites) {
|
|
11866
|
+
if (typeof compiled.destination === "string") {
|
|
11867
|
+
serializableRules.push({
|
|
11868
|
+
source: compiled.source,
|
|
11869
|
+
destination: compiled.destination,
|
|
11870
|
+
has: compiled.has
|
|
11871
|
+
});
|
|
11872
|
+
} else {
|
|
11873
|
+
console.warn(
|
|
11874
|
+
`[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.`
|
|
11875
|
+
);
|
|
11876
|
+
}
|
|
11877
|
+
}
|
|
11878
|
+
const manifest = {
|
|
11879
|
+
version: 1,
|
|
11880
|
+
rewrites: serializableRules
|
|
11881
|
+
};
|
|
11882
|
+
fs11.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
11883
|
+
}
|
|
11884
|
+
|
|
11403
11885
|
// modules/build/bundler/client.ts
|
|
11404
11886
|
import { rspack as rspack2 } from "@rspack/core";
|
|
11405
11887
|
|
|
11406
11888
|
// modules/build/config/client.ts
|
|
11407
|
-
import
|
|
11408
|
-
import
|
|
11889
|
+
import path13 from "path";
|
|
11890
|
+
import fs13 from "fs";
|
|
11409
11891
|
import { rspack } from "@rspack/core";
|
|
11410
11892
|
|
|
11411
11893
|
// modules/build/utils/index.ts
|
|
11412
|
-
import
|
|
11413
|
-
import
|
|
11894
|
+
import fs12 from "fs";
|
|
11895
|
+
import path12 from "path";
|
|
11414
11896
|
function ensureDir(dir) {
|
|
11415
|
-
|
|
11897
|
+
fs12.mkdirSync(dir, { recursive: true });
|
|
11416
11898
|
}
|
|
11417
11899
|
function loadAliasesFromTsconfig(projectRoot) {
|
|
11418
|
-
const tsconfigPath =
|
|
11900
|
+
const tsconfigPath = path12.join(projectRoot, "tsconfig.json");
|
|
11419
11901
|
const aliases = {};
|
|
11420
|
-
if (!
|
|
11421
|
-
aliases["@app"] =
|
|
11902
|
+
if (!fs12.existsSync(tsconfigPath)) {
|
|
11903
|
+
aliases["@app"] = path12.resolve(projectRoot, "app");
|
|
11422
11904
|
return aliases;
|
|
11423
11905
|
}
|
|
11424
11906
|
let tsconfig;
|
|
11425
11907
|
try {
|
|
11426
|
-
tsconfig = JSON.parse(
|
|
11908
|
+
tsconfig = JSON.parse(fs12.readFileSync(tsconfigPath, "utf-8"));
|
|
11427
11909
|
} catch (err) {
|
|
11428
11910
|
console.warn("\u26A0\uFE0F [framework] Could not read tsconfig.json:", err instanceof Error ? err.message : String(err));
|
|
11429
11911
|
console.warn("\u{1F4A1} Using default path aliases. For custom aliases, ensure tsconfig.json is valid.");
|
|
11430
|
-
aliases["@app"] =
|
|
11912
|
+
aliases["@app"] = path12.resolve(projectRoot, "app");
|
|
11431
11913
|
return aliases;
|
|
11432
11914
|
}
|
|
11433
11915
|
const compilerOptions = tsconfig.compilerOptions ?? {};
|
|
@@ -11438,40 +11920,40 @@ function loadAliasesFromTsconfig(projectRoot) {
|
|
|
11438
11920
|
const aliasKey = aliasPattern.replace(/\/\*$/, "");
|
|
11439
11921
|
const firstTarget = targets[0];
|
|
11440
11922
|
const targetPath = firstTarget.replace(/\/\*$/, "");
|
|
11441
|
-
const resolved =
|
|
11923
|
+
const resolved = path12.resolve(projectRoot, baseUrl, targetPath);
|
|
11442
11924
|
aliases[aliasKey] = resolved;
|
|
11443
11925
|
}
|
|
11444
11926
|
if (!aliases["@app"]) {
|
|
11445
|
-
aliases["@app"] =
|
|
11927
|
+
aliases["@app"] = path12.resolve(projectRoot, "app");
|
|
11446
11928
|
}
|
|
11447
11929
|
return aliases;
|
|
11448
11930
|
}
|
|
11449
11931
|
function copyDirRecursive(srcDir, destDir) {
|
|
11450
|
-
if (!
|
|
11932
|
+
if (!fs12.existsSync(srcDir)) return;
|
|
11451
11933
|
ensureDir(destDir);
|
|
11452
|
-
const entries =
|
|
11934
|
+
const entries = fs12.readdirSync(srcDir, { withFileTypes: true });
|
|
11453
11935
|
for (const entry of entries) {
|
|
11454
|
-
const srcPath =
|
|
11455
|
-
const destPath =
|
|
11936
|
+
const srcPath = path12.join(srcDir, entry.name);
|
|
11937
|
+
const destPath = path12.join(destDir, entry.name);
|
|
11456
11938
|
if (entry.isDirectory()) {
|
|
11457
11939
|
copyDirRecursive(srcPath, destPath);
|
|
11458
11940
|
} else if (entry.isFile()) {
|
|
11459
|
-
|
|
11941
|
+
fs12.copyFileSync(srcPath, destPath);
|
|
11460
11942
|
}
|
|
11461
11943
|
}
|
|
11462
11944
|
}
|
|
11463
11945
|
function copyStaticAssets(projectRoot, outDir) {
|
|
11464
|
-
const assetsSrc =
|
|
11465
|
-
const assetsDest =
|
|
11946
|
+
const assetsSrc = path12.join(projectRoot, "assets");
|
|
11947
|
+
const assetsDest = path12.join(outDir, "assets");
|
|
11466
11948
|
copyDirRecursive(assetsSrc, assetsDest);
|
|
11467
|
-
const publicDir =
|
|
11949
|
+
const publicDir = path12.join(projectRoot, "public");
|
|
11468
11950
|
const candidates = ["favicon.ico", "favicon.png"];
|
|
11469
11951
|
for (const name of candidates) {
|
|
11470
|
-
const fromPublic =
|
|
11471
|
-
if (
|
|
11472
|
-
const dest =
|
|
11473
|
-
ensureDir(
|
|
11474
|
-
|
|
11952
|
+
const fromPublic = path12.join(publicDir, name);
|
|
11953
|
+
if (fs12.existsSync(fromPublic)) {
|
|
11954
|
+
const dest = path12.join(outDir, name);
|
|
11955
|
+
ensureDir(path12.dirname(dest));
|
|
11956
|
+
fs12.copyFileSync(fromPublic, dest);
|
|
11475
11957
|
break;
|
|
11476
11958
|
}
|
|
11477
11959
|
}
|
|
@@ -11481,10 +11963,10 @@ function getFaviconInfo(projectRoot, staticDir = "public", isDev = false) {
|
|
|
11481
11963
|
{ name: "favicon.ico", type: "image/x-icon" },
|
|
11482
11964
|
{ name: "favicon.png", type: "image/png" }
|
|
11483
11965
|
];
|
|
11484
|
-
const publicDir =
|
|
11966
|
+
const publicDir = path12.join(projectRoot, staticDir);
|
|
11485
11967
|
for (const candidate of candidates) {
|
|
11486
|
-
const publicPath =
|
|
11487
|
-
if (
|
|
11968
|
+
const publicPath = path12.join(publicDir, candidate.name);
|
|
11969
|
+
if (fs12.existsSync(publicPath)) {
|
|
11488
11970
|
return {
|
|
11489
11971
|
path: `/${candidate.name}`,
|
|
11490
11972
|
// Served at root from public/
|
|
@@ -11502,10 +11984,10 @@ function generateAssetManifest(outDir, stats) {
|
|
|
11502
11984
|
},
|
|
11503
11985
|
chunks: {}
|
|
11504
11986
|
};
|
|
11505
|
-
if (!
|
|
11987
|
+
if (!fs12.existsSync(outDir)) {
|
|
11506
11988
|
return manifest;
|
|
11507
11989
|
}
|
|
11508
|
-
const files =
|
|
11990
|
+
const files = fs12.readdirSync(outDir);
|
|
11509
11991
|
if (stats) {
|
|
11510
11992
|
try {
|
|
11511
11993
|
const statsJson = stats.toJson({
|
|
@@ -11634,12 +12116,12 @@ function generateAssetManifest(outDir, stats) {
|
|
|
11634
12116
|
}
|
|
11635
12117
|
function loadAssetManifest(projectRoot) {
|
|
11636
12118
|
const { BUILD_FOLDER_NAME: BUILD_FOLDER_NAME2 } = (init_globals(), __toCommonJS(globals_exports));
|
|
11637
|
-
const manifestPath =
|
|
11638
|
-
if (!
|
|
12119
|
+
const manifestPath = path12.join(projectRoot, BUILD_FOLDER_NAME2, "asset-manifest.json");
|
|
12120
|
+
if (!fs12.existsSync(manifestPath)) {
|
|
11639
12121
|
return null;
|
|
11640
12122
|
}
|
|
11641
12123
|
try {
|
|
11642
|
-
const manifest = JSON.parse(
|
|
12124
|
+
const manifest = JSON.parse(fs12.readFileSync(manifestPath, "utf-8"));
|
|
11643
12125
|
return manifest;
|
|
11644
12126
|
} catch (err) {
|
|
11645
12127
|
return null;
|
|
@@ -11662,11 +12144,11 @@ function getClientCssPath(projectRoot) {
|
|
|
11662
12144
|
init_globals();
|
|
11663
12145
|
import dotenv from "dotenv";
|
|
11664
12146
|
function createClientConfig(projectRoot, mode) {
|
|
11665
|
-
const buildDir =
|
|
11666
|
-
const clientEntry =
|
|
11667
|
-
const outDir =
|
|
11668
|
-
const envPath2 =
|
|
11669
|
-
if (
|
|
12147
|
+
const buildDir = path13.join(projectRoot, BUILD_FOLDER_NAME);
|
|
12148
|
+
const clientEntry = path13.join(buildDir, "boostrap.ts");
|
|
12149
|
+
const outDir = path13.join(buildDir, "client");
|
|
12150
|
+
const envPath2 = path13.join(projectRoot, ".env");
|
|
12151
|
+
if (fs13.existsSync(envPath2)) {
|
|
11670
12152
|
dotenv.config({ path: envPath2 });
|
|
11671
12153
|
}
|
|
11672
12154
|
const publicEnv = {};
|
|
@@ -11787,8 +12269,8 @@ function createClientConfig(projectRoot, mode) {
|
|
|
11787
12269
|
|
|
11788
12270
|
// modules/build/bundler/client.ts
|
|
11789
12271
|
init_globals();
|
|
11790
|
-
import
|
|
11791
|
-
import
|
|
12272
|
+
import path14 from "path";
|
|
12273
|
+
import fs14 from "fs";
|
|
11792
12274
|
function startClientBundler(projectRoot, mode = "development") {
|
|
11793
12275
|
const { config, outDir } = createClientConfig(projectRoot, mode);
|
|
11794
12276
|
copyStaticAssets(projectRoot, outDir);
|
|
@@ -11897,18 +12379,18 @@ function buildClientBundle(projectRoot) {
|
|
|
11897
12379
|
}
|
|
11898
12380
|
copyStaticAssets(projectRoot, outDir);
|
|
11899
12381
|
const assetManifest = generateAssetManifest(outDir, stats);
|
|
11900
|
-
const manifestPath =
|
|
11901
|
-
|
|
12382
|
+
const manifestPath = path14.join(projectRoot, BUILD_FOLDER_NAME, "asset-manifest.json");
|
|
12383
|
+
fs14.writeFileSync(manifestPath, JSON.stringify(assetManifest, null, 2), "utf-8");
|
|
11902
12384
|
resolve3({ outDir });
|
|
11903
12385
|
});
|
|
11904
12386
|
});
|
|
11905
12387
|
}
|
|
11906
12388
|
|
|
11907
12389
|
// modules/build/ssg/builder.ts
|
|
11908
|
-
import
|
|
12390
|
+
import path21 from "path";
|
|
11909
12391
|
|
|
11910
12392
|
// modules/build/ssg/path.ts
|
|
11911
|
-
import
|
|
12393
|
+
import path15 from "path";
|
|
11912
12394
|
function buildPathFromPattern(pattern, params) {
|
|
11913
12395
|
const segments = pattern.split("/").filter(Boolean);
|
|
11914
12396
|
const parts = [];
|
|
@@ -11937,12 +12419,12 @@ function buildPathFromPattern(pattern, params) {
|
|
|
11937
12419
|
}
|
|
11938
12420
|
function pathToOutDir(baseDir, urlPath) {
|
|
11939
12421
|
const clean = urlPath === "/" ? "" : urlPath.replace(/^\/+/, "");
|
|
11940
|
-
return
|
|
12422
|
+
return path15.join(baseDir, clean);
|
|
11941
12423
|
}
|
|
11942
12424
|
|
|
11943
12425
|
// modules/build/ssg/renderer.ts
|
|
11944
|
-
import
|
|
11945
|
-
import
|
|
12426
|
+
import fs16 from "fs";
|
|
12427
|
+
import path20 from "path";
|
|
11946
12428
|
import { renderToString } from "react-dom/server";
|
|
11947
12429
|
|
|
11948
12430
|
// modules/rendering/createDocumentTree/index.ts
|
|
@@ -12365,7 +12847,7 @@ init_globals();
|
|
|
12365
12847
|
import { renderToPipeableStream } from "react-dom/server";
|
|
12366
12848
|
|
|
12367
12849
|
// modules/server/handlers/middleware.ts
|
|
12368
|
-
import
|
|
12850
|
+
import path16 from "path";
|
|
12369
12851
|
|
|
12370
12852
|
// modules/logger/index.ts
|
|
12371
12853
|
import pino from "pino";
|
|
@@ -12497,12 +12979,12 @@ var DEFAULT_IGNORED_PATHS = [
|
|
|
12497
12979
|
/^\/sockjs-node/
|
|
12498
12980
|
// Hot reload websocket
|
|
12499
12981
|
];
|
|
12500
|
-
function shouldIgnorePath(
|
|
12982
|
+
function shouldIgnorePath(path31, ignoredPaths) {
|
|
12501
12983
|
return ignoredPaths.some((pattern) => {
|
|
12502
12984
|
if (typeof pattern === "string") {
|
|
12503
|
-
return
|
|
12985
|
+
return path31 === pattern || path31.startsWith(pattern);
|
|
12504
12986
|
}
|
|
12505
|
-
return pattern.test(
|
|
12987
|
+
return pattern.test(path31);
|
|
12506
12988
|
});
|
|
12507
12989
|
}
|
|
12508
12990
|
function requestLoggerMiddleware(options = {}) {
|
|
@@ -12564,7 +13046,7 @@ async function runRouteMiddlewares(route, ctx) {
|
|
|
12564
13046
|
);
|
|
12565
13047
|
} catch (error) {
|
|
12566
13048
|
const reqLogger = getRequestLogger(ctx.req);
|
|
12567
|
-
const relativePath = route.pageFile ?
|
|
13049
|
+
const relativePath = route.pageFile ? path16.relative(process.cwd(), route.pageFile) : route.pattern;
|
|
12568
13050
|
reqLogger.error("Route middleware failed", error instanceof Error ? error : new Error(String(error)), {
|
|
12569
13051
|
route: route.pattern,
|
|
12570
13052
|
middlewareIndex: i,
|
|
@@ -12579,7 +13061,7 @@ async function runRouteMiddlewares(route, ctx) {
|
|
|
12579
13061
|
}
|
|
12580
13062
|
|
|
12581
13063
|
// modules/server/handlers/server-hook.ts
|
|
12582
|
-
import
|
|
13064
|
+
import path17 from "path";
|
|
12583
13065
|
function createServerHookErrorMessage(error, hookType, routePattern, filePath) {
|
|
12584
13066
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
12585
13067
|
const errorStack = error instanceof Error ? error.stack : void 0;
|
|
@@ -12588,7 +13070,7 @@ function createServerHookErrorMessage(error, hookType, routePattern, filePath) {
|
|
|
12588
13070
|
message += `Route: ${routePattern}
|
|
12589
13071
|
`;
|
|
12590
13072
|
if (filePath) {
|
|
12591
|
-
const relativePath =
|
|
13073
|
+
const relativePath = path17.relative(process.cwd(), filePath);
|
|
12592
13074
|
message += `File: ${relativePath}
|
|
12593
13075
|
`;
|
|
12594
13076
|
}
|
|
@@ -12649,7 +13131,9 @@ function handleDataResponse(res, loaderResult, theme, layoutProps, pageProps, er
|
|
|
12649
13131
|
// Combined props for backward compatibility
|
|
12650
13132
|
props: loaderResult.props ?? {},
|
|
12651
13133
|
metadata: loaderResult.metadata ?? null,
|
|
12652
|
-
theme: loaderResult.theme ?? theme ?? null
|
|
13134
|
+
theme: loaderResult.theme ?? theme ?? null,
|
|
13135
|
+
// Include pathname if provided (for rewrites - client needs to know the rewritten path)
|
|
13136
|
+
...loaderResult.pathname ? { pathname: loaderResult.pathname } : {}
|
|
12653
13137
|
};
|
|
12654
13138
|
if (layoutProps !== void 0 && layoutProps !== null) {
|
|
12655
13139
|
response.layoutProps = layoutProps;
|
|
@@ -12681,24 +13165,24 @@ function handleNotFound(res, urlPath) {
|
|
|
12681
13165
|
}
|
|
12682
13166
|
|
|
12683
13167
|
// modules/server/handlers/ssg.ts
|
|
12684
|
-
import
|
|
12685
|
-
import
|
|
13168
|
+
import fs15 from "fs";
|
|
13169
|
+
import path18 from "path";
|
|
12686
13170
|
var logger2 = createModuleLogger("ssg");
|
|
12687
13171
|
function getSsgDirForPath(baseDir, urlPath) {
|
|
12688
13172
|
const clean = urlPath === "/" ? "" : urlPath.replace(/^\/+/, "");
|
|
12689
|
-
return
|
|
13173
|
+
return path18.join(baseDir, clean);
|
|
12690
13174
|
}
|
|
12691
13175
|
function getSsgHtmlPath(baseDir, urlPath) {
|
|
12692
13176
|
const dir = getSsgDirForPath(baseDir, urlPath);
|
|
12693
|
-
return
|
|
13177
|
+
return path18.join(dir, "index.html");
|
|
12694
13178
|
}
|
|
12695
13179
|
function getSsgDataPath(baseDir, urlPath) {
|
|
12696
13180
|
const dir = getSsgDirForPath(baseDir, urlPath);
|
|
12697
|
-
return
|
|
13181
|
+
return path18.join(dir, "data.json");
|
|
12698
13182
|
}
|
|
12699
13183
|
function tryServeSsgHtml(res, ssgOutDir, urlPath) {
|
|
12700
13184
|
const ssgHtmlPath = getSsgHtmlPath(ssgOutDir, urlPath);
|
|
12701
|
-
if (!
|
|
13185
|
+
if (!fs15.existsSync(ssgHtmlPath)) {
|
|
12702
13186
|
return false;
|
|
12703
13187
|
}
|
|
12704
13188
|
logger2.info("Serving SSG HTML", { urlPath, ssgHtmlPath });
|
|
@@ -12708,17 +13192,17 @@ function tryServeSsgHtml(res, ssgOutDir, urlPath) {
|
|
|
12708
13192
|
);
|
|
12709
13193
|
res.statusCode = 200;
|
|
12710
13194
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
12711
|
-
const stream =
|
|
13195
|
+
const stream = fs15.createReadStream(ssgHtmlPath, { encoding: "utf-8" });
|
|
12712
13196
|
stream.pipe(res);
|
|
12713
13197
|
return true;
|
|
12714
13198
|
}
|
|
12715
13199
|
function tryServeSsgData(res, ssgOutDir, urlPath) {
|
|
12716
13200
|
const ssgDataPath = getSsgDataPath(ssgOutDir, urlPath);
|
|
12717
|
-
if (!
|
|
13201
|
+
if (!fs15.existsSync(ssgDataPath)) {
|
|
12718
13202
|
return false;
|
|
12719
13203
|
}
|
|
12720
13204
|
try {
|
|
12721
|
-
const raw =
|
|
13205
|
+
const raw = fs15.readFileSync(ssgDataPath, "utf-8");
|
|
12722
13206
|
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
12723
13207
|
res.status(200).end(raw);
|
|
12724
13208
|
return true;
|
|
@@ -12784,7 +13268,7 @@ function sanitizeQuery(query) {
|
|
|
12784
13268
|
}
|
|
12785
13269
|
|
|
12786
13270
|
// modules/server/handlers/pages.ts
|
|
12787
|
-
import
|
|
13271
|
+
import path19 from "path";
|
|
12788
13272
|
function mergeMetadata(base, override) {
|
|
12789
13273
|
if (!base && !override) return null;
|
|
12790
13274
|
if (!base) return override;
|
|
@@ -12851,8 +13335,43 @@ async function handlePageRequestInternal(options) {
|
|
|
12851
13335
|
ssgOutDir,
|
|
12852
13336
|
theme,
|
|
12853
13337
|
projectRoot,
|
|
12854
|
-
config
|
|
13338
|
+
config,
|
|
13339
|
+
rewriteLoader
|
|
12855
13340
|
} = options;
|
|
13341
|
+
let finalUrlPath = urlPath;
|
|
13342
|
+
let extractedParams = {};
|
|
13343
|
+
if (rewriteLoader) {
|
|
13344
|
+
try {
|
|
13345
|
+
const compiledRewrites = await rewriteLoader.loadRewrites();
|
|
13346
|
+
const rewriteResult = await processRewrites(urlPath, compiledRewrites, req);
|
|
13347
|
+
if (rewriteResult) {
|
|
13348
|
+
finalUrlPath = rewriteResult.rewrittenPath;
|
|
13349
|
+
extractedParams = rewriteResult.extractedParams;
|
|
13350
|
+
finalUrlPath = finalUrlPath.replace(/\/+/g, "/").replace(/^([^/])/, "/$1").replace(/\/$/, "") || "/";
|
|
13351
|
+
if (env === "dev") {
|
|
13352
|
+
const reqLogger2 = getRequestLogger(req);
|
|
13353
|
+
reqLogger2.debug("Rewrite applied", {
|
|
13354
|
+
originalPath: urlPath,
|
|
13355
|
+
rewrittenPath: finalUrlPath,
|
|
13356
|
+
extractedParams,
|
|
13357
|
+
host: req.get("host")
|
|
13358
|
+
});
|
|
13359
|
+
}
|
|
13360
|
+
Object.assign(req.query, extractedParams);
|
|
13361
|
+
if (!req.locals) {
|
|
13362
|
+
req.locals = {};
|
|
13363
|
+
}
|
|
13364
|
+
Object.assign(req.locals, extractedParams);
|
|
13365
|
+
}
|
|
13366
|
+
} catch (error) {
|
|
13367
|
+
const reqLogger2 = getRequestLogger(req);
|
|
13368
|
+
reqLogger2.error("Error processing rewrites", error, {
|
|
13369
|
+
urlPath,
|
|
13370
|
+
host: req.get("host")
|
|
13371
|
+
});
|
|
13372
|
+
}
|
|
13373
|
+
}
|
|
13374
|
+
finalUrlPath = finalUrlPath.replace(/\/$/, "") || "/";
|
|
12856
13375
|
const clientJsPath = env === "dev" ? "/static/client.js" : projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
|
|
12857
13376
|
const clientCssPath = env === "dev" ? "/static/client.css" : projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
|
|
12858
13377
|
const assetManifest = env === "prod" && projectRoot ? loadAssetManifest(projectRoot) : null;
|
|
@@ -12861,18 +13380,43 @@ async function handlePageRequestInternal(options) {
|
|
|
12861
13380
|
const skipLayoutHooks = isDataReq && req.headers["x-skip-layout-hooks"] === "true";
|
|
12862
13381
|
if (env === "prod" && ssgOutDir) {
|
|
12863
13382
|
if (isDataReq) {
|
|
12864
|
-
if (tryServeSsgData(res, ssgOutDir,
|
|
13383
|
+
if (tryServeSsgData(res, ssgOutDir, finalUrlPath)) {
|
|
12865
13384
|
return;
|
|
12866
13385
|
}
|
|
12867
13386
|
} else {
|
|
12868
|
-
if (tryServeSsgHtml(res, ssgOutDir,
|
|
13387
|
+
if (tryServeSsgHtml(res, ssgOutDir, finalUrlPath)) {
|
|
12869
13388
|
return;
|
|
12870
13389
|
}
|
|
12871
13390
|
}
|
|
12872
13391
|
}
|
|
12873
|
-
const matched = matchRoute(routes,
|
|
13392
|
+
const matched = matchRoute(routes, finalUrlPath);
|
|
13393
|
+
if (env === "dev") {
|
|
13394
|
+
const reqLogger2 = getRequestLogger(req);
|
|
13395
|
+
if (finalUrlPath !== urlPath) {
|
|
13396
|
+
reqLogger2.debug("Route matching after rewrite", {
|
|
13397
|
+
originalPath: urlPath,
|
|
13398
|
+
rewrittenPath: finalUrlPath,
|
|
13399
|
+
matched: !!matched,
|
|
13400
|
+
matchedRoute: matched?.route.pattern,
|
|
13401
|
+
matchedParams: matched?.params,
|
|
13402
|
+
availableRoutes: routes.slice(0, 10).map((r) => r.pattern)
|
|
13403
|
+
// Show first 10 routes
|
|
13404
|
+
});
|
|
13405
|
+
} else if (!matched) {
|
|
13406
|
+
reqLogger2.debug("No route match found", {
|
|
13407
|
+
path: finalUrlPath,
|
|
13408
|
+
availableRoutes: routes.slice(0, 10).map((r) => r.pattern)
|
|
13409
|
+
});
|
|
13410
|
+
}
|
|
13411
|
+
}
|
|
12874
13412
|
const routerData = buildRouterData(req);
|
|
12875
13413
|
if (!matched) {
|
|
13414
|
+
if (isDataReq) {
|
|
13415
|
+
res.statusCode = 404;
|
|
13416
|
+
res.setHeader("Content-Type", "application/json; charset=utf-8");
|
|
13417
|
+
res.end(JSON.stringify({ notFound: true, pathname: finalUrlPath }));
|
|
13418
|
+
return;
|
|
13419
|
+
}
|
|
12876
13420
|
if (notFoundPage) {
|
|
12877
13421
|
const ctx2 = {
|
|
12878
13422
|
req,
|
|
@@ -12896,7 +13440,7 @@ async function handlePageRequestInternal(options) {
|
|
|
12896
13440
|
} catch (error) {
|
|
12897
13441
|
const reqLogger2 = getRequestLogger(req);
|
|
12898
13442
|
const layoutFile = notFoundPage.layoutFiles[i];
|
|
12899
|
-
const relativeLayoutPath = layoutFile ?
|
|
13443
|
+
const relativeLayoutPath = layoutFile ? path19.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
|
|
12900
13444
|
reqLogger2.error("Layout middleware failed for not-found page", error instanceof Error ? error : new Error(String(error)), {
|
|
12901
13445
|
layoutIndex: i,
|
|
12902
13446
|
layoutFile: relativeLayoutPath
|
|
@@ -12917,7 +13461,7 @@ async function handlePageRequestInternal(options) {
|
|
|
12917
13461
|
} catch (error) {
|
|
12918
13462
|
const reqLogger2 = getRequestLogger(req);
|
|
12919
13463
|
const layoutFile = notFoundPage.layoutFiles[i];
|
|
12920
|
-
const relativeLayoutPath = layoutFile ?
|
|
13464
|
+
const relativeLayoutPath = layoutFile ? path19.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
|
|
12921
13465
|
reqLogger2.warn("Layout server hook failed for not-found page", {
|
|
12922
13466
|
error: error instanceof Error ? error.message : String(error),
|
|
12923
13467
|
stack: error instanceof Error ? error.stack : void 0,
|
|
@@ -12951,7 +13495,7 @@ async function handlePageRequestInternal(options) {
|
|
|
12951
13495
|
);
|
|
12952
13496
|
return;
|
|
12953
13497
|
}
|
|
12954
|
-
const initialData2 = buildInitialData(
|
|
13498
|
+
const initialData2 = buildInitialData(finalUrlPath, {}, combinedLoaderResult2);
|
|
12955
13499
|
const appTree2 = buildAppTree(notFoundPage, {}, initialData2.props);
|
|
12956
13500
|
initialData2.notFound = true;
|
|
12957
13501
|
const nonce2 = res.locals.nonce || void 0;
|
|
@@ -13037,7 +13581,7 @@ async function handlePageRequestInternal(options) {
|
|
|
13037
13581
|
);
|
|
13038
13582
|
} catch (error) {
|
|
13039
13583
|
const layoutFile = route.layoutFiles[i];
|
|
13040
|
-
const relativeLayoutPath = layoutFile ?
|
|
13584
|
+
const relativeLayoutPath = layoutFile ? path19.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
|
|
13041
13585
|
reqLogger.error("Layout middleware failed", error instanceof Error ? error : new Error(String(error)), {
|
|
13042
13586
|
route: route.pattern,
|
|
13043
13587
|
layoutIndex: i,
|
|
@@ -13061,7 +13605,7 @@ async function handlePageRequestInternal(options) {
|
|
|
13061
13605
|
}
|
|
13062
13606
|
} catch (error) {
|
|
13063
13607
|
const layoutFile = route.layoutFiles[i];
|
|
13064
|
-
const relativeLayoutPath = layoutFile ?
|
|
13608
|
+
const relativeLayoutPath = layoutFile ? path19.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
|
|
13065
13609
|
reqLogger.warn("Layout server hook failed", {
|
|
13066
13610
|
error: error instanceof Error ? error.message : String(error),
|
|
13067
13611
|
stack: error instanceof Error ? error.stack : void 0,
|
|
@@ -13081,7 +13625,7 @@ async function handlePageRequestInternal(options) {
|
|
|
13081
13625
|
loaderResult.theme = theme;
|
|
13082
13626
|
}
|
|
13083
13627
|
} catch (error) {
|
|
13084
|
-
const relativePagePath = route.pageFile ?
|
|
13628
|
+
const relativePagePath = route.pageFile ? path19.relative(projectRoot || process.cwd(), route.pageFile) : "unknown";
|
|
13085
13629
|
reqLogger.error("Page server hook failed", {
|
|
13086
13630
|
error: error instanceof Error ? error.message : String(error),
|
|
13087
13631
|
stack: error instanceof Error ? error.stack : void 0,
|
|
@@ -13128,7 +13672,9 @@ async function handlePageRequestInternal(options) {
|
|
|
13128
13672
|
const combinedLoaderResult = {
|
|
13129
13673
|
...loaderResult,
|
|
13130
13674
|
props: combinedProps,
|
|
13131
|
-
metadata: combinedMetadata
|
|
13675
|
+
metadata: combinedMetadata,
|
|
13676
|
+
pathname: finalUrlPath
|
|
13677
|
+
// Include rewritten pathname for client-side matching
|
|
13132
13678
|
};
|
|
13133
13679
|
if (isDataReq) {
|
|
13134
13680
|
const pagePropsOnly = loaderResult.props || {};
|
|
@@ -13153,7 +13699,7 @@ async function handlePageRequestInternal(options) {
|
|
|
13153
13699
|
}
|
|
13154
13700
|
return;
|
|
13155
13701
|
}
|
|
13156
|
-
const initialData = buildInitialData(
|
|
13702
|
+
const initialData = buildInitialData(finalUrlPath, params, combinedLoaderResult);
|
|
13157
13703
|
const appTree = buildAppTree(route, params, initialData.props);
|
|
13158
13704
|
const chunkName = routeChunks[route.pattern];
|
|
13159
13705
|
let chunkHref = null;
|
|
@@ -13258,7 +13804,7 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
13258
13804
|
);
|
|
13259
13805
|
} catch (error2) {
|
|
13260
13806
|
const layoutFile = errorPage.layoutFiles[i];
|
|
13261
|
-
const relativeLayoutPath = layoutFile ?
|
|
13807
|
+
const relativeLayoutPath = layoutFile ? path19.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
|
|
13262
13808
|
reqLogger.error("Layout middleware failed for error page", error2 instanceof Error ? error2 : new Error(String(error2)), {
|
|
13263
13809
|
layoutIndex: i,
|
|
13264
13810
|
layoutFile: relativeLayoutPath
|
|
@@ -13278,7 +13824,7 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
13278
13824
|
}
|
|
13279
13825
|
} catch (err) {
|
|
13280
13826
|
const layoutFile = errorPage.layoutFiles[i];
|
|
13281
|
-
const relativeLayoutPath = layoutFile ?
|
|
13827
|
+
const relativeLayoutPath = layoutFile ? path19.relative(projectRoot || process.cwd(), layoutFile) : "unknown";
|
|
13282
13828
|
reqLogger.warn("Layout server hook failed for error page", {
|
|
13283
13829
|
error: err instanceof Error ? err.message : String(err),
|
|
13284
13830
|
stack: err instanceof Error ? err.stack : void 0,
|
|
@@ -13515,16 +14061,16 @@ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params,
|
|
|
13515
14061
|
const html = "<!DOCTYPE html>" + renderToString(documentTree);
|
|
13516
14062
|
const dir = pathToOutDir(ssgOutDir, urlPath);
|
|
13517
14063
|
ensureDir(dir);
|
|
13518
|
-
const htmlFile =
|
|
13519
|
-
const dataFile =
|
|
13520
|
-
|
|
13521
|
-
|
|
14064
|
+
const htmlFile = path20.join(dir, "index.html");
|
|
14065
|
+
const dataFile = path20.join(dir, "data.json");
|
|
14066
|
+
fs16.writeFileSync(htmlFile, html, "utf-8");
|
|
14067
|
+
fs16.writeFileSync(dataFile, JSON.stringify(initialData, null, 2), "utf-8");
|
|
13522
14068
|
}
|
|
13523
14069
|
|
|
13524
14070
|
// modules/build/ssg/builder.ts
|
|
13525
14071
|
init_globals();
|
|
13526
14072
|
async function buildStaticPages(projectRoot, routes, config) {
|
|
13527
|
-
const ssgOutDir =
|
|
14073
|
+
const ssgOutDir = path21.join(projectRoot, BUILD_FOLDER_NAME, "ssg");
|
|
13528
14074
|
ensureDir(ssgOutDir);
|
|
13529
14075
|
for (const route of routes) {
|
|
13530
14076
|
if (route.dynamic !== "force-static") continue;
|
|
@@ -13579,27 +14125,27 @@ async function buildStaticPages(projectRoot, routes, config) {
|
|
|
13579
14125
|
}
|
|
13580
14126
|
|
|
13581
14127
|
// modules/build/bundler/server.ts
|
|
13582
|
-
import
|
|
13583
|
-
import
|
|
14128
|
+
import path23 from "path";
|
|
14129
|
+
import fs18 from "fs";
|
|
13584
14130
|
import esbuild from "esbuild";
|
|
13585
14131
|
|
|
13586
14132
|
// modules/server/utils/server-dir.ts
|
|
13587
14133
|
init_globals();
|
|
13588
|
-
import
|
|
13589
|
-
import
|
|
14134
|
+
import fs17 from "fs";
|
|
14135
|
+
import path22 from "path";
|
|
13590
14136
|
var getServerFile = async (projectRoot, fileName) => {
|
|
13591
|
-
const fileTS =
|
|
13592
|
-
const fileJS =
|
|
14137
|
+
const fileTS = path22.join(projectRoot, `${fileName}.ts`);
|
|
14138
|
+
const fileJS = path22.join(projectRoot, BUILD_FOLDER_NAME, "server", `${fileName}.js`);
|
|
13593
14139
|
const isDev = process.env.NODE_ENV === "development";
|
|
13594
14140
|
let mod = null;
|
|
13595
14141
|
if (isDev) {
|
|
13596
|
-
if (!
|
|
14142
|
+
if (!fs17.existsSync(fileTS)) {
|
|
13597
14143
|
return null;
|
|
13598
14144
|
}
|
|
13599
14145
|
__require("tsx/cjs");
|
|
13600
14146
|
mod = __require(fileTS);
|
|
13601
14147
|
} else {
|
|
13602
|
-
if (!
|
|
14148
|
+
if (!fs17.existsSync(fileJS)) {
|
|
13603
14149
|
return null;
|
|
13604
14150
|
}
|
|
13605
14151
|
mod = __require(fileJS);
|
|
@@ -13781,29 +14327,29 @@ init_globals();
|
|
|
13781
14327
|
var SERVER_FILES = [INIT_FILE_NAME, CONFIG_FILE_NAME];
|
|
13782
14328
|
function createPathAliasPlugin(projectRoot, outDir) {
|
|
13783
14329
|
const aliases = loadAliasesFromTsconfig(projectRoot);
|
|
13784
|
-
const tsconfigPath =
|
|
14330
|
+
const tsconfigPath = path23.join(projectRoot, "tsconfig.json");
|
|
13785
14331
|
let baseUrl = ".";
|
|
13786
|
-
if (
|
|
14332
|
+
if (fs18.existsSync(tsconfigPath)) {
|
|
13787
14333
|
try {
|
|
13788
|
-
const tsconfig = JSON.parse(
|
|
14334
|
+
const tsconfig = JSON.parse(fs18.readFileSync(tsconfigPath, "utf-8"));
|
|
13789
14335
|
baseUrl = tsconfig.compilerOptions?.baseUrl ?? ".";
|
|
13790
14336
|
} catch {
|
|
13791
14337
|
}
|
|
13792
14338
|
}
|
|
13793
14339
|
function resolveAliasToRelative(importPath, sourceFile) {
|
|
13794
|
-
if (importPath.startsWith(".") || importPath.startsWith("/") ||
|
|
14340
|
+
if (importPath.startsWith(".") || importPath.startsWith("/") || path23.isAbsolute(importPath) || importPath.includes("node_modules")) {
|
|
13795
14341
|
return null;
|
|
13796
14342
|
}
|
|
13797
14343
|
for (const [aliasKey, aliasPath] of Object.entries(aliases)) {
|
|
13798
14344
|
if (importPath.startsWith(aliasKey + "/") || importPath === aliasKey) {
|
|
13799
14345
|
const restPath = importPath.startsWith(aliasKey + "/") ? importPath.slice(aliasKey.length + 1) : "";
|
|
13800
|
-
const resolvedPath = restPath ?
|
|
14346
|
+
const resolvedPath = restPath ? path23.join(aliasPath, restPath) : aliasPath;
|
|
13801
14347
|
let actualPath = null;
|
|
13802
14348
|
const extensions = [".ts", ".tsx", ".js", ".jsx", ".json"];
|
|
13803
|
-
if (
|
|
14349
|
+
if (fs18.existsSync(resolvedPath) && fs18.statSync(resolvedPath).isDirectory()) {
|
|
13804
14350
|
for (const ext of extensions) {
|
|
13805
|
-
const indexPath =
|
|
13806
|
-
if (
|
|
14351
|
+
const indexPath = path23.join(resolvedPath, `index${ext}`);
|
|
14352
|
+
if (fs18.existsSync(indexPath)) {
|
|
13807
14353
|
actualPath = indexPath;
|
|
13808
14354
|
break;
|
|
13809
14355
|
}
|
|
@@ -13811,20 +14357,20 @@ function createPathAliasPlugin(projectRoot, outDir) {
|
|
|
13811
14357
|
} else {
|
|
13812
14358
|
for (const ext of extensions) {
|
|
13813
14359
|
const filePath = resolvedPath + ext;
|
|
13814
|
-
if (
|
|
14360
|
+
if (fs18.existsSync(filePath)) {
|
|
13815
14361
|
actualPath = filePath;
|
|
13816
14362
|
break;
|
|
13817
14363
|
}
|
|
13818
14364
|
}
|
|
13819
|
-
if (!actualPath &&
|
|
14365
|
+
if (!actualPath && fs18.existsSync(resolvedPath)) {
|
|
13820
14366
|
actualPath = resolvedPath;
|
|
13821
14367
|
}
|
|
13822
14368
|
}
|
|
13823
14369
|
if (actualPath) {
|
|
13824
|
-
const relativePath =
|
|
14370
|
+
const relativePath = path23.relative(outDir, actualPath);
|
|
13825
14371
|
const normalizedPath = relativePath.replace(/\\/g, "/");
|
|
13826
14372
|
const finalPath = normalizedPath.startsWith(".") ? normalizedPath : `./${normalizedPath}`;
|
|
13827
|
-
const ext =
|
|
14373
|
+
const ext = path23.extname(finalPath);
|
|
13828
14374
|
const pathWithoutExt = ext === ".json" ? finalPath : finalPath.slice(0, -ext.length);
|
|
13829
14375
|
return pathWithoutExt;
|
|
13830
14376
|
}
|
|
@@ -13836,13 +14382,13 @@ function createPathAliasPlugin(projectRoot, outDir) {
|
|
|
13836
14382
|
name: "path-alias-resolver",
|
|
13837
14383
|
setup(build) {
|
|
13838
14384
|
build.onLoad({ filter: /\.(ts|tsx|js|jsx)$/ }, (args) => {
|
|
13839
|
-
const fileName =
|
|
14385
|
+
const fileName = path23.basename(args.path);
|
|
13840
14386
|
const isServerFile = SERVER_FILES.some((f) => fileName === `${f}.ts` || fileName === `${f}.tsx` || fileName === `${f}.js` || fileName === `${f}.jsx`);
|
|
13841
|
-
const isInProjectRoot =
|
|
14387
|
+
const isInProjectRoot = path23.dirname(args.path) === projectRoot;
|
|
13842
14388
|
if (!isServerFile || !isInProjectRoot) {
|
|
13843
14389
|
return null;
|
|
13844
14390
|
}
|
|
13845
|
-
const contents =
|
|
14391
|
+
const contents = fs18.readFileSync(args.path, "utf-8");
|
|
13846
14392
|
let transformed = contents;
|
|
13847
14393
|
const aliasPatterns = Object.keys(aliases).sort((a, b) => b.length - a.length);
|
|
13848
14394
|
for (const aliasKey of aliasPatterns) {
|
|
@@ -13862,7 +14408,7 @@ function createPathAliasPlugin(projectRoot, outDir) {
|
|
|
13862
14408
|
}
|
|
13863
14409
|
return {
|
|
13864
14410
|
contents: transformed,
|
|
13865
|
-
loader:
|
|
14411
|
+
loader: path23.extname(args.path).slice(1)
|
|
13866
14412
|
};
|
|
13867
14413
|
});
|
|
13868
14414
|
build.onResolve({ filter: /.*/ }, (args) => {
|
|
@@ -13881,9 +14427,9 @@ function createPathAliasPlugin(projectRoot, outDir) {
|
|
|
13881
14427
|
function collectAppSources(appDir) {
|
|
13882
14428
|
const entries = [];
|
|
13883
14429
|
function walk(dir) {
|
|
13884
|
-
const items =
|
|
14430
|
+
const items = fs18.readdirSync(dir, { withFileTypes: true });
|
|
13885
14431
|
for (const item of items) {
|
|
13886
|
-
const full =
|
|
14432
|
+
const full = path23.join(dir, item.name);
|
|
13887
14433
|
if (item.isDirectory()) {
|
|
13888
14434
|
walk(full);
|
|
13889
14435
|
continue;
|
|
@@ -13900,7 +14446,7 @@ function collectAppSources(appDir) {
|
|
|
13900
14446
|
return entries;
|
|
13901
14447
|
}
|
|
13902
14448
|
async function buildServerApp(projectRoot, appDir) {
|
|
13903
|
-
const outDir =
|
|
14449
|
+
const outDir = path23.join(projectRoot, BUILD_FOLDER_NAME, "server");
|
|
13904
14450
|
const entryPoints = collectAppSources(appDir);
|
|
13905
14451
|
ensureDir(outDir);
|
|
13906
14452
|
if (entryPoints.length === 0) {
|
|
@@ -13918,14 +14464,14 @@ async function buildServerApp(projectRoot, appDir) {
|
|
|
13918
14464
|
bundle: true,
|
|
13919
14465
|
splitting: false,
|
|
13920
14466
|
logLevel: "info",
|
|
13921
|
-
tsconfig:
|
|
14467
|
+
tsconfig: path23.join(projectRoot, "tsconfig.json"),
|
|
13922
14468
|
packages: "external"
|
|
13923
14469
|
});
|
|
13924
14470
|
const pathAliasPlugin = createPathAliasPlugin(projectRoot, outDir);
|
|
13925
14471
|
for (const fileName of SERVER_FILES) {
|
|
13926
|
-
const initTS =
|
|
13927
|
-
const initJS =
|
|
13928
|
-
if (
|
|
14472
|
+
const initTS = path23.join(projectRoot, `${fileName}.ts`);
|
|
14473
|
+
const initJS = path23.join(outDir, `${fileName}.js`);
|
|
14474
|
+
if (fs18.existsSync(initTS)) {
|
|
13929
14475
|
await esbuild.build({
|
|
13930
14476
|
entryPoints: [initTS],
|
|
13931
14477
|
outfile: initJS,
|
|
@@ -13936,7 +14482,7 @@ async function buildServerApp(projectRoot, appDir) {
|
|
|
13936
14482
|
sourcemap: true,
|
|
13937
14483
|
bundle: false,
|
|
13938
14484
|
logLevel: "info",
|
|
13939
|
-
tsconfig:
|
|
14485
|
+
tsconfig: path23.join(projectRoot, "tsconfig.json"),
|
|
13940
14486
|
plugins: [pathAliasPlugin]
|
|
13941
14487
|
});
|
|
13942
14488
|
}
|
|
@@ -13949,8 +14495,8 @@ init_globals();
|
|
|
13949
14495
|
|
|
13950
14496
|
// src/config.ts
|
|
13951
14497
|
init_globals();
|
|
13952
|
-
import
|
|
13953
|
-
import
|
|
14498
|
+
import path24 from "path";
|
|
14499
|
+
import fs19 from "fs";
|
|
13954
14500
|
var DEFAULT_CONFIG2 = {
|
|
13955
14501
|
directories: {
|
|
13956
14502
|
app: "app",
|
|
@@ -14016,8 +14562,8 @@ function validateConfig(config, projectRoot) {
|
|
|
14016
14562
|
if (!config.directories.app || typeof config.directories.app !== "string") {
|
|
14017
14563
|
errors.push("config.directories.app must be a non-empty string");
|
|
14018
14564
|
} else {
|
|
14019
|
-
const appDir =
|
|
14020
|
-
if (!
|
|
14565
|
+
const appDir = path24.join(projectRoot, config.directories.app);
|
|
14566
|
+
if (!fs19.existsSync(appDir) && process.env.NODE_ENV !== "test") {
|
|
14021
14567
|
errors.push(
|
|
14022
14568
|
`App directory not found: ${config.directories.app}
|
|
14023
14569
|
Expected at: ${appDir}
|
|
@@ -14121,17 +14667,17 @@ function validateConfig(config, projectRoot) {
|
|
|
14121
14667
|
}
|
|
14122
14668
|
function loadConfig(projectRoot) {
|
|
14123
14669
|
const configFiles = [
|
|
14124
|
-
|
|
14125
|
-
|
|
14126
|
-
|
|
14670
|
+
path24.join(projectRoot, "loly.config.ts"),
|
|
14671
|
+
path24.join(projectRoot, "loly.config.js"),
|
|
14672
|
+
path24.join(projectRoot, "loly.config.json")
|
|
14127
14673
|
];
|
|
14128
14674
|
let userConfig = {};
|
|
14129
14675
|
let loadedConfigFile = null;
|
|
14130
14676
|
for (const configFile of configFiles) {
|
|
14131
|
-
if (
|
|
14677
|
+
if (fs19.existsSync(configFile)) {
|
|
14132
14678
|
try {
|
|
14133
14679
|
if (configFile.endsWith(".json")) {
|
|
14134
|
-
const content =
|
|
14680
|
+
const content = fs19.readFileSync(configFile, "utf-8");
|
|
14135
14681
|
userConfig = JSON.parse(content);
|
|
14136
14682
|
} else {
|
|
14137
14683
|
if (process.env.NODE_ENV === "development") {
|
|
@@ -14140,12 +14686,12 @@ function loadConfig(projectRoot) {
|
|
|
14140
14686
|
const mod = __require(configFile);
|
|
14141
14687
|
userConfig = typeof mod.default === "function" ? mod.default(process.env.NODE_ENV) : mod.default || mod.config || mod;
|
|
14142
14688
|
}
|
|
14143
|
-
loadedConfigFile =
|
|
14689
|
+
loadedConfigFile = path24.relative(projectRoot, configFile);
|
|
14144
14690
|
break;
|
|
14145
14691
|
} catch (error) {
|
|
14146
14692
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
14147
14693
|
throw new ConfigValidationError(
|
|
14148
|
-
`Failed to load configuration from ${
|
|
14694
|
+
`Failed to load configuration from ${path24.relative(projectRoot, configFile)}:
|
|
14149
14695
|
${errorMessage}
|
|
14150
14696
|
\u{1F4A1} Suggestion: Check that your config file exports a valid configuration object`
|
|
14151
14697
|
);
|
|
@@ -14169,13 +14715,13 @@ ${error.message}`;
|
|
|
14169
14715
|
return config;
|
|
14170
14716
|
}
|
|
14171
14717
|
function getAppDir(projectRoot, config) {
|
|
14172
|
-
return
|
|
14718
|
+
return path24.resolve(projectRoot, config.directories.app);
|
|
14173
14719
|
}
|
|
14174
14720
|
function getBuildDir(projectRoot, config) {
|
|
14175
|
-
return
|
|
14721
|
+
return path24.join(projectRoot, config.directories.build);
|
|
14176
14722
|
}
|
|
14177
14723
|
function getStaticDir(projectRoot, config) {
|
|
14178
|
-
return
|
|
14724
|
+
return path24.resolve(projectRoot, config.directories.static);
|
|
14179
14725
|
}
|
|
14180
14726
|
|
|
14181
14727
|
// modules/build/index.ts
|
|
@@ -14220,6 +14766,7 @@ async function buildApp(options = {}) {
|
|
|
14220
14766
|
});
|
|
14221
14767
|
writeClientBoostrapManifest(projectRoot);
|
|
14222
14768
|
writeClientRoutesManifest(routes, projectRoot);
|
|
14769
|
+
await writeRewritesManifest(projectRoot);
|
|
14223
14770
|
await buildClientBundle(projectRoot);
|
|
14224
14771
|
await buildStaticPages(projectRoot, routes, config);
|
|
14225
14772
|
delete process.env.LOLY_BUILD;
|
|
@@ -14227,13 +14774,13 @@ async function buildApp(options = {}) {
|
|
|
14227
14774
|
}
|
|
14228
14775
|
|
|
14229
14776
|
// src/server.ts
|
|
14230
|
-
import
|
|
14231
|
-
import
|
|
14777
|
+
import fs21 from "fs";
|
|
14778
|
+
import path29 from "path";
|
|
14232
14779
|
|
|
14233
14780
|
// modules/server/setup.ts
|
|
14234
14781
|
import express from "express";
|
|
14235
|
-
import
|
|
14236
|
-
import
|
|
14782
|
+
import path27 from "path";
|
|
14783
|
+
import fs20 from "fs";
|
|
14237
14784
|
|
|
14238
14785
|
// ../../node_modules/.pnpm/chokidar@4.0.3/node_modules/chokidar/esm/index.js
|
|
14239
14786
|
import { stat as statcb } from "fs";
|
|
@@ -14311,7 +14858,7 @@ var ReaddirpStream = class extends Readable {
|
|
|
14311
14858
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
14312
14859
|
const statMethod = opts.lstat ? lstat : stat;
|
|
14313
14860
|
if (wantBigintFsStats) {
|
|
14314
|
-
this._stat = (
|
|
14861
|
+
this._stat = (path31) => statMethod(path31, { bigint: true });
|
|
14315
14862
|
} else {
|
|
14316
14863
|
this._stat = statMethod;
|
|
14317
14864
|
}
|
|
@@ -14336,8 +14883,8 @@ var ReaddirpStream = class extends Readable {
|
|
|
14336
14883
|
const par = this.parent;
|
|
14337
14884
|
const fil = par && par.files;
|
|
14338
14885
|
if (fil && fil.length > 0) {
|
|
14339
|
-
const { path:
|
|
14340
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
14886
|
+
const { path: path31, depth } = par;
|
|
14887
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path31));
|
|
14341
14888
|
const awaited = await Promise.all(slice);
|
|
14342
14889
|
for (const entry of awaited) {
|
|
14343
14890
|
if (!entry)
|
|
@@ -14377,20 +14924,20 @@ var ReaddirpStream = class extends Readable {
|
|
|
14377
14924
|
this.reading = false;
|
|
14378
14925
|
}
|
|
14379
14926
|
}
|
|
14380
|
-
async _exploreDir(
|
|
14927
|
+
async _exploreDir(path31, depth) {
|
|
14381
14928
|
let files;
|
|
14382
14929
|
try {
|
|
14383
|
-
files = await readdir(
|
|
14930
|
+
files = await readdir(path31, this._rdOptions);
|
|
14384
14931
|
} catch (error) {
|
|
14385
14932
|
this._onError(error);
|
|
14386
14933
|
}
|
|
14387
|
-
return { files, depth, path:
|
|
14934
|
+
return { files, depth, path: path31 };
|
|
14388
14935
|
}
|
|
14389
|
-
async _formatEntry(dirent,
|
|
14936
|
+
async _formatEntry(dirent, path31) {
|
|
14390
14937
|
let entry;
|
|
14391
14938
|
const basename3 = this._isDirent ? dirent.name : dirent;
|
|
14392
14939
|
try {
|
|
14393
|
-
const fullPath = presolve(pjoin(
|
|
14940
|
+
const fullPath = presolve(pjoin(path31, basename3));
|
|
14394
14941
|
entry = { path: prelative(this._root, fullPath), fullPath, basename: basename3 };
|
|
14395
14942
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
14396
14943
|
} catch (err) {
|
|
@@ -14790,16 +15337,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
14790
15337
|
};
|
|
14791
15338
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
14792
15339
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
14793
|
-
function createFsWatchInstance(
|
|
15340
|
+
function createFsWatchInstance(path31, options, listener, errHandler, emitRaw) {
|
|
14794
15341
|
const handleEvent = (rawEvent, evPath) => {
|
|
14795
|
-
listener(
|
|
14796
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
14797
|
-
if (evPath &&
|
|
14798
|
-
fsWatchBroadcast(sysPath.resolve(
|
|
15342
|
+
listener(path31);
|
|
15343
|
+
emitRaw(rawEvent, evPath, { watchedPath: path31 });
|
|
15344
|
+
if (evPath && path31 !== evPath) {
|
|
15345
|
+
fsWatchBroadcast(sysPath.resolve(path31, evPath), KEY_LISTENERS, sysPath.join(path31, evPath));
|
|
14799
15346
|
}
|
|
14800
15347
|
};
|
|
14801
15348
|
try {
|
|
14802
|
-
return fs_watch(
|
|
15349
|
+
return fs_watch(path31, {
|
|
14803
15350
|
persistent: options.persistent
|
|
14804
15351
|
}, handleEvent);
|
|
14805
15352
|
} catch (error) {
|
|
@@ -14815,12 +15362,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
14815
15362
|
listener(val1, val2, val3);
|
|
14816
15363
|
});
|
|
14817
15364
|
};
|
|
14818
|
-
var setFsWatchListener = (
|
|
15365
|
+
var setFsWatchListener = (path31, fullPath, options, handlers) => {
|
|
14819
15366
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
14820
15367
|
let cont = FsWatchInstances.get(fullPath);
|
|
14821
15368
|
let watcher;
|
|
14822
15369
|
if (!options.persistent) {
|
|
14823
|
-
watcher = createFsWatchInstance(
|
|
15370
|
+
watcher = createFsWatchInstance(path31, options, listener, errHandler, rawEmitter);
|
|
14824
15371
|
if (!watcher)
|
|
14825
15372
|
return;
|
|
14826
15373
|
return watcher.close.bind(watcher);
|
|
@@ -14831,7 +15378,7 @@ var setFsWatchListener = (path29, fullPath, options, handlers) => {
|
|
|
14831
15378
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
14832
15379
|
} else {
|
|
14833
15380
|
watcher = createFsWatchInstance(
|
|
14834
|
-
|
|
15381
|
+
path31,
|
|
14835
15382
|
options,
|
|
14836
15383
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
14837
15384
|
errHandler,
|
|
@@ -14846,7 +15393,7 @@ var setFsWatchListener = (path29, fullPath, options, handlers) => {
|
|
|
14846
15393
|
cont.watcherUnusable = true;
|
|
14847
15394
|
if (isWindows && error.code === "EPERM") {
|
|
14848
15395
|
try {
|
|
14849
|
-
const fd = await open(
|
|
15396
|
+
const fd = await open(path31, "r");
|
|
14850
15397
|
await fd.close();
|
|
14851
15398
|
broadcastErr(error);
|
|
14852
15399
|
} catch (err) {
|
|
@@ -14877,7 +15424,7 @@ var setFsWatchListener = (path29, fullPath, options, handlers) => {
|
|
|
14877
15424
|
};
|
|
14878
15425
|
};
|
|
14879
15426
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
14880
|
-
var setFsWatchFileListener = (
|
|
15427
|
+
var setFsWatchFileListener = (path31, fullPath, options, handlers) => {
|
|
14881
15428
|
const { listener, rawEmitter } = handlers;
|
|
14882
15429
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
14883
15430
|
const copts = cont && cont.options;
|
|
@@ -14899,7 +15446,7 @@ var setFsWatchFileListener = (path29, fullPath, options, handlers) => {
|
|
|
14899
15446
|
});
|
|
14900
15447
|
const currmtime = curr.mtimeMs;
|
|
14901
15448
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
14902
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
15449
|
+
foreach(cont.listeners, (listener2) => listener2(path31, curr));
|
|
14903
15450
|
}
|
|
14904
15451
|
})
|
|
14905
15452
|
};
|
|
@@ -14927,13 +15474,13 @@ var NodeFsHandler = class {
|
|
|
14927
15474
|
* @param listener on fs change
|
|
14928
15475
|
* @returns closer for the watcher instance
|
|
14929
15476
|
*/
|
|
14930
|
-
_watchWithNodeFs(
|
|
15477
|
+
_watchWithNodeFs(path31, listener) {
|
|
14931
15478
|
const opts = this.fsw.options;
|
|
14932
|
-
const directory = sysPath.dirname(
|
|
14933
|
-
const basename3 = sysPath.basename(
|
|
15479
|
+
const directory = sysPath.dirname(path31);
|
|
15480
|
+
const basename3 = sysPath.basename(path31);
|
|
14934
15481
|
const parent = this.fsw._getWatchedDir(directory);
|
|
14935
15482
|
parent.add(basename3);
|
|
14936
|
-
const absolutePath = sysPath.resolve(
|
|
15483
|
+
const absolutePath = sysPath.resolve(path31);
|
|
14937
15484
|
const options = {
|
|
14938
15485
|
persistent: opts.persistent
|
|
14939
15486
|
};
|
|
@@ -14943,12 +15490,12 @@ var NodeFsHandler = class {
|
|
|
14943
15490
|
if (opts.usePolling) {
|
|
14944
15491
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
14945
15492
|
options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
|
|
14946
|
-
closer = setFsWatchFileListener(
|
|
15493
|
+
closer = setFsWatchFileListener(path31, absolutePath, options, {
|
|
14947
15494
|
listener,
|
|
14948
15495
|
rawEmitter: this.fsw._emitRaw
|
|
14949
15496
|
});
|
|
14950
15497
|
} else {
|
|
14951
|
-
closer = setFsWatchListener(
|
|
15498
|
+
closer = setFsWatchListener(path31, absolutePath, options, {
|
|
14952
15499
|
listener,
|
|
14953
15500
|
errHandler: this._boundHandleError,
|
|
14954
15501
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -14970,7 +15517,7 @@ var NodeFsHandler = class {
|
|
|
14970
15517
|
let prevStats = stats;
|
|
14971
15518
|
if (parent.has(basename3))
|
|
14972
15519
|
return;
|
|
14973
|
-
const listener = async (
|
|
15520
|
+
const listener = async (path31, newStats) => {
|
|
14974
15521
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
14975
15522
|
return;
|
|
14976
15523
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -14984,11 +15531,11 @@ var NodeFsHandler = class {
|
|
|
14984
15531
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
14985
15532
|
}
|
|
14986
15533
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
14987
|
-
this.fsw._closeFile(
|
|
15534
|
+
this.fsw._closeFile(path31);
|
|
14988
15535
|
prevStats = newStats2;
|
|
14989
15536
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
14990
15537
|
if (closer2)
|
|
14991
|
-
this.fsw._addPathCloser(
|
|
15538
|
+
this.fsw._addPathCloser(path31, closer2);
|
|
14992
15539
|
} else {
|
|
14993
15540
|
prevStats = newStats2;
|
|
14994
15541
|
}
|
|
@@ -15020,7 +15567,7 @@ var NodeFsHandler = class {
|
|
|
15020
15567
|
* @param item basename of this item
|
|
15021
15568
|
* @returns true if no more processing is needed for this entry.
|
|
15022
15569
|
*/
|
|
15023
|
-
async _handleSymlink(entry, directory,
|
|
15570
|
+
async _handleSymlink(entry, directory, path31, item) {
|
|
15024
15571
|
if (this.fsw.closed) {
|
|
15025
15572
|
return;
|
|
15026
15573
|
}
|
|
@@ -15030,7 +15577,7 @@ var NodeFsHandler = class {
|
|
|
15030
15577
|
this.fsw._incrReadyCount();
|
|
15031
15578
|
let linkPath;
|
|
15032
15579
|
try {
|
|
15033
|
-
linkPath = await fsrealpath(
|
|
15580
|
+
linkPath = await fsrealpath(path31);
|
|
15034
15581
|
} catch (e) {
|
|
15035
15582
|
this.fsw._emitReady();
|
|
15036
15583
|
return true;
|
|
@@ -15040,12 +15587,12 @@ var NodeFsHandler = class {
|
|
|
15040
15587
|
if (dir.has(item)) {
|
|
15041
15588
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
15042
15589
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
15043
|
-
this.fsw._emit(EV.CHANGE,
|
|
15590
|
+
this.fsw._emit(EV.CHANGE, path31, entry.stats);
|
|
15044
15591
|
}
|
|
15045
15592
|
} else {
|
|
15046
15593
|
dir.add(item);
|
|
15047
15594
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
15048
|
-
this.fsw._emit(EV.ADD,
|
|
15595
|
+
this.fsw._emit(EV.ADD, path31, entry.stats);
|
|
15049
15596
|
}
|
|
15050
15597
|
this.fsw._emitReady();
|
|
15051
15598
|
return true;
|
|
@@ -15074,9 +15621,9 @@ var NodeFsHandler = class {
|
|
|
15074
15621
|
return;
|
|
15075
15622
|
}
|
|
15076
15623
|
const item = entry.path;
|
|
15077
|
-
let
|
|
15624
|
+
let path31 = sysPath.join(directory, item);
|
|
15078
15625
|
current.add(item);
|
|
15079
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
15626
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path31, item)) {
|
|
15080
15627
|
return;
|
|
15081
15628
|
}
|
|
15082
15629
|
if (this.fsw.closed) {
|
|
@@ -15085,8 +15632,8 @@ var NodeFsHandler = class {
|
|
|
15085
15632
|
}
|
|
15086
15633
|
if (item === target || !target && !previous.has(item)) {
|
|
15087
15634
|
this.fsw._incrReadyCount();
|
|
15088
|
-
|
|
15089
|
-
this._addToNodeFs(
|
|
15635
|
+
path31 = sysPath.join(dir, sysPath.relative(dir, path31));
|
|
15636
|
+
this._addToNodeFs(path31, initialAdd, wh, depth + 1);
|
|
15090
15637
|
}
|
|
15091
15638
|
}).on(EV.ERROR, this._boundHandleError);
|
|
15092
15639
|
return new Promise((resolve3, reject) => {
|
|
@@ -15155,13 +15702,13 @@ var NodeFsHandler = class {
|
|
|
15155
15702
|
* @param depth Child path actually targeted for watch
|
|
15156
15703
|
* @param target Child path actually targeted for watch
|
|
15157
15704
|
*/
|
|
15158
|
-
async _addToNodeFs(
|
|
15705
|
+
async _addToNodeFs(path31, initialAdd, priorWh, depth, target) {
|
|
15159
15706
|
const ready = this.fsw._emitReady;
|
|
15160
|
-
if (this.fsw._isIgnored(
|
|
15707
|
+
if (this.fsw._isIgnored(path31) || this.fsw.closed) {
|
|
15161
15708
|
ready();
|
|
15162
15709
|
return false;
|
|
15163
15710
|
}
|
|
15164
|
-
const wh = this.fsw._getWatchHelpers(
|
|
15711
|
+
const wh = this.fsw._getWatchHelpers(path31);
|
|
15165
15712
|
if (priorWh) {
|
|
15166
15713
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
15167
15714
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -15177,8 +15724,8 @@ var NodeFsHandler = class {
|
|
|
15177
15724
|
const follow = this.fsw.options.followSymlinks;
|
|
15178
15725
|
let closer;
|
|
15179
15726
|
if (stats.isDirectory()) {
|
|
15180
|
-
const absPath = sysPath.resolve(
|
|
15181
|
-
const targetPath = follow ? await fsrealpath(
|
|
15727
|
+
const absPath = sysPath.resolve(path31);
|
|
15728
|
+
const targetPath = follow ? await fsrealpath(path31) : path31;
|
|
15182
15729
|
if (this.fsw.closed)
|
|
15183
15730
|
return;
|
|
15184
15731
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -15188,29 +15735,29 @@ var NodeFsHandler = class {
|
|
|
15188
15735
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
15189
15736
|
}
|
|
15190
15737
|
} else if (stats.isSymbolicLink()) {
|
|
15191
|
-
const targetPath = follow ? await fsrealpath(
|
|
15738
|
+
const targetPath = follow ? await fsrealpath(path31) : path31;
|
|
15192
15739
|
if (this.fsw.closed)
|
|
15193
15740
|
return;
|
|
15194
15741
|
const parent = sysPath.dirname(wh.watchPath);
|
|
15195
15742
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
15196
15743
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
15197
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
15744
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path31, wh, targetPath);
|
|
15198
15745
|
if (this.fsw.closed)
|
|
15199
15746
|
return;
|
|
15200
15747
|
if (targetPath !== void 0) {
|
|
15201
|
-
this.fsw._symlinkPaths.set(sysPath.resolve(
|
|
15748
|
+
this.fsw._symlinkPaths.set(sysPath.resolve(path31), targetPath);
|
|
15202
15749
|
}
|
|
15203
15750
|
} else {
|
|
15204
15751
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
15205
15752
|
}
|
|
15206
15753
|
ready();
|
|
15207
15754
|
if (closer)
|
|
15208
|
-
this.fsw._addPathCloser(
|
|
15755
|
+
this.fsw._addPathCloser(path31, closer);
|
|
15209
15756
|
return false;
|
|
15210
15757
|
} catch (error) {
|
|
15211
15758
|
if (this.fsw._handleError(error)) {
|
|
15212
15759
|
ready();
|
|
15213
|
-
return
|
|
15760
|
+
return path31;
|
|
15214
15761
|
}
|
|
15215
15762
|
}
|
|
15216
15763
|
}
|
|
@@ -15253,26 +15800,26 @@ function createPattern(matcher) {
|
|
|
15253
15800
|
}
|
|
15254
15801
|
return () => false;
|
|
15255
15802
|
}
|
|
15256
|
-
function normalizePath(
|
|
15257
|
-
if (typeof
|
|
15803
|
+
function normalizePath(path31) {
|
|
15804
|
+
if (typeof path31 !== "string")
|
|
15258
15805
|
throw new Error("string expected");
|
|
15259
|
-
|
|
15260
|
-
|
|
15806
|
+
path31 = sysPath2.normalize(path31);
|
|
15807
|
+
path31 = path31.replace(/\\/g, "/");
|
|
15261
15808
|
let prepend = false;
|
|
15262
|
-
if (
|
|
15809
|
+
if (path31.startsWith("//"))
|
|
15263
15810
|
prepend = true;
|
|
15264
15811
|
const DOUBLE_SLASH_RE2 = /\/\//;
|
|
15265
|
-
while (
|
|
15266
|
-
|
|
15812
|
+
while (path31.match(DOUBLE_SLASH_RE2))
|
|
15813
|
+
path31 = path31.replace(DOUBLE_SLASH_RE2, "/");
|
|
15267
15814
|
if (prepend)
|
|
15268
|
-
|
|
15269
|
-
return
|
|
15815
|
+
path31 = "/" + path31;
|
|
15816
|
+
return path31;
|
|
15270
15817
|
}
|
|
15271
15818
|
function matchPatterns(patterns, testString, stats) {
|
|
15272
|
-
const
|
|
15819
|
+
const path31 = normalizePath(testString);
|
|
15273
15820
|
for (let index = 0; index < patterns.length; index++) {
|
|
15274
15821
|
const pattern = patterns[index];
|
|
15275
|
-
if (pattern(
|
|
15822
|
+
if (pattern(path31, stats)) {
|
|
15276
15823
|
return true;
|
|
15277
15824
|
}
|
|
15278
15825
|
}
|
|
@@ -15312,19 +15859,19 @@ var toUnix = (string) => {
|
|
|
15312
15859
|
}
|
|
15313
15860
|
return str;
|
|
15314
15861
|
};
|
|
15315
|
-
var normalizePathToUnix = (
|
|
15316
|
-
var normalizeIgnored = (cwd = "") => (
|
|
15317
|
-
if (typeof
|
|
15318
|
-
return normalizePathToUnix(sysPath2.isAbsolute(
|
|
15862
|
+
var normalizePathToUnix = (path31) => toUnix(sysPath2.normalize(toUnix(path31)));
|
|
15863
|
+
var normalizeIgnored = (cwd = "") => (path31) => {
|
|
15864
|
+
if (typeof path31 === "string") {
|
|
15865
|
+
return normalizePathToUnix(sysPath2.isAbsolute(path31) ? path31 : sysPath2.join(cwd, path31));
|
|
15319
15866
|
} else {
|
|
15320
|
-
return
|
|
15867
|
+
return path31;
|
|
15321
15868
|
}
|
|
15322
15869
|
};
|
|
15323
|
-
var getAbsolutePath = (
|
|
15324
|
-
if (sysPath2.isAbsolute(
|
|
15325
|
-
return
|
|
15870
|
+
var getAbsolutePath = (path31, cwd) => {
|
|
15871
|
+
if (sysPath2.isAbsolute(path31)) {
|
|
15872
|
+
return path31;
|
|
15326
15873
|
}
|
|
15327
|
-
return sysPath2.join(cwd,
|
|
15874
|
+
return sysPath2.join(cwd, path31);
|
|
15328
15875
|
};
|
|
15329
15876
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
15330
15877
|
var DirEntry = class {
|
|
@@ -15379,10 +15926,10 @@ var DirEntry = class {
|
|
|
15379
15926
|
var STAT_METHOD_F = "stat";
|
|
15380
15927
|
var STAT_METHOD_L = "lstat";
|
|
15381
15928
|
var WatchHelper = class {
|
|
15382
|
-
constructor(
|
|
15929
|
+
constructor(path31, follow, fsw) {
|
|
15383
15930
|
this.fsw = fsw;
|
|
15384
|
-
const watchPath =
|
|
15385
|
-
this.path =
|
|
15931
|
+
const watchPath = path31;
|
|
15932
|
+
this.path = path31 = path31.replace(REPLACER_RE, "");
|
|
15386
15933
|
this.watchPath = watchPath;
|
|
15387
15934
|
this.fullWatchPath = sysPath2.resolve(watchPath);
|
|
15388
15935
|
this.dirParts = [];
|
|
@@ -15504,20 +16051,20 @@ var FSWatcher = class extends EventEmitter {
|
|
|
15504
16051
|
this._closePromise = void 0;
|
|
15505
16052
|
let paths = unifyPaths(paths_);
|
|
15506
16053
|
if (cwd) {
|
|
15507
|
-
paths = paths.map((
|
|
15508
|
-
const absPath = getAbsolutePath(
|
|
16054
|
+
paths = paths.map((path31) => {
|
|
16055
|
+
const absPath = getAbsolutePath(path31, cwd);
|
|
15509
16056
|
return absPath;
|
|
15510
16057
|
});
|
|
15511
16058
|
}
|
|
15512
|
-
paths.forEach((
|
|
15513
|
-
this._removeIgnoredPath(
|
|
16059
|
+
paths.forEach((path31) => {
|
|
16060
|
+
this._removeIgnoredPath(path31);
|
|
15514
16061
|
});
|
|
15515
16062
|
this._userIgnored = void 0;
|
|
15516
16063
|
if (!this._readyCount)
|
|
15517
16064
|
this._readyCount = 0;
|
|
15518
16065
|
this._readyCount += paths.length;
|
|
15519
|
-
Promise.all(paths.map(async (
|
|
15520
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
16066
|
+
Promise.all(paths.map(async (path31) => {
|
|
16067
|
+
const res = await this._nodeFsHandler._addToNodeFs(path31, !_internal, void 0, 0, _origAdd);
|
|
15521
16068
|
if (res)
|
|
15522
16069
|
this._emitReady();
|
|
15523
16070
|
return res;
|
|
@@ -15539,17 +16086,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
15539
16086
|
return this;
|
|
15540
16087
|
const paths = unifyPaths(paths_);
|
|
15541
16088
|
const { cwd } = this.options;
|
|
15542
|
-
paths.forEach((
|
|
15543
|
-
if (!sysPath2.isAbsolute(
|
|
16089
|
+
paths.forEach((path31) => {
|
|
16090
|
+
if (!sysPath2.isAbsolute(path31) && !this._closers.has(path31)) {
|
|
15544
16091
|
if (cwd)
|
|
15545
|
-
|
|
15546
|
-
|
|
16092
|
+
path31 = sysPath2.join(cwd, path31);
|
|
16093
|
+
path31 = sysPath2.resolve(path31);
|
|
15547
16094
|
}
|
|
15548
|
-
this._closePath(
|
|
15549
|
-
this._addIgnoredPath(
|
|
15550
|
-
if (this._watched.has(
|
|
16095
|
+
this._closePath(path31);
|
|
16096
|
+
this._addIgnoredPath(path31);
|
|
16097
|
+
if (this._watched.has(path31)) {
|
|
15551
16098
|
this._addIgnoredPath({
|
|
15552
|
-
path:
|
|
16099
|
+
path: path31,
|
|
15553
16100
|
recursive: true
|
|
15554
16101
|
});
|
|
15555
16102
|
}
|
|
@@ -15613,38 +16160,38 @@ var FSWatcher = class extends EventEmitter {
|
|
|
15613
16160
|
* @param stats arguments to be passed with event
|
|
15614
16161
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
15615
16162
|
*/
|
|
15616
|
-
async _emit(event,
|
|
16163
|
+
async _emit(event, path31, stats) {
|
|
15617
16164
|
if (this.closed)
|
|
15618
16165
|
return;
|
|
15619
16166
|
const opts = this.options;
|
|
15620
16167
|
if (isWindows)
|
|
15621
|
-
|
|
16168
|
+
path31 = sysPath2.normalize(path31);
|
|
15622
16169
|
if (opts.cwd)
|
|
15623
|
-
|
|
15624
|
-
const args = [
|
|
16170
|
+
path31 = sysPath2.relative(opts.cwd, path31);
|
|
16171
|
+
const args = [path31];
|
|
15625
16172
|
if (stats != null)
|
|
15626
16173
|
args.push(stats);
|
|
15627
16174
|
const awf = opts.awaitWriteFinish;
|
|
15628
16175
|
let pw;
|
|
15629
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
16176
|
+
if (awf && (pw = this._pendingWrites.get(path31))) {
|
|
15630
16177
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
15631
16178
|
return this;
|
|
15632
16179
|
}
|
|
15633
16180
|
if (opts.atomic) {
|
|
15634
16181
|
if (event === EVENTS.UNLINK) {
|
|
15635
|
-
this._pendingUnlinks.set(
|
|
16182
|
+
this._pendingUnlinks.set(path31, [event, ...args]);
|
|
15636
16183
|
setTimeout(() => {
|
|
15637
|
-
this._pendingUnlinks.forEach((entry,
|
|
16184
|
+
this._pendingUnlinks.forEach((entry, path32) => {
|
|
15638
16185
|
this.emit(...entry);
|
|
15639
16186
|
this.emit(EVENTS.ALL, ...entry);
|
|
15640
|
-
this._pendingUnlinks.delete(
|
|
16187
|
+
this._pendingUnlinks.delete(path32);
|
|
15641
16188
|
});
|
|
15642
16189
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
15643
16190
|
return this;
|
|
15644
16191
|
}
|
|
15645
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
16192
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path31)) {
|
|
15646
16193
|
event = EVENTS.CHANGE;
|
|
15647
|
-
this._pendingUnlinks.delete(
|
|
16194
|
+
this._pendingUnlinks.delete(path31);
|
|
15648
16195
|
}
|
|
15649
16196
|
}
|
|
15650
16197
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -15662,16 +16209,16 @@ var FSWatcher = class extends EventEmitter {
|
|
|
15662
16209
|
this.emitWithAll(event, args);
|
|
15663
16210
|
}
|
|
15664
16211
|
};
|
|
15665
|
-
this._awaitWriteFinish(
|
|
16212
|
+
this._awaitWriteFinish(path31, awf.stabilityThreshold, event, awfEmit);
|
|
15666
16213
|
return this;
|
|
15667
16214
|
}
|
|
15668
16215
|
if (event === EVENTS.CHANGE) {
|
|
15669
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
16216
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path31, 50);
|
|
15670
16217
|
if (isThrottled)
|
|
15671
16218
|
return this;
|
|
15672
16219
|
}
|
|
15673
16220
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
15674
|
-
const fullPath = opts.cwd ? sysPath2.join(opts.cwd,
|
|
16221
|
+
const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path31) : path31;
|
|
15675
16222
|
let stats2;
|
|
15676
16223
|
try {
|
|
15677
16224
|
stats2 = await stat3(fullPath);
|
|
@@ -15702,23 +16249,23 @@ var FSWatcher = class extends EventEmitter {
|
|
|
15702
16249
|
* @param timeout duration of time to suppress duplicate actions
|
|
15703
16250
|
* @returns tracking object or false if action should be suppressed
|
|
15704
16251
|
*/
|
|
15705
|
-
_throttle(actionType,
|
|
16252
|
+
_throttle(actionType, path31, timeout) {
|
|
15706
16253
|
if (!this._throttled.has(actionType)) {
|
|
15707
16254
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
15708
16255
|
}
|
|
15709
16256
|
const action = this._throttled.get(actionType);
|
|
15710
16257
|
if (!action)
|
|
15711
16258
|
throw new Error("invalid throttle");
|
|
15712
|
-
const actionPath = action.get(
|
|
16259
|
+
const actionPath = action.get(path31);
|
|
15713
16260
|
if (actionPath) {
|
|
15714
16261
|
actionPath.count++;
|
|
15715
16262
|
return false;
|
|
15716
16263
|
}
|
|
15717
16264
|
let timeoutObject;
|
|
15718
16265
|
const clear = () => {
|
|
15719
|
-
const item = action.get(
|
|
16266
|
+
const item = action.get(path31);
|
|
15720
16267
|
const count = item ? item.count : 0;
|
|
15721
|
-
action.delete(
|
|
16268
|
+
action.delete(path31);
|
|
15722
16269
|
clearTimeout(timeoutObject);
|
|
15723
16270
|
if (item)
|
|
15724
16271
|
clearTimeout(item.timeoutObject);
|
|
@@ -15726,7 +16273,7 @@ var FSWatcher = class extends EventEmitter {
|
|
|
15726
16273
|
};
|
|
15727
16274
|
timeoutObject = setTimeout(clear, timeout);
|
|
15728
16275
|
const thr = { timeoutObject, clear, count: 0 };
|
|
15729
|
-
action.set(
|
|
16276
|
+
action.set(path31, thr);
|
|
15730
16277
|
return thr;
|
|
15731
16278
|
}
|
|
15732
16279
|
_incrReadyCount() {
|
|
@@ -15740,44 +16287,44 @@ var FSWatcher = class extends EventEmitter {
|
|
|
15740
16287
|
* @param event
|
|
15741
16288
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
15742
16289
|
*/
|
|
15743
|
-
_awaitWriteFinish(
|
|
16290
|
+
_awaitWriteFinish(path31, threshold, event, awfEmit) {
|
|
15744
16291
|
const awf = this.options.awaitWriteFinish;
|
|
15745
16292
|
if (typeof awf !== "object")
|
|
15746
16293
|
return;
|
|
15747
16294
|
const pollInterval = awf.pollInterval;
|
|
15748
16295
|
let timeoutHandler;
|
|
15749
|
-
let fullPath =
|
|
15750
|
-
if (this.options.cwd && !sysPath2.isAbsolute(
|
|
15751
|
-
fullPath = sysPath2.join(this.options.cwd,
|
|
16296
|
+
let fullPath = path31;
|
|
16297
|
+
if (this.options.cwd && !sysPath2.isAbsolute(path31)) {
|
|
16298
|
+
fullPath = sysPath2.join(this.options.cwd, path31);
|
|
15752
16299
|
}
|
|
15753
16300
|
const now = /* @__PURE__ */ new Date();
|
|
15754
16301
|
const writes = this._pendingWrites;
|
|
15755
16302
|
function awaitWriteFinishFn(prevStat) {
|
|
15756
16303
|
statcb(fullPath, (err, curStat) => {
|
|
15757
|
-
if (err || !writes.has(
|
|
16304
|
+
if (err || !writes.has(path31)) {
|
|
15758
16305
|
if (err && err.code !== "ENOENT")
|
|
15759
16306
|
awfEmit(err);
|
|
15760
16307
|
return;
|
|
15761
16308
|
}
|
|
15762
16309
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
15763
16310
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
15764
|
-
writes.get(
|
|
16311
|
+
writes.get(path31).lastChange = now2;
|
|
15765
16312
|
}
|
|
15766
|
-
const pw = writes.get(
|
|
16313
|
+
const pw = writes.get(path31);
|
|
15767
16314
|
const df = now2 - pw.lastChange;
|
|
15768
16315
|
if (df >= threshold) {
|
|
15769
|
-
writes.delete(
|
|
16316
|
+
writes.delete(path31);
|
|
15770
16317
|
awfEmit(void 0, curStat);
|
|
15771
16318
|
} else {
|
|
15772
16319
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
15773
16320
|
}
|
|
15774
16321
|
});
|
|
15775
16322
|
}
|
|
15776
|
-
if (!writes.has(
|
|
15777
|
-
writes.set(
|
|
16323
|
+
if (!writes.has(path31)) {
|
|
16324
|
+
writes.set(path31, {
|
|
15778
16325
|
lastChange: now,
|
|
15779
16326
|
cancelWait: () => {
|
|
15780
|
-
writes.delete(
|
|
16327
|
+
writes.delete(path31);
|
|
15781
16328
|
clearTimeout(timeoutHandler);
|
|
15782
16329
|
return event;
|
|
15783
16330
|
}
|
|
@@ -15788,8 +16335,8 @@ var FSWatcher = class extends EventEmitter {
|
|
|
15788
16335
|
/**
|
|
15789
16336
|
* Determines whether user has asked to ignore this path.
|
|
15790
16337
|
*/
|
|
15791
|
-
_isIgnored(
|
|
15792
|
-
if (this.options.atomic && DOT_RE.test(
|
|
16338
|
+
_isIgnored(path31, stats) {
|
|
16339
|
+
if (this.options.atomic && DOT_RE.test(path31))
|
|
15793
16340
|
return true;
|
|
15794
16341
|
if (!this._userIgnored) {
|
|
15795
16342
|
const { cwd } = this.options;
|
|
@@ -15799,17 +16346,17 @@ var FSWatcher = class extends EventEmitter {
|
|
|
15799
16346
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
15800
16347
|
this._userIgnored = anymatch(list, void 0);
|
|
15801
16348
|
}
|
|
15802
|
-
return this._userIgnored(
|
|
16349
|
+
return this._userIgnored(path31, stats);
|
|
15803
16350
|
}
|
|
15804
|
-
_isntIgnored(
|
|
15805
|
-
return !this._isIgnored(
|
|
16351
|
+
_isntIgnored(path31, stat4) {
|
|
16352
|
+
return !this._isIgnored(path31, stat4);
|
|
15806
16353
|
}
|
|
15807
16354
|
/**
|
|
15808
16355
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
15809
16356
|
* @param path file or directory pattern being watched
|
|
15810
16357
|
*/
|
|
15811
|
-
_getWatchHelpers(
|
|
15812
|
-
return new WatchHelper(
|
|
16358
|
+
_getWatchHelpers(path31) {
|
|
16359
|
+
return new WatchHelper(path31, this.options.followSymlinks, this);
|
|
15813
16360
|
}
|
|
15814
16361
|
// Directory helpers
|
|
15815
16362
|
// -----------------
|
|
@@ -15841,63 +16388,63 @@ var FSWatcher = class extends EventEmitter {
|
|
|
15841
16388
|
* @param item base path of item/directory
|
|
15842
16389
|
*/
|
|
15843
16390
|
_remove(directory, item, isDirectory) {
|
|
15844
|
-
const
|
|
15845
|
-
const fullPath = sysPath2.resolve(
|
|
15846
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
15847
|
-
if (!this._throttle("remove",
|
|
16391
|
+
const path31 = sysPath2.join(directory, item);
|
|
16392
|
+
const fullPath = sysPath2.resolve(path31);
|
|
16393
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path31) || this._watched.has(fullPath);
|
|
16394
|
+
if (!this._throttle("remove", path31, 100))
|
|
15848
16395
|
return;
|
|
15849
16396
|
if (!isDirectory && this._watched.size === 1) {
|
|
15850
16397
|
this.add(directory, item, true);
|
|
15851
16398
|
}
|
|
15852
|
-
const wp = this._getWatchedDir(
|
|
16399
|
+
const wp = this._getWatchedDir(path31);
|
|
15853
16400
|
const nestedDirectoryChildren = wp.getChildren();
|
|
15854
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
16401
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path31, nested));
|
|
15855
16402
|
const parent = this._getWatchedDir(directory);
|
|
15856
16403
|
const wasTracked = parent.has(item);
|
|
15857
16404
|
parent.remove(item);
|
|
15858
16405
|
if (this._symlinkPaths.has(fullPath)) {
|
|
15859
16406
|
this._symlinkPaths.delete(fullPath);
|
|
15860
16407
|
}
|
|
15861
|
-
let relPath =
|
|
16408
|
+
let relPath = path31;
|
|
15862
16409
|
if (this.options.cwd)
|
|
15863
|
-
relPath = sysPath2.relative(this.options.cwd,
|
|
16410
|
+
relPath = sysPath2.relative(this.options.cwd, path31);
|
|
15864
16411
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
15865
16412
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
15866
16413
|
if (event === EVENTS.ADD)
|
|
15867
16414
|
return;
|
|
15868
16415
|
}
|
|
15869
|
-
this._watched.delete(
|
|
16416
|
+
this._watched.delete(path31);
|
|
15870
16417
|
this._watched.delete(fullPath);
|
|
15871
16418
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
15872
|
-
if (wasTracked && !this._isIgnored(
|
|
15873
|
-
this._emit(eventName,
|
|
15874
|
-
this._closePath(
|
|
16419
|
+
if (wasTracked && !this._isIgnored(path31))
|
|
16420
|
+
this._emit(eventName, path31);
|
|
16421
|
+
this._closePath(path31);
|
|
15875
16422
|
}
|
|
15876
16423
|
/**
|
|
15877
16424
|
* Closes all watchers for a path
|
|
15878
16425
|
*/
|
|
15879
|
-
_closePath(
|
|
15880
|
-
this._closeFile(
|
|
15881
|
-
const dir = sysPath2.dirname(
|
|
15882
|
-
this._getWatchedDir(dir).remove(sysPath2.basename(
|
|
16426
|
+
_closePath(path31) {
|
|
16427
|
+
this._closeFile(path31);
|
|
16428
|
+
const dir = sysPath2.dirname(path31);
|
|
16429
|
+
this._getWatchedDir(dir).remove(sysPath2.basename(path31));
|
|
15883
16430
|
}
|
|
15884
16431
|
/**
|
|
15885
16432
|
* Closes only file-specific watchers
|
|
15886
16433
|
*/
|
|
15887
|
-
_closeFile(
|
|
15888
|
-
const closers = this._closers.get(
|
|
16434
|
+
_closeFile(path31) {
|
|
16435
|
+
const closers = this._closers.get(path31);
|
|
15889
16436
|
if (!closers)
|
|
15890
16437
|
return;
|
|
15891
16438
|
closers.forEach((closer) => closer());
|
|
15892
|
-
this._closers.delete(
|
|
16439
|
+
this._closers.delete(path31);
|
|
15893
16440
|
}
|
|
15894
|
-
_addPathCloser(
|
|
16441
|
+
_addPathCloser(path31, closer) {
|
|
15895
16442
|
if (!closer)
|
|
15896
16443
|
return;
|
|
15897
|
-
let list = this._closers.get(
|
|
16444
|
+
let list = this._closers.get(path31);
|
|
15898
16445
|
if (!list) {
|
|
15899
16446
|
list = [];
|
|
15900
|
-
this._closers.set(
|
|
16447
|
+
this._closers.set(path31, list);
|
|
15901
16448
|
}
|
|
15902
16449
|
list.push(closer);
|
|
15903
16450
|
}
|
|
@@ -15928,7 +16475,7 @@ var esm_default = { watch, FSWatcher };
|
|
|
15928
16475
|
|
|
15929
16476
|
// modules/dev/hot-reload-client/index.ts
|
|
15930
16477
|
init_globals();
|
|
15931
|
-
import
|
|
16478
|
+
import path25 from "path";
|
|
15932
16479
|
function setupHotReload({
|
|
15933
16480
|
app,
|
|
15934
16481
|
appDir,
|
|
@@ -15969,7 +16516,7 @@ function setupHotReload({
|
|
|
15969
16516
|
});
|
|
15970
16517
|
});
|
|
15971
16518
|
console.log(`[hot-reload-server] \u2705 SSE endpoint registered at ${route}`);
|
|
15972
|
-
const resolvedProjectRoot = projectRoot ?
|
|
16519
|
+
const resolvedProjectRoot = projectRoot ? path25.resolve(projectRoot) : path25.dirname(path25.resolve(appDir));
|
|
15973
16520
|
const watcher = esm_default.watch(resolvedProjectRoot, {
|
|
15974
16521
|
ignoreInitial: true,
|
|
15975
16522
|
ignored: [
|
|
@@ -16009,11 +16556,11 @@ function setupHotReload({
|
|
|
16009
16556
|
let broadcastTimeout = null;
|
|
16010
16557
|
const BROADCAST_DEBOUNCE_MS = 300;
|
|
16011
16558
|
async function broadcastReload(reason, filePath) {
|
|
16012
|
-
const normalizedPath =
|
|
16559
|
+
const normalizedPath = path25.normalize(filePath);
|
|
16013
16560
|
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-")) {
|
|
16014
16561
|
return;
|
|
16015
16562
|
}
|
|
16016
|
-
const rel =
|
|
16563
|
+
const rel = path25.relative(appDir, filePath);
|
|
16017
16564
|
console.log(`[hot-reload] ${reason}: ${rel}`);
|
|
16018
16565
|
if (broadcastTimeout) {
|
|
16019
16566
|
clearTimeout(broadcastTimeout);
|
|
@@ -16063,9 +16610,9 @@ data: reload:${rel}
|
|
|
16063
16610
|
}
|
|
16064
16611
|
|
|
16065
16612
|
// modules/dev/hot-reload-server/index.ts
|
|
16066
|
-
import
|
|
16613
|
+
import path26 from "path";
|
|
16067
16614
|
function clearAppRequireCache(appDir) {
|
|
16068
|
-
const appDirNormalized =
|
|
16615
|
+
const appDirNormalized = path26.resolve(appDir);
|
|
16069
16616
|
for (const id of Object.keys(__require.cache)) {
|
|
16070
16617
|
if (id.startsWith(appDirNormalized)) {
|
|
16071
16618
|
delete __require.cache[id];
|
|
@@ -16078,7 +16625,7 @@ init_globals();
|
|
|
16078
16625
|
function setupStaticFiles(app, projectRoot, config) {
|
|
16079
16626
|
if (!config) return;
|
|
16080
16627
|
const staticDir = getStaticDir(projectRoot, config);
|
|
16081
|
-
if (
|
|
16628
|
+
if (fs20.existsSync(staticDir)) {
|
|
16082
16629
|
app.use(
|
|
16083
16630
|
express.static(staticDir, {
|
|
16084
16631
|
// In production, add caching headers for better performance
|
|
@@ -16104,7 +16651,7 @@ function setupServer(app, options) {
|
|
|
16104
16651
|
var getRoutes = getRoutes2;
|
|
16105
16652
|
const { outDir, waitForBuild } = startClientBundler(projectRoot, "development");
|
|
16106
16653
|
const onFileChange = async (filePath) => {
|
|
16107
|
-
const rel =
|
|
16654
|
+
const rel = path27.relative(appDir, filePath);
|
|
16108
16655
|
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");
|
|
16109
16656
|
const isTsFile = filePath.endsWith(".ts") || filePath.endsWith(".tsx");
|
|
16110
16657
|
if (isTsFile) {
|
|
@@ -16140,8 +16687,8 @@ function setupServer(app, options) {
|
|
|
16140
16687
|
const wssRoutes = routeLoader.loadWssRoutes();
|
|
16141
16688
|
const notFoundPage = routeLoader.loadNotFoundRoute();
|
|
16142
16689
|
const errorPage = routeLoader.loadErrorRoute();
|
|
16143
|
-
const buildDir = config ? getBuildDir(projectRoot, config) :
|
|
16144
|
-
const clientOutDir =
|
|
16690
|
+
const buildDir = config ? getBuildDir(projectRoot, config) : path27.join(projectRoot, BUILD_FOLDER_NAME);
|
|
16691
|
+
const clientOutDir = path27.join(buildDir, "client");
|
|
16145
16692
|
app.use(
|
|
16146
16693
|
"/static",
|
|
16147
16694
|
express.static(clientOutDir, {
|
|
@@ -16268,11 +16815,11 @@ function createStrictRateLimiterFromConfig(config) {
|
|
|
16268
16815
|
}
|
|
16269
16816
|
|
|
16270
16817
|
// modules/server/middleware/auto-rate-limit.ts
|
|
16271
|
-
function matchesStrictPattern(
|
|
16818
|
+
function matchesStrictPattern(path31, patterns) {
|
|
16272
16819
|
for (const pattern of patterns) {
|
|
16273
16820
|
const regexPattern = pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/\//g, "\\/");
|
|
16274
16821
|
const regex = new RegExp(`^${regexPattern}$`);
|
|
16275
|
-
if (regex.test(
|
|
16822
|
+
if (regex.test(path31)) {
|
|
16276
16823
|
return true;
|
|
16277
16824
|
}
|
|
16278
16825
|
}
|
|
@@ -16307,8 +16854,31 @@ function getAutoRateLimiter(route, strictPatterns = [], rateLimitConfig) {
|
|
|
16307
16854
|
|
|
16308
16855
|
// modules/server/handlers/api.ts
|
|
16309
16856
|
async function handleApiRequest(options) {
|
|
16310
|
-
const { apiRoutes, urlPath, req, res, env = "dev" } = options;
|
|
16311
|
-
|
|
16857
|
+
const { apiRoutes, urlPath, req, res, env = "dev", rewriteLoader } = options;
|
|
16858
|
+
let finalUrlPath = urlPath;
|
|
16859
|
+
let extractedParams = {};
|
|
16860
|
+
if (rewriteLoader) {
|
|
16861
|
+
try {
|
|
16862
|
+
const compiledRewrites = await rewriteLoader.loadRewrites();
|
|
16863
|
+
const rewriteResult = await processRewrites(urlPath, compiledRewrites, req);
|
|
16864
|
+
if (rewriteResult) {
|
|
16865
|
+
finalUrlPath = rewriteResult.rewrittenPath;
|
|
16866
|
+
extractedParams = rewriteResult.extractedParams;
|
|
16867
|
+
Object.assign(req.query, extractedParams);
|
|
16868
|
+
if (!req.locals) {
|
|
16869
|
+
req.locals = {};
|
|
16870
|
+
}
|
|
16871
|
+
Object.assign(req.locals, extractedParams);
|
|
16872
|
+
}
|
|
16873
|
+
} catch (error) {
|
|
16874
|
+
const reqLogger = getRequestLogger(req);
|
|
16875
|
+
reqLogger.error("Error processing rewrites", error, {
|
|
16876
|
+
urlPath
|
|
16877
|
+
});
|
|
16878
|
+
}
|
|
16879
|
+
}
|
|
16880
|
+
finalUrlPath = finalUrlPath.replace(/\/$/, "") || "/";
|
|
16881
|
+
const matched = matchApiRoute(apiRoutes, finalUrlPath);
|
|
16312
16882
|
if (!matched) {
|
|
16313
16883
|
res.status(404).json({ error: "Not Found" });
|
|
16314
16884
|
return;
|
|
@@ -16329,9 +16899,13 @@ async function handleApiRequest(options) {
|
|
|
16329
16899
|
Response: (body = {}, status = 200) => res.status(status).json(body),
|
|
16330
16900
|
NotFound: (body = {}) => res.status(404).json(body),
|
|
16331
16901
|
params: sanitizedParams,
|
|
16332
|
-
pathname:
|
|
16902
|
+
pathname: finalUrlPath,
|
|
16903
|
+
// Use rewritten path
|
|
16333
16904
|
locals: {}
|
|
16334
16905
|
};
|
|
16906
|
+
if (extractedParams && Object.keys(extractedParams).length > 0) {
|
|
16907
|
+
Object.assign(ctx.locals, extractedParams);
|
|
16908
|
+
}
|
|
16335
16909
|
req.query = sanitizedQuery;
|
|
16336
16910
|
try {
|
|
16337
16911
|
const autoRateLimiter = getAutoRateLimiter(
|
|
@@ -16410,7 +16984,19 @@ async function handleApiRequest(options) {
|
|
|
16410
16984
|
|
|
16411
16985
|
// modules/server/routes.ts
|
|
16412
16986
|
init_globals();
|
|
16413
|
-
import
|
|
16987
|
+
import path28 from "path";
|
|
16988
|
+
var cachedRewriteLoader = null;
|
|
16989
|
+
var cachedProjectRoot = null;
|
|
16990
|
+
var cachedIsDev = null;
|
|
16991
|
+
function getRewriteLoader(projectRoot, isDev) {
|
|
16992
|
+
if (cachedRewriteLoader && cachedProjectRoot === projectRoot && cachedIsDev === isDev) {
|
|
16993
|
+
return cachedRewriteLoader;
|
|
16994
|
+
}
|
|
16995
|
+
cachedRewriteLoader = createRewriteLoader(projectRoot, isDev);
|
|
16996
|
+
cachedProjectRoot = projectRoot;
|
|
16997
|
+
cachedIsDev = isDev;
|
|
16998
|
+
return cachedRewriteLoader;
|
|
16999
|
+
}
|
|
16414
17000
|
function setupRoutes(options) {
|
|
16415
17001
|
const {
|
|
16416
17002
|
app,
|
|
@@ -16425,8 +17011,9 @@ function setupRoutes(options) {
|
|
|
16425
17011
|
config
|
|
16426
17012
|
} = options;
|
|
16427
17013
|
const routeChunks = routeLoader.loadRouteChunks();
|
|
16428
|
-
const
|
|
16429
|
-
|
|
17014
|
+
const rewriteLoader = getRewriteLoader(projectRoot, isDev);
|
|
17015
|
+
const ssgOutDir = path28.join(
|
|
17016
|
+
config ? getBuildDir(projectRoot, config) : path28.join(projectRoot, BUILD_FOLDER_NAME),
|
|
16430
17017
|
"ssg"
|
|
16431
17018
|
);
|
|
16432
17019
|
app.all("/api/*", async (req, res) => {
|
|
@@ -16441,7 +17028,8 @@ function setupRoutes(options) {
|
|
|
16441
17028
|
res,
|
|
16442
17029
|
env: isDev ? "dev" : "prod",
|
|
16443
17030
|
strictRateLimitPatterns: strictPatterns,
|
|
16444
|
-
rateLimitConfig
|
|
17031
|
+
rateLimitConfig,
|
|
17032
|
+
rewriteLoader
|
|
16445
17033
|
});
|
|
16446
17034
|
});
|
|
16447
17035
|
app.get("*", async (req, res) => {
|
|
@@ -16464,7 +17052,8 @@ function setupRoutes(options) {
|
|
|
16464
17052
|
ssgOutDir,
|
|
16465
17053
|
theme: req.cookies?.theme || "light",
|
|
16466
17054
|
projectRoot,
|
|
16467
|
-
config
|
|
17055
|
+
config,
|
|
17056
|
+
rewriteLoader
|
|
16468
17057
|
});
|
|
16469
17058
|
});
|
|
16470
17059
|
}
|
|
@@ -17653,8 +18242,8 @@ var setupApplication = async ({
|
|
|
17653
18242
|
|
|
17654
18243
|
// src/server.ts
|
|
17655
18244
|
import dotenv2 from "dotenv";
|
|
17656
|
-
var envPath =
|
|
17657
|
-
if (
|
|
18245
|
+
var envPath = path29.join(process.cwd(), ".env");
|
|
18246
|
+
if (fs21.existsSync(envPath)) {
|
|
17658
18247
|
dotenv2.config({ path: envPath });
|
|
17659
18248
|
} else {
|
|
17660
18249
|
dotenv2.config();
|
|
@@ -17675,8 +18264,8 @@ async function startServer(options = {}) {
|
|
|
17675
18264
|
}
|
|
17676
18265
|
const port = options.port ?? (process.env.PORT ? parseInt(process.env.PORT, 10) : void 0) ?? config.server.port;
|
|
17677
18266
|
const host = process.env.HOST ?? (!isDev ? "0.0.0.0" : void 0) ?? config.server.host;
|
|
17678
|
-
const appDir = options.appDir ?? (isDev ? getAppDir(projectRoot, config) :
|
|
17679
|
-
if (!isDev && !
|
|
18267
|
+
const appDir = options.appDir ?? (isDev ? getAppDir(projectRoot, config) : path29.join(getBuildDir(projectRoot, config), "server"));
|
|
18268
|
+
if (!isDev && !fs21.existsSync(appDir)) {
|
|
17680
18269
|
logger4.error("Compiled directory not found", void 0, {
|
|
17681
18270
|
buildDir: config.directories.build,
|
|
17682
18271
|
appDir,
|
|
@@ -17872,7 +18461,7 @@ async function run() {
|
|
|
17872
18461
|
}
|
|
17873
18462
|
const args = parseArgs(argv.slice(1));
|
|
17874
18463
|
const projectRoot = process2.cwd();
|
|
17875
|
-
const appDir =
|
|
18464
|
+
const appDir = path30.resolve(projectRoot, args.appDir || "app");
|
|
17876
18465
|
const port = typeof args.port === "string" && args.port.trim().length > 0 ? Number(args.port) : 3e3;
|
|
17877
18466
|
switch (command) {
|
|
17878
18467
|
case "dev": {
|