@staticbolt/core 1.0.0-beta.0 → 1.0.0-beta.10

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.
@@ -1,5 +1,5 @@
1
- import { A as isHtmlMetadata, C as PrintFormattedError, D as filterScriptMetadata, E as traverse, F as isSvgMetadata, I as isTextAssetMetadata, L as isWebManifestMetadata, M as isPackageMetadata, N as isScriptMetadata, O as filterStyleMetadata, P as isStyleMetadata, R as isScriptType, S as valueOrError, T as generator, c as cloneObject, f as hashContent, g as isURL, j as isMarkdownMetadata, k as isBinaryAssetMetadata, l as downloadContent, p as humanReadableBytes, r as bytesToKB, t as DependencyTracker, u as escapeHtml, v as mergeMaps, w as printFmtError, x as safeReadFileSync, z as METADATA_TYPES } from "../dependency-tracker-BuZfopIj.mjs";
2
- import { _ as relative, c as extname, d as isSubpath, f as join, h as parse$2, i as CUSTOM_ATTRIBUTES, m as normalize, n as createLog, o as basename, p as matchPath, r as CONFIG_FILE_NAME, s as dirname, t as Log, u as isAbsolute, v as replaceExtension, y as resolve } from "../logger-BuxMGhij.mjs";
1
+ import { A as isHtmlMetadata, B as DependencyTracker, C as PrintFormattedError, D as filterScriptMetadata, E as traverse, F as isSvgMetadata, I as isTextAssetMetadata, L as isWebManifestMetadata, M as isPackageMetadata, N as isScriptMetadata, O as filterStyleMetadata, P as isStyleMetadata, R as isScriptType, S as valueOrError, T as generator, _ as mergeMaps, b as safeReadFileSync, c as downloadContent, d as hashContent, f as humanReadableBytes, h as isURL, j as isMarkdownMetadata, k as isBinaryAssetMetadata, l as escapeHtml, n as bytesToKB, s as cloneObject, w as printFmtError, z as METADATA_TYPES } from "../utilities-CZmLMi93.mjs";
2
+ import { _ as CUSTOM_ATTRIBUTES, a as extname, c as join, d as parse$2, g as CONFIG_FILE_NAME, h as resolve, i as dirname, l as matchPath, m as replaceExtension, n as createLog, o as isAbsolute, p as relative, r as basename, s as isSubpath, t as Log, u as normalize } from "../logger-BfIn1ytK.mjs";
3
3
  import { createRequire } from "node:module";
4
4
  import nodePath from "node:path";
5
5
  import { HTMLElement, NodeType, parse } from "@staticbolt/node-html-parser";
@@ -1146,6 +1146,7 @@ function parseOptionFromImgPath(imgPath, defaultQuality, defaultPreset) {
1146
1146
  function copyAssetsPlugin(options = {}) {
1147
1147
  const include = options.include ?? ["sources/assets/**/*"];
1148
1148
  const ignore = options.exclude ?? [];
1149
+ const publicDirectory = options.publicDirectory ?? "public";
1149
1150
  return {
1150
1151
  name: "copy-assets",
1151
1152
  postBuild() {
@@ -1157,7 +1158,6 @@ function copyAssetsPlugin(options = {}) {
1157
1158
  nodir: true,
1158
1159
  cwd: this.root
1159
1160
  });
1160
- if (assetsFiles.length === 0) return;
1161
1161
  for (const file of assetsFiles) {
1162
1162
  const inputFile = join(this.root, file);
1163
1163
  if (convertedImages.has(inputFile)) continue;
@@ -1167,6 +1167,20 @@ function copyAssetsPlugin(options = {}) {
1167
1167
  mkdirSync(dirname(outputFile), { recursive: true });
1168
1168
  copyFileSync(inputFile, outputFile);
1169
1169
  }
1170
+ const publicFiles = globSync("**/*", {
1171
+ ignore,
1172
+ nodir: true,
1173
+ cwd: join(this.root, publicDirectory)
1174
+ });
1175
+ for (const file of publicFiles) {
1176
+ const inputFile = join(this.root, publicDirectory, file);
1177
+ if (convertedImages.has(inputFile)) continue;
1178
+ if (optimizedSvgList.has(inputFile)) continue;
1179
+ const outputFile = join(this.outdir, file);
1180
+ if (existsSync(outputFile)) continue;
1181
+ mkdirSync(dirname(outputFile), { recursive: true });
1182
+ copyFileSync(inputFile, outputFile);
1183
+ }
1170
1184
  }
1171
1185
  };
1172
1186
  }
@@ -2421,7 +2435,7 @@ function loadSourcesPlugin(options) {
2421
2435
  const ignore = options.exclude ?? [];
2422
2436
  return {
2423
2437
  name: "load-sources",
2424
- async setup() {
2438
+ setup() {
2425
2439
  const entryFiles = globSync(options.include, {
2426
2440
  ignore,
2427
2441
  cwd: this.root,
@@ -2436,16 +2450,6 @@ function loadSourcesPlugin(options) {
2436
2450
  this.entryPoints.add(normalized);
2437
2451
  this.watcher?.add(normalized);
2438
2452
  }
2439
- if (!this.production) return;
2440
- for (const entryFile of this.entryPoints) {
2441
- if (this.findMetadata({ id: entryFile })) continue;
2442
- const metadata = await this.load(entryFile);
2443
- if (!metadata) {
2444
- this.log.error(`Could not load "${entryFile}".`);
2445
- return;
2446
- }
2447
- this.addMetadata(metadata);
2448
- }
2449
2453
  },
2450
2454
  onFileEvent(event, id) {
2451
2455
  if (event === "change") return;
@@ -3071,29 +3075,24 @@ function htmlBuildTimeScript(options = {}) {
3071
3075
  //#region src/plugins/html-bundle-script/esbuild-plugin.ts
3072
3076
  function loaderPlugin(outFile, checkExternal) {
3073
3077
  const root = this.root;
3074
- const appThis = () => this;
3078
+ const outFileAbs = join(root, outFile);
3079
+ const app = this;
3075
3080
  return {
3076
3081
  name: "resolve-loader",
3077
3082
  setup(build) {
3078
3083
  build.onResolve({ filter: /\.(js|mjs|cjs)$/ }, (arguments_) => {
3079
3084
  if (!arguments_.path.startsWith(".")) return;
3080
- const app = appThis();
3081
3085
  const absSource = join(arguments_.resolveDir, arguments_.path);
3082
3086
  const source = relative(root, absSource);
3083
- const relativeToOutFile = relative(dirname(outFile), source);
3084
- const external = checkExternal(source);
3085
- if (external) return {
3086
- path: relativeToOutFile,
3087
- external
3087
+ if (checkExternal(source)) return {
3088
+ path: relative(dirname(outFile), source),
3089
+ external: true
3088
3090
  };
3089
3091
  if (matchPath(source, {
3090
3092
  include: ["**/node_modules/**"],
3091
3093
  ignore: [],
3092
3094
  root
3093
- })) return {
3094
- path: absSource,
3095
- external
3096
- };
3095
+ })) return { path: absSource };
3097
3096
  const scriptMetadata = app.findMetadata({ filePath: source });
3098
3097
  if (!isScriptMetadata(scriptMetadata)) {
3099
3098
  Log.error(`[htmlBundleScriptPlugin:onResolve] Script metadata for the path "${source}" not found`);
@@ -3102,8 +3101,7 @@ function loaderPlugin(outFile, checkExternal) {
3102
3101
  return {
3103
3102
  path: absSource,
3104
3103
  namespace: "loader",
3105
- pluginData: scriptMetadata,
3106
- external
3104
+ pluginData: scriptMetadata
3107
3105
  };
3108
3106
  });
3109
3107
  build.onLoad({
@@ -3115,9 +3113,11 @@ function loaderPlugin(outFile, checkExternal) {
3115
3113
  Log.error(`[htmlBundleScriptPlugin:onLoad] Script metadata for the path "${arguments_.path}" not found."`);
3116
3114
  return;
3117
3115
  }
3116
+ const clone = app.clone(scriptMetadata);
3117
+ await app.rebase(clone, outFileAbs);
3118
3118
  return {
3119
- contents: await appThis().stringify(scriptMetadata),
3120
- resolveDir: dirname(arguments_.path),
3119
+ contents: await app.stringify(clone),
3120
+ resolveDir: dirname(outFileAbs),
3121
3121
  loader: "js"
3122
3122
  };
3123
3123
  });
@@ -3161,22 +3161,21 @@ async function bundleScriptWithEsbuild(options) {
3161
3161
  //#endregion
3162
3162
  //#region src/plugins/html-bundle-script/html-bundle-script-plugin.ts
3163
3163
  /**
3164
- * A plugin that bundles `<script>` tags in HTML files using esbuild.
3164
+ * A plugin that bundles script tags in HTML files using esbuild.
3165
3165
  *
3166
- * Bundling is opt-in per script tag via the `bundle` attribute (configurable via {@link HtmlBundleScriptOptions.bundleAttribute}).
3166
+ * Bundling is opt-in per script tag via the "bundle" attribute (configurable via HtmlBundleScriptOptions.bundleAttribute).
3167
3167
  *
3168
- * **Inlining vs. separate file**
3168
+ * Inlining vs. separate file
3169
3169
  *
3170
- * - Inline script, no `bundle-out` attribute —> bundled output replaces the tag's content in place.
3171
- * - Inline script, `bundle-out` attribute set —> tag content is cleared and `src` is set to the output file.
3172
- * - `src` script, no `bundle-out` attribute —> bundle is written to `{filename}.bundle.js` and `src` is updated to point to it.
3173
- * - `src` script, `bundle-out` attribute set —> bundle is written to the specified path and `src` is updated to point to it.
3170
+ * - Inline script, no "bundle-out" attribute: bundled output replaces the tag content in place.
3171
+ * - Inline script, "bundle-out" attribute set: tag content is cleared and "src" is set to the output file.
3172
+ * - "src" script, no "bundle-out" attribute: bundle is written to "{filename}.bundle.js" and "src" is updated.
3173
+ * - "src" script, "bundle-out" attribute set: bundle is written to the specified path and "src" is updated.
3174
3174
  *
3175
- * **Externals resolution**
3175
+ * Externals resolution
3176
3176
  *
3177
- * Glob patterns in {@link HtmlBundleScriptOptions.externals} and {@link HtmlBundleScriptOptions.externalsExclude} are matched
3178
- * against each resolved module path. A module is treated as external if it matches `externals` and does not match
3179
- * `externalsExclude`.
3177
+ * Glob patterns in HtmlBundleScriptOptions.externals and HtmlBundleScriptOptions.externalsExclude are matched against each
3178
+ * resolved module path. A module is treated as external if it matches "externals" and does not match "externalsExclude".
3180
3179
  */
3181
3180
  function htmlBundleScriptPlugin(options = {}) {
3182
3181
  const defaultExternal = options.externals ?? ["**/node_modules/**"];
@@ -3207,6 +3206,7 @@ function htmlBundleScriptPlugin(options = {}) {
3207
3206
  }
3208
3207
  });
3209
3208
  }
3209
+ return sources;
3210
3210
  },
3211
3211
  async transform(metadata) {
3212
3212
  if (!isHtmlMetadata(metadata)) return;
@@ -3240,28 +3240,40 @@ function htmlBundleScriptPlugin(options = {}) {
3240
3240
  let entryPoint = "";
3241
3241
  let outfile = "";
3242
3242
  let contents = "";
3243
- if (bundleOut) outfile = bundleOut;
3244
3243
  if (hasContent) {
3245
- contents = await this.stringify(scriptMetadata);
3246
- entryPoint = metadata.filePath;
3247
- if (!bundleOut) outfile = filePath;
3248
- if (!inline) node.textContent = "";
3249
- }
3250
- if (scriptSource) {
3251
- entryPoint = join(dirname(filePath), scriptSource);
3252
- if (!bundleOut) {
3253
- const outFileName = replaceExtension(basename(scriptSource), ".bundle.js");
3254
- outfile = join(dirname(filePath), outFileName);
3244
+ outfile = bundleOut ?? filePath;
3245
+ if (inline) {
3246
+ entryPoint = metadata.filePath;
3247
+ contents = await this.stringify(scriptMetadata);
3248
+ } else {
3249
+ node.textContent = "";
3250
+ if (this.findMetadata({ filePath: outfile })) {
3251
+ this.log.info(`The entry point "${entryPoint}" is already bundled in "${outfile}", skipping...`);
3252
+ continue;
3253
+ }
3254
+ entryPoint = outfile;
3255
+ const clone = this.clone(scriptMetadata);
3256
+ await this.rebase(clone, join(this.root, outfile));
3257
+ contents = await this.stringify(clone);
3258
+ }
3259
+ } else if (scriptSource) {
3260
+ outfile = bundleOut ?? normalize(replaceExtension(basename(scriptSource), ".bundle.js"));
3261
+ entryPoint = outfile;
3262
+ if (this.findMetadata({ filePath: outfile })) {
3263
+ this.log.info(`The entry point "${entryPoint}" is already bundled in "${outfile}", skipping...`);
3264
+ continue;
3255
3265
  }
3256
- const scriptMetadata = this.findMetadata({ filePath: entryPoint });
3257
- if (!isScriptMetadata(scriptMetadata)) {
3266
+ const sourceScriptMetadata = this.findMetadata({ filePath: join(dirname(filePath), scriptSource) });
3267
+ if (!isScriptMetadata(sourceScriptMetadata)) {
3258
3268
  printFmtError(`Script metadata for the path "${entryPoint}" not found`, {
3259
3269
  node,
3260
3270
  filePath
3261
3271
  });
3262
3272
  continue;
3263
3273
  }
3264
- contents = await this.stringify(scriptMetadata);
3274
+ const clone = this.clone(sourceScriptMetadata);
3275
+ await this.rebase(clone, join(this.root, outfile));
3276
+ contents = await this.stringify(clone);
3265
3277
  }
3266
3278
  const checkExternal = (string) => {
3267
3279
  return matchPath(string, {
@@ -3283,7 +3295,7 @@ function htmlBundleScriptPlugin(options = {}) {
3283
3295
  });
3284
3296
  continue;
3285
3297
  }
3286
- const newMetadataPath = normalize(inline ? metadata.filePath : outfile);
3298
+ const newMetadataPath = normalize(inline ? filePath : outfile);
3287
3299
  const newScriptMetadata = await this.load(newMetadataPath, {
3288
3300
  code: bundleString,
3289
3301
  type: "js"
@@ -3838,11 +3850,11 @@ function htmlInsertPlugin(options = {}) {
3838
3850
  //#endregion
3839
3851
  //#region src/plugins/html-layout/fill-placeholders.ts
3840
3852
  /** (any){{any}} */
3841
- const placeholderRe$1 = /(\\)?{{\s*([\s\S]*?)\s*}}/g;
3853
+ const placeholderRe$2 = /(\\)?{{\s*([\s\S]*?)\s*}}/g;
3842
3854
  /** `{{ JavaScript expression }}` */
3843
3855
  function fillLayoutPlaceholders(html, placeholders) {
3844
3856
  const errors = [];
3845
- const result = html.replace(placeholderRe$1, (match, escape, content) => {
3857
+ const result = html.replace(placeholderRe$2, (match, escape, content) => {
3846
3858
  if (escape === "\\") return match.slice(1);
3847
3859
  const [expression, executeError] = executeExpression$1(content, placeholders);
3848
3860
  if (executeError) {
@@ -4488,11 +4500,11 @@ function cutLeadingSubpath(pathToCut, leadingSubpath) {
4488
4500
  //#endregion
4489
4501
  //#region src/plugins/html-pages/fill-placeholders.ts
4490
4502
  /** (any){{any}} */
4491
- const placeholderRe = /(\\)?{{\s*([\s\S]*?)\s*}}/g;
4503
+ const placeholderRe$1 = /(\\)?{{\s*([\s\S]*?)\s*}}/g;
4492
4504
  /** `{{ JavaScript expression }}` */
4493
4505
  function fillPlaceholders(html, routeData) {
4494
4506
  const errors = [];
4495
- const result = html.replace(placeholderRe, (match, escape, content) => {
4507
+ const result = html.replace(placeholderRe$1, (match, escape, content) => {
4496
4508
  if (escape === "\\") return match.slice(1);
4497
4509
  const [expression, executeError] = executeExpression(content, routeData);
4498
4510
  if (executeError) {
@@ -5054,6 +5066,8 @@ function stringifySrcset(entries) {
5054
5066
  for (const entry of entries) srcset += entry.descriptor ? `, ${entry.url} ${entry.descriptor}` : `, ${entry.url}`;
5055
5067
  return srcset;
5056
5068
  }
5069
+ /** Match placeholders [[ has $ ]] or {{ has $ }} */
5070
+ const placeholderRe = /(?:\[\[([^\]]*\$[^\]]*?)\]\]|\{\{([^}]*\$[^}]*?)\}\})/;
5057
5071
  function parseHtmlSources(ast) {
5058
5072
  const links = [];
5059
5073
  for (const node of ast.querySelectorAll(combinedSelector)) {
@@ -5065,19 +5079,23 @@ function parseHtmlSources(ast) {
5065
5079
  if (!value) continue;
5066
5080
  if (attribute === "srcset") {
5067
5081
  const entries = parseSrcset(value);
5068
- for (const [index, entry] of entries.entries()) links.push({
5069
- node,
5070
- get source() {
5071
- return decodeURIComponent(entry.url);
5072
- },
5073
- set source(newValue) {
5074
- const current = parseSrcset(node.getAttribute("srcset") || "");
5075
- current[index].url = newValue;
5076
- node.setAttribute("srcset", stringifySrcset(current));
5077
- }
5078
- });
5082
+ for (const [index, entry] of entries.entries()) {
5083
+ if (placeholderRe.test(entry.url)) continue;
5084
+ links.push({
5085
+ node,
5086
+ get source() {
5087
+ return decodeURIComponent(entry.url);
5088
+ },
5089
+ set source(newValue) {
5090
+ const current = parseSrcset(node.getAttribute("srcset") || "");
5091
+ current[index].url = newValue;
5092
+ node.setAttribute("srcset", stringifySrcset(current));
5093
+ }
5094
+ });
5095
+ }
5079
5096
  continue;
5080
5097
  }
5098
+ if (placeholderRe.test(value)) continue;
5081
5099
  links.push({
5082
5100
  node,
5083
5101
  get source() {
@@ -5095,7 +5113,10 @@ function parseHtmlSources(ast) {
5095
5113
  //#endregion
5096
5114
  //#region src/parsers/html-parser.ts
5097
5115
  function parseHtmlUnsafe(html, options = {}) {
5098
- return parse(html, options);
5116
+ return parse(html, {
5117
+ comment: true,
5118
+ ...options
5119
+ });
5099
5120
  }
5100
5121
  /** Parse HTML string and return the root node */
5101
5122
  const parseHtml = valueOrError(parseHtmlUnsafe);
@@ -5198,24 +5219,25 @@ function coreHtmlPlugin(options = {}) {
5198
5219
  const nodeIdMap = /* @__PURE__ */ new Map();
5199
5220
  const scriptsAndStyles = metadata.ast.querySelectorAll("script,style");
5200
5221
  for (const node of scriptsAndStyles) {
5201
- const minifyTag = minify || node.hasAttribute(minifyAttribute);
5202
- node.removeAttribute(minifyAttribute);
5203
- const id = node.getAttribute(CUSTOM_ATTRIBUTES.MetadataID);
5204
- if (!id) continue;
5205
- nodeIdMap.set(node, id);
5206
- node.removeAttribute(CUSTOM_ATTRIBUTES.MetadataID);
5222
+ const hasMinifyAttribute = node.hasAttribute(minifyAttribute);
5223
+ const shouldMinify = minify || hasMinifyAttribute;
5207
5224
  const isScript = node.tagName === "SCRIPT";
5225
+ node.removeAttribute(minifyAttribute);
5208
5226
  const scriptType = node.getAttribute("type");
5209
5227
  if (isScript && !isScriptType(scriptType)) continue;
5210
- const tagMetadata = metadata[isScript ? "scriptsMetadataList" : "stylesMetadataList"].get(id);
5228
+ const metadataID = node.getAttribute(CUSTOM_ATTRIBUTES.MetadataID);
5229
+ if (!metadataID) continue;
5230
+ nodeIdMap.set(node, metadataID);
5231
+ node.removeAttribute(CUSTOM_ATTRIBUTES.MetadataID);
5232
+ const tagMetadata = metadata[isScript ? "scriptsMetadataList" : "stylesMetadataList"].get(metadataID);
5211
5233
  if (!tagMetadata) continue;
5212
5234
  const code = await this.stringify(tagMetadata, {
5213
- format: format && !minifyTag,
5214
- minify: minifyTag
5235
+ format: format && !shouldMinify,
5236
+ minify: shouldMinify
5215
5237
  });
5216
5238
  if (!code) continue;
5217
5239
  node.textContent = code;
5218
- if (format && minifyTag) node.replaceWith(ignoreFormatComment + node.outerHTML);
5240
+ if (format && hasMinifyAttribute) node.replaceWith(ignoreFormatComment + node.outerHTML);
5219
5241
  }
5220
5242
  const code = metadata.ast.toString();
5221
5243
  for (const [node, metadataID] of nodeIdMap) node.setAttribute(CUSTOM_ATTRIBUTES.MetadataID, metadataID);
@@ -5380,12 +5402,8 @@ function coreMarkdownPlugin(options = {}) {
5380
5402
 
5381
5403
  //#endregion
5382
5404
  //#region src/ast-utilities/babel-utils/parse-script-srouces.ts
5383
- function parseScriptSources({ ast, filePath }) {
5405
+ function parseScriptSources({ ast }) {
5384
5406
  const result = [];
5385
- const printFmtError = PrintFormattedError.create({
5386
- function: parseScriptSources,
5387
- filePath
5388
- });
5389
5407
  t.traverseFast(ast, (node) => {
5390
5408
  if (t.isImportDeclaration(node)) {
5391
5409
  if (!t.isStringLiteral(node.source)) return;
@@ -5459,10 +5477,7 @@ function parseScriptSources({ ast, filePath }) {
5459
5477
  if (t.isNewExpression(node)) {
5460
5478
  if (!t.isIdentifier(node.callee, { name: "URL" })) return;
5461
5479
  const firstArgument = node.arguments[0];
5462
- if (!t.isStringLiteral(firstArgument)) {
5463
- printFmtError("The first argument of `URL` should be a string", { node });
5464
- return;
5465
- }
5480
+ if (!t.isStringLiteral(firstArgument)) return;
5466
5481
  const setSource = (newValue) => {
5467
5482
  node.arguments[0] = t.stringLiteral(newValue);
5468
5483
  };
@@ -6048,6 +6063,7 @@ function developmentServerPlugin(options = {}) {
6048
6063
  function upgradeWebSocketHandler(request, socket, head) {
6049
6064
  websocket.handleUpgrade(request, socket, head, (ws) => {
6050
6065
  wsClients.add(ws);
6066
+ websocket.emit("connection", ws, request);
6051
6067
  ws.send(JSON.stringify({ data: "connected" }));
6052
6068
  ws.on("close", () => {
6053
6069
  wsClients.delete(ws);
@@ -6084,6 +6100,14 @@ function developmentServerPlugin(options = {}) {
6084
6100
  }
6085
6101
  this.log.info(c.bold("Server listening on"), c.green(address + entry));
6086
6102
  });
6103
+ websocket.on("connection", () => {
6104
+ const sortedByAge = Array.from(entryPointAgeMap).toSorted((a, b) => a[1] - b[1]).map(([id]) => id);
6105
+ const excess = sortedByAge.length - wsClients.size;
6106
+ if (excess > 0) for (const id of sortedByAge.slice(0, excess)) {
6107
+ entryPointAgeMap.delete(id);
6108
+ removeAndPruneOrphans(this.metadataList, id);
6109
+ }
6110
+ });
6087
6111
  },
6088
6112
  async onFileEvent(event, changedSource) {
6089
6113
  if (event === "unlink") {
@@ -6101,11 +6125,15 @@ function developmentServerPlugin(options = {}) {
6101
6125
  if (oldMetadataList.length === 0) continue;
6102
6126
  const oldDeps = new Set(oldMetadataList.flatMap((m) => Array.from(m.directDependencies)));
6103
6127
  this.removeMetadata(oldMetadataList);
6104
- await this.process(id);
6128
+ if (!await this.process(id)) {
6129
+ this.addMetadata(oldMetadataList);
6130
+ continue;
6131
+ }
6105
6132
  const newMetadataList = this.filterMetadata({ id });
6106
6133
  const newDeps = new Set(newMetadataList.flatMap((m) => Array.from(m.directDependencies)));
6107
6134
  const removedDeps = Array.from(oldDeps).filter((dep) => !newDeps.has(dep));
6108
- for (const dep of removedDeps) if (!this.metadataList.some((m) => m.directDependencies && m.directDependencies.has(dep))) {
6135
+ for (const dep of removedDeps) {
6136
+ if (this.metadataList.some((m) => m.directDependencies && m.directDependencies.has(dep))) continue;
6109
6137
  const orphans = this.filterMetadata({ id: dep });
6110
6138
  if (orphans && orphans.length > 0) this.removeMetadata(orphans);
6111
6139
  }
@@ -6135,12 +6163,6 @@ function developmentServerPlugin(options = {}) {
6135
6163
  if (this.entryPoints.has(metadata.id) && isHtmlMetadata(metadata)) {
6136
6164
  injectReloadScript(metadata);
6137
6165
  entryPointAgeMap.set(metadata.id, Date.now());
6138
- const sortedByAge = Array.from(entryPointAgeMap).toSorted((a, b) => a[1] - b[1]).map(([id]) => id);
6139
- const excess = sortedByAge.length - wsClients.size;
6140
- if (excess > 0) for (const id of sortedByAge.slice(0, excess)) {
6141
- entryPointAgeMap.delete(id);
6142
- removeAndPruneOrphans(this.metadataList, id);
6143
- }
6144
6166
  }
6145
6167
  const stringified = await this.stringify(metadata);
6146
6168
  if (typeof stringified !== "string") return;
@@ -6555,6 +6577,15 @@ var App = class {
6555
6577
  this.log.info("Dev mode: on-demand build active, skipping build pipeline");
6556
6578
  return;
6557
6579
  }
6580
+ for (const entryFile of this.entryPoints) {
6581
+ if (this.findMetadata({ id: entryFile })) continue;
6582
+ const metadata = await this.load(entryFile);
6583
+ if (!metadata) {
6584
+ this.log.error(`Could not load "${entryFile}".`);
6585
+ return;
6586
+ }
6587
+ this.addMetadata(metadata);
6588
+ }
6558
6589
  this.log.info(`Resolving ${this.metadataList.length} entry point(s)`);
6559
6590
  await this.resolveAndLoad(this.metadataList);
6560
6591
  this.log.info(`Transforming ${this.metadataList.length} file(s)`);
@@ -6572,7 +6603,7 @@ var App = class {
6572
6603
  const metadata = await this.load(id);
6573
6604
  if (!metadata) {
6574
6605
  this.log.error(`Could not load "${id}".`);
6575
- return;
6606
+ return false;
6576
6607
  }
6577
6608
  const metadataList = await this.resolveAndLoad(metadata);
6578
6609
  const previouslyTransformed = new Set(this.metadataList);
@@ -6580,6 +6611,7 @@ var App = class {
6580
6611
  for (const plugin of this.plugins) await this.callPluginMethod(plugin, "preTransform");
6581
6612
  for (const plugin of this.plugins) for (const metadataItem of this.metadataList) if (!previouslyTransformed.has(metadataItem)) await this.callPluginMethod(plugin, "transform", metadataItem);
6582
6613
  for (const plugin of this.plugins) await this.callPluginMethod(plugin, "postTransform");
6614
+ return true;
6583
6615
  }
6584
6616
  async resolve(metadata) {
6585
6617
  if (!this.isPluginInitialized) this.log.warn("[resolve] Plugins are not fully setup yet.");