@lolyjs/core 0.3.0-alpha.4 → 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/dist/index.mjs CHANGED
@@ -9957,8 +9957,8 @@ var require_built3 = __commonJS({
9957
9957
  });
9958
9958
 
9959
9959
  // src/server.ts
9960
- import fs21 from "fs";
9961
- import path27 from "path";
9960
+ import fs23 from "fs";
9961
+ import path30 from "path";
9962
9962
 
9963
9963
  // modules/server/utils/server-dir.ts
9964
9964
  init_globals();
@@ -11794,6 +11794,7 @@ async function processRewrites(urlPath, compiledRewrites, req) {
11794
11794
  const normalizedPath = urlPath.replace(/\/$/, "") || "/";
11795
11795
  if (normalizedPath.startsWith("/static/") || // Static assets (client.js, client.css, etc.)
11796
11796
  normalizedPath.startsWith("/__fw/") || // Framework internal routes (hot reload, etc.)
11797
+ normalizedPath.startsWith("/_loly/") || // Framework internal routes (image optimization, etc.)
11797
11798
  normalizedPath === "/favicon.ico" || // Favicon
11798
11799
  normalizedPath.startsWith("/wss/")) {
11799
11800
  if (process.env.NODE_ENV === "development") {
@@ -12703,7 +12704,7 @@ var ReaddirpStream = class extends Readable {
12703
12704
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
12704
12705
  const statMethod = opts.lstat ? lstat : stat;
12705
12706
  if (wantBigintFsStats) {
12706
- this._stat = (path33) => statMethod(path33, { bigint: true });
12707
+ this._stat = (path36) => statMethod(path36, { bigint: true });
12707
12708
  } else {
12708
12709
  this._stat = statMethod;
12709
12710
  }
@@ -12728,8 +12729,8 @@ var ReaddirpStream = class extends Readable {
12728
12729
  const par = this.parent;
12729
12730
  const fil = par && par.files;
12730
12731
  if (fil && fil.length > 0) {
12731
- const { path: path33, depth } = par;
12732
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path33));
12732
+ const { path: path36, depth } = par;
12733
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path36));
12733
12734
  const awaited = await Promise.all(slice);
12734
12735
  for (const entry of awaited) {
12735
12736
  if (!entry)
@@ -12769,20 +12770,20 @@ var ReaddirpStream = class extends Readable {
12769
12770
  this.reading = false;
12770
12771
  }
12771
12772
  }
12772
- async _exploreDir(path33, depth) {
12773
+ async _exploreDir(path36, depth) {
12773
12774
  let files;
12774
12775
  try {
12775
- files = await readdir(path33, this._rdOptions);
12776
+ files = await readdir(path36, this._rdOptions);
12776
12777
  } catch (error) {
12777
12778
  this._onError(error);
12778
12779
  }
12779
- return { files, depth, path: path33 };
12780
+ return { files, depth, path: path36 };
12780
12781
  }
12781
- async _formatEntry(dirent, path33) {
12782
+ async _formatEntry(dirent, path36) {
12782
12783
  let entry;
12783
12784
  const basename3 = this._isDirent ? dirent.name : dirent;
12784
12785
  try {
12785
- const fullPath = presolve(pjoin(path33, basename3));
12786
+ const fullPath = presolve(pjoin(path36, basename3));
12786
12787
  entry = { path: prelative(this._root, fullPath), fullPath, basename: basename3 };
12787
12788
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
12788
12789
  } catch (err) {
@@ -13182,16 +13183,16 @@ var delFromSet = (main, prop, item) => {
13182
13183
  };
13183
13184
  var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
13184
13185
  var FsWatchInstances = /* @__PURE__ */ new Map();
13185
- function createFsWatchInstance(path33, options, listener, errHandler, emitRaw) {
13186
+ function createFsWatchInstance(path36, options, listener, errHandler, emitRaw) {
13186
13187
  const handleEvent = (rawEvent, evPath) => {
13187
- listener(path33);
13188
- emitRaw(rawEvent, evPath, { watchedPath: path33 });
13189
- if (evPath && path33 !== evPath) {
13190
- fsWatchBroadcast(sysPath.resolve(path33, evPath), KEY_LISTENERS, sysPath.join(path33, evPath));
13188
+ listener(path36);
13189
+ emitRaw(rawEvent, evPath, { watchedPath: path36 });
13190
+ if (evPath && path36 !== evPath) {
13191
+ fsWatchBroadcast(sysPath.resolve(path36, evPath), KEY_LISTENERS, sysPath.join(path36, evPath));
13191
13192
  }
13192
13193
  };
13193
13194
  try {
13194
- return fs_watch(path33, {
13195
+ return fs_watch(path36, {
13195
13196
  persistent: options.persistent
13196
13197
  }, handleEvent);
13197
13198
  } catch (error) {
@@ -13207,12 +13208,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
13207
13208
  listener(val1, val2, val3);
13208
13209
  });
13209
13210
  };
13210
- var setFsWatchListener = (path33, fullPath, options, handlers) => {
13211
+ var setFsWatchListener = (path36, fullPath, options, handlers) => {
13211
13212
  const { listener, errHandler, rawEmitter } = handlers;
13212
13213
  let cont = FsWatchInstances.get(fullPath);
13213
13214
  let watcher;
13214
13215
  if (!options.persistent) {
13215
- watcher = createFsWatchInstance(path33, options, listener, errHandler, rawEmitter);
13216
+ watcher = createFsWatchInstance(path36, options, listener, errHandler, rawEmitter);
13216
13217
  if (!watcher)
13217
13218
  return;
13218
13219
  return watcher.close.bind(watcher);
@@ -13223,7 +13224,7 @@ var setFsWatchListener = (path33, fullPath, options, handlers) => {
13223
13224
  addAndConvert(cont, KEY_RAW, rawEmitter);
13224
13225
  } else {
13225
13226
  watcher = createFsWatchInstance(
13226
- path33,
13227
+ path36,
13227
13228
  options,
13228
13229
  fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
13229
13230
  errHandler,
@@ -13238,7 +13239,7 @@ var setFsWatchListener = (path33, fullPath, options, handlers) => {
13238
13239
  cont.watcherUnusable = true;
13239
13240
  if (isWindows && error.code === "EPERM") {
13240
13241
  try {
13241
- const fd = await open(path33, "r");
13242
+ const fd = await open(path36, "r");
13242
13243
  await fd.close();
13243
13244
  broadcastErr(error);
13244
13245
  } catch (err) {
@@ -13269,7 +13270,7 @@ var setFsWatchListener = (path33, fullPath, options, handlers) => {
13269
13270
  };
13270
13271
  };
13271
13272
  var FsWatchFileInstances = /* @__PURE__ */ new Map();
13272
- var setFsWatchFileListener = (path33, fullPath, options, handlers) => {
13273
+ var setFsWatchFileListener = (path36, fullPath, options, handlers) => {
13273
13274
  const { listener, rawEmitter } = handlers;
13274
13275
  let cont = FsWatchFileInstances.get(fullPath);
13275
13276
  const copts = cont && cont.options;
@@ -13291,7 +13292,7 @@ var setFsWatchFileListener = (path33, fullPath, options, handlers) => {
13291
13292
  });
13292
13293
  const currmtime = curr.mtimeMs;
13293
13294
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
13294
- foreach(cont.listeners, (listener2) => listener2(path33, curr));
13295
+ foreach(cont.listeners, (listener2) => listener2(path36, curr));
13295
13296
  }
13296
13297
  })
13297
13298
  };
@@ -13319,13 +13320,13 @@ var NodeFsHandler = class {
13319
13320
  * @param listener on fs change
13320
13321
  * @returns closer for the watcher instance
13321
13322
  */
13322
- _watchWithNodeFs(path33, listener) {
13323
+ _watchWithNodeFs(path36, listener) {
13323
13324
  const opts = this.fsw.options;
13324
- const directory = sysPath.dirname(path33);
13325
- const basename3 = sysPath.basename(path33);
13325
+ const directory = sysPath.dirname(path36);
13326
+ const basename3 = sysPath.basename(path36);
13326
13327
  const parent = this.fsw._getWatchedDir(directory);
13327
13328
  parent.add(basename3);
13328
- const absolutePath = sysPath.resolve(path33);
13329
+ const absolutePath = sysPath.resolve(path36);
13329
13330
  const options = {
13330
13331
  persistent: opts.persistent
13331
13332
  };
@@ -13335,12 +13336,12 @@ var NodeFsHandler = class {
13335
13336
  if (opts.usePolling) {
13336
13337
  const enableBin = opts.interval !== opts.binaryInterval;
13337
13338
  options.interval = enableBin && isBinaryPath(basename3) ? opts.binaryInterval : opts.interval;
13338
- closer = setFsWatchFileListener(path33, absolutePath, options, {
13339
+ closer = setFsWatchFileListener(path36, absolutePath, options, {
13339
13340
  listener,
13340
13341
  rawEmitter: this.fsw._emitRaw
13341
13342
  });
13342
13343
  } else {
13343
- closer = setFsWatchListener(path33, absolutePath, options, {
13344
+ closer = setFsWatchListener(path36, absolutePath, options, {
13344
13345
  listener,
13345
13346
  errHandler: this._boundHandleError,
13346
13347
  rawEmitter: this.fsw._emitRaw
@@ -13362,7 +13363,7 @@ var NodeFsHandler = class {
13362
13363
  let prevStats = stats;
13363
13364
  if (parent.has(basename3))
13364
13365
  return;
13365
- const listener = async (path33, newStats) => {
13366
+ const listener = async (path36, newStats) => {
13366
13367
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file, 5))
13367
13368
  return;
13368
13369
  if (!newStats || newStats.mtimeMs === 0) {
@@ -13376,11 +13377,11 @@ var NodeFsHandler = class {
13376
13377
  this.fsw._emit(EV.CHANGE, file, newStats2);
13377
13378
  }
13378
13379
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
13379
- this.fsw._closeFile(path33);
13380
+ this.fsw._closeFile(path36);
13380
13381
  prevStats = newStats2;
13381
13382
  const closer2 = this._watchWithNodeFs(file, listener);
13382
13383
  if (closer2)
13383
- this.fsw._addPathCloser(path33, closer2);
13384
+ this.fsw._addPathCloser(path36, closer2);
13384
13385
  } else {
13385
13386
  prevStats = newStats2;
13386
13387
  }
@@ -13412,7 +13413,7 @@ var NodeFsHandler = class {
13412
13413
  * @param item basename of this item
13413
13414
  * @returns true if no more processing is needed for this entry.
13414
13415
  */
13415
- async _handleSymlink(entry, directory, path33, item) {
13416
+ async _handleSymlink(entry, directory, path36, item) {
13416
13417
  if (this.fsw.closed) {
13417
13418
  return;
13418
13419
  }
@@ -13422,7 +13423,7 @@ var NodeFsHandler = class {
13422
13423
  this.fsw._incrReadyCount();
13423
13424
  let linkPath;
13424
13425
  try {
13425
- linkPath = await fsrealpath(path33);
13426
+ linkPath = await fsrealpath(path36);
13426
13427
  } catch (e) {
13427
13428
  this.fsw._emitReady();
13428
13429
  return true;
@@ -13432,12 +13433,12 @@ var NodeFsHandler = class {
13432
13433
  if (dir.has(item)) {
13433
13434
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
13434
13435
  this.fsw._symlinkPaths.set(full, linkPath);
13435
- this.fsw._emit(EV.CHANGE, path33, entry.stats);
13436
+ this.fsw._emit(EV.CHANGE, path36, entry.stats);
13436
13437
  }
13437
13438
  } else {
13438
13439
  dir.add(item);
13439
13440
  this.fsw._symlinkPaths.set(full, linkPath);
13440
- this.fsw._emit(EV.ADD, path33, entry.stats);
13441
+ this.fsw._emit(EV.ADD, path36, entry.stats);
13441
13442
  }
13442
13443
  this.fsw._emitReady();
13443
13444
  return true;
@@ -13466,9 +13467,9 @@ var NodeFsHandler = class {
13466
13467
  return;
13467
13468
  }
13468
13469
  const item = entry.path;
13469
- let path33 = sysPath.join(directory, item);
13470
+ let path36 = sysPath.join(directory, item);
13470
13471
  current.add(item);
13471
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path33, item)) {
13472
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path36, item)) {
13472
13473
  return;
13473
13474
  }
13474
13475
  if (this.fsw.closed) {
@@ -13477,8 +13478,8 @@ var NodeFsHandler = class {
13477
13478
  }
13478
13479
  if (item === target || !target && !previous.has(item)) {
13479
13480
  this.fsw._incrReadyCount();
13480
- path33 = sysPath.join(dir, sysPath.relative(dir, path33));
13481
- this._addToNodeFs(path33, initialAdd, wh, depth + 1);
13481
+ path36 = sysPath.join(dir, sysPath.relative(dir, path36));
13482
+ this._addToNodeFs(path36, initialAdd, wh, depth + 1);
13482
13483
  }
13483
13484
  }).on(EV.ERROR, this._boundHandleError);
13484
13485
  return new Promise((resolve3, reject) => {
@@ -13547,13 +13548,13 @@ var NodeFsHandler = class {
13547
13548
  * @param depth Child path actually targeted for watch
13548
13549
  * @param target Child path actually targeted for watch
13549
13550
  */
13550
- async _addToNodeFs(path33, initialAdd, priorWh, depth, target) {
13551
+ async _addToNodeFs(path36, initialAdd, priorWh, depth, target) {
13551
13552
  const ready = this.fsw._emitReady;
13552
- if (this.fsw._isIgnored(path33) || this.fsw.closed) {
13553
+ if (this.fsw._isIgnored(path36) || this.fsw.closed) {
13553
13554
  ready();
13554
13555
  return false;
13555
13556
  }
13556
- const wh = this.fsw._getWatchHelpers(path33);
13557
+ const wh = this.fsw._getWatchHelpers(path36);
13557
13558
  if (priorWh) {
13558
13559
  wh.filterPath = (entry) => priorWh.filterPath(entry);
13559
13560
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -13569,8 +13570,8 @@ var NodeFsHandler = class {
13569
13570
  const follow = this.fsw.options.followSymlinks;
13570
13571
  let closer;
13571
13572
  if (stats.isDirectory()) {
13572
- const absPath = sysPath.resolve(path33);
13573
- const targetPath = follow ? await fsrealpath(path33) : path33;
13573
+ const absPath = sysPath.resolve(path36);
13574
+ const targetPath = follow ? await fsrealpath(path36) : path36;
13574
13575
  if (this.fsw.closed)
13575
13576
  return;
13576
13577
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -13580,29 +13581,29 @@ var NodeFsHandler = class {
13580
13581
  this.fsw._symlinkPaths.set(absPath, targetPath);
13581
13582
  }
13582
13583
  } else if (stats.isSymbolicLink()) {
13583
- const targetPath = follow ? await fsrealpath(path33) : path33;
13584
+ const targetPath = follow ? await fsrealpath(path36) : path36;
13584
13585
  if (this.fsw.closed)
13585
13586
  return;
13586
13587
  const parent = sysPath.dirname(wh.watchPath);
13587
13588
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
13588
13589
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
13589
- closer = await this._handleDir(parent, stats, initialAdd, depth, path33, wh, targetPath);
13590
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path36, wh, targetPath);
13590
13591
  if (this.fsw.closed)
13591
13592
  return;
13592
13593
  if (targetPath !== void 0) {
13593
- this.fsw._symlinkPaths.set(sysPath.resolve(path33), targetPath);
13594
+ this.fsw._symlinkPaths.set(sysPath.resolve(path36), targetPath);
13594
13595
  }
13595
13596
  } else {
13596
13597
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
13597
13598
  }
13598
13599
  ready();
13599
13600
  if (closer)
13600
- this.fsw._addPathCloser(path33, closer);
13601
+ this.fsw._addPathCloser(path36, closer);
13601
13602
  return false;
13602
13603
  } catch (error) {
13603
13604
  if (this.fsw._handleError(error)) {
13604
13605
  ready();
13605
- return path33;
13606
+ return path36;
13606
13607
  }
13607
13608
  }
13608
13609
  }
@@ -13645,26 +13646,26 @@ function createPattern(matcher) {
13645
13646
  }
13646
13647
  return () => false;
13647
13648
  }
13648
- function normalizePath(path33) {
13649
- if (typeof path33 !== "string")
13649
+ function normalizePath(path36) {
13650
+ if (typeof path36 !== "string")
13650
13651
  throw new Error("string expected");
13651
- path33 = sysPath2.normalize(path33);
13652
- path33 = path33.replace(/\\/g, "/");
13652
+ path36 = sysPath2.normalize(path36);
13653
+ path36 = path36.replace(/\\/g, "/");
13653
13654
  let prepend = false;
13654
- if (path33.startsWith("//"))
13655
+ if (path36.startsWith("//"))
13655
13656
  prepend = true;
13656
13657
  const DOUBLE_SLASH_RE2 = /\/\//;
13657
- while (path33.match(DOUBLE_SLASH_RE2))
13658
- path33 = path33.replace(DOUBLE_SLASH_RE2, "/");
13658
+ while (path36.match(DOUBLE_SLASH_RE2))
13659
+ path36 = path36.replace(DOUBLE_SLASH_RE2, "/");
13659
13660
  if (prepend)
13660
- path33 = "/" + path33;
13661
- return path33;
13661
+ path36 = "/" + path36;
13662
+ return path36;
13662
13663
  }
13663
13664
  function matchPatterns(patterns, testString, stats) {
13664
- const path33 = normalizePath(testString);
13665
+ const path36 = normalizePath(testString);
13665
13666
  for (let index = 0; index < patterns.length; index++) {
13666
13667
  const pattern = patterns[index];
13667
- if (pattern(path33, stats)) {
13668
+ if (pattern(path36, stats)) {
13668
13669
  return true;
13669
13670
  }
13670
13671
  }
@@ -13704,19 +13705,19 @@ var toUnix = (string) => {
13704
13705
  }
13705
13706
  return str;
13706
13707
  };
13707
- var normalizePathToUnix = (path33) => toUnix(sysPath2.normalize(toUnix(path33)));
13708
- var normalizeIgnored = (cwd = "") => (path33) => {
13709
- if (typeof path33 === "string") {
13710
- return normalizePathToUnix(sysPath2.isAbsolute(path33) ? path33 : sysPath2.join(cwd, path33));
13708
+ var normalizePathToUnix = (path36) => toUnix(sysPath2.normalize(toUnix(path36)));
13709
+ var normalizeIgnored = (cwd = "") => (path36) => {
13710
+ if (typeof path36 === "string") {
13711
+ return normalizePathToUnix(sysPath2.isAbsolute(path36) ? path36 : sysPath2.join(cwd, path36));
13711
13712
  } else {
13712
- return path33;
13713
+ return path36;
13713
13714
  }
13714
13715
  };
13715
- var getAbsolutePath = (path33, cwd) => {
13716
- if (sysPath2.isAbsolute(path33)) {
13717
- return path33;
13716
+ var getAbsolutePath = (path36, cwd) => {
13717
+ if (sysPath2.isAbsolute(path36)) {
13718
+ return path36;
13718
13719
  }
13719
- return sysPath2.join(cwd, path33);
13720
+ return sysPath2.join(cwd, path36);
13720
13721
  };
13721
13722
  var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
13722
13723
  var DirEntry = class {
@@ -13771,10 +13772,10 @@ var DirEntry = class {
13771
13772
  var STAT_METHOD_F = "stat";
13772
13773
  var STAT_METHOD_L = "lstat";
13773
13774
  var WatchHelper = class {
13774
- constructor(path33, follow, fsw) {
13775
+ constructor(path36, follow, fsw) {
13775
13776
  this.fsw = fsw;
13776
- const watchPath = path33;
13777
- this.path = path33 = path33.replace(REPLACER_RE, "");
13777
+ const watchPath = path36;
13778
+ this.path = path36 = path36.replace(REPLACER_RE, "");
13778
13779
  this.watchPath = watchPath;
13779
13780
  this.fullWatchPath = sysPath2.resolve(watchPath);
13780
13781
  this.dirParts = [];
@@ -13896,20 +13897,20 @@ var FSWatcher = class extends EventEmitter {
13896
13897
  this._closePromise = void 0;
13897
13898
  let paths = unifyPaths(paths_);
13898
13899
  if (cwd) {
13899
- paths = paths.map((path33) => {
13900
- const absPath = getAbsolutePath(path33, cwd);
13900
+ paths = paths.map((path36) => {
13901
+ const absPath = getAbsolutePath(path36, cwd);
13901
13902
  return absPath;
13902
13903
  });
13903
13904
  }
13904
- paths.forEach((path33) => {
13905
- this._removeIgnoredPath(path33);
13905
+ paths.forEach((path36) => {
13906
+ this._removeIgnoredPath(path36);
13906
13907
  });
13907
13908
  this._userIgnored = void 0;
13908
13909
  if (!this._readyCount)
13909
13910
  this._readyCount = 0;
13910
13911
  this._readyCount += paths.length;
13911
- Promise.all(paths.map(async (path33) => {
13912
- const res = await this._nodeFsHandler._addToNodeFs(path33, !_internal, void 0, 0, _origAdd);
13912
+ Promise.all(paths.map(async (path36) => {
13913
+ const res = await this._nodeFsHandler._addToNodeFs(path36, !_internal, void 0, 0, _origAdd);
13913
13914
  if (res)
13914
13915
  this._emitReady();
13915
13916
  return res;
@@ -13931,17 +13932,17 @@ var FSWatcher = class extends EventEmitter {
13931
13932
  return this;
13932
13933
  const paths = unifyPaths(paths_);
13933
13934
  const { cwd } = this.options;
13934
- paths.forEach((path33) => {
13935
- if (!sysPath2.isAbsolute(path33) && !this._closers.has(path33)) {
13935
+ paths.forEach((path36) => {
13936
+ if (!sysPath2.isAbsolute(path36) && !this._closers.has(path36)) {
13936
13937
  if (cwd)
13937
- path33 = sysPath2.join(cwd, path33);
13938
- path33 = sysPath2.resolve(path33);
13938
+ path36 = sysPath2.join(cwd, path36);
13939
+ path36 = sysPath2.resolve(path36);
13939
13940
  }
13940
- this._closePath(path33);
13941
- this._addIgnoredPath(path33);
13942
- if (this._watched.has(path33)) {
13941
+ this._closePath(path36);
13942
+ this._addIgnoredPath(path36);
13943
+ if (this._watched.has(path36)) {
13943
13944
  this._addIgnoredPath({
13944
- path: path33,
13945
+ path: path36,
13945
13946
  recursive: true
13946
13947
  });
13947
13948
  }
@@ -14005,38 +14006,38 @@ var FSWatcher = class extends EventEmitter {
14005
14006
  * @param stats arguments to be passed with event
14006
14007
  * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
14007
14008
  */
14008
- async _emit(event, path33, stats) {
14009
+ async _emit(event, path36, stats) {
14009
14010
  if (this.closed)
14010
14011
  return;
14011
14012
  const opts = this.options;
14012
14013
  if (isWindows)
14013
- path33 = sysPath2.normalize(path33);
14014
+ path36 = sysPath2.normalize(path36);
14014
14015
  if (opts.cwd)
14015
- path33 = sysPath2.relative(opts.cwd, path33);
14016
- const args = [path33];
14016
+ path36 = sysPath2.relative(opts.cwd, path36);
14017
+ const args = [path36];
14017
14018
  if (stats != null)
14018
14019
  args.push(stats);
14019
14020
  const awf = opts.awaitWriteFinish;
14020
14021
  let pw;
14021
- if (awf && (pw = this._pendingWrites.get(path33))) {
14022
+ if (awf && (pw = this._pendingWrites.get(path36))) {
14022
14023
  pw.lastChange = /* @__PURE__ */ new Date();
14023
14024
  return this;
14024
14025
  }
14025
14026
  if (opts.atomic) {
14026
14027
  if (event === EVENTS.UNLINK) {
14027
- this._pendingUnlinks.set(path33, [event, ...args]);
14028
+ this._pendingUnlinks.set(path36, [event, ...args]);
14028
14029
  setTimeout(() => {
14029
- this._pendingUnlinks.forEach((entry, path34) => {
14030
+ this._pendingUnlinks.forEach((entry, path37) => {
14030
14031
  this.emit(...entry);
14031
14032
  this.emit(EVENTS.ALL, ...entry);
14032
- this._pendingUnlinks.delete(path34);
14033
+ this._pendingUnlinks.delete(path37);
14033
14034
  });
14034
14035
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
14035
14036
  return this;
14036
14037
  }
14037
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path33)) {
14038
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path36)) {
14038
14039
  event = EVENTS.CHANGE;
14039
- this._pendingUnlinks.delete(path33);
14040
+ this._pendingUnlinks.delete(path36);
14040
14041
  }
14041
14042
  }
14042
14043
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -14054,16 +14055,16 @@ var FSWatcher = class extends EventEmitter {
14054
14055
  this.emitWithAll(event, args);
14055
14056
  }
14056
14057
  };
14057
- this._awaitWriteFinish(path33, awf.stabilityThreshold, event, awfEmit);
14058
+ this._awaitWriteFinish(path36, awf.stabilityThreshold, event, awfEmit);
14058
14059
  return this;
14059
14060
  }
14060
14061
  if (event === EVENTS.CHANGE) {
14061
- const isThrottled = !this._throttle(EVENTS.CHANGE, path33, 50);
14062
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path36, 50);
14062
14063
  if (isThrottled)
14063
14064
  return this;
14064
14065
  }
14065
14066
  if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
14066
- const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path33) : path33;
14067
+ const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path36) : path36;
14067
14068
  let stats2;
14068
14069
  try {
14069
14070
  stats2 = await stat3(fullPath);
@@ -14094,23 +14095,23 @@ var FSWatcher = class extends EventEmitter {
14094
14095
  * @param timeout duration of time to suppress duplicate actions
14095
14096
  * @returns tracking object or false if action should be suppressed
14096
14097
  */
14097
- _throttle(actionType, path33, timeout) {
14098
+ _throttle(actionType, path36, timeout) {
14098
14099
  if (!this._throttled.has(actionType)) {
14099
14100
  this._throttled.set(actionType, /* @__PURE__ */ new Map());
14100
14101
  }
14101
14102
  const action = this._throttled.get(actionType);
14102
14103
  if (!action)
14103
14104
  throw new Error("invalid throttle");
14104
- const actionPath = action.get(path33);
14105
+ const actionPath = action.get(path36);
14105
14106
  if (actionPath) {
14106
14107
  actionPath.count++;
14107
14108
  return false;
14108
14109
  }
14109
14110
  let timeoutObject;
14110
14111
  const clear = () => {
14111
- const item = action.get(path33);
14112
+ const item = action.get(path36);
14112
14113
  const count = item ? item.count : 0;
14113
- action.delete(path33);
14114
+ action.delete(path36);
14114
14115
  clearTimeout(timeoutObject);
14115
14116
  if (item)
14116
14117
  clearTimeout(item.timeoutObject);
@@ -14118,7 +14119,7 @@ var FSWatcher = class extends EventEmitter {
14118
14119
  };
14119
14120
  timeoutObject = setTimeout(clear, timeout);
14120
14121
  const thr = { timeoutObject, clear, count: 0 };
14121
- action.set(path33, thr);
14122
+ action.set(path36, thr);
14122
14123
  return thr;
14123
14124
  }
14124
14125
  _incrReadyCount() {
@@ -14132,44 +14133,44 @@ var FSWatcher = class extends EventEmitter {
14132
14133
  * @param event
14133
14134
  * @param awfEmit Callback to be called when ready for event to be emitted.
14134
14135
  */
14135
- _awaitWriteFinish(path33, threshold, event, awfEmit) {
14136
+ _awaitWriteFinish(path36, threshold, event, awfEmit) {
14136
14137
  const awf = this.options.awaitWriteFinish;
14137
14138
  if (typeof awf !== "object")
14138
14139
  return;
14139
14140
  const pollInterval = awf.pollInterval;
14140
14141
  let timeoutHandler;
14141
- let fullPath = path33;
14142
- if (this.options.cwd && !sysPath2.isAbsolute(path33)) {
14143
- fullPath = sysPath2.join(this.options.cwd, path33);
14142
+ let fullPath = path36;
14143
+ if (this.options.cwd && !sysPath2.isAbsolute(path36)) {
14144
+ fullPath = sysPath2.join(this.options.cwd, path36);
14144
14145
  }
14145
14146
  const now = /* @__PURE__ */ new Date();
14146
14147
  const writes = this._pendingWrites;
14147
14148
  function awaitWriteFinishFn(prevStat) {
14148
14149
  statcb(fullPath, (err, curStat) => {
14149
- if (err || !writes.has(path33)) {
14150
+ if (err || !writes.has(path36)) {
14150
14151
  if (err && err.code !== "ENOENT")
14151
14152
  awfEmit(err);
14152
14153
  return;
14153
14154
  }
14154
14155
  const now2 = Number(/* @__PURE__ */ new Date());
14155
14156
  if (prevStat && curStat.size !== prevStat.size) {
14156
- writes.get(path33).lastChange = now2;
14157
+ writes.get(path36).lastChange = now2;
14157
14158
  }
14158
- const pw = writes.get(path33);
14159
+ const pw = writes.get(path36);
14159
14160
  const df = now2 - pw.lastChange;
14160
14161
  if (df >= threshold) {
14161
- writes.delete(path33);
14162
+ writes.delete(path36);
14162
14163
  awfEmit(void 0, curStat);
14163
14164
  } else {
14164
14165
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
14165
14166
  }
14166
14167
  });
14167
14168
  }
14168
- if (!writes.has(path33)) {
14169
- writes.set(path33, {
14169
+ if (!writes.has(path36)) {
14170
+ writes.set(path36, {
14170
14171
  lastChange: now,
14171
14172
  cancelWait: () => {
14172
- writes.delete(path33);
14173
+ writes.delete(path36);
14173
14174
  clearTimeout(timeoutHandler);
14174
14175
  return event;
14175
14176
  }
@@ -14180,8 +14181,8 @@ var FSWatcher = class extends EventEmitter {
14180
14181
  /**
14181
14182
  * Determines whether user has asked to ignore this path.
14182
14183
  */
14183
- _isIgnored(path33, stats) {
14184
- if (this.options.atomic && DOT_RE.test(path33))
14184
+ _isIgnored(path36, stats) {
14185
+ if (this.options.atomic && DOT_RE.test(path36))
14185
14186
  return true;
14186
14187
  if (!this._userIgnored) {
14187
14188
  const { cwd } = this.options;
@@ -14191,17 +14192,17 @@ var FSWatcher = class extends EventEmitter {
14191
14192
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
14192
14193
  this._userIgnored = anymatch(list, void 0);
14193
14194
  }
14194
- return this._userIgnored(path33, stats);
14195
+ return this._userIgnored(path36, stats);
14195
14196
  }
14196
- _isntIgnored(path33, stat4) {
14197
- return !this._isIgnored(path33, stat4);
14197
+ _isntIgnored(path36, stat4) {
14198
+ return !this._isIgnored(path36, stat4);
14198
14199
  }
14199
14200
  /**
14200
14201
  * Provides a set of common helpers and properties relating to symlink handling.
14201
14202
  * @param path file or directory pattern being watched
14202
14203
  */
14203
- _getWatchHelpers(path33) {
14204
- return new WatchHelper(path33, this.options.followSymlinks, this);
14204
+ _getWatchHelpers(path36) {
14205
+ return new WatchHelper(path36, this.options.followSymlinks, this);
14205
14206
  }
14206
14207
  // Directory helpers
14207
14208
  // -----------------
@@ -14233,63 +14234,63 @@ var FSWatcher = class extends EventEmitter {
14233
14234
  * @param item base path of item/directory
14234
14235
  */
14235
14236
  _remove(directory, item, isDirectory) {
14236
- const path33 = sysPath2.join(directory, item);
14237
- const fullPath = sysPath2.resolve(path33);
14238
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path33) || this._watched.has(fullPath);
14239
- if (!this._throttle("remove", path33, 100))
14237
+ const path36 = sysPath2.join(directory, item);
14238
+ const fullPath = sysPath2.resolve(path36);
14239
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path36) || this._watched.has(fullPath);
14240
+ if (!this._throttle("remove", path36, 100))
14240
14241
  return;
14241
14242
  if (!isDirectory && this._watched.size === 1) {
14242
14243
  this.add(directory, item, true);
14243
14244
  }
14244
- const wp = this._getWatchedDir(path33);
14245
+ const wp = this._getWatchedDir(path36);
14245
14246
  const nestedDirectoryChildren = wp.getChildren();
14246
- nestedDirectoryChildren.forEach((nested) => this._remove(path33, nested));
14247
+ nestedDirectoryChildren.forEach((nested) => this._remove(path36, nested));
14247
14248
  const parent = this._getWatchedDir(directory);
14248
14249
  const wasTracked = parent.has(item);
14249
14250
  parent.remove(item);
14250
14251
  if (this._symlinkPaths.has(fullPath)) {
14251
14252
  this._symlinkPaths.delete(fullPath);
14252
14253
  }
14253
- let relPath = path33;
14254
+ let relPath = path36;
14254
14255
  if (this.options.cwd)
14255
- relPath = sysPath2.relative(this.options.cwd, path33);
14256
+ relPath = sysPath2.relative(this.options.cwd, path36);
14256
14257
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
14257
14258
  const event = this._pendingWrites.get(relPath).cancelWait();
14258
14259
  if (event === EVENTS.ADD)
14259
14260
  return;
14260
14261
  }
14261
- this._watched.delete(path33);
14262
+ this._watched.delete(path36);
14262
14263
  this._watched.delete(fullPath);
14263
14264
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
14264
- if (wasTracked && !this._isIgnored(path33))
14265
- this._emit(eventName, path33);
14266
- this._closePath(path33);
14265
+ if (wasTracked && !this._isIgnored(path36))
14266
+ this._emit(eventName, path36);
14267
+ this._closePath(path36);
14267
14268
  }
14268
14269
  /**
14269
14270
  * Closes all watchers for a path
14270
14271
  */
14271
- _closePath(path33) {
14272
- this._closeFile(path33);
14273
- const dir = sysPath2.dirname(path33);
14274
- this._getWatchedDir(dir).remove(sysPath2.basename(path33));
14272
+ _closePath(path36) {
14273
+ this._closeFile(path36);
14274
+ const dir = sysPath2.dirname(path36);
14275
+ this._getWatchedDir(dir).remove(sysPath2.basename(path36));
14275
14276
  }
14276
14277
  /**
14277
14278
  * Closes only file-specific watchers
14278
14279
  */
14279
- _closeFile(path33) {
14280
- const closers = this._closers.get(path33);
14280
+ _closeFile(path36) {
14281
+ const closers = this._closers.get(path36);
14281
14282
  if (!closers)
14282
14283
  return;
14283
14284
  closers.forEach((closer) => closer());
14284
- this._closers.delete(path33);
14285
+ this._closers.delete(path36);
14285
14286
  }
14286
- _addPathCloser(path33, closer) {
14287
+ _addPathCloser(path36, closer) {
14287
14288
  if (!closer)
14288
14289
  return;
14289
- let list = this._closers.get(path33);
14290
+ let list = this._closers.get(path36);
14290
14291
  if (!list) {
14291
14292
  list = [];
14292
- this._closers.set(path33, list);
14293
+ this._closers.set(path36, list);
14293
14294
  }
14294
14295
  list.push(closer);
14295
14296
  }
@@ -14505,7 +14506,20 @@ var DEFAULT_CONFIG = {
14505
14506
  ssr: true,
14506
14507
  ssg: true
14507
14508
  },
14508
- plugins: []
14509
+ plugins: [],
14510
+ images: {
14511
+ remotePatterns: [],
14512
+ domains: [],
14513
+ deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
14514
+ imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
14515
+ formats: ["image/webp", "image/avif"],
14516
+ quality: 75,
14517
+ minimumCacheTTL: 60,
14518
+ dangerouslyAllowSVG: false,
14519
+ contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
14520
+ maxWidth: 3840,
14521
+ maxHeight: 3840
14522
+ }
14509
14523
  };
14510
14524
  function deepMerge(target, source) {
14511
14525
  const result = { ...target };
@@ -14622,6 +14636,53 @@ function validateConfig(config, projectRoot) {
14622
14636
  if (typeof config.rendering.ssg !== "boolean") {
14623
14637
  errors.push("config.rendering.ssg must be a boolean");
14624
14638
  }
14639
+ if (config.images) {
14640
+ if (config.images.quality !== void 0) {
14641
+ if (typeof config.images.quality !== "number" || config.images.quality < 1 || config.images.quality > 100) {
14642
+ errors.push("config.images.quality must be a number between 1 and 100");
14643
+ }
14644
+ }
14645
+ if (config.images.minimumCacheTTL !== void 0) {
14646
+ if (typeof config.images.minimumCacheTTL !== "number" || config.images.minimumCacheTTL < 0) {
14647
+ errors.push("config.images.minimumCacheTTL must be a non-negative number");
14648
+ }
14649
+ }
14650
+ if (config.images.deviceSizes) {
14651
+ if (!Array.isArray(config.images.deviceSizes) || config.images.deviceSizes.some((s) => typeof s !== "number" || s <= 0)) {
14652
+ errors.push("config.images.deviceSizes must be an array of positive numbers");
14653
+ }
14654
+ }
14655
+ if (config.images.imageSizes) {
14656
+ if (!Array.isArray(config.images.imageSizes) || config.images.imageSizes.some((s) => typeof s !== "number" || s <= 0)) {
14657
+ errors.push("config.images.imageSizes must be an array of positive numbers");
14658
+ }
14659
+ }
14660
+ if (config.images.formats) {
14661
+ const validFormats = ["image/webp", "image/avif"];
14662
+ if (!Array.isArray(config.images.formats) || config.images.formats.some((f) => !validFormats.includes(f))) {
14663
+ errors.push(`config.images.formats must be an array containing only: ${validFormats.join(", ")}`);
14664
+ }
14665
+ }
14666
+ if (config.images.remotePatterns) {
14667
+ if (!Array.isArray(config.images.remotePatterns)) {
14668
+ errors.push("config.images.remotePatterns must be an array");
14669
+ } else {
14670
+ config.images.remotePatterns.forEach((pattern, idx) => {
14671
+ if (!pattern.hostname || typeof pattern.hostname !== "string") {
14672
+ errors.push(`config.images.remotePatterns[${idx}].hostname must be a non-empty string`);
14673
+ }
14674
+ if (pattern.protocol && !["http", "https"].includes(pattern.protocol)) {
14675
+ errors.push(`config.images.remotePatterns[${idx}].protocol must be 'http' or 'https'`);
14676
+ }
14677
+ });
14678
+ }
14679
+ }
14680
+ if (config.images.domains) {
14681
+ if (!Array.isArray(config.images.domains) || config.images.domains.some((d) => typeof d !== "string")) {
14682
+ errors.push("config.images.domains must be an array of strings");
14683
+ }
14684
+ }
14685
+ }
14625
14686
  if (errors.length > 0) {
14626
14687
  const errorMessage = [
14627
14688
  "\u274C Configuration validation failed:",
@@ -14967,12 +15028,12 @@ var DEFAULT_IGNORED_PATHS = [
14967
15028
  /^\/sockjs-node/
14968
15029
  // Hot reload websocket
14969
15030
  ];
14970
- function shouldIgnorePath(path33, ignoredPaths) {
15031
+ function shouldIgnorePath(path36, ignoredPaths) {
14971
15032
  return ignoredPaths.some((pattern) => {
14972
15033
  if (typeof pattern === "string") {
14973
- return path33 === pattern || path33.startsWith(pattern);
15034
+ return path36 === pattern || path36.startsWith(pattern);
14974
15035
  }
14975
- return pattern.test(path33);
15036
+ return pattern.test(path36);
14976
15037
  });
14977
15038
  }
14978
15039
  function requestLoggerMiddleware(options = {}) {
@@ -15131,11 +15192,11 @@ function createStrictRateLimiterFromConfig(config) {
15131
15192
  }
15132
15193
 
15133
15194
  // modules/server/middleware/auto-rate-limit.ts
15134
- function matchesStrictPattern(path33, patterns) {
15195
+ function matchesStrictPattern(path36, patterns) {
15135
15196
  for (const pattern of patterns) {
15136
15197
  const regexPattern = pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*").replace(/\//g, "\\/");
15137
15198
  const regex = new RegExp(`^${regexPattern}$`);
15138
- if (regex.test(path33)) {
15199
+ if (regex.test(path36)) {
15139
15200
  return true;
15140
15201
  }
15141
15202
  }
@@ -15658,7 +15719,7 @@ function createDocumentTree(options) {
15658
15719
  }),
15659
15720
  ...extraMetaTags,
15660
15721
  ...linkTags,
15661
- ...entrypointFiles.length > 0 ? entrypointFiles.slice(0, -1).map(
15722
+ ...entrypointFiles.length > 0 ? entrypointFiles.map(
15662
15723
  (file) => React.createElement("link", {
15663
15724
  key: `preload-${file}`,
15664
15725
  rel: "preload",
@@ -15679,6 +15740,13 @@ function createDocumentTree(options) {
15679
15740
  href: faviconPath,
15680
15741
  type: faviconType || (faviconPath.endsWith(".ico") ? "image/x-icon" : "image/png")
15681
15742
  }),
15743
+ // Preload CSS para evitar bloqueo de renderizado
15744
+ React.createElement("link", {
15745
+ key: "preload-css",
15746
+ rel: "preload",
15747
+ href: clientCssPath,
15748
+ as: "style"
15749
+ }),
15682
15750
  React.createElement("link", {
15683
15751
  rel: "stylesheet",
15684
15752
  href: clientCssPath
@@ -16825,6 +16893,438 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
16825
16893
  }
16826
16894
  }
16827
16895
 
16896
+ // modules/server/image-optimizer/index.ts
16897
+ import sharp from "sharp";
16898
+ import fs22 from "fs";
16899
+ import path28 from "path";
16900
+
16901
+ // modules/server/image-optimizer/validation.ts
16902
+ import path26 from "path";
16903
+ function isRemoteUrl(url) {
16904
+ return url.startsWith("http://") || url.startsWith("https://");
16905
+ }
16906
+ function sanitizeImagePath(imagePath) {
16907
+ const normalized = path26.normalize(imagePath).replace(/^(\.\.(\/|\\|$))+/, "");
16908
+ return normalized.replace(/^[/\\]+/, "");
16909
+ }
16910
+ function patternToRegex(pattern) {
16911
+ const parts = [];
16912
+ if (pattern.protocol) {
16913
+ parts.push(pattern.protocol === "https" ? "https" : "http");
16914
+ } else {
16915
+ parts.push("https?");
16916
+ }
16917
+ parts.push("://");
16918
+ let hostnamePattern = pattern.hostname.replace(/\./g, "\\.").replace(/\*\*/g, ".*").replace(/\*/g, "[^.]*");
16919
+ parts.push(hostnamePattern);
16920
+ if (pattern.port) {
16921
+ parts.push(`:${pattern.port}`);
16922
+ }
16923
+ if (pattern.pathname) {
16924
+ let pathnamePattern = pattern.pathname.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*");
16925
+ parts.push(pathnamePattern);
16926
+ } else {
16927
+ parts.push(".*");
16928
+ }
16929
+ const regexSource = `^${parts.join("")}`;
16930
+ return new RegExp(regexSource);
16931
+ }
16932
+ function validateRemoteUrl(url, config) {
16933
+ if (!config.remotePatterns && !config.domains) {
16934
+ return false;
16935
+ }
16936
+ try {
16937
+ const urlObj = new URL(url);
16938
+ const protocol = urlObj.protocol.replace(":", "");
16939
+ const hostname = urlObj.hostname;
16940
+ const port = urlObj.port || "";
16941
+ const pathname = urlObj.pathname;
16942
+ if (config.remotePatterns && config.remotePatterns.length > 0) {
16943
+ for (const pattern of config.remotePatterns) {
16944
+ const regex = patternToRegex(pattern);
16945
+ const testUrl = `${protocol}://${hostname}${port ? `:${port}` : ""}${pathname}`;
16946
+ if (regex.test(testUrl)) {
16947
+ if (pattern.protocol && pattern.protocol !== protocol) {
16948
+ continue;
16949
+ }
16950
+ if (pattern.port && pattern.port !== port) {
16951
+ continue;
16952
+ }
16953
+ return true;
16954
+ }
16955
+ }
16956
+ }
16957
+ if (config.domains && config.domains.length > 0) {
16958
+ for (const domain of config.domains) {
16959
+ const domainPattern = domain.replace(/\./g, "\\.").replace(/\*\*/g, ".*").replace(/\*/g, "[^.]*");
16960
+ const regex = new RegExp(`^${domainPattern}$`);
16961
+ if (regex.test(hostname)) {
16962
+ if (process.env.NODE_ENV === "production" && protocol !== "https") {
16963
+ continue;
16964
+ }
16965
+ return true;
16966
+ }
16967
+ }
16968
+ }
16969
+ return false;
16970
+ } catch (error) {
16971
+ return false;
16972
+ }
16973
+ }
16974
+ function validateImageDimensions(width, height, config) {
16975
+ const maxWidth = config.maxWidth || 3840;
16976
+ const maxHeight = config.maxHeight || 3840;
16977
+ if (width !== void 0 && (width <= 0 || width > maxWidth)) {
16978
+ return {
16979
+ valid: false,
16980
+ error: `Image width must be between 1 and ${maxWidth}, got ${width}`
16981
+ };
16982
+ }
16983
+ if (height !== void 0 && (height <= 0 || height > maxHeight)) {
16984
+ return {
16985
+ valid: false,
16986
+ error: `Image height must be between 1 and ${maxHeight}, got ${height}`
16987
+ };
16988
+ }
16989
+ return { valid: true };
16990
+ }
16991
+ function validateQuality(quality) {
16992
+ if (quality === void 0) {
16993
+ return { valid: true };
16994
+ }
16995
+ if (typeof quality !== "number" || quality < 1 || quality > 100) {
16996
+ return {
16997
+ valid: false,
16998
+ error: `Image quality must be between 1 and 100, got ${quality}`
16999
+ };
17000
+ }
17001
+ return { valid: true };
17002
+ }
17003
+
17004
+ // modules/server/image-optimizer/cache.ts
17005
+ import fs21 from "fs";
17006
+ import path27 from "path";
17007
+ import crypto from "crypto";
17008
+ function generateCacheKey(src, width, height, quality, format) {
17009
+ const data = `${src}-${width || ""}-${height || ""}-${quality || ""}-${format || ""}`;
17010
+ return crypto.createHash("sha256").update(data).digest("hex");
17011
+ }
17012
+ function getCacheDir(projectRoot, config) {
17013
+ const buildDir = getBuildDir(projectRoot, config);
17014
+ return path27.join(buildDir, "cache", "images");
17015
+ }
17016
+ function ensureCacheDir(cacheDir) {
17017
+ if (!fs21.existsSync(cacheDir)) {
17018
+ fs21.mkdirSync(cacheDir, { recursive: true });
17019
+ }
17020
+ }
17021
+ function getCachedImagePath(cacheKey, extension, cacheDir) {
17022
+ return path27.join(cacheDir, `${cacheKey}.${extension}`);
17023
+ }
17024
+ function hasCachedImage(cacheKey, extension, cacheDir) {
17025
+ const cachedPath = getCachedImagePath(cacheKey, extension, cacheDir);
17026
+ return fs21.existsSync(cachedPath);
17027
+ }
17028
+ function readCachedImage(cacheKey, extension, cacheDir) {
17029
+ const cachedPath = getCachedImagePath(cacheKey, extension, cacheDir);
17030
+ try {
17031
+ if (fs21.existsSync(cachedPath)) {
17032
+ return fs21.readFileSync(cachedPath);
17033
+ }
17034
+ } catch (error) {
17035
+ console.warn(`[image-optimizer] Failed to read cached image: ${cachedPath}`, error);
17036
+ }
17037
+ return null;
17038
+ }
17039
+ function writeCachedImage(cacheKey, extension, cacheDir, imageBuffer) {
17040
+ ensureCacheDir(cacheDir);
17041
+ const cachedPath = getCachedImagePath(cacheKey, extension, cacheDir);
17042
+ try {
17043
+ fs21.writeFileSync(cachedPath, imageBuffer);
17044
+ } catch (error) {
17045
+ console.warn(`[image-optimizer] Failed to write cached image: ${cachedPath}`, error);
17046
+ }
17047
+ }
17048
+ function getImageMimeType(format) {
17049
+ const formatMap = {
17050
+ webp: "image/webp",
17051
+ avif: "image/avif",
17052
+ jpeg: "image/jpeg",
17053
+ jpg: "image/jpeg",
17054
+ png: "image/png",
17055
+ gif: "image/gif",
17056
+ svg: "image/svg+xml"
17057
+ };
17058
+ const normalized = format.toLowerCase();
17059
+ return formatMap[normalized] || "image/jpeg";
17060
+ }
17061
+ function getImageExtension(format) {
17062
+ const formatMap = {
17063
+ "image/webp": "webp",
17064
+ "image/avif": "avif",
17065
+ "image/jpeg": "jpg",
17066
+ "image/png": "png",
17067
+ "image/gif": "gif",
17068
+ "image/svg+xml": "svg",
17069
+ webp: "webp",
17070
+ avif: "avif",
17071
+ jpeg: "jpg",
17072
+ jpg: "jpg",
17073
+ png: "png",
17074
+ gif: "gif",
17075
+ svg: "svg"
17076
+ };
17077
+ const normalized = format.toLowerCase();
17078
+ return formatMap[normalized] || "jpg";
17079
+ }
17080
+
17081
+ // modules/server/image-optimizer/index.ts
17082
+ async function downloadRemoteImage(url, timeout = 1e4) {
17083
+ let fetchFn;
17084
+ try {
17085
+ if (typeof fetch !== "undefined") {
17086
+ fetchFn = fetch;
17087
+ } else {
17088
+ const { fetch: undiciFetch } = await import("undici");
17089
+ fetchFn = undiciFetch;
17090
+ }
17091
+ } catch (error) {
17092
+ throw new Error("Failed to load fetch implementation. Node 18+ required or install undici.");
17093
+ }
17094
+ const controller = new AbortController();
17095
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
17096
+ try {
17097
+ const response = await fetchFn(url, {
17098
+ signal: controller.signal,
17099
+ headers: {
17100
+ "User-Agent": "Loly-Image-Optimizer/1.0"
17101
+ }
17102
+ });
17103
+ clearTimeout(timeoutId);
17104
+ if (!response.ok) {
17105
+ throw new Error(`Failed to download image: ${response.status} ${response.statusText}`);
17106
+ }
17107
+ const arrayBuffer = await response.arrayBuffer();
17108
+ return Buffer.from(arrayBuffer);
17109
+ } catch (error) {
17110
+ clearTimeout(timeoutId);
17111
+ if (error instanceof Error && error.name === "AbortError") {
17112
+ throw new Error(`Image download timeout after ${timeout}ms`);
17113
+ }
17114
+ throw error;
17115
+ }
17116
+ }
17117
+ function readLocalImage(src, projectRoot, config) {
17118
+ const sanitized = sanitizeImagePath(src);
17119
+ const staticDir = getStaticDir(projectRoot, config);
17120
+ const staticPath = path28.join(staticDir, sanitized);
17121
+ if (fs22.existsSync(staticPath)) {
17122
+ return fs22.readFileSync(staticPath);
17123
+ }
17124
+ if (src.startsWith("/")) {
17125
+ const absolutePath = path28.join(projectRoot, sanitized);
17126
+ if (fs22.existsSync(absolutePath)) {
17127
+ return fs22.readFileSync(absolutePath);
17128
+ }
17129
+ }
17130
+ throw new Error(`Image not found: ${src}`);
17131
+ }
17132
+ function determineOutputFormat(sourceFormat, requestedFormat, config) {
17133
+ if (sourceFormat === "svg") {
17134
+ return "svg";
17135
+ }
17136
+ if (requestedFormat && requestedFormat !== "auto") {
17137
+ return requestedFormat;
17138
+ }
17139
+ const supportedFormats = config.formats || ["image/webp"];
17140
+ if (supportedFormats.includes("image/avif")) {
17141
+ return "avif";
17142
+ }
17143
+ if (supportedFormats.includes("image/webp")) {
17144
+ return "webp";
17145
+ }
17146
+ return sourceFormat === "svg" ? "jpeg" : sourceFormat;
17147
+ }
17148
+ async function optimizeImage(options, projectRoot, config) {
17149
+ const imageConfig = config.images || {};
17150
+ const dimValidation = validateImageDimensions(options.width, options.height, imageConfig);
17151
+ if (!dimValidation.valid) {
17152
+ throw new Error(dimValidation.error);
17153
+ }
17154
+ const qualityValidation = validateQuality(options.quality);
17155
+ if (!qualityValidation.valid) {
17156
+ throw new Error(qualityValidation.error);
17157
+ }
17158
+ if (isRemoteUrl(options.src)) {
17159
+ if (!validateRemoteUrl(options.src, imageConfig)) {
17160
+ throw new Error(`Remote image domain not allowed: ${options.src}`);
17161
+ }
17162
+ }
17163
+ const sourceFormat = path28.extname(options.src).slice(1).toLowerCase() || "jpeg";
17164
+ const outputFormat = determineOutputFormat(
17165
+ sourceFormat,
17166
+ options.format,
17167
+ imageConfig
17168
+ );
17169
+ const cacheKey = generateCacheKey(
17170
+ options.src,
17171
+ options.width,
17172
+ options.height,
17173
+ options.quality || imageConfig.quality || 75,
17174
+ outputFormat
17175
+ );
17176
+ const cacheDir = getCacheDir(projectRoot, config);
17177
+ const extension = getImageExtension(outputFormat);
17178
+ if (hasCachedImage(cacheKey, extension, cacheDir)) {
17179
+ const cached = readCachedImage(cacheKey, extension, cacheDir);
17180
+ if (cached) {
17181
+ const metadata2 = await sharp(cached).metadata();
17182
+ return {
17183
+ buffer: cached,
17184
+ format: outputFormat,
17185
+ mimeType: getImageMimeType(outputFormat),
17186
+ width: metadata2.width || options.width || 0,
17187
+ height: metadata2.height || options.height || 0
17188
+ };
17189
+ }
17190
+ }
17191
+ let imageBuffer;
17192
+ if (isRemoteUrl(options.src)) {
17193
+ imageBuffer = await downloadRemoteImage(options.src);
17194
+ } else {
17195
+ imageBuffer = readLocalImage(options.src, projectRoot, config);
17196
+ }
17197
+ if (outputFormat === "svg" || sourceFormat === "svg") {
17198
+ if (!imageConfig.dangerouslyAllowSVG) {
17199
+ throw new Error("SVG images are not allowed. Set images.dangerouslyAllowSVG to true to enable.");
17200
+ }
17201
+ return {
17202
+ buffer: imageBuffer,
17203
+ format: "svg",
17204
+ mimeType: "image/svg+xml",
17205
+ width: options.width || 0,
17206
+ height: options.height || 0
17207
+ };
17208
+ }
17209
+ let sharpInstance = sharp(imageBuffer);
17210
+ const metadata = await sharpInstance.metadata();
17211
+ if (options.width || options.height) {
17212
+ const fit = options.fit || "cover";
17213
+ sharpInstance = sharpInstance.resize(options.width, options.height, {
17214
+ fit,
17215
+ withoutEnlargement: true
17216
+ });
17217
+ }
17218
+ const quality = options.quality || imageConfig.quality || 75;
17219
+ switch (outputFormat) {
17220
+ case "webp":
17221
+ sharpInstance = sharpInstance.webp({ quality });
17222
+ break;
17223
+ case "avif":
17224
+ sharpInstance = sharpInstance.avif({ quality });
17225
+ break;
17226
+ case "jpeg":
17227
+ case "jpg":
17228
+ sharpInstance = sharpInstance.jpeg({ quality });
17229
+ break;
17230
+ case "png":
17231
+ sharpInstance = sharpInstance.png({ quality: Math.round(quality / 100 * 9) });
17232
+ break;
17233
+ default:
17234
+ sharpInstance = sharpInstance.jpeg({ quality });
17235
+ }
17236
+ const optimizedBuffer = await sharpInstance.toBuffer();
17237
+ const finalMetadata = await sharp(optimizedBuffer).metadata();
17238
+ writeCachedImage(cacheKey, extension, cacheDir, optimizedBuffer);
17239
+ return {
17240
+ buffer: optimizedBuffer,
17241
+ format: outputFormat,
17242
+ mimeType: getImageMimeType(outputFormat),
17243
+ width: finalMetadata.width || options.width || metadata.width || 0,
17244
+ height: finalMetadata.height || options.height || metadata.height || 0
17245
+ };
17246
+ }
17247
+
17248
+ // modules/server/handlers/image.ts
17249
+ async function handleImageRequest(options) {
17250
+ const { req, res, projectRoot, config } = options;
17251
+ try {
17252
+ const src = req.query.src;
17253
+ const width = req.query.w ? parseInt(req.query.w, 10) : void 0;
17254
+ const height = req.query.h ? parseInt(req.query.h, 10) : void 0;
17255
+ const quality = req.query.q ? parseInt(req.query.q, 10) : void 0;
17256
+ const format = req.query.format;
17257
+ const fit = req.query.fit;
17258
+ if (!src) {
17259
+ res.status(400).json({
17260
+ error: "Missing required parameter: src"
17261
+ });
17262
+ return;
17263
+ }
17264
+ if (typeof src !== "string") {
17265
+ res.status(400).json({
17266
+ error: "Parameter 'src' must be a string"
17267
+ });
17268
+ return;
17269
+ }
17270
+ const result = await optimizeImage(
17271
+ {
17272
+ src,
17273
+ width,
17274
+ height,
17275
+ quality,
17276
+ format,
17277
+ fit
17278
+ },
17279
+ projectRoot,
17280
+ config
17281
+ );
17282
+ const imageConfig = config.images || {};
17283
+ const cacheTTL = imageConfig.minimumCacheTTL || 60;
17284
+ res.setHeader("Content-Type", result.mimeType);
17285
+ res.setHeader("Content-Length", result.buffer.length);
17286
+ res.setHeader("Cache-Control", `public, max-age=${cacheTTL}, immutable`);
17287
+ res.setHeader("X-Content-Type-Options", "nosniff");
17288
+ res.send(result.buffer);
17289
+ } catch (error) {
17290
+ if (error instanceof Error) {
17291
+ if (error.message.includes("not allowed")) {
17292
+ res.status(403).json({
17293
+ error: "Forbidden",
17294
+ message: error.message
17295
+ });
17296
+ return;
17297
+ }
17298
+ if (error.message.includes("not found") || error.message.includes("Image not found")) {
17299
+ res.status(404).json({
17300
+ error: "Not Found",
17301
+ message: error.message
17302
+ });
17303
+ return;
17304
+ }
17305
+ if (error.message.includes("must be")) {
17306
+ res.status(400).json({
17307
+ error: "Bad Request",
17308
+ message: error.message
17309
+ });
17310
+ return;
17311
+ }
17312
+ if (error.message.includes("timeout") || error.message.includes("download")) {
17313
+ res.status(504).json({
17314
+ error: "Gateway Timeout",
17315
+ message: error.message
17316
+ });
17317
+ return;
17318
+ }
17319
+ }
17320
+ console.error("[image-optimizer] Error processing image:", error);
17321
+ res.status(500).json({
17322
+ error: "Internal Server Error",
17323
+ message: "Failed to process image"
17324
+ });
17325
+ }
17326
+ }
17327
+
16828
17328
  // modules/server/routes.ts
16829
17329
  init_globals();
16830
17330
 
@@ -16986,7 +17486,7 @@ function validateRealtimeConfig(config) {
16986
17486
  }
16987
17487
 
16988
17488
  // modules/server/routes.ts
16989
- import path26 from "path";
17489
+ import path29 from "path";
16990
17490
  var cachedRewriteLoader = null;
16991
17491
  var cachedProjectRoot = null;
16992
17492
  var cachedIsDev = null;
@@ -17014,10 +17514,20 @@ function setupRoutes(options) {
17014
17514
  } = options;
17015
17515
  const routeChunks = routeLoader.loadRouteChunks();
17016
17516
  const rewriteLoader = getRewriteLoader(projectRoot, isDev);
17017
- const ssgOutDir = path26.join(
17018
- config ? getBuildDir(projectRoot, config) : path26.join(projectRoot, BUILD_FOLDER_NAME),
17517
+ const ssgOutDir = path29.join(
17518
+ config ? getBuildDir(projectRoot, config) : path29.join(projectRoot, BUILD_FOLDER_NAME),
17019
17519
  "ssg"
17020
17520
  );
17521
+ if (config) {
17522
+ app.get("/_loly/image", async (req, res) => {
17523
+ await handleImageRequest({
17524
+ req,
17525
+ res,
17526
+ projectRoot,
17527
+ config
17528
+ });
17529
+ });
17530
+ }
17021
17531
  app.all("/api/*", async (req, res) => {
17022
17532
  const apiRoutes = isDev && getRoutes ? (await getRoutes()).apiRoutes : initialApiRoutes;
17023
17533
  const serverConfig = await getServerConfig(projectRoot);
@@ -18064,7 +18574,7 @@ import cors from "cors";
18064
18574
  import helmet from "helmet";
18065
18575
  import cookieParser from "cookie-parser";
18066
18576
  import compression from "compression";
18067
- import crypto from "crypto";
18577
+ import crypto2 from "crypto";
18068
18578
  var setupApplication = async ({
18069
18579
  projectRoot
18070
18580
  }) => {
@@ -18173,7 +18683,7 @@ var setupApplication = async ({
18173
18683
  if (process.env.NODE_ENV !== "development" && security?.contentSecurityPolicy !== false) {
18174
18684
  app.use(
18175
18685
  (req, res, next) => {
18176
- const nonce = crypto.randomBytes(16).toString("base64");
18686
+ const nonce = crypto2.randomBytes(16).toString("base64");
18177
18687
  res.locals.nonce = nonce;
18178
18688
  next();
18179
18689
  }
@@ -18244,8 +18754,8 @@ var setupApplication = async ({
18244
18754
 
18245
18755
  // src/server.ts
18246
18756
  import dotenv2 from "dotenv";
18247
- var envPath = path27.join(process.cwd(), ".env");
18248
- if (fs21.existsSync(envPath)) {
18757
+ var envPath = path30.join(process.cwd(), ".env");
18758
+ if (fs23.existsSync(envPath)) {
18249
18759
  dotenv2.config({ path: envPath });
18250
18760
  } else {
18251
18761
  dotenv2.config();
@@ -18266,8 +18776,8 @@ async function startServer(options = {}) {
18266
18776
  }
18267
18777
  const port = options.port ?? (process.env.PORT ? parseInt(process.env.PORT, 10) : void 0) ?? config.server.port;
18268
18778
  const host = process.env.HOST ?? (!isDev ? "0.0.0.0" : void 0) ?? config.server.host;
18269
- const appDir = options.appDir ?? (isDev ? getAppDir(projectRoot, config) : path27.join(getBuildDir(projectRoot, config), "server"));
18270
- if (!isDev && !fs21.existsSync(appDir)) {
18779
+ const appDir = options.appDir ?? (isDev ? getAppDir(projectRoot, config) : path30.join(getBuildDir(projectRoot, config), "server"));
18780
+ if (!isDev && !fs23.existsSync(appDir)) {
18271
18781
  logger4.error("Compiled directory not found", void 0, {
18272
18782
  buildDir: config.directories.build,
18273
18783
  appDir,
@@ -18338,14 +18848,14 @@ async function startProdServer(options = {}) {
18338
18848
  }
18339
18849
 
18340
18850
  // modules/build/index.ts
18341
- import path32 from "path";
18342
- import fs24 from "fs";
18851
+ import path35 from "path";
18852
+ import fs26 from "fs";
18343
18853
 
18344
18854
  // modules/build/ssg/builder.ts
18345
- import path30 from "path";
18855
+ import path33 from "path";
18346
18856
 
18347
18857
  // modules/build/ssg/path.ts
18348
- import path28 from "path";
18858
+ import path31 from "path";
18349
18859
  function buildPathFromPattern(pattern, params) {
18350
18860
  const segments = pattern.split("/").filter(Boolean);
18351
18861
  const parts = [];
@@ -18374,12 +18884,12 @@ function buildPathFromPattern(pattern, params) {
18374
18884
  }
18375
18885
  function pathToOutDir(baseDir, urlPath) {
18376
18886
  const clean = urlPath === "/" ? "" : urlPath.replace(/^\/+/, "");
18377
- return path28.join(baseDir, clean);
18887
+ return path31.join(baseDir, clean);
18378
18888
  }
18379
18889
 
18380
18890
  // modules/build/ssg/renderer.ts
18381
- import fs22 from "fs";
18382
- import path29 from "path";
18891
+ import fs24 from "fs";
18892
+ import path32 from "path";
18383
18893
  import { renderToString } from "react-dom/server";
18384
18894
  init_globals();
18385
18895
  async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params, config) {
@@ -18515,16 +19025,16 @@ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params,
18515
19025
  const html = "<!DOCTYPE html>" + renderToString(documentTree);
18516
19026
  const dir = pathToOutDir(ssgOutDir, urlPath);
18517
19027
  ensureDir(dir);
18518
- const htmlFile = path29.join(dir, "index.html");
18519
- const dataFile = path29.join(dir, "data.json");
18520
- fs22.writeFileSync(htmlFile, html, "utf-8");
18521
- fs22.writeFileSync(dataFile, JSON.stringify(initialData, null, 2), "utf-8");
19028
+ const htmlFile = path32.join(dir, "index.html");
19029
+ const dataFile = path32.join(dir, "data.json");
19030
+ fs24.writeFileSync(htmlFile, html, "utf-8");
19031
+ fs24.writeFileSync(dataFile, JSON.stringify(initialData, null, 2), "utf-8");
18522
19032
  }
18523
19033
 
18524
19034
  // modules/build/ssg/builder.ts
18525
19035
  init_globals();
18526
19036
  async function buildStaticPages(projectRoot, routes, config) {
18527
- const ssgOutDir = path30.join(projectRoot, BUILD_FOLDER_NAME, "ssg");
19037
+ const ssgOutDir = path33.join(projectRoot, BUILD_FOLDER_NAME, "ssg");
18528
19038
  ensureDir(ssgOutDir);
18529
19039
  for (const route of routes) {
18530
19040
  if (route.dynamic !== "force-static") continue;
@@ -18579,36 +19089,36 @@ async function buildStaticPages(projectRoot, routes, config) {
18579
19089
  }
18580
19090
 
18581
19091
  // modules/build/bundler/server.ts
18582
- import path31 from "path";
18583
- import fs23 from "fs";
19092
+ import path34 from "path";
19093
+ import fs25 from "fs";
18584
19094
  import esbuild from "esbuild";
18585
19095
  init_globals();
18586
19096
  var SERVER_FILES = [INIT_FILE_NAME, CONFIG_FILE_NAME];
18587
19097
  function createPathAliasPlugin(projectRoot, outDir) {
18588
19098
  const aliases = loadAliasesFromTsconfig(projectRoot);
18589
- const tsconfigPath = path31.join(projectRoot, "tsconfig.json");
19099
+ const tsconfigPath = path34.join(projectRoot, "tsconfig.json");
18590
19100
  let baseUrl = ".";
18591
- if (fs23.existsSync(tsconfigPath)) {
19101
+ if (fs25.existsSync(tsconfigPath)) {
18592
19102
  try {
18593
- const tsconfig = JSON.parse(fs23.readFileSync(tsconfigPath, "utf-8"));
19103
+ const tsconfig = JSON.parse(fs25.readFileSync(tsconfigPath, "utf-8"));
18594
19104
  baseUrl = tsconfig.compilerOptions?.baseUrl ?? ".";
18595
19105
  } catch {
18596
19106
  }
18597
19107
  }
18598
19108
  function resolveAliasToRelative(importPath, sourceFile) {
18599
- if (importPath.startsWith(".") || importPath.startsWith("/") || path31.isAbsolute(importPath) || importPath.includes("node_modules")) {
19109
+ if (importPath.startsWith(".") || importPath.startsWith("/") || path34.isAbsolute(importPath) || importPath.includes("node_modules")) {
18600
19110
  return null;
18601
19111
  }
18602
19112
  for (const [aliasKey, aliasPath] of Object.entries(aliases)) {
18603
19113
  if (importPath.startsWith(aliasKey + "/") || importPath === aliasKey) {
18604
19114
  const restPath = importPath.startsWith(aliasKey + "/") ? importPath.slice(aliasKey.length + 1) : "";
18605
- const resolvedPath = restPath ? path31.join(aliasPath, restPath) : aliasPath;
19115
+ const resolvedPath = restPath ? path34.join(aliasPath, restPath) : aliasPath;
18606
19116
  let actualPath = null;
18607
19117
  const extensions = [".ts", ".tsx", ".js", ".jsx", ".json"];
18608
- if (fs23.existsSync(resolvedPath) && fs23.statSync(resolvedPath).isDirectory()) {
19118
+ if (fs25.existsSync(resolvedPath) && fs25.statSync(resolvedPath).isDirectory()) {
18609
19119
  for (const ext of extensions) {
18610
- const indexPath = path31.join(resolvedPath, `index${ext}`);
18611
- if (fs23.existsSync(indexPath)) {
19120
+ const indexPath = path34.join(resolvedPath, `index${ext}`);
19121
+ if (fs25.existsSync(indexPath)) {
18612
19122
  actualPath = indexPath;
18613
19123
  break;
18614
19124
  }
@@ -18616,20 +19126,20 @@ function createPathAliasPlugin(projectRoot, outDir) {
18616
19126
  } else {
18617
19127
  for (const ext of extensions) {
18618
19128
  const filePath = resolvedPath + ext;
18619
- if (fs23.existsSync(filePath)) {
19129
+ if (fs25.existsSync(filePath)) {
18620
19130
  actualPath = filePath;
18621
19131
  break;
18622
19132
  }
18623
19133
  }
18624
- if (!actualPath && fs23.existsSync(resolvedPath)) {
19134
+ if (!actualPath && fs25.existsSync(resolvedPath)) {
18625
19135
  actualPath = resolvedPath;
18626
19136
  }
18627
19137
  }
18628
19138
  if (actualPath) {
18629
- const relativePath = path31.relative(outDir, actualPath);
19139
+ const relativePath = path34.relative(outDir, actualPath);
18630
19140
  const normalizedPath = relativePath.replace(/\\/g, "/");
18631
19141
  const finalPath = normalizedPath.startsWith(".") ? normalizedPath : `./${normalizedPath}`;
18632
- const ext = path31.extname(finalPath);
19142
+ const ext = path34.extname(finalPath);
18633
19143
  const pathWithoutExt = ext === ".json" ? finalPath : finalPath.slice(0, -ext.length);
18634
19144
  return pathWithoutExt;
18635
19145
  }
@@ -18641,19 +19151,19 @@ function createPathAliasPlugin(projectRoot, outDir) {
18641
19151
  name: "path-alias-resolver",
18642
19152
  setup(build) {
18643
19153
  function resolveAliasToAbsolute(importPath) {
18644
- if (importPath.startsWith(".") || importPath.startsWith("/") || path31.isAbsolute(importPath) || importPath.includes("node_modules")) {
19154
+ if (importPath.startsWith(".") || importPath.startsWith("/") || path34.isAbsolute(importPath) || importPath.includes("node_modules")) {
18645
19155
  return null;
18646
19156
  }
18647
19157
  for (const [aliasKey, aliasPath] of Object.entries(aliases)) {
18648
19158
  if (importPath.startsWith(aliasKey + "/") || importPath === aliasKey) {
18649
19159
  const restPath = importPath.startsWith(aliasKey + "/") ? importPath.slice(aliasKey.length + 1) : "";
18650
- const resolvedPath = restPath ? path31.join(aliasPath, restPath) : aliasPath;
19160
+ const resolvedPath = restPath ? path34.join(aliasPath, restPath) : aliasPath;
18651
19161
  let actualPath = null;
18652
19162
  const extensions = [".ts", ".tsx", ".js", ".jsx", ".json"];
18653
- if (fs23.existsSync(resolvedPath) && fs23.statSync(resolvedPath).isDirectory()) {
19163
+ if (fs25.existsSync(resolvedPath) && fs25.statSync(resolvedPath).isDirectory()) {
18654
19164
  for (const ext of extensions) {
18655
- const indexPath = path31.join(resolvedPath, `index${ext}`);
18656
- if (fs23.existsSync(indexPath)) {
19165
+ const indexPath = path34.join(resolvedPath, `index${ext}`);
19166
+ if (fs25.existsSync(indexPath)) {
18657
19167
  actualPath = indexPath;
18658
19168
  break;
18659
19169
  }
@@ -18661,12 +19171,12 @@ function createPathAliasPlugin(projectRoot, outDir) {
18661
19171
  } else {
18662
19172
  for (const ext of extensions) {
18663
19173
  const filePath = resolvedPath + ext;
18664
- if (fs23.existsSync(filePath)) {
19174
+ if (fs25.existsSync(filePath)) {
18665
19175
  actualPath = filePath;
18666
19176
  break;
18667
19177
  }
18668
19178
  }
18669
- if (!actualPath && fs23.existsSync(resolvedPath)) {
19179
+ if (!actualPath && fs25.existsSync(resolvedPath)) {
18670
19180
  actualPath = resolvedPath;
18671
19181
  }
18672
19182
  }
@@ -18679,7 +19189,7 @@ function createPathAliasPlugin(projectRoot, outDir) {
18679
19189
  }
18680
19190
  build.onResolve({ filter: /^[^./]/ }, (args) => {
18681
19191
  const absolutePath = resolveAliasToAbsolute(args.path);
18682
- if (absolutePath && fs23.existsSync(absolutePath)) {
19192
+ if (absolutePath && fs25.existsSync(absolutePath)) {
18683
19193
  return {
18684
19194
  path: absolutePath,
18685
19195
  namespace: "file"
@@ -18688,13 +19198,13 @@ function createPathAliasPlugin(projectRoot, outDir) {
18688
19198
  return null;
18689
19199
  });
18690
19200
  build.onLoad({ filter: /\.(ts|tsx|js|jsx)$/ }, (args) => {
18691
- const fileName = path31.basename(args.path);
19201
+ const fileName = path34.basename(args.path);
18692
19202
  const isServerFile = SERVER_FILES.some((f) => fileName === `${f}.ts` || fileName === `${f}.tsx` || fileName === `${f}.js` || fileName === `${f}.jsx`);
18693
- const isInProjectRoot = path31.dirname(args.path) === projectRoot;
19203
+ const isInProjectRoot = path34.dirname(args.path) === projectRoot;
18694
19204
  if (!isServerFile || !isInProjectRoot) {
18695
19205
  return null;
18696
19206
  }
18697
- const contents = fs23.readFileSync(args.path, "utf-8");
19207
+ const contents = fs25.readFileSync(args.path, "utf-8");
18698
19208
  let transformed = contents;
18699
19209
  const aliasPatterns = Object.keys(aliases).sort((a, b) => b.length - a.length);
18700
19210
  for (const aliasKey of aliasPatterns) {
@@ -18714,7 +19224,7 @@ function createPathAliasPlugin(projectRoot, outDir) {
18714
19224
  }
18715
19225
  return {
18716
19226
  contents: transformed,
18717
- loader: path31.extname(args.path).slice(1)
19227
+ loader: path34.extname(args.path).slice(1)
18718
19228
  };
18719
19229
  });
18720
19230
  }
@@ -18726,13 +19236,13 @@ function rewritePathAliasesInOutput(outDir, projectRoot, appDir) {
18726
19236
  for (const [aliasKey, aliasSourcePath] of Object.entries(aliases)) {
18727
19237
  if (aliasPath.startsWith(aliasKey + "/") || aliasPath === aliasKey) {
18728
19238
  const restPath = aliasPath.startsWith(aliasKey + "/") ? aliasPath.slice(aliasKey.length + 1) : "";
18729
- const resolvedSourcePath = restPath ? path31.join(aliasSourcePath, restPath) : aliasSourcePath;
19239
+ const resolvedSourcePath = restPath ? path34.join(aliasSourcePath, restPath) : aliasSourcePath;
18730
19240
  let actualSourcePath = null;
18731
19241
  const extensions = [".ts", ".tsx", ".js", ".jsx", ".json"];
18732
- if (fs23.existsSync(resolvedSourcePath) && fs23.statSync(resolvedSourcePath).isDirectory()) {
19242
+ if (fs25.existsSync(resolvedSourcePath) && fs25.statSync(resolvedSourcePath).isDirectory()) {
18733
19243
  for (const ext of extensions) {
18734
- const indexPath = path31.join(resolvedSourcePath, `index${ext}`);
18735
- if (fs23.existsSync(indexPath)) {
19244
+ const indexPath = path34.join(resolvedSourcePath, `index${ext}`);
19245
+ if (fs25.existsSync(indexPath)) {
18736
19246
  actualSourcePath = indexPath;
18737
19247
  break;
18738
19248
  }
@@ -18740,21 +19250,21 @@ function rewritePathAliasesInOutput(outDir, projectRoot, appDir) {
18740
19250
  } else {
18741
19251
  for (const ext of extensions) {
18742
19252
  const filePath = resolvedSourcePath + ext;
18743
- if (fs23.existsSync(filePath)) {
19253
+ if (fs25.existsSync(filePath)) {
18744
19254
  actualSourcePath = filePath;
18745
19255
  break;
18746
19256
  }
18747
19257
  }
18748
- if (!actualSourcePath && fs23.existsSync(resolvedSourcePath)) {
19258
+ if (!actualSourcePath && fs25.existsSync(resolvedSourcePath)) {
18749
19259
  actualSourcePath = resolvedSourcePath;
18750
19260
  }
18751
19261
  }
18752
19262
  if (actualSourcePath) {
18753
- const relativeFromApp = path31.relative(appDir, actualSourcePath);
18754
- const outputPath = path31.join(outDir, relativeFromApp);
19263
+ const relativeFromApp = path34.relative(appDir, actualSourcePath);
19264
+ const outputPath = path34.join(outDir, relativeFromApp);
18755
19265
  const pathWithoutExt = outputPath.replace(/\.(ts|tsx|js|jsx|json)$/, "");
18756
19266
  const compiledPath = pathWithoutExt + ".mjs";
18757
- if (fs23.existsSync(compiledPath)) {
19267
+ if (fs25.existsSync(compiledPath)) {
18758
19268
  return compiledPath;
18759
19269
  }
18760
19270
  }
@@ -18763,17 +19273,17 @@ function rewritePathAliasesInOutput(outDir, projectRoot, appDir) {
18763
19273
  return null;
18764
19274
  }
18765
19275
  function walkAndRewrite(dir) {
18766
- if (!fs23.existsSync(dir)) return;
18767
- const items = fs23.readdirSync(dir, { withFileTypes: true });
19276
+ if (!fs25.existsSync(dir)) return;
19277
+ const items = fs25.readdirSync(dir, { withFileTypes: true });
18768
19278
  for (const item of items) {
18769
- const full = path31.join(dir, item.name);
19279
+ const full = path34.join(dir, item.name);
18770
19280
  if (item.isDirectory()) {
18771
19281
  walkAndRewrite(full);
18772
19282
  continue;
18773
19283
  }
18774
19284
  if (item.isFile() && full.endsWith(".mjs")) {
18775
19285
  try {
18776
- let content = fs23.readFileSync(full, "utf-8");
19286
+ let content = fs25.readFileSync(full, "utf-8");
18777
19287
  let modified = false;
18778
19288
  const aliasPatterns = Object.keys(aliases).sort((a, b) => b.length - a.length);
18779
19289
  for (const aliasKey of aliasPatterns) {
@@ -18785,8 +19295,8 @@ function rewritePathAliasesInOutput(outDir, projectRoot, appDir) {
18785
19295
  content = content.replace(aliasInQuotesPattern, (match, quote1, rest, quote2) => {
18786
19296
  const fullAliasPath = aliasKey + (rest || "");
18787
19297
  const resolvedOutputPath = resolveAliasToOutputPath(fullAliasPath);
18788
- if (resolvedOutputPath && fs23.existsSync(resolvedOutputPath)) {
18789
- const relativePath = path31.relative(path31.dirname(full), resolvedOutputPath);
19298
+ if (resolvedOutputPath && fs25.existsSync(resolvedOutputPath)) {
19299
+ const relativePath = path34.relative(path34.dirname(full), resolvedOutputPath);
18790
19300
  let normalizedPath = relativePath.replace(/\\/g, "/");
18791
19301
  if (!normalizedPath.startsWith(".")) {
18792
19302
  normalizedPath = `./${normalizedPath}`;
@@ -18799,7 +19309,7 @@ function rewritePathAliasesInOutput(outDir, projectRoot, appDir) {
18799
19309
  });
18800
19310
  }
18801
19311
  if (modified) {
18802
- fs23.writeFileSync(full, content, "utf-8");
19312
+ fs25.writeFileSync(full, content, "utf-8");
18803
19313
  }
18804
19314
  } catch (error) {
18805
19315
  console.warn(`[framework] Warning: Could not rewrite path aliases in ${full}:`, error instanceof Error ? error.message : String(error));
@@ -18810,14 +19320,14 @@ function rewritePathAliasesInOutput(outDir, projectRoot, appDir) {
18810
19320
  walkAndRewrite(outDir);
18811
19321
  }
18812
19322
  function copyStaticFilesFromApp(appDir, outDir) {
18813
- if (!fs23.existsSync(appDir)) return;
19323
+ if (!fs25.existsSync(appDir)) return;
18814
19324
  const sourceExtensions = [".ts", ".tsx", ".js", ".jsx", ".d.ts", ".map"];
18815
19325
  function walk(srcDir, destDir) {
18816
- if (!fs23.existsSync(srcDir)) return;
18817
- const items = fs23.readdirSync(srcDir, { withFileTypes: true });
19326
+ if (!fs25.existsSync(srcDir)) return;
19327
+ const items = fs25.readdirSync(srcDir, { withFileTypes: true });
18818
19328
  for (const item of items) {
18819
- const srcPath = path31.join(srcDir, item.name);
18820
- const destPath = path31.join(destDir, item.name);
19329
+ const srcPath = path34.join(srcDir, item.name);
19330
+ const destPath = path34.join(destDir, item.name);
18821
19331
  if (item.isDirectory()) {
18822
19332
  if (item.name === "node_modules" || item.name.startsWith(".")) {
18823
19333
  continue;
@@ -18827,10 +19337,10 @@ function copyStaticFilesFromApp(appDir, outDir) {
18827
19337
  continue;
18828
19338
  }
18829
19339
  if (item.isFile()) {
18830
- const ext = path31.extname(item.name).toLowerCase();
19340
+ const ext = path34.extname(item.name).toLowerCase();
18831
19341
  if (!sourceExtensions.includes(ext)) {
18832
19342
  ensureDir(destDir);
18833
- fs23.copyFileSync(srcPath, destPath);
19343
+ fs25.copyFileSync(srcPath, destPath);
18834
19344
  }
18835
19345
  }
18836
19346
  }
@@ -18840,9 +19350,9 @@ function copyStaticFilesFromApp(appDir, outDir) {
18840
19350
  function collectAppSources(appDir) {
18841
19351
  const entries = [];
18842
19352
  function walk(dir) {
18843
- const items = fs23.readdirSync(dir, { withFileTypes: true });
19353
+ const items = fs25.readdirSync(dir, { withFileTypes: true });
18844
19354
  for (const item of items) {
18845
- const full = path31.join(dir, item.name);
19355
+ const full = path34.join(dir, item.name);
18846
19356
  if (item.isDirectory()) {
18847
19357
  walk(full);
18848
19358
  continue;
@@ -18859,7 +19369,7 @@ function collectAppSources(appDir) {
18859
19369
  return entries;
18860
19370
  }
18861
19371
  async function buildServerApp(projectRoot, appDir, config) {
18862
- const outDir = path31.join(projectRoot, BUILD_FOLDER_NAME, "server");
19372
+ const outDir = path34.join(projectRoot, BUILD_FOLDER_NAME, "server");
18863
19373
  const entryPoints = collectAppSources(appDir);
18864
19374
  ensureDir(outDir);
18865
19375
  if (entryPoints.length === 0) {
@@ -18878,7 +19388,7 @@ async function buildServerApp(projectRoot, appDir, config) {
18878
19388
  bundle: true,
18879
19389
  splitting: false,
18880
19390
  logLevel: "info",
18881
- tsconfig: path31.join(projectRoot, "tsconfig.json"),
19391
+ tsconfig: path34.join(projectRoot, "tsconfig.json"),
18882
19392
  packages: "external",
18883
19393
  outExtension: { ".js": ".mjs" },
18884
19394
  plugins: [pathAliasPlugin]
@@ -18887,9 +19397,9 @@ async function buildServerApp(projectRoot, appDir, config) {
18887
19397
  copyStaticFilesFromApp(appDir, outDir);
18888
19398
  rewritePathAliasesInOutput(outDir, projectRoot, appDir);
18889
19399
  for (const fileName of SERVER_FILES) {
18890
- const initTS = path31.join(projectRoot, `${fileName}.ts`);
18891
- if (fs23.existsSync(initTS)) {
18892
- const initJSWithExt = path31.join(outDir, `${fileName}.mjs`);
19400
+ const initTS = path34.join(projectRoot, `${fileName}.ts`);
19401
+ if (fs25.existsSync(initTS)) {
19402
+ const initJSWithExt = path34.join(outDir, `${fileName}.mjs`);
18893
19403
  await esbuild.build({
18894
19404
  entryPoints: [initTS],
18895
19405
  outfile: initJSWithExt,
@@ -18901,7 +19411,7 @@ async function buildServerApp(projectRoot, appDir, config) {
18901
19411
  bundle: true,
18902
19412
  packages: "external",
18903
19413
  logLevel: "info",
18904
- tsconfig: path31.join(projectRoot, "tsconfig.json"),
19414
+ tsconfig: path34.join(projectRoot, "tsconfig.json"),
18905
19415
  plugins: [pathAliasPlugin],
18906
19416
  outExtension: { ".js": ".mjs" }
18907
19417
  });
@@ -18917,8 +19427,8 @@ async function buildApp(options = {}) {
18917
19427
  const config = options.config ?? loadConfig(projectRoot);
18918
19428
  const appDir = options.appDir ?? getAppDir(projectRoot, config);
18919
19429
  try {
18920
- const tsxPath = path32.join(projectRoot, "node_modules", "tsx", "dist", "esm", "index.mjs");
18921
- if (fs24.existsSync(tsxPath)) {
19430
+ const tsxPath = path35.join(projectRoot, "node_modules", "tsx", "dist", "esm", "index.mjs");
19431
+ if (fs26.existsSync(tsxPath)) {
18922
19432
  const { pathToFileURL: pathToFileURL2 } = await import("url");
18923
19433
  const tsxUrl = pathToFileURL2(tsxPath).href;
18924
19434
  await import(tsxUrl);
@@ -19187,132 +19697,134 @@ function getOrCreateLink(rel, href) {
19187
19697
  }
19188
19698
  function applyMetadata(md) {
19189
19699
  if (!md) return;
19190
- if (md.title) {
19191
- document.title = md.title;
19192
- }
19193
- if (md.description) {
19194
- const meta = getOrCreateMeta('meta[name="description"]', { name: "description" });
19195
- meta.content = md.description;
19196
- }
19197
- if (md.robots) {
19198
- const meta = getOrCreateMeta('meta[name="robots"]', { name: "robots" });
19199
- meta.content = md.robots;
19200
- }
19201
- if (md.themeColor) {
19202
- const meta = getOrCreateMeta('meta[name="theme-color"]', { name: "theme-color" });
19203
- meta.content = md.themeColor;
19204
- }
19205
- if (md.viewport) {
19206
- const meta = getOrCreateMeta('meta[name="viewport"]', { name: "viewport" });
19207
- meta.content = md.viewport;
19208
- }
19209
- if (md.canonical) {
19210
- getOrCreateLink("canonical", md.canonical);
19211
- }
19212
- if (md.openGraph) {
19213
- const og = md.openGraph;
19214
- if (og.title) {
19215
- const meta = getOrCreateMeta('meta[property="og:title"]', { property: "og:title" });
19216
- meta.content = og.title;
19217
- }
19218
- if (og.description) {
19219
- const meta = getOrCreateMeta('meta[property="og:description"]', { property: "og:description" });
19220
- meta.content = og.description;
19221
- }
19222
- if (og.type) {
19223
- const meta = getOrCreateMeta('meta[property="og:type"]', { property: "og:type" });
19224
- meta.content = og.type;
19225
- }
19226
- if (og.url) {
19227
- const meta = getOrCreateMeta('meta[property="og:url"]', { property: "og:url" });
19228
- meta.content = og.url;
19229
- }
19230
- if (og.image) {
19231
- if (typeof og.image === "string") {
19232
- const meta = getOrCreateMeta('meta[property="og:image"]', { property: "og:image" });
19233
- meta.content = og.image;
19234
- } else {
19235
- const meta = getOrCreateMeta('meta[property="og:image"]', { property: "og:image" });
19236
- meta.content = og.image.url;
19237
- if (og.image.width) {
19238
- const metaWidth = getOrCreateMeta('meta[property="og:image:width"]', { property: "og:image:width" });
19239
- metaWidth.content = String(og.image.width);
19240
- }
19241
- if (og.image.height) {
19242
- const metaHeight = getOrCreateMeta('meta[property="og:image:height"]', { property: "og:image:height" });
19243
- metaHeight.content = String(og.image.height);
19244
- }
19245
- if (og.image.alt) {
19246
- const metaAlt = getOrCreateMeta('meta[property="og:image:alt"]', { property: "og:image:alt" });
19247
- metaAlt.content = og.image.alt;
19700
+ requestAnimationFrame(() => {
19701
+ if (md.title) {
19702
+ document.title = md.title;
19703
+ }
19704
+ if (md.description) {
19705
+ const meta = getOrCreateMeta('meta[name="description"]', { name: "description" });
19706
+ meta.content = md.description;
19707
+ }
19708
+ if (md.robots) {
19709
+ const meta = getOrCreateMeta('meta[name="robots"]', { name: "robots" });
19710
+ meta.content = md.robots;
19711
+ }
19712
+ if (md.themeColor) {
19713
+ const meta = getOrCreateMeta('meta[name="theme-color"]', { name: "theme-color" });
19714
+ meta.content = md.themeColor;
19715
+ }
19716
+ if (md.viewport) {
19717
+ const meta = getOrCreateMeta('meta[name="viewport"]', { name: "viewport" });
19718
+ meta.content = md.viewport;
19719
+ }
19720
+ if (md.canonical) {
19721
+ getOrCreateLink("canonical", md.canonical);
19722
+ }
19723
+ if (md.openGraph) {
19724
+ const og = md.openGraph;
19725
+ if (og.title) {
19726
+ const meta = getOrCreateMeta('meta[property="og:title"]', { property: "og:title" });
19727
+ meta.content = og.title;
19728
+ }
19729
+ if (og.description) {
19730
+ const meta = getOrCreateMeta('meta[property="og:description"]', { property: "og:description" });
19731
+ meta.content = og.description;
19732
+ }
19733
+ if (og.type) {
19734
+ const meta = getOrCreateMeta('meta[property="og:type"]', { property: "og:type" });
19735
+ meta.content = og.type;
19736
+ }
19737
+ if (og.url) {
19738
+ const meta = getOrCreateMeta('meta[property="og:url"]', { property: "og:url" });
19739
+ meta.content = og.url;
19740
+ }
19741
+ if (og.image) {
19742
+ if (typeof og.image === "string") {
19743
+ const meta = getOrCreateMeta('meta[property="og:image"]', { property: "og:image" });
19744
+ meta.content = og.image;
19745
+ } else {
19746
+ const meta = getOrCreateMeta('meta[property="og:image"]', { property: "og:image" });
19747
+ meta.content = og.image.url;
19748
+ if (og.image.width) {
19749
+ const metaWidth = getOrCreateMeta('meta[property="og:image:width"]', { property: "og:image:width" });
19750
+ metaWidth.content = String(og.image.width);
19751
+ }
19752
+ if (og.image.height) {
19753
+ const metaHeight = getOrCreateMeta('meta[property="og:image:height"]', { property: "og:image:height" });
19754
+ metaHeight.content = String(og.image.height);
19755
+ }
19756
+ if (og.image.alt) {
19757
+ const metaAlt = getOrCreateMeta('meta[property="og:image:alt"]', { property: "og:image:alt" });
19758
+ metaAlt.content = og.image.alt;
19759
+ }
19248
19760
  }
19249
19761
  }
19762
+ if (og.siteName) {
19763
+ const meta = getOrCreateMeta('meta[property="og:site_name"]', { property: "og:site_name" });
19764
+ meta.content = og.siteName;
19765
+ }
19766
+ if (og.locale) {
19767
+ const meta = getOrCreateMeta('meta[property="og:locale"]', { property: "og:locale" });
19768
+ meta.content = og.locale;
19769
+ }
19250
19770
  }
19251
- if (og.siteName) {
19252
- const meta = getOrCreateMeta('meta[property="og:site_name"]', { property: "og:site_name" });
19253
- meta.content = og.siteName;
19254
- }
19255
- if (og.locale) {
19256
- const meta = getOrCreateMeta('meta[property="og:locale"]', { property: "og:locale" });
19257
- meta.content = og.locale;
19258
- }
19259
- }
19260
- if (md.twitter) {
19261
- const twitter = md.twitter;
19262
- if (twitter.card) {
19263
- const meta = getOrCreateMeta('meta[name="twitter:card"]', { name: "twitter:card" });
19264
- meta.content = twitter.card;
19265
- }
19266
- if (twitter.title) {
19267
- const meta = getOrCreateMeta('meta[name="twitter:title"]', { name: "twitter:title" });
19268
- meta.content = twitter.title;
19269
- }
19270
- if (twitter.description) {
19271
- const meta = getOrCreateMeta('meta[name="twitter:description"]', { name: "twitter:description" });
19272
- meta.content = twitter.description;
19273
- }
19274
- if (twitter.image) {
19275
- const meta = getOrCreateMeta('meta[name="twitter:image"]', { name: "twitter:image" });
19276
- meta.content = twitter.image;
19771
+ if (md.twitter) {
19772
+ const twitter = md.twitter;
19773
+ if (twitter.card) {
19774
+ const meta = getOrCreateMeta('meta[name="twitter:card"]', { name: "twitter:card" });
19775
+ meta.content = twitter.card;
19776
+ }
19777
+ if (twitter.title) {
19778
+ const meta = getOrCreateMeta('meta[name="twitter:title"]', { name: "twitter:title" });
19779
+ meta.content = twitter.title;
19780
+ }
19781
+ if (twitter.description) {
19782
+ const meta = getOrCreateMeta('meta[name="twitter:description"]', { name: "twitter:description" });
19783
+ meta.content = twitter.description;
19784
+ }
19785
+ if (twitter.image) {
19786
+ const meta = getOrCreateMeta('meta[name="twitter:image"]', { name: "twitter:image" });
19787
+ meta.content = twitter.image;
19788
+ }
19789
+ if (twitter.imageAlt) {
19790
+ const meta = getOrCreateMeta('meta[name="twitter:image:alt"]', { name: "twitter:image:alt" });
19791
+ meta.content = twitter.imageAlt;
19792
+ }
19793
+ if (twitter.site) {
19794
+ const meta = getOrCreateMeta('meta[name="twitter:site"]', { name: "twitter:site" });
19795
+ meta.content = twitter.site;
19796
+ }
19797
+ if (twitter.creator) {
19798
+ const meta = getOrCreateMeta('meta[name="twitter:creator"]', { name: "twitter:creator" });
19799
+ meta.content = twitter.creator;
19800
+ }
19277
19801
  }
19278
- if (twitter.imageAlt) {
19279
- const meta = getOrCreateMeta('meta[name="twitter:image:alt"]', { name: "twitter:image:alt" });
19280
- meta.content = twitter.imageAlt;
19802
+ if (md.metaTags && Array.isArray(md.metaTags)) {
19803
+ md.metaTags.forEach((tag) => {
19804
+ let selector = "";
19805
+ if (tag.name) {
19806
+ selector = `meta[name="${tag.name}"]`;
19807
+ } else if (tag.property) {
19808
+ selector = `meta[property="${tag.property}"]`;
19809
+ } else if (tag.httpEquiv) {
19810
+ selector = `meta[http-equiv="${tag.httpEquiv}"]`;
19811
+ }
19812
+ if (selector) {
19813
+ const meta = getOrCreateMeta(selector, {
19814
+ name: tag.name,
19815
+ property: tag.property,
19816
+ httpEquiv: tag.httpEquiv
19817
+ });
19818
+ meta.content = tag.content;
19819
+ }
19820
+ });
19281
19821
  }
19282
- if (twitter.site) {
19283
- const meta = getOrCreateMeta('meta[name="twitter:site"]', { name: "twitter:site" });
19284
- meta.content = twitter.site;
19822
+ if (md.links && Array.isArray(md.links)) {
19823
+ md.links.forEach((link) => {
19824
+ getOrCreateLink(link.rel, link.href);
19825
+ });
19285
19826
  }
19286
- if (twitter.creator) {
19287
- const meta = getOrCreateMeta('meta[name="twitter:creator"]', { name: "twitter:creator" });
19288
- meta.content = twitter.creator;
19289
- }
19290
- }
19291
- if (md.metaTags && Array.isArray(md.metaTags)) {
19292
- md.metaTags.forEach((tag) => {
19293
- let selector = "";
19294
- if (tag.name) {
19295
- selector = `meta[name="${tag.name}"]`;
19296
- } else if (tag.property) {
19297
- selector = `meta[property="${tag.property}"]`;
19298
- } else if (tag.httpEquiv) {
19299
- selector = `meta[http-equiv="${tag.httpEquiv}"]`;
19300
- }
19301
- if (selector) {
19302
- const meta = getOrCreateMeta(selector, {
19303
- name: tag.name,
19304
- property: tag.property,
19305
- httpEquiv: tag.httpEquiv
19306
- });
19307
- meta.content = tag.content;
19308
- }
19309
- });
19310
- }
19311
- if (md.links && Array.isArray(md.links)) {
19312
- md.links.forEach((link) => {
19313
- getOrCreateLink(link.rel, link.href);
19314
- });
19315
- }
19827
+ });
19316
19828
  }
19317
19829
 
19318
19830
  // modules/runtime/client/AppShell.tsx
@@ -20202,11 +20714,11 @@ var ValidationError = class extends Error {
20202
20714
  format() {
20203
20715
  const formatted = {};
20204
20716
  for (const error of this.errors) {
20205
- const path33 = error.path.join(".");
20206
- if (!formatted[path33]) {
20207
- formatted[path33] = [];
20717
+ const path36 = error.path.join(".");
20718
+ if (!formatted[path36]) {
20719
+ formatted[path36] = [];
20208
20720
  }
20209
- formatted[path33].push(error.message);
20721
+ formatted[path36].push(error.message);
20210
20722
  }
20211
20723
  return formatted;
20212
20724
  }