@lolyjs/core 0.3.0-alpha.5 → 0.3.0-alpha.6
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 +74 -0
- package/dist/cli.cjs +664 -161
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +664 -161
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +737 -234
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +26 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.mjs +737 -234
- package/dist/index.mjs.map +1 -1
- package/dist/react/components.cjs +122 -5
- package/dist/react/components.cjs.map +1 -1
- package/dist/react/components.d.mts +18 -4
- package/dist/react/components.d.ts +18 -4
- package/dist/react/components.mjs +123 -6
- package/dist/react/components.mjs.map +1 -1
- package/package.json +3 -1
package/dist/cli.cjs
CHANGED
|
@@ -9953,7 +9953,7 @@ var require_built3 = __commonJS({
|
|
|
9953
9953
|
});
|
|
9954
9954
|
|
|
9955
9955
|
// modules/cli/index.ts
|
|
9956
|
-
var
|
|
9956
|
+
var import_path40 = __toESM(require("path"));
|
|
9957
9957
|
var import_process = __toESM(require("process"));
|
|
9958
9958
|
|
|
9959
9959
|
// modules/build/index.ts
|
|
@@ -11742,6 +11742,7 @@ async function processRewrites(urlPath, compiledRewrites, req) {
|
|
|
11742
11742
|
const normalizedPath = urlPath.replace(/\/$/, "") || "/";
|
|
11743
11743
|
if (normalizedPath.startsWith("/static/") || // Static assets (client.js, client.css, etc.)
|
|
11744
11744
|
normalizedPath.startsWith("/__fw/") || // Framework internal routes (hot reload, etc.)
|
|
11745
|
+
normalizedPath.startsWith("/_loly/") || // Framework internal routes (image optimization, etc.)
|
|
11745
11746
|
normalizedPath === "/favicon.ico" || // Favicon
|
|
11746
11747
|
normalizedPath.startsWith("/wss/")) {
|
|
11747
11748
|
if (process.env.NODE_ENV === "development") {
|
|
@@ -13175,12 +13176,12 @@ var DEFAULT_IGNORED_PATHS = [
|
|
|
13175
13176
|
/^\/sockjs-node/
|
|
13176
13177
|
// Hot reload websocket
|
|
13177
13178
|
];
|
|
13178
|
-
function shouldIgnorePath(
|
|
13179
|
+
function shouldIgnorePath(path37, ignoredPaths) {
|
|
13179
13180
|
return ignoredPaths.some((pattern) => {
|
|
13180
13181
|
if (typeof pattern === "string") {
|
|
13181
|
-
return
|
|
13182
|
+
return path37 === pattern || path37.startsWith(pattern);
|
|
13182
13183
|
}
|
|
13183
|
-
return pattern.test(
|
|
13184
|
+
return pattern.test(path37);
|
|
13184
13185
|
});
|
|
13185
13186
|
}
|
|
13186
13187
|
function requestLoggerMiddleware(options = {}) {
|
|
@@ -15143,7 +15144,20 @@ var DEFAULT_CONFIG2 = {
|
|
|
15143
15144
|
ssr: true,
|
|
15144
15145
|
ssg: true
|
|
15145
15146
|
},
|
|
15146
|
-
plugins: []
|
|
15147
|
+
plugins: [],
|
|
15148
|
+
images: {
|
|
15149
|
+
remotePatterns: [],
|
|
15150
|
+
domains: [],
|
|
15151
|
+
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
|
|
15152
|
+
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
|
|
15153
|
+
formats: ["image/webp", "image/avif"],
|
|
15154
|
+
quality: 75,
|
|
15155
|
+
minimumCacheTTL: 60,
|
|
15156
|
+
dangerouslyAllowSVG: false,
|
|
15157
|
+
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
|
|
15158
|
+
maxWidth: 3840,
|
|
15159
|
+
maxHeight: 3840
|
|
15160
|
+
}
|
|
15147
15161
|
};
|
|
15148
15162
|
function deepMerge(target, source) {
|
|
15149
15163
|
const result = { ...target };
|
|
@@ -15260,6 +15274,53 @@ function validateConfig(config, projectRoot) {
|
|
|
15260
15274
|
if (typeof config.rendering.ssg !== "boolean") {
|
|
15261
15275
|
errors.push("config.rendering.ssg must be a boolean");
|
|
15262
15276
|
}
|
|
15277
|
+
if (config.images) {
|
|
15278
|
+
if (config.images.quality !== void 0) {
|
|
15279
|
+
if (typeof config.images.quality !== "number" || config.images.quality < 1 || config.images.quality > 100) {
|
|
15280
|
+
errors.push("config.images.quality must be a number between 1 and 100");
|
|
15281
|
+
}
|
|
15282
|
+
}
|
|
15283
|
+
if (config.images.minimumCacheTTL !== void 0) {
|
|
15284
|
+
if (typeof config.images.minimumCacheTTL !== "number" || config.images.minimumCacheTTL < 0) {
|
|
15285
|
+
errors.push("config.images.minimumCacheTTL must be a non-negative number");
|
|
15286
|
+
}
|
|
15287
|
+
}
|
|
15288
|
+
if (config.images.deviceSizes) {
|
|
15289
|
+
if (!Array.isArray(config.images.deviceSizes) || config.images.deviceSizes.some((s) => typeof s !== "number" || s <= 0)) {
|
|
15290
|
+
errors.push("config.images.deviceSizes must be an array of positive numbers");
|
|
15291
|
+
}
|
|
15292
|
+
}
|
|
15293
|
+
if (config.images.imageSizes) {
|
|
15294
|
+
if (!Array.isArray(config.images.imageSizes) || config.images.imageSizes.some((s) => typeof s !== "number" || s <= 0)) {
|
|
15295
|
+
errors.push("config.images.imageSizes must be an array of positive numbers");
|
|
15296
|
+
}
|
|
15297
|
+
}
|
|
15298
|
+
if (config.images.formats) {
|
|
15299
|
+
const validFormats = ["image/webp", "image/avif"];
|
|
15300
|
+
if (!Array.isArray(config.images.formats) || config.images.formats.some((f) => !validFormats.includes(f))) {
|
|
15301
|
+
errors.push(`config.images.formats must be an array containing only: ${validFormats.join(", ")}`);
|
|
15302
|
+
}
|
|
15303
|
+
}
|
|
15304
|
+
if (config.images.remotePatterns) {
|
|
15305
|
+
if (!Array.isArray(config.images.remotePatterns)) {
|
|
15306
|
+
errors.push("config.images.remotePatterns must be an array");
|
|
15307
|
+
} else {
|
|
15308
|
+
config.images.remotePatterns.forEach((pattern, idx) => {
|
|
15309
|
+
if (!pattern.hostname || typeof pattern.hostname !== "string") {
|
|
15310
|
+
errors.push(`config.images.remotePatterns[${idx}].hostname must be a non-empty string`);
|
|
15311
|
+
}
|
|
15312
|
+
if (pattern.protocol && !["http", "https"].includes(pattern.protocol)) {
|
|
15313
|
+
errors.push(`config.images.remotePatterns[${idx}].protocol must be 'http' or 'https'`);
|
|
15314
|
+
}
|
|
15315
|
+
});
|
|
15316
|
+
}
|
|
15317
|
+
}
|
|
15318
|
+
if (config.images.domains) {
|
|
15319
|
+
if (!Array.isArray(config.images.domains) || config.images.domains.some((d) => typeof d !== "string")) {
|
|
15320
|
+
errors.push("config.images.domains must be an array of strings");
|
|
15321
|
+
}
|
|
15322
|
+
}
|
|
15323
|
+
}
|
|
15263
15324
|
if (errors.length > 0) {
|
|
15264
15325
|
const errorMessage = [
|
|
15265
15326
|
"\u274C Configuration validation failed:",
|
|
@@ -15393,8 +15454,8 @@ async function buildApp(options = {}) {
|
|
|
15393
15454
|
}
|
|
15394
15455
|
|
|
15395
15456
|
// src/server.ts
|
|
15396
|
-
var
|
|
15397
|
-
var
|
|
15457
|
+
var import_fs28 = __toESM(require("fs"));
|
|
15458
|
+
var import_path39 = __toESM(require("path"));
|
|
15398
15459
|
|
|
15399
15460
|
// modules/server/setup.ts
|
|
15400
15461
|
var import_express = __toESM(require("express"));
|
|
@@ -15477,7 +15538,7 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
15477
15538
|
this._directoryFilter = normalizeFilter(opts.directoryFilter);
|
|
15478
15539
|
const statMethod = opts.lstat ? import_promises.lstat : import_promises.stat;
|
|
15479
15540
|
if (wantBigintFsStats) {
|
|
15480
|
-
this._stat = (
|
|
15541
|
+
this._stat = (path37) => statMethod(path37, { bigint: true });
|
|
15481
15542
|
} else {
|
|
15482
15543
|
this._stat = statMethod;
|
|
15483
15544
|
}
|
|
@@ -15502,8 +15563,8 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
15502
15563
|
const par = this.parent;
|
|
15503
15564
|
const fil = par && par.files;
|
|
15504
15565
|
if (fil && fil.length > 0) {
|
|
15505
|
-
const { path:
|
|
15506
|
-
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent,
|
|
15566
|
+
const { path: path37, depth } = par;
|
|
15567
|
+
const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path37));
|
|
15507
15568
|
const awaited = await Promise.all(slice);
|
|
15508
15569
|
for (const entry of awaited) {
|
|
15509
15570
|
if (!entry)
|
|
@@ -15543,20 +15604,20 @@ var ReaddirpStream = class extends import_node_stream.Readable {
|
|
|
15543
15604
|
this.reading = false;
|
|
15544
15605
|
}
|
|
15545
15606
|
}
|
|
15546
|
-
async _exploreDir(
|
|
15607
|
+
async _exploreDir(path37, depth) {
|
|
15547
15608
|
let files;
|
|
15548
15609
|
try {
|
|
15549
|
-
files = await (0, import_promises.readdir)(
|
|
15610
|
+
files = await (0, import_promises.readdir)(path37, this._rdOptions);
|
|
15550
15611
|
} catch (error) {
|
|
15551
15612
|
this._onError(error);
|
|
15552
15613
|
}
|
|
15553
|
-
return { files, depth, path:
|
|
15614
|
+
return { files, depth, path: path37 };
|
|
15554
15615
|
}
|
|
15555
|
-
async _formatEntry(dirent,
|
|
15616
|
+
async _formatEntry(dirent, path37) {
|
|
15556
15617
|
let entry;
|
|
15557
15618
|
const basename3 = this._isDirent ? dirent.name : dirent;
|
|
15558
15619
|
try {
|
|
15559
|
-
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(
|
|
15620
|
+
const fullPath = (0, import_node_path.resolve)((0, import_node_path.join)(path37, basename3));
|
|
15560
15621
|
entry = { path: (0, import_node_path.relative)(this._root, fullPath), fullPath, basename: basename3 };
|
|
15561
15622
|
entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
|
|
15562
15623
|
} catch (err) {
|
|
@@ -15956,16 +16017,16 @@ var delFromSet = (main, prop, item) => {
|
|
|
15956
16017
|
};
|
|
15957
16018
|
var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
|
|
15958
16019
|
var FsWatchInstances = /* @__PURE__ */ new Map();
|
|
15959
|
-
function createFsWatchInstance(
|
|
16020
|
+
function createFsWatchInstance(path37, options, listener, errHandler, emitRaw) {
|
|
15960
16021
|
const handleEvent = (rawEvent, evPath) => {
|
|
15961
|
-
listener(
|
|
15962
|
-
emitRaw(rawEvent, evPath, { watchedPath:
|
|
15963
|
-
if (evPath &&
|
|
15964
|
-
fsWatchBroadcast(sysPath.resolve(
|
|
16022
|
+
listener(path37);
|
|
16023
|
+
emitRaw(rawEvent, evPath, { watchedPath: path37 });
|
|
16024
|
+
if (evPath && path37 !== evPath) {
|
|
16025
|
+
fsWatchBroadcast(sysPath.resolve(path37, evPath), KEY_LISTENERS, sysPath.join(path37, evPath));
|
|
15965
16026
|
}
|
|
15966
16027
|
};
|
|
15967
16028
|
try {
|
|
15968
|
-
return (0, import_fs23.watch)(
|
|
16029
|
+
return (0, import_fs23.watch)(path37, {
|
|
15969
16030
|
persistent: options.persistent
|
|
15970
16031
|
}, handleEvent);
|
|
15971
16032
|
} catch (error) {
|
|
@@ -15981,12 +16042,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
|
|
|
15981
16042
|
listener(val1, val2, val3);
|
|
15982
16043
|
});
|
|
15983
16044
|
};
|
|
15984
|
-
var setFsWatchListener = (
|
|
16045
|
+
var setFsWatchListener = (path37, fullPath, options, handlers) => {
|
|
15985
16046
|
const { listener, errHandler, rawEmitter } = handlers;
|
|
15986
16047
|
let cont = FsWatchInstances.get(fullPath);
|
|
15987
16048
|
let watcher;
|
|
15988
16049
|
if (!options.persistent) {
|
|
15989
|
-
watcher = createFsWatchInstance(
|
|
16050
|
+
watcher = createFsWatchInstance(path37, options, listener, errHandler, rawEmitter);
|
|
15990
16051
|
if (!watcher)
|
|
15991
16052
|
return;
|
|
15992
16053
|
return watcher.close.bind(watcher);
|
|
@@ -15997,7 +16058,7 @@ var setFsWatchListener = (path34, fullPath, options, handlers) => {
|
|
|
15997
16058
|
addAndConvert(cont, KEY_RAW, rawEmitter);
|
|
15998
16059
|
} else {
|
|
15999
16060
|
watcher = createFsWatchInstance(
|
|
16000
|
-
|
|
16061
|
+
path37,
|
|
16001
16062
|
options,
|
|
16002
16063
|
fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
|
|
16003
16064
|
errHandler,
|
|
@@ -16012,7 +16073,7 @@ var setFsWatchListener = (path34, fullPath, options, handlers) => {
|
|
|
16012
16073
|
cont.watcherUnusable = true;
|
|
16013
16074
|
if (isWindows && error.code === "EPERM") {
|
|
16014
16075
|
try {
|
|
16015
|
-
const fd = await (0, import_promises2.open)(
|
|
16076
|
+
const fd = await (0, import_promises2.open)(path37, "r");
|
|
16016
16077
|
await fd.close();
|
|
16017
16078
|
broadcastErr(error);
|
|
16018
16079
|
} catch (err) {
|
|
@@ -16043,7 +16104,7 @@ var setFsWatchListener = (path34, fullPath, options, handlers) => {
|
|
|
16043
16104
|
};
|
|
16044
16105
|
};
|
|
16045
16106
|
var FsWatchFileInstances = /* @__PURE__ */ new Map();
|
|
16046
|
-
var setFsWatchFileListener = (
|
|
16107
|
+
var setFsWatchFileListener = (path37, fullPath, options, handlers) => {
|
|
16047
16108
|
const { listener, rawEmitter } = handlers;
|
|
16048
16109
|
let cont = FsWatchFileInstances.get(fullPath);
|
|
16049
16110
|
const copts = cont && cont.options;
|
|
@@ -16065,7 +16126,7 @@ var setFsWatchFileListener = (path34, fullPath, options, handlers) => {
|
|
|
16065
16126
|
});
|
|
16066
16127
|
const currmtime = curr.mtimeMs;
|
|
16067
16128
|
if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
|
|
16068
|
-
foreach(cont.listeners, (listener2) => listener2(
|
|
16129
|
+
foreach(cont.listeners, (listener2) => listener2(path37, curr));
|
|
16069
16130
|
}
|
|
16070
16131
|
})
|
|
16071
16132
|
};
|
|
@@ -16093,13 +16154,13 @@ var NodeFsHandler = class {
|
|
|
16093
16154
|
* @param listener on fs change
|
|
16094
16155
|
* @returns closer for the watcher instance
|
|
16095
16156
|
*/
|
|
16096
|
-
_watchWithNodeFs(
|
|
16157
|
+
_watchWithNodeFs(path37, listener) {
|
|
16097
16158
|
const opts = this.fsw.options;
|
|
16098
|
-
const directory = sysPath.dirname(
|
|
16099
|
-
const basename3 = sysPath.basename(
|
|
16159
|
+
const directory = sysPath.dirname(path37);
|
|
16160
|
+
const basename3 = sysPath.basename(path37);
|
|
16100
16161
|
const parent = this.fsw._getWatchedDir(directory);
|
|
16101
16162
|
parent.add(basename3);
|
|
16102
|
-
const absolutePath = sysPath.resolve(
|
|
16163
|
+
const absolutePath = sysPath.resolve(path37);
|
|
16103
16164
|
const options = {
|
|
16104
16165
|
persistent: opts.persistent
|
|
16105
16166
|
};
|
|
@@ -16109,12 +16170,12 @@ var NodeFsHandler = class {
|
|
|
16109
16170
|
if (opts.usePolling) {
|
|
16110
16171
|
const enableBin = opts.interval !== opts.binaryInterval;
|
|
16111
16172
|
options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
|
|
16112
|
-
closer = setFsWatchFileListener(
|
|
16173
|
+
closer = setFsWatchFileListener(path37, absolutePath, options, {
|
|
16113
16174
|
listener,
|
|
16114
16175
|
rawEmitter: this.fsw._emitRaw
|
|
16115
16176
|
});
|
|
16116
16177
|
} else {
|
|
16117
|
-
closer = setFsWatchListener(
|
|
16178
|
+
closer = setFsWatchListener(path37, absolutePath, options, {
|
|
16118
16179
|
listener,
|
|
16119
16180
|
errHandler: this._boundHandleError,
|
|
16120
16181
|
rawEmitter: this.fsw._emitRaw
|
|
@@ -16136,7 +16197,7 @@ var NodeFsHandler = class {
|
|
|
16136
16197
|
let prevStats = stats;
|
|
16137
16198
|
if (parent.has(basename3))
|
|
16138
16199
|
return;
|
|
16139
|
-
const listener = async (
|
|
16200
|
+
const listener = async (path37, newStats) => {
|
|
16140
16201
|
if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
|
|
16141
16202
|
return;
|
|
16142
16203
|
if (!newStats || newStats.mtimeMs === 0) {
|
|
@@ -16150,11 +16211,11 @@ var NodeFsHandler = class {
|
|
|
16150
16211
|
this.fsw._emit(EV.CHANGE, file, newStats2);
|
|
16151
16212
|
}
|
|
16152
16213
|
if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
|
|
16153
|
-
this.fsw._closeFile(
|
|
16214
|
+
this.fsw._closeFile(path37);
|
|
16154
16215
|
prevStats = newStats2;
|
|
16155
16216
|
const closer2 = this._watchWithNodeFs(file, listener);
|
|
16156
16217
|
if (closer2)
|
|
16157
|
-
this.fsw._addPathCloser(
|
|
16218
|
+
this.fsw._addPathCloser(path37, closer2);
|
|
16158
16219
|
} else {
|
|
16159
16220
|
prevStats = newStats2;
|
|
16160
16221
|
}
|
|
@@ -16186,7 +16247,7 @@ var NodeFsHandler = class {
|
|
|
16186
16247
|
* @param item basename of this item
|
|
16187
16248
|
* @returns true if no more processing is needed for this entry.
|
|
16188
16249
|
*/
|
|
16189
|
-
async _handleSymlink(entry, directory,
|
|
16250
|
+
async _handleSymlink(entry, directory, path37, item) {
|
|
16190
16251
|
if (this.fsw.closed) {
|
|
16191
16252
|
return;
|
|
16192
16253
|
}
|
|
@@ -16196,7 +16257,7 @@ var NodeFsHandler = class {
|
|
|
16196
16257
|
this.fsw._incrReadyCount();
|
|
16197
16258
|
let linkPath;
|
|
16198
16259
|
try {
|
|
16199
|
-
linkPath = await (0, import_promises2.realpath)(
|
|
16260
|
+
linkPath = await (0, import_promises2.realpath)(path37);
|
|
16200
16261
|
} catch (e) {
|
|
16201
16262
|
this.fsw._emitReady();
|
|
16202
16263
|
return true;
|
|
@@ -16206,12 +16267,12 @@ var NodeFsHandler = class {
|
|
|
16206
16267
|
if (dir.has(item)) {
|
|
16207
16268
|
if (this.fsw._symlinkPaths.get(full) !== linkPath) {
|
|
16208
16269
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
16209
|
-
this.fsw._emit(EV.CHANGE,
|
|
16270
|
+
this.fsw._emit(EV.CHANGE, path37, entry.stats);
|
|
16210
16271
|
}
|
|
16211
16272
|
} else {
|
|
16212
16273
|
dir.add(item);
|
|
16213
16274
|
this.fsw._symlinkPaths.set(full, linkPath);
|
|
16214
|
-
this.fsw._emit(EV.ADD,
|
|
16275
|
+
this.fsw._emit(EV.ADD, path37, entry.stats);
|
|
16215
16276
|
}
|
|
16216
16277
|
this.fsw._emitReady();
|
|
16217
16278
|
return true;
|
|
@@ -16240,9 +16301,9 @@ var NodeFsHandler = class {
|
|
|
16240
16301
|
return;
|
|
16241
16302
|
}
|
|
16242
16303
|
const item = entry.path;
|
|
16243
|
-
let
|
|
16304
|
+
let path37 = sysPath.join(directory, item);
|
|
16244
16305
|
current.add(item);
|
|
16245
|
-
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory,
|
|
16306
|
+
if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path37, item)) {
|
|
16246
16307
|
return;
|
|
16247
16308
|
}
|
|
16248
16309
|
if (this.fsw.closed) {
|
|
@@ -16251,8 +16312,8 @@ var NodeFsHandler = class {
|
|
|
16251
16312
|
}
|
|
16252
16313
|
if (item === target || !target && !previous.has(item)) {
|
|
16253
16314
|
this.fsw._incrReadyCount();
|
|
16254
|
-
|
|
16255
|
-
this._addToNodeFs(
|
|
16315
|
+
path37 = sysPath.join(dir, sysPath.relative(dir, path37));
|
|
16316
|
+
this._addToNodeFs(path37, initialAdd, wh, depth + 1);
|
|
16256
16317
|
}
|
|
16257
16318
|
}).on(EV.ERROR, this._boundHandleError);
|
|
16258
16319
|
return new Promise((resolve3, reject) => {
|
|
@@ -16321,13 +16382,13 @@ var NodeFsHandler = class {
|
|
|
16321
16382
|
* @param depth Child path actually targeted for watch
|
|
16322
16383
|
* @param target Child path actually targeted for watch
|
|
16323
16384
|
*/
|
|
16324
|
-
async _addToNodeFs(
|
|
16385
|
+
async _addToNodeFs(path37, initialAdd, priorWh, depth, target) {
|
|
16325
16386
|
const ready = this.fsw._emitReady;
|
|
16326
|
-
if (this.fsw._isIgnored(
|
|
16387
|
+
if (this.fsw._isIgnored(path37) || this.fsw.closed) {
|
|
16327
16388
|
ready();
|
|
16328
16389
|
return false;
|
|
16329
16390
|
}
|
|
16330
|
-
const wh = this.fsw._getWatchHelpers(
|
|
16391
|
+
const wh = this.fsw._getWatchHelpers(path37);
|
|
16331
16392
|
if (priorWh) {
|
|
16332
16393
|
wh.filterPath = (entry) => priorWh.filterPath(entry);
|
|
16333
16394
|
wh.filterDir = (entry) => priorWh.filterDir(entry);
|
|
@@ -16343,8 +16404,8 @@ var NodeFsHandler = class {
|
|
|
16343
16404
|
const follow = this.fsw.options.followSymlinks;
|
|
16344
16405
|
let closer;
|
|
16345
16406
|
if (stats.isDirectory()) {
|
|
16346
|
-
const absPath = sysPath.resolve(
|
|
16347
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
16407
|
+
const absPath = sysPath.resolve(path37);
|
|
16408
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path37) : path37;
|
|
16348
16409
|
if (this.fsw.closed)
|
|
16349
16410
|
return;
|
|
16350
16411
|
closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
|
|
@@ -16354,29 +16415,29 @@ var NodeFsHandler = class {
|
|
|
16354
16415
|
this.fsw._symlinkPaths.set(absPath, targetPath);
|
|
16355
16416
|
}
|
|
16356
16417
|
} else if (stats.isSymbolicLink()) {
|
|
16357
|
-
const targetPath = follow ? await (0, import_promises2.realpath)(
|
|
16418
|
+
const targetPath = follow ? await (0, import_promises2.realpath)(path37) : path37;
|
|
16358
16419
|
if (this.fsw.closed)
|
|
16359
16420
|
return;
|
|
16360
16421
|
const parent = sysPath.dirname(wh.watchPath);
|
|
16361
16422
|
this.fsw._getWatchedDir(parent).add(wh.watchPath);
|
|
16362
16423
|
this.fsw._emit(EV.ADD, wh.watchPath, stats);
|
|
16363
|
-
closer = await this._handleDir(parent, stats, initialAdd, depth,
|
|
16424
|
+
closer = await this._handleDir(parent, stats, initialAdd, depth, path37, wh, targetPath);
|
|
16364
16425
|
if (this.fsw.closed)
|
|
16365
16426
|
return;
|
|
16366
16427
|
if (targetPath !== void 0) {
|
|
16367
|
-
this.fsw._symlinkPaths.set(sysPath.resolve(
|
|
16428
|
+
this.fsw._symlinkPaths.set(sysPath.resolve(path37), targetPath);
|
|
16368
16429
|
}
|
|
16369
16430
|
} else {
|
|
16370
16431
|
closer = this._handleFile(wh.watchPath, stats, initialAdd);
|
|
16371
16432
|
}
|
|
16372
16433
|
ready();
|
|
16373
16434
|
if (closer)
|
|
16374
|
-
this.fsw._addPathCloser(
|
|
16435
|
+
this.fsw._addPathCloser(path37, closer);
|
|
16375
16436
|
return false;
|
|
16376
16437
|
} catch (error) {
|
|
16377
16438
|
if (this.fsw._handleError(error)) {
|
|
16378
16439
|
ready();
|
|
16379
|
-
return
|
|
16440
|
+
return path37;
|
|
16380
16441
|
}
|
|
16381
16442
|
}
|
|
16382
16443
|
}
|
|
@@ -16419,26 +16480,26 @@ function createPattern(matcher) {
|
|
|
16419
16480
|
}
|
|
16420
16481
|
return () => false;
|
|
16421
16482
|
}
|
|
16422
|
-
function normalizePath(
|
|
16423
|
-
if (typeof
|
|
16483
|
+
function normalizePath(path37) {
|
|
16484
|
+
if (typeof path37 !== "string")
|
|
16424
16485
|
throw new Error("string expected");
|
|
16425
|
-
|
|
16426
|
-
|
|
16486
|
+
path37 = sysPath2.normalize(path37);
|
|
16487
|
+
path37 = path37.replace(/\\/g, "/");
|
|
16427
16488
|
let prepend = false;
|
|
16428
|
-
if (
|
|
16489
|
+
if (path37.startsWith("//"))
|
|
16429
16490
|
prepend = true;
|
|
16430
16491
|
const DOUBLE_SLASH_RE2 = /\/\//;
|
|
16431
|
-
while (
|
|
16432
|
-
|
|
16492
|
+
while (path37.match(DOUBLE_SLASH_RE2))
|
|
16493
|
+
path37 = path37.replace(DOUBLE_SLASH_RE2, "/");
|
|
16433
16494
|
if (prepend)
|
|
16434
|
-
|
|
16435
|
-
return
|
|
16495
|
+
path37 = "/" + path37;
|
|
16496
|
+
return path37;
|
|
16436
16497
|
}
|
|
16437
16498
|
function matchPatterns(patterns, testString, stats) {
|
|
16438
|
-
const
|
|
16499
|
+
const path37 = normalizePath(testString);
|
|
16439
16500
|
for (let index = 0; index < patterns.length; index++) {
|
|
16440
16501
|
const pattern = patterns[index];
|
|
16441
|
-
if (pattern(
|
|
16502
|
+
if (pattern(path37, stats)) {
|
|
16442
16503
|
return true;
|
|
16443
16504
|
}
|
|
16444
16505
|
}
|
|
@@ -16478,19 +16539,19 @@ var toUnix = (string) => {
|
|
|
16478
16539
|
}
|
|
16479
16540
|
return str;
|
|
16480
16541
|
};
|
|
16481
|
-
var normalizePathToUnix = (
|
|
16482
|
-
var normalizeIgnored = (cwd = "") => (
|
|
16483
|
-
if (typeof
|
|
16484
|
-
return normalizePathToUnix(sysPath2.isAbsolute(
|
|
16542
|
+
var normalizePathToUnix = (path37) => toUnix(sysPath2.normalize(toUnix(path37)));
|
|
16543
|
+
var normalizeIgnored = (cwd = "") => (path37) => {
|
|
16544
|
+
if (typeof path37 === "string") {
|
|
16545
|
+
return normalizePathToUnix(sysPath2.isAbsolute(path37) ? path37 : sysPath2.join(cwd, path37));
|
|
16485
16546
|
} else {
|
|
16486
|
-
return
|
|
16547
|
+
return path37;
|
|
16487
16548
|
}
|
|
16488
16549
|
};
|
|
16489
|
-
var getAbsolutePath = (
|
|
16490
|
-
if (sysPath2.isAbsolute(
|
|
16491
|
-
return
|
|
16550
|
+
var getAbsolutePath = (path37, cwd) => {
|
|
16551
|
+
if (sysPath2.isAbsolute(path37)) {
|
|
16552
|
+
return path37;
|
|
16492
16553
|
}
|
|
16493
|
-
return sysPath2.join(cwd,
|
|
16554
|
+
return sysPath2.join(cwd, path37);
|
|
16494
16555
|
};
|
|
16495
16556
|
var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
|
|
16496
16557
|
var DirEntry = class {
|
|
@@ -16545,10 +16606,10 @@ var DirEntry = class {
|
|
|
16545
16606
|
var STAT_METHOD_F = "stat";
|
|
16546
16607
|
var STAT_METHOD_L = "lstat";
|
|
16547
16608
|
var WatchHelper = class {
|
|
16548
|
-
constructor(
|
|
16609
|
+
constructor(path37, follow, fsw) {
|
|
16549
16610
|
this.fsw = fsw;
|
|
16550
|
-
const watchPath =
|
|
16551
|
-
this.path =
|
|
16611
|
+
const watchPath = path37;
|
|
16612
|
+
this.path = path37 = path37.replace(REPLACER_RE, "");
|
|
16552
16613
|
this.watchPath = watchPath;
|
|
16553
16614
|
this.fullWatchPath = sysPath2.resolve(watchPath);
|
|
16554
16615
|
this.dirParts = [];
|
|
@@ -16670,20 +16731,20 @@ var FSWatcher = class extends import_events.EventEmitter {
|
|
|
16670
16731
|
this._closePromise = void 0;
|
|
16671
16732
|
let paths = unifyPaths(paths_);
|
|
16672
16733
|
if (cwd) {
|
|
16673
|
-
paths = paths.map((
|
|
16674
|
-
const absPath = getAbsolutePath(
|
|
16734
|
+
paths = paths.map((path37) => {
|
|
16735
|
+
const absPath = getAbsolutePath(path37, cwd);
|
|
16675
16736
|
return absPath;
|
|
16676
16737
|
});
|
|
16677
16738
|
}
|
|
16678
|
-
paths.forEach((
|
|
16679
|
-
this._removeIgnoredPath(
|
|
16739
|
+
paths.forEach((path37) => {
|
|
16740
|
+
this._removeIgnoredPath(path37);
|
|
16680
16741
|
});
|
|
16681
16742
|
this._userIgnored = void 0;
|
|
16682
16743
|
if (!this._readyCount)
|
|
16683
16744
|
this._readyCount = 0;
|
|
16684
16745
|
this._readyCount += paths.length;
|
|
16685
|
-
Promise.all(paths.map(async (
|
|
16686
|
-
const res = await this._nodeFsHandler._addToNodeFs(
|
|
16746
|
+
Promise.all(paths.map(async (path37) => {
|
|
16747
|
+
const res = await this._nodeFsHandler._addToNodeFs(path37, !_internal, void 0, 0, _origAdd);
|
|
16687
16748
|
if (res)
|
|
16688
16749
|
this._emitReady();
|
|
16689
16750
|
return res;
|
|
@@ -16705,17 +16766,17 @@ var FSWatcher = class extends import_events.EventEmitter {
|
|
|
16705
16766
|
return this;
|
|
16706
16767
|
const paths = unifyPaths(paths_);
|
|
16707
16768
|
const { cwd } = this.options;
|
|
16708
|
-
paths.forEach((
|
|
16709
|
-
if (!sysPath2.isAbsolute(
|
|
16769
|
+
paths.forEach((path37) => {
|
|
16770
|
+
if (!sysPath2.isAbsolute(path37) && !this._closers.has(path37)) {
|
|
16710
16771
|
if (cwd)
|
|
16711
|
-
|
|
16712
|
-
|
|
16772
|
+
path37 = sysPath2.join(cwd, path37);
|
|
16773
|
+
path37 = sysPath2.resolve(path37);
|
|
16713
16774
|
}
|
|
16714
|
-
this._closePath(
|
|
16715
|
-
this._addIgnoredPath(
|
|
16716
|
-
if (this._watched.has(
|
|
16775
|
+
this._closePath(path37);
|
|
16776
|
+
this._addIgnoredPath(path37);
|
|
16777
|
+
if (this._watched.has(path37)) {
|
|
16717
16778
|
this._addIgnoredPath({
|
|
16718
|
-
path:
|
|
16779
|
+
path: path37,
|
|
16719
16780
|
recursive: true
|
|
16720
16781
|
});
|
|
16721
16782
|
}
|
|
@@ -16779,38 +16840,38 @@ var FSWatcher = class extends import_events.EventEmitter {
|
|
|
16779
16840
|
* @param stats arguments to be passed with event
|
|
16780
16841
|
* @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
|
|
16781
16842
|
*/
|
|
16782
|
-
async _emit(event,
|
|
16843
|
+
async _emit(event, path37, stats) {
|
|
16783
16844
|
if (this.closed)
|
|
16784
16845
|
return;
|
|
16785
16846
|
const opts = this.options;
|
|
16786
16847
|
if (isWindows)
|
|
16787
|
-
|
|
16848
|
+
path37 = sysPath2.normalize(path37);
|
|
16788
16849
|
if (opts.cwd)
|
|
16789
|
-
|
|
16790
|
-
const args = [
|
|
16850
|
+
path37 = sysPath2.relative(opts.cwd, path37);
|
|
16851
|
+
const args = [path37];
|
|
16791
16852
|
if (stats != null)
|
|
16792
16853
|
args.push(stats);
|
|
16793
16854
|
const awf = opts.awaitWriteFinish;
|
|
16794
16855
|
let pw;
|
|
16795
|
-
if (awf && (pw = this._pendingWrites.get(
|
|
16856
|
+
if (awf && (pw = this._pendingWrites.get(path37))) {
|
|
16796
16857
|
pw.lastChange = /* @__PURE__ */ new Date();
|
|
16797
16858
|
return this;
|
|
16798
16859
|
}
|
|
16799
16860
|
if (opts.atomic) {
|
|
16800
16861
|
if (event === EVENTS.UNLINK) {
|
|
16801
|
-
this._pendingUnlinks.set(
|
|
16862
|
+
this._pendingUnlinks.set(path37, [event, ...args]);
|
|
16802
16863
|
setTimeout(() => {
|
|
16803
|
-
this._pendingUnlinks.forEach((entry,
|
|
16864
|
+
this._pendingUnlinks.forEach((entry, path38) => {
|
|
16804
16865
|
this.emit(...entry);
|
|
16805
16866
|
this.emit(EVENTS.ALL, ...entry);
|
|
16806
|
-
this._pendingUnlinks.delete(
|
|
16867
|
+
this._pendingUnlinks.delete(path38);
|
|
16807
16868
|
});
|
|
16808
16869
|
}, typeof opts.atomic === "number" ? opts.atomic : 100);
|
|
16809
16870
|
return this;
|
|
16810
16871
|
}
|
|
16811
|
-
if (event === EVENTS.ADD && this._pendingUnlinks.has(
|
|
16872
|
+
if (event === EVENTS.ADD && this._pendingUnlinks.has(path37)) {
|
|
16812
16873
|
event = EVENTS.CHANGE;
|
|
16813
|
-
this._pendingUnlinks.delete(
|
|
16874
|
+
this._pendingUnlinks.delete(path37);
|
|
16814
16875
|
}
|
|
16815
16876
|
}
|
|
16816
16877
|
if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
|
|
@@ -16828,16 +16889,16 @@ var FSWatcher = class extends import_events.EventEmitter {
|
|
|
16828
16889
|
this.emitWithAll(event, args);
|
|
16829
16890
|
}
|
|
16830
16891
|
};
|
|
16831
|
-
this._awaitWriteFinish(
|
|
16892
|
+
this._awaitWriteFinish(path37, awf.stabilityThreshold, event, awfEmit);
|
|
16832
16893
|
return this;
|
|
16833
16894
|
}
|
|
16834
16895
|
if (event === EVENTS.CHANGE) {
|
|
16835
|
-
const isThrottled = !this._throttle(EVENTS.CHANGE,
|
|
16896
|
+
const isThrottled = !this._throttle(EVENTS.CHANGE, path37, 50);
|
|
16836
16897
|
if (isThrottled)
|
|
16837
16898
|
return this;
|
|
16838
16899
|
}
|
|
16839
16900
|
if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
|
|
16840
|
-
const fullPath = opts.cwd ? sysPath2.join(opts.cwd,
|
|
16901
|
+
const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path37) : path37;
|
|
16841
16902
|
let stats2;
|
|
16842
16903
|
try {
|
|
16843
16904
|
stats2 = await (0, import_promises3.stat)(fullPath);
|
|
@@ -16868,23 +16929,23 @@ var FSWatcher = class extends import_events.EventEmitter {
|
|
|
16868
16929
|
* @param timeout duration of time to suppress duplicate actions
|
|
16869
16930
|
* @returns tracking object or false if action should be suppressed
|
|
16870
16931
|
*/
|
|
16871
|
-
_throttle(actionType,
|
|
16932
|
+
_throttle(actionType, path37, timeout) {
|
|
16872
16933
|
if (!this._throttled.has(actionType)) {
|
|
16873
16934
|
this._throttled.set(actionType, /* @__PURE__ */ new Map());
|
|
16874
16935
|
}
|
|
16875
16936
|
const action = this._throttled.get(actionType);
|
|
16876
16937
|
if (!action)
|
|
16877
16938
|
throw new Error("invalid throttle");
|
|
16878
|
-
const actionPath = action.get(
|
|
16939
|
+
const actionPath = action.get(path37);
|
|
16879
16940
|
if (actionPath) {
|
|
16880
16941
|
actionPath.count++;
|
|
16881
16942
|
return false;
|
|
16882
16943
|
}
|
|
16883
16944
|
let timeoutObject;
|
|
16884
16945
|
const clear = () => {
|
|
16885
|
-
const item = action.get(
|
|
16946
|
+
const item = action.get(path37);
|
|
16886
16947
|
const count = item ? item.count : 0;
|
|
16887
|
-
action.delete(
|
|
16948
|
+
action.delete(path37);
|
|
16888
16949
|
clearTimeout(timeoutObject);
|
|
16889
16950
|
if (item)
|
|
16890
16951
|
clearTimeout(item.timeoutObject);
|
|
@@ -16892,7 +16953,7 @@ var FSWatcher = class extends import_events.EventEmitter {
|
|
|
16892
16953
|
};
|
|
16893
16954
|
timeoutObject = setTimeout(clear, timeout);
|
|
16894
16955
|
const thr = { timeoutObject, clear, count: 0 };
|
|
16895
|
-
action.set(
|
|
16956
|
+
action.set(path37, thr);
|
|
16896
16957
|
return thr;
|
|
16897
16958
|
}
|
|
16898
16959
|
_incrReadyCount() {
|
|
@@ -16906,44 +16967,44 @@ var FSWatcher = class extends import_events.EventEmitter {
|
|
|
16906
16967
|
* @param event
|
|
16907
16968
|
* @param awfEmit Callback to be called when ready for event to be emitted.
|
|
16908
16969
|
*/
|
|
16909
|
-
_awaitWriteFinish(
|
|
16970
|
+
_awaitWriteFinish(path37, threshold, event, awfEmit) {
|
|
16910
16971
|
const awf = this.options.awaitWriteFinish;
|
|
16911
16972
|
if (typeof awf !== "object")
|
|
16912
16973
|
return;
|
|
16913
16974
|
const pollInterval = awf.pollInterval;
|
|
16914
16975
|
let timeoutHandler;
|
|
16915
|
-
let fullPath =
|
|
16916
|
-
if (this.options.cwd && !sysPath2.isAbsolute(
|
|
16917
|
-
fullPath = sysPath2.join(this.options.cwd,
|
|
16976
|
+
let fullPath = path37;
|
|
16977
|
+
if (this.options.cwd && !sysPath2.isAbsolute(path37)) {
|
|
16978
|
+
fullPath = sysPath2.join(this.options.cwd, path37);
|
|
16918
16979
|
}
|
|
16919
16980
|
const now = /* @__PURE__ */ new Date();
|
|
16920
16981
|
const writes = this._pendingWrites;
|
|
16921
16982
|
function awaitWriteFinishFn(prevStat) {
|
|
16922
16983
|
(0, import_fs24.stat)(fullPath, (err, curStat) => {
|
|
16923
|
-
if (err || !writes.has(
|
|
16984
|
+
if (err || !writes.has(path37)) {
|
|
16924
16985
|
if (err && err.code !== "ENOENT")
|
|
16925
16986
|
awfEmit(err);
|
|
16926
16987
|
return;
|
|
16927
16988
|
}
|
|
16928
16989
|
const now2 = Number(/* @__PURE__ */ new Date());
|
|
16929
16990
|
if (prevStat && curStat.size !== prevStat.size) {
|
|
16930
|
-
writes.get(
|
|
16991
|
+
writes.get(path37).lastChange = now2;
|
|
16931
16992
|
}
|
|
16932
|
-
const pw = writes.get(
|
|
16993
|
+
const pw = writes.get(path37);
|
|
16933
16994
|
const df = now2 - pw.lastChange;
|
|
16934
16995
|
if (df >= threshold) {
|
|
16935
|
-
writes.delete(
|
|
16996
|
+
writes.delete(path37);
|
|
16936
16997
|
awfEmit(void 0, curStat);
|
|
16937
16998
|
} else {
|
|
16938
16999
|
timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
|
|
16939
17000
|
}
|
|
16940
17001
|
});
|
|
16941
17002
|
}
|
|
16942
|
-
if (!writes.has(
|
|
16943
|
-
writes.set(
|
|
17003
|
+
if (!writes.has(path37)) {
|
|
17004
|
+
writes.set(path37, {
|
|
16944
17005
|
lastChange: now,
|
|
16945
17006
|
cancelWait: () => {
|
|
16946
|
-
writes.delete(
|
|
17007
|
+
writes.delete(path37);
|
|
16947
17008
|
clearTimeout(timeoutHandler);
|
|
16948
17009
|
return event;
|
|
16949
17010
|
}
|
|
@@ -16954,8 +17015,8 @@ var FSWatcher = class extends import_events.EventEmitter {
|
|
|
16954
17015
|
/**
|
|
16955
17016
|
* Determines whether user has asked to ignore this path.
|
|
16956
17017
|
*/
|
|
16957
|
-
_isIgnored(
|
|
16958
|
-
if (this.options.atomic && DOT_RE.test(
|
|
17018
|
+
_isIgnored(path37, stats) {
|
|
17019
|
+
if (this.options.atomic && DOT_RE.test(path37))
|
|
16959
17020
|
return true;
|
|
16960
17021
|
if (!this._userIgnored) {
|
|
16961
17022
|
const { cwd } = this.options;
|
|
@@ -16965,17 +17026,17 @@ var FSWatcher = class extends import_events.EventEmitter {
|
|
|
16965
17026
|
const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
|
|
16966
17027
|
this._userIgnored = anymatch(list, void 0);
|
|
16967
17028
|
}
|
|
16968
|
-
return this._userIgnored(
|
|
17029
|
+
return this._userIgnored(path37, stats);
|
|
16969
17030
|
}
|
|
16970
|
-
_isntIgnored(
|
|
16971
|
-
return !this._isIgnored(
|
|
17031
|
+
_isntIgnored(path37, stat4) {
|
|
17032
|
+
return !this._isIgnored(path37, stat4);
|
|
16972
17033
|
}
|
|
16973
17034
|
/**
|
|
16974
17035
|
* Provides a set of common helpers and properties relating to symlink handling.
|
|
16975
17036
|
* @param path file or directory pattern being watched
|
|
16976
17037
|
*/
|
|
16977
|
-
_getWatchHelpers(
|
|
16978
|
-
return new WatchHelper(
|
|
17038
|
+
_getWatchHelpers(path37) {
|
|
17039
|
+
return new WatchHelper(path37, this.options.followSymlinks, this);
|
|
16979
17040
|
}
|
|
16980
17041
|
// Directory helpers
|
|
16981
17042
|
// -----------------
|
|
@@ -17007,63 +17068,63 @@ var FSWatcher = class extends import_events.EventEmitter {
|
|
|
17007
17068
|
* @param item base path of item/directory
|
|
17008
17069
|
*/
|
|
17009
17070
|
_remove(directory, item, isDirectory) {
|
|
17010
|
-
const
|
|
17011
|
-
const fullPath = sysPath2.resolve(
|
|
17012
|
-
isDirectory = isDirectory != null ? isDirectory : this._watched.has(
|
|
17013
|
-
if (!this._throttle("remove",
|
|
17071
|
+
const path37 = sysPath2.join(directory, item);
|
|
17072
|
+
const fullPath = sysPath2.resolve(path37);
|
|
17073
|
+
isDirectory = isDirectory != null ? isDirectory : this._watched.has(path37) || this._watched.has(fullPath);
|
|
17074
|
+
if (!this._throttle("remove", path37, 100))
|
|
17014
17075
|
return;
|
|
17015
17076
|
if (!isDirectory && this._watched.size === 1) {
|
|
17016
17077
|
this.add(directory, item, true);
|
|
17017
17078
|
}
|
|
17018
|
-
const wp = this._getWatchedDir(
|
|
17079
|
+
const wp = this._getWatchedDir(path37);
|
|
17019
17080
|
const nestedDirectoryChildren = wp.getChildren();
|
|
17020
|
-
nestedDirectoryChildren.forEach((nested) => this._remove(
|
|
17081
|
+
nestedDirectoryChildren.forEach((nested) => this._remove(path37, nested));
|
|
17021
17082
|
const parent = this._getWatchedDir(directory);
|
|
17022
17083
|
const wasTracked = parent.has(item);
|
|
17023
17084
|
parent.remove(item);
|
|
17024
17085
|
if (this._symlinkPaths.has(fullPath)) {
|
|
17025
17086
|
this._symlinkPaths.delete(fullPath);
|
|
17026
17087
|
}
|
|
17027
|
-
let relPath =
|
|
17088
|
+
let relPath = path37;
|
|
17028
17089
|
if (this.options.cwd)
|
|
17029
|
-
relPath = sysPath2.relative(this.options.cwd,
|
|
17090
|
+
relPath = sysPath2.relative(this.options.cwd, path37);
|
|
17030
17091
|
if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
|
|
17031
17092
|
const event = this._pendingWrites.get(relPath).cancelWait();
|
|
17032
17093
|
if (event === EVENTS.ADD)
|
|
17033
17094
|
return;
|
|
17034
17095
|
}
|
|
17035
|
-
this._watched.delete(
|
|
17096
|
+
this._watched.delete(path37);
|
|
17036
17097
|
this._watched.delete(fullPath);
|
|
17037
17098
|
const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
|
|
17038
|
-
if (wasTracked && !this._isIgnored(
|
|
17039
|
-
this._emit(eventName,
|
|
17040
|
-
this._closePath(
|
|
17099
|
+
if (wasTracked && !this._isIgnored(path37))
|
|
17100
|
+
this._emit(eventName, path37);
|
|
17101
|
+
this._closePath(path37);
|
|
17041
17102
|
}
|
|
17042
17103
|
/**
|
|
17043
17104
|
* Closes all watchers for a path
|
|
17044
17105
|
*/
|
|
17045
|
-
_closePath(
|
|
17046
|
-
this._closeFile(
|
|
17047
|
-
const dir = sysPath2.dirname(
|
|
17048
|
-
this._getWatchedDir(dir).remove(sysPath2.basename(
|
|
17106
|
+
_closePath(path37) {
|
|
17107
|
+
this._closeFile(path37);
|
|
17108
|
+
const dir = sysPath2.dirname(path37);
|
|
17109
|
+
this._getWatchedDir(dir).remove(sysPath2.basename(path37));
|
|
17049
17110
|
}
|
|
17050
17111
|
/**
|
|
17051
17112
|
* Closes only file-specific watchers
|
|
17052
17113
|
*/
|
|
17053
|
-
_closeFile(
|
|
17054
|
-
const closers = this._closers.get(
|
|
17114
|
+
_closeFile(path37) {
|
|
17115
|
+
const closers = this._closers.get(path37);
|
|
17055
17116
|
if (!closers)
|
|
17056
17117
|
return;
|
|
17057
17118
|
closers.forEach((closer) => closer());
|
|
17058
|
-
this._closers.delete(
|
|
17119
|
+
this._closers.delete(path37);
|
|
17059
17120
|
}
|
|
17060
|
-
_addPathCloser(
|
|
17121
|
+
_addPathCloser(path37, closer) {
|
|
17061
17122
|
if (!closer)
|
|
17062
17123
|
return;
|
|
17063
|
-
let list = this._closers.get(
|
|
17124
|
+
let list = this._closers.get(path37);
|
|
17064
17125
|
if (!list) {
|
|
17065
17126
|
list = [];
|
|
17066
|
-
this._closers.set(
|
|
17127
|
+
this._closers.set(path37, list);
|
|
17067
17128
|
}
|
|
17068
17129
|
list.push(closer);
|
|
17069
17130
|
}
|
|
@@ -17433,11 +17494,11 @@ function createStrictRateLimiterFromConfig(config) {
|
|
|
17433
17494
|
}
|
|
17434
17495
|
|
|
17435
17496
|
// modules/server/middleware/auto-rate-limit.ts
|
|
17436
|
-
function matchesStrictPattern(
|
|
17497
|
+
function matchesStrictPattern(path37, patterns) {
|
|
17437
17498
|
for (const pattern of patterns) {
|
|
17438
17499
|
const regexPattern = pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/\//g, "\\/");
|
|
17439
17500
|
const regex = new RegExp(`^${regexPattern}$`);
|
|
17440
|
-
if (regex.test(
|
|
17501
|
+
if (regex.test(path37)) {
|
|
17441
17502
|
return true;
|
|
17442
17503
|
}
|
|
17443
17504
|
}
|
|
@@ -17627,9 +17688,441 @@ async function handleApiRequest(options) {
|
|
|
17627
17688
|
}
|
|
17628
17689
|
}
|
|
17629
17690
|
|
|
17691
|
+
// modules/server/image-optimizer/index.ts
|
|
17692
|
+
var import_sharp = __toESM(require("sharp"));
|
|
17693
|
+
var import_fs27 = __toESM(require("fs"));
|
|
17694
|
+
var import_path37 = __toESM(require("path"));
|
|
17695
|
+
|
|
17696
|
+
// modules/server/image-optimizer/validation.ts
|
|
17697
|
+
var import_path35 = __toESM(require("path"));
|
|
17698
|
+
function isRemoteUrl(url) {
|
|
17699
|
+
return url.startsWith("http://") || url.startsWith("https://");
|
|
17700
|
+
}
|
|
17701
|
+
function sanitizeImagePath(imagePath) {
|
|
17702
|
+
const normalized = import_path35.default.normalize(imagePath).replace(/^(\.\.(\/|\\|$))+/, "");
|
|
17703
|
+
return normalized.replace(/^[/\\]+/, "");
|
|
17704
|
+
}
|
|
17705
|
+
function patternToRegex(pattern) {
|
|
17706
|
+
const parts = [];
|
|
17707
|
+
if (pattern.protocol) {
|
|
17708
|
+
parts.push(pattern.protocol === "https" ? "https" : "http");
|
|
17709
|
+
} else {
|
|
17710
|
+
parts.push("https?");
|
|
17711
|
+
}
|
|
17712
|
+
parts.push("://");
|
|
17713
|
+
let hostnamePattern = pattern.hostname.replace(/\./g, "\\.").replace(/\*\*/g, ".*").replace(/\*/g, "[^.]*");
|
|
17714
|
+
parts.push(hostnamePattern);
|
|
17715
|
+
if (pattern.port) {
|
|
17716
|
+
parts.push(`:${pattern.port}`);
|
|
17717
|
+
}
|
|
17718
|
+
if (pattern.pathname) {
|
|
17719
|
+
let pathnamePattern = pattern.pathname.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*");
|
|
17720
|
+
parts.push(pathnamePattern);
|
|
17721
|
+
} else {
|
|
17722
|
+
parts.push(".*");
|
|
17723
|
+
}
|
|
17724
|
+
const regexSource = `^${parts.join("")}`;
|
|
17725
|
+
return new RegExp(regexSource);
|
|
17726
|
+
}
|
|
17727
|
+
function validateRemoteUrl(url, config) {
|
|
17728
|
+
if (!config.remotePatterns && !config.domains) {
|
|
17729
|
+
return false;
|
|
17730
|
+
}
|
|
17731
|
+
try {
|
|
17732
|
+
const urlObj = new URL(url);
|
|
17733
|
+
const protocol = urlObj.protocol.replace(":", "");
|
|
17734
|
+
const hostname = urlObj.hostname;
|
|
17735
|
+
const port = urlObj.port || "";
|
|
17736
|
+
const pathname = urlObj.pathname;
|
|
17737
|
+
if (config.remotePatterns && config.remotePatterns.length > 0) {
|
|
17738
|
+
for (const pattern of config.remotePatterns) {
|
|
17739
|
+
const regex = patternToRegex(pattern);
|
|
17740
|
+
const testUrl = `${protocol}://${hostname}${port ? `:${port}` : ""}${pathname}`;
|
|
17741
|
+
if (regex.test(testUrl)) {
|
|
17742
|
+
if (pattern.protocol && pattern.protocol !== protocol) {
|
|
17743
|
+
continue;
|
|
17744
|
+
}
|
|
17745
|
+
if (pattern.port && pattern.port !== port) {
|
|
17746
|
+
continue;
|
|
17747
|
+
}
|
|
17748
|
+
return true;
|
|
17749
|
+
}
|
|
17750
|
+
}
|
|
17751
|
+
}
|
|
17752
|
+
if (config.domains && config.domains.length > 0) {
|
|
17753
|
+
for (const domain of config.domains) {
|
|
17754
|
+
const domainPattern = domain.replace(/\./g, "\\.").replace(/\*\*/g, ".*").replace(/\*/g, "[^.]*");
|
|
17755
|
+
const regex = new RegExp(`^${domainPattern}$`);
|
|
17756
|
+
if (regex.test(hostname)) {
|
|
17757
|
+
if (process.env.NODE_ENV === "production" && protocol !== "https") {
|
|
17758
|
+
continue;
|
|
17759
|
+
}
|
|
17760
|
+
return true;
|
|
17761
|
+
}
|
|
17762
|
+
}
|
|
17763
|
+
}
|
|
17764
|
+
return false;
|
|
17765
|
+
} catch (error) {
|
|
17766
|
+
return false;
|
|
17767
|
+
}
|
|
17768
|
+
}
|
|
17769
|
+
function validateImageDimensions(width, height, config) {
|
|
17770
|
+
const maxWidth = config.maxWidth || 3840;
|
|
17771
|
+
const maxHeight = config.maxHeight || 3840;
|
|
17772
|
+
if (width !== void 0 && (width <= 0 || width > maxWidth)) {
|
|
17773
|
+
return {
|
|
17774
|
+
valid: false,
|
|
17775
|
+
error: `Image width must be between 1 and ${maxWidth}, got ${width}`
|
|
17776
|
+
};
|
|
17777
|
+
}
|
|
17778
|
+
if (height !== void 0 && (height <= 0 || height > maxHeight)) {
|
|
17779
|
+
return {
|
|
17780
|
+
valid: false,
|
|
17781
|
+
error: `Image height must be between 1 and ${maxHeight}, got ${height}`
|
|
17782
|
+
};
|
|
17783
|
+
}
|
|
17784
|
+
return { valid: true };
|
|
17785
|
+
}
|
|
17786
|
+
function validateQuality(quality) {
|
|
17787
|
+
if (quality === void 0) {
|
|
17788
|
+
return { valid: true };
|
|
17789
|
+
}
|
|
17790
|
+
if (typeof quality !== "number" || quality < 1 || quality > 100) {
|
|
17791
|
+
return {
|
|
17792
|
+
valid: false,
|
|
17793
|
+
error: `Image quality must be between 1 and 100, got ${quality}`
|
|
17794
|
+
};
|
|
17795
|
+
}
|
|
17796
|
+
return { valid: true };
|
|
17797
|
+
}
|
|
17798
|
+
|
|
17799
|
+
// modules/server/image-optimizer/cache.ts
|
|
17800
|
+
var import_fs26 = __toESM(require("fs"));
|
|
17801
|
+
var import_path36 = __toESM(require("path"));
|
|
17802
|
+
var import_crypto = __toESM(require("crypto"));
|
|
17803
|
+
function generateCacheKey(src, width, height, quality, format) {
|
|
17804
|
+
const data = `${src}-${width || ""}-${height || ""}-${quality || ""}-${format || ""}`;
|
|
17805
|
+
return import_crypto.default.createHash("sha256").update(data).digest("hex");
|
|
17806
|
+
}
|
|
17807
|
+
function getCacheDir(projectRoot, config) {
|
|
17808
|
+
const buildDir = getBuildDir(projectRoot, config);
|
|
17809
|
+
return import_path36.default.join(buildDir, "cache", "images");
|
|
17810
|
+
}
|
|
17811
|
+
function ensureCacheDir(cacheDir) {
|
|
17812
|
+
if (!import_fs26.default.existsSync(cacheDir)) {
|
|
17813
|
+
import_fs26.default.mkdirSync(cacheDir, { recursive: true });
|
|
17814
|
+
}
|
|
17815
|
+
}
|
|
17816
|
+
function getCachedImagePath(cacheKey, extension, cacheDir) {
|
|
17817
|
+
return import_path36.default.join(cacheDir, `${cacheKey}.${extension}`);
|
|
17818
|
+
}
|
|
17819
|
+
function hasCachedImage(cacheKey, extension, cacheDir) {
|
|
17820
|
+
const cachedPath = getCachedImagePath(cacheKey, extension, cacheDir);
|
|
17821
|
+
return import_fs26.default.existsSync(cachedPath);
|
|
17822
|
+
}
|
|
17823
|
+
function readCachedImage(cacheKey, extension, cacheDir) {
|
|
17824
|
+
const cachedPath = getCachedImagePath(cacheKey, extension, cacheDir);
|
|
17825
|
+
try {
|
|
17826
|
+
if (import_fs26.default.existsSync(cachedPath)) {
|
|
17827
|
+
return import_fs26.default.readFileSync(cachedPath);
|
|
17828
|
+
}
|
|
17829
|
+
} catch (error) {
|
|
17830
|
+
console.warn(`[image-optimizer] Failed to read cached image: ${cachedPath}`, error);
|
|
17831
|
+
}
|
|
17832
|
+
return null;
|
|
17833
|
+
}
|
|
17834
|
+
function writeCachedImage(cacheKey, extension, cacheDir, imageBuffer) {
|
|
17835
|
+
ensureCacheDir(cacheDir);
|
|
17836
|
+
const cachedPath = getCachedImagePath(cacheKey, extension, cacheDir);
|
|
17837
|
+
try {
|
|
17838
|
+
import_fs26.default.writeFileSync(cachedPath, imageBuffer);
|
|
17839
|
+
} catch (error) {
|
|
17840
|
+
console.warn(`[image-optimizer] Failed to write cached image: ${cachedPath}`, error);
|
|
17841
|
+
}
|
|
17842
|
+
}
|
|
17843
|
+
function getImageMimeType(format) {
|
|
17844
|
+
const formatMap = {
|
|
17845
|
+
webp: "image/webp",
|
|
17846
|
+
avif: "image/avif",
|
|
17847
|
+
jpeg: "image/jpeg",
|
|
17848
|
+
jpg: "image/jpeg",
|
|
17849
|
+
png: "image/png",
|
|
17850
|
+
gif: "image/gif",
|
|
17851
|
+
svg: "image/svg+xml"
|
|
17852
|
+
};
|
|
17853
|
+
const normalized = format.toLowerCase();
|
|
17854
|
+
return formatMap[normalized] || "image/jpeg";
|
|
17855
|
+
}
|
|
17856
|
+
function getImageExtension(format) {
|
|
17857
|
+
const formatMap = {
|
|
17858
|
+
"image/webp": "webp",
|
|
17859
|
+
"image/avif": "avif",
|
|
17860
|
+
"image/jpeg": "jpg",
|
|
17861
|
+
"image/png": "png",
|
|
17862
|
+
"image/gif": "gif",
|
|
17863
|
+
"image/svg+xml": "svg",
|
|
17864
|
+
webp: "webp",
|
|
17865
|
+
avif: "avif",
|
|
17866
|
+
jpeg: "jpg",
|
|
17867
|
+
jpg: "jpg",
|
|
17868
|
+
png: "png",
|
|
17869
|
+
gif: "gif",
|
|
17870
|
+
svg: "svg"
|
|
17871
|
+
};
|
|
17872
|
+
const normalized = format.toLowerCase();
|
|
17873
|
+
return formatMap[normalized] || "jpg";
|
|
17874
|
+
}
|
|
17875
|
+
|
|
17876
|
+
// modules/server/image-optimizer/index.ts
|
|
17877
|
+
async function downloadRemoteImage(url, timeout = 1e4) {
|
|
17878
|
+
let fetchFn;
|
|
17879
|
+
try {
|
|
17880
|
+
if (typeof fetch !== "undefined") {
|
|
17881
|
+
fetchFn = fetch;
|
|
17882
|
+
} else {
|
|
17883
|
+
const { fetch: undiciFetch } = await import("undici");
|
|
17884
|
+
fetchFn = undiciFetch;
|
|
17885
|
+
}
|
|
17886
|
+
} catch (error) {
|
|
17887
|
+
throw new Error("Failed to load fetch implementation. Node 18+ required or install undici.");
|
|
17888
|
+
}
|
|
17889
|
+
const controller = new AbortController();
|
|
17890
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
17891
|
+
try {
|
|
17892
|
+
const response = await fetchFn(url, {
|
|
17893
|
+
signal: controller.signal,
|
|
17894
|
+
headers: {
|
|
17895
|
+
"User-Agent": "Loly-Image-Optimizer/1.0"
|
|
17896
|
+
}
|
|
17897
|
+
});
|
|
17898
|
+
clearTimeout(timeoutId);
|
|
17899
|
+
if (!response.ok) {
|
|
17900
|
+
throw new Error(`Failed to download image: ${response.status} ${response.statusText}`);
|
|
17901
|
+
}
|
|
17902
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
17903
|
+
return Buffer.from(arrayBuffer);
|
|
17904
|
+
} catch (error) {
|
|
17905
|
+
clearTimeout(timeoutId);
|
|
17906
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
17907
|
+
throw new Error(`Image download timeout after ${timeout}ms`);
|
|
17908
|
+
}
|
|
17909
|
+
throw error;
|
|
17910
|
+
}
|
|
17911
|
+
}
|
|
17912
|
+
function readLocalImage(src, projectRoot, config) {
|
|
17913
|
+
const sanitized = sanitizeImagePath(src);
|
|
17914
|
+
const staticDir = getStaticDir(projectRoot, config);
|
|
17915
|
+
const staticPath = import_path37.default.join(staticDir, sanitized);
|
|
17916
|
+
if (import_fs27.default.existsSync(staticPath)) {
|
|
17917
|
+
return import_fs27.default.readFileSync(staticPath);
|
|
17918
|
+
}
|
|
17919
|
+
if (src.startsWith("/")) {
|
|
17920
|
+
const absolutePath = import_path37.default.join(projectRoot, sanitized);
|
|
17921
|
+
if (import_fs27.default.existsSync(absolutePath)) {
|
|
17922
|
+
return import_fs27.default.readFileSync(absolutePath);
|
|
17923
|
+
}
|
|
17924
|
+
}
|
|
17925
|
+
throw new Error(`Image not found: ${src}`);
|
|
17926
|
+
}
|
|
17927
|
+
function determineOutputFormat(sourceFormat, requestedFormat, config) {
|
|
17928
|
+
if (sourceFormat === "svg") {
|
|
17929
|
+
return "svg";
|
|
17930
|
+
}
|
|
17931
|
+
if (requestedFormat && requestedFormat !== "auto") {
|
|
17932
|
+
return requestedFormat;
|
|
17933
|
+
}
|
|
17934
|
+
const supportedFormats = config.formats || ["image/webp"];
|
|
17935
|
+
if (supportedFormats.includes("image/avif")) {
|
|
17936
|
+
return "avif";
|
|
17937
|
+
}
|
|
17938
|
+
if (supportedFormats.includes("image/webp")) {
|
|
17939
|
+
return "webp";
|
|
17940
|
+
}
|
|
17941
|
+
return sourceFormat === "svg" ? "jpeg" : sourceFormat;
|
|
17942
|
+
}
|
|
17943
|
+
async function optimizeImage(options, projectRoot, config) {
|
|
17944
|
+
const imageConfig = config.images || {};
|
|
17945
|
+
const dimValidation = validateImageDimensions(options.width, options.height, imageConfig);
|
|
17946
|
+
if (!dimValidation.valid) {
|
|
17947
|
+
throw new Error(dimValidation.error);
|
|
17948
|
+
}
|
|
17949
|
+
const qualityValidation = validateQuality(options.quality);
|
|
17950
|
+
if (!qualityValidation.valid) {
|
|
17951
|
+
throw new Error(qualityValidation.error);
|
|
17952
|
+
}
|
|
17953
|
+
if (isRemoteUrl(options.src)) {
|
|
17954
|
+
if (!validateRemoteUrl(options.src, imageConfig)) {
|
|
17955
|
+
throw new Error(`Remote image domain not allowed: ${options.src}`);
|
|
17956
|
+
}
|
|
17957
|
+
}
|
|
17958
|
+
const sourceFormat = import_path37.default.extname(options.src).slice(1).toLowerCase() || "jpeg";
|
|
17959
|
+
const outputFormat = determineOutputFormat(
|
|
17960
|
+
sourceFormat,
|
|
17961
|
+
options.format,
|
|
17962
|
+
imageConfig
|
|
17963
|
+
);
|
|
17964
|
+
const cacheKey = generateCacheKey(
|
|
17965
|
+
options.src,
|
|
17966
|
+
options.width,
|
|
17967
|
+
options.height,
|
|
17968
|
+
options.quality || imageConfig.quality || 75,
|
|
17969
|
+
outputFormat
|
|
17970
|
+
);
|
|
17971
|
+
const cacheDir = getCacheDir(projectRoot, config);
|
|
17972
|
+
const extension = getImageExtension(outputFormat);
|
|
17973
|
+
if (hasCachedImage(cacheKey, extension, cacheDir)) {
|
|
17974
|
+
const cached = readCachedImage(cacheKey, extension, cacheDir);
|
|
17975
|
+
if (cached) {
|
|
17976
|
+
const metadata2 = await (0, import_sharp.default)(cached).metadata();
|
|
17977
|
+
return {
|
|
17978
|
+
buffer: cached,
|
|
17979
|
+
format: outputFormat,
|
|
17980
|
+
mimeType: getImageMimeType(outputFormat),
|
|
17981
|
+
width: metadata2.width || options.width || 0,
|
|
17982
|
+
height: metadata2.height || options.height || 0
|
|
17983
|
+
};
|
|
17984
|
+
}
|
|
17985
|
+
}
|
|
17986
|
+
let imageBuffer;
|
|
17987
|
+
if (isRemoteUrl(options.src)) {
|
|
17988
|
+
imageBuffer = await downloadRemoteImage(options.src);
|
|
17989
|
+
} else {
|
|
17990
|
+
imageBuffer = readLocalImage(options.src, projectRoot, config);
|
|
17991
|
+
}
|
|
17992
|
+
if (outputFormat === "svg" || sourceFormat === "svg") {
|
|
17993
|
+
if (!imageConfig.dangerouslyAllowSVG) {
|
|
17994
|
+
throw new Error("SVG images are not allowed. Set images.dangerouslyAllowSVG to true to enable.");
|
|
17995
|
+
}
|
|
17996
|
+
return {
|
|
17997
|
+
buffer: imageBuffer,
|
|
17998
|
+
format: "svg",
|
|
17999
|
+
mimeType: "image/svg+xml",
|
|
18000
|
+
width: options.width || 0,
|
|
18001
|
+
height: options.height || 0
|
|
18002
|
+
};
|
|
18003
|
+
}
|
|
18004
|
+
let sharpInstance = (0, import_sharp.default)(imageBuffer);
|
|
18005
|
+
const metadata = await sharpInstance.metadata();
|
|
18006
|
+
if (options.width || options.height) {
|
|
18007
|
+
const fit = options.fit || "cover";
|
|
18008
|
+
sharpInstance = sharpInstance.resize(options.width, options.height, {
|
|
18009
|
+
fit,
|
|
18010
|
+
withoutEnlargement: true
|
|
18011
|
+
});
|
|
18012
|
+
}
|
|
18013
|
+
const quality = options.quality || imageConfig.quality || 75;
|
|
18014
|
+
switch (outputFormat) {
|
|
18015
|
+
case "webp":
|
|
18016
|
+
sharpInstance = sharpInstance.webp({ quality });
|
|
18017
|
+
break;
|
|
18018
|
+
case "avif":
|
|
18019
|
+
sharpInstance = sharpInstance.avif({ quality });
|
|
18020
|
+
break;
|
|
18021
|
+
case "jpeg":
|
|
18022
|
+
case "jpg":
|
|
18023
|
+
sharpInstance = sharpInstance.jpeg({ quality });
|
|
18024
|
+
break;
|
|
18025
|
+
case "png":
|
|
18026
|
+
sharpInstance = sharpInstance.png({ quality: Math.round(quality / 100 * 9) });
|
|
18027
|
+
break;
|
|
18028
|
+
default:
|
|
18029
|
+
sharpInstance = sharpInstance.jpeg({ quality });
|
|
18030
|
+
}
|
|
18031
|
+
const optimizedBuffer = await sharpInstance.toBuffer();
|
|
18032
|
+
const finalMetadata = await (0, import_sharp.default)(optimizedBuffer).metadata();
|
|
18033
|
+
writeCachedImage(cacheKey, extension, cacheDir, optimizedBuffer);
|
|
18034
|
+
return {
|
|
18035
|
+
buffer: optimizedBuffer,
|
|
18036
|
+
format: outputFormat,
|
|
18037
|
+
mimeType: getImageMimeType(outputFormat),
|
|
18038
|
+
width: finalMetadata.width || options.width || metadata.width || 0,
|
|
18039
|
+
height: finalMetadata.height || options.height || metadata.height || 0
|
|
18040
|
+
};
|
|
18041
|
+
}
|
|
18042
|
+
|
|
18043
|
+
// modules/server/handlers/image.ts
|
|
18044
|
+
async function handleImageRequest(options) {
|
|
18045
|
+
const { req, res, projectRoot, config } = options;
|
|
18046
|
+
try {
|
|
18047
|
+
const src = req.query.src;
|
|
18048
|
+
const width = req.query.w ? parseInt(req.query.w, 10) : void 0;
|
|
18049
|
+
const height = req.query.h ? parseInt(req.query.h, 10) : void 0;
|
|
18050
|
+
const quality = req.query.q ? parseInt(req.query.q, 10) : void 0;
|
|
18051
|
+
const format = req.query.format;
|
|
18052
|
+
const fit = req.query.fit;
|
|
18053
|
+
if (!src) {
|
|
18054
|
+
res.status(400).json({
|
|
18055
|
+
error: "Missing required parameter: src"
|
|
18056
|
+
});
|
|
18057
|
+
return;
|
|
18058
|
+
}
|
|
18059
|
+
if (typeof src !== "string") {
|
|
18060
|
+
res.status(400).json({
|
|
18061
|
+
error: "Parameter 'src' must be a string"
|
|
18062
|
+
});
|
|
18063
|
+
return;
|
|
18064
|
+
}
|
|
18065
|
+
const result = await optimizeImage(
|
|
18066
|
+
{
|
|
18067
|
+
src,
|
|
18068
|
+
width,
|
|
18069
|
+
height,
|
|
18070
|
+
quality,
|
|
18071
|
+
format,
|
|
18072
|
+
fit
|
|
18073
|
+
},
|
|
18074
|
+
projectRoot,
|
|
18075
|
+
config
|
|
18076
|
+
);
|
|
18077
|
+
const imageConfig = config.images || {};
|
|
18078
|
+
const cacheTTL = imageConfig.minimumCacheTTL || 60;
|
|
18079
|
+
res.setHeader("Content-Type", result.mimeType);
|
|
18080
|
+
res.setHeader("Content-Length", result.buffer.length);
|
|
18081
|
+
res.setHeader("Cache-Control", `public, max-age=${cacheTTL}, immutable`);
|
|
18082
|
+
res.setHeader("X-Content-Type-Options", "nosniff");
|
|
18083
|
+
res.send(result.buffer);
|
|
18084
|
+
} catch (error) {
|
|
18085
|
+
if (error instanceof Error) {
|
|
18086
|
+
if (error.message.includes("not allowed")) {
|
|
18087
|
+
res.status(403).json({
|
|
18088
|
+
error: "Forbidden",
|
|
18089
|
+
message: error.message
|
|
18090
|
+
});
|
|
18091
|
+
return;
|
|
18092
|
+
}
|
|
18093
|
+
if (error.message.includes("not found") || error.message.includes("Image not found")) {
|
|
18094
|
+
res.status(404).json({
|
|
18095
|
+
error: "Not Found",
|
|
18096
|
+
message: error.message
|
|
18097
|
+
});
|
|
18098
|
+
return;
|
|
18099
|
+
}
|
|
18100
|
+
if (error.message.includes("must be")) {
|
|
18101
|
+
res.status(400).json({
|
|
18102
|
+
error: "Bad Request",
|
|
18103
|
+
message: error.message
|
|
18104
|
+
});
|
|
18105
|
+
return;
|
|
18106
|
+
}
|
|
18107
|
+
if (error.message.includes("timeout") || error.message.includes("download")) {
|
|
18108
|
+
res.status(504).json({
|
|
18109
|
+
error: "Gateway Timeout",
|
|
18110
|
+
message: error.message
|
|
18111
|
+
});
|
|
18112
|
+
return;
|
|
18113
|
+
}
|
|
18114
|
+
}
|
|
18115
|
+
console.error("[image-optimizer] Error processing image:", error);
|
|
18116
|
+
res.status(500).json({
|
|
18117
|
+
error: "Internal Server Error",
|
|
18118
|
+
message: "Failed to process image"
|
|
18119
|
+
});
|
|
18120
|
+
}
|
|
18121
|
+
}
|
|
18122
|
+
|
|
17630
18123
|
// modules/server/routes.ts
|
|
17631
18124
|
init_globals();
|
|
17632
|
-
var
|
|
18125
|
+
var import_path38 = __toESM(require("path"));
|
|
17633
18126
|
var cachedRewriteLoader = null;
|
|
17634
18127
|
var cachedProjectRoot = null;
|
|
17635
18128
|
var cachedIsDev = null;
|
|
@@ -17657,10 +18150,20 @@ function setupRoutes(options) {
|
|
|
17657
18150
|
} = options;
|
|
17658
18151
|
const routeChunks = routeLoader.loadRouteChunks();
|
|
17659
18152
|
const rewriteLoader = getRewriteLoader(projectRoot, isDev);
|
|
17660
|
-
const ssgOutDir =
|
|
17661
|
-
config ? getBuildDir(projectRoot, config) :
|
|
18153
|
+
const ssgOutDir = import_path38.default.join(
|
|
18154
|
+
config ? getBuildDir(projectRoot, config) : import_path38.default.join(projectRoot, BUILD_FOLDER_NAME),
|
|
17662
18155
|
"ssg"
|
|
17663
18156
|
);
|
|
18157
|
+
if (config) {
|
|
18158
|
+
app.get("/_loly/image", async (req, res) => {
|
|
18159
|
+
await handleImageRequest({
|
|
18160
|
+
req,
|
|
18161
|
+
res,
|
|
18162
|
+
projectRoot,
|
|
18163
|
+
config
|
|
18164
|
+
});
|
|
18165
|
+
});
|
|
18166
|
+
}
|
|
17664
18167
|
app.all("/api/*", async (req, res) => {
|
|
17665
18168
|
const apiRoutes = isDev && getRoutes ? (await getRoutes()).apiRoutes : initialApiRoutes;
|
|
17666
18169
|
const serverConfig = await getServerConfig(projectRoot);
|
|
@@ -18707,7 +19210,7 @@ var import_cors = __toESM(require("cors"));
|
|
|
18707
19210
|
var import_helmet = __toESM(require("helmet"));
|
|
18708
19211
|
var import_cookie_parser = __toESM(require("cookie-parser"));
|
|
18709
19212
|
var import_compression = __toESM(require("compression"));
|
|
18710
|
-
var
|
|
19213
|
+
var import_crypto2 = __toESM(require("crypto"));
|
|
18711
19214
|
var setupApplication = async ({
|
|
18712
19215
|
projectRoot
|
|
18713
19216
|
}) => {
|
|
@@ -18816,7 +19319,7 @@ var setupApplication = async ({
|
|
|
18816
19319
|
if (process.env.NODE_ENV !== "development" && security?.contentSecurityPolicy !== false) {
|
|
18817
19320
|
app.use(
|
|
18818
19321
|
(req, res, next) => {
|
|
18819
|
-
const nonce =
|
|
19322
|
+
const nonce = import_crypto2.default.randomBytes(16).toString("base64");
|
|
18820
19323
|
res.locals.nonce = nonce;
|
|
18821
19324
|
next();
|
|
18822
19325
|
}
|
|
@@ -18887,8 +19390,8 @@ var setupApplication = async ({
|
|
|
18887
19390
|
|
|
18888
19391
|
// src/server.ts
|
|
18889
19392
|
var import_dotenv2 = __toESM(require("dotenv"));
|
|
18890
|
-
var envPath =
|
|
18891
|
-
if (
|
|
19393
|
+
var envPath = import_path39.default.join(process.cwd(), ".env");
|
|
19394
|
+
if (import_fs28.default.existsSync(envPath)) {
|
|
18892
19395
|
import_dotenv2.default.config({ path: envPath });
|
|
18893
19396
|
} else {
|
|
18894
19397
|
import_dotenv2.default.config();
|
|
@@ -18909,8 +19412,8 @@ async function startServer(options = {}) {
|
|
|
18909
19412
|
}
|
|
18910
19413
|
const port = options.port ?? (process.env.PORT ? parseInt(process.env.PORT, 10) : void 0) ?? config.server.port;
|
|
18911
19414
|
const host = process.env.HOST ?? (!isDev ? "0.0.0.0" : void 0) ?? config.server.host;
|
|
18912
|
-
const appDir = options.appDir ?? (isDev ? getAppDir(projectRoot, config) :
|
|
18913
|
-
if (!isDev && !
|
|
19415
|
+
const appDir = options.appDir ?? (isDev ? getAppDir(projectRoot, config) : import_path39.default.join(getBuildDir(projectRoot, config), "server"));
|
|
19416
|
+
if (!isDev && !import_fs28.default.existsSync(appDir)) {
|
|
18914
19417
|
logger4.error("Compiled directory not found", void 0, {
|
|
18915
19418
|
buildDir: config.directories.build,
|
|
18916
19419
|
appDir,
|
|
@@ -19106,7 +19609,7 @@ async function run() {
|
|
|
19106
19609
|
}
|
|
19107
19610
|
const args = parseArgs(argv.slice(1));
|
|
19108
19611
|
const projectRoot = import_process.default.cwd();
|
|
19109
|
-
const appDir =
|
|
19612
|
+
const appDir = import_path40.default.resolve(projectRoot, args.appDir || "app");
|
|
19110
19613
|
const port = typeof args.port === "string" && args.port.trim().length > 0 ? Number(args.port) : 3e3;
|
|
19111
19614
|
switch (command) {
|
|
19112
19615
|
case "dev": {
|