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