@emkodev/emroute 1.7.2 → 1.7.3

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.
Files changed (61) hide show
  1. package/dist/emroute.js +135 -31
  2. package/dist/emroute.js.map +2 -2
  3. package/dist/runtime/abstract.runtime.d.ts +11 -0
  4. package/dist/runtime/abstract.runtime.js +53 -0
  5. package/dist/runtime/abstract.runtime.js.map +1 -1
  6. package/dist/runtime/bun/fs/bun-fs.runtime.js +3 -1
  7. package/dist/runtime/bun/fs/bun-fs.runtime.js.map +1 -1
  8. package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js +3 -1
  9. package/dist/runtime/bun/sqlite/bun-sqlite.runtime.js.map +1 -1
  10. package/dist/runtime/universal/fs/universal-fs.runtime.js +3 -1
  11. package/dist/runtime/universal/fs/universal-fs.runtime.js.map +1 -1
  12. package/dist/server/build.util.js +35 -6
  13. package/dist/server/build.util.js.map +1 -1
  14. package/dist/server/emroute.server.js +17 -7
  15. package/dist/server/emroute.server.js.map +1 -1
  16. package/dist/server/server-api.type.d.ts +3 -0
  17. package/dist/src/component/abstract.component.d.ts +1 -1
  18. package/dist/src/component/abstract.component.js.map +1 -1
  19. package/dist/src/element/component.element.js +17 -3
  20. package/dist/src/element/component.element.js.map +1 -1
  21. package/dist/src/element/markdown.element.js +1 -1
  22. package/dist/src/element/markdown.element.js.map +1 -1
  23. package/dist/src/index.d.ts +1 -0
  24. package/dist/src/index.js.map +1 -1
  25. package/dist/src/renderer/spa/thin-client.js +28 -6
  26. package/dist/src/renderer/spa/thin-client.js.map +1 -1
  27. package/dist/src/renderer/ssr/html.renderer.js +1 -1
  28. package/dist/src/renderer/ssr/html.renderer.js.map +1 -1
  29. package/dist/src/renderer/ssr/md.renderer.js +2 -2
  30. package/dist/src/renderer/ssr/md.renderer.js.map +1 -1
  31. package/dist/src/renderer/ssr/ssr.renderer.js +6 -6
  32. package/dist/src/renderer/ssr/ssr.renderer.js.map +1 -1
  33. package/dist/src/route/route.core.js +21 -7
  34. package/dist/src/route/route.core.js.map +1 -1
  35. package/dist/src/type/element.type.d.ts +19 -0
  36. package/dist/src/type/element.type.js +9 -0
  37. package/dist/src/type/element.type.js.map +1 -0
  38. package/dist/src/util/widget-resolve.util.js +1 -1
  39. package/dist/src/util/widget-resolve.util.js.map +1 -1
  40. package/dist/src/widget/widget.registry.js +1 -1
  41. package/dist/src/widget/widget.registry.js.map +1 -1
  42. package/package.json +1 -1
  43. package/runtime/abstract.runtime.ts +67 -0
  44. package/runtime/bun/fs/bun-fs.runtime.ts +2 -0
  45. package/runtime/bun/sqlite/bun-sqlite.runtime.ts +2 -0
  46. package/runtime/universal/fs/universal-fs.runtime.ts +2 -0
  47. package/server/build.util.ts +37 -5
  48. package/server/emroute.server.ts +20 -6
  49. package/server/server-api.type.ts +4 -0
  50. package/src/component/abstract.component.ts +1 -1
  51. package/src/element/component.element.ts +16 -4
  52. package/src/element/markdown.element.ts +1 -1
  53. package/src/index.ts +1 -0
  54. package/src/renderer/spa/thin-client.ts +30 -5
  55. package/src/renderer/ssr/html.renderer.ts +1 -1
  56. package/src/renderer/ssr/md.renderer.ts +5 -4
  57. package/src/renderer/ssr/ssr.renderer.ts +6 -6
  58. package/src/route/route.core.ts +17 -8
  59. package/src/type/element.type.ts +22 -0
  60. package/src/util/widget-resolve.util.ts +4 -4
  61. package/src/widget/widget.registry.ts +1 -1
package/dist/emroute.js CHANGED
@@ -177,7 +177,7 @@ var MarkdownElement = class _MarkdownElement extends HTMLElementBase {
177
177
  async loadFromSrc(src) {
178
178
  const signal = this.abortController?.signal;
179
179
  try {
180
- const response = await fetch(src, { signal });
180
+ const response = await fetch(src, signal ? { signal } : {});
181
181
  if (!response.ok) {
182
182
  throw new Error(`Failed to fetch ${src}: ${response.status}`);
183
183
  }
@@ -205,6 +205,17 @@ var MarkdownElement = class _MarkdownElement extends HTMLElementBase {
205
205
  };
206
206
 
207
207
  // dist/src/element/component.element.js
208
+ function filterUndefined(obj) {
209
+ const result = {};
210
+ let hasValue = false;
211
+ for (const [k, v] of Object.entries(obj)) {
212
+ if (v !== void 0) {
213
+ result[k] = v;
214
+ hasValue = true;
215
+ }
216
+ }
217
+ return hasValue ? result : void 0;
218
+ }
208
219
  var ComponentElement = class _ComponentElement extends HTMLElementBase {
209
220
  /** Shared file content cache — deduplicates fetches across all widget instances. */
210
221
  static fileCache = /* @__PURE__ */ new Map();
@@ -367,12 +378,13 @@ var ComponentElement = class _ComponentElement extends HTMLElementBase {
367
378
  if (signal.aborted)
368
379
  return;
369
380
  const currentUrl = globalThis.location ? new URL(location.href) : new URL("http://localhost/");
381
+ const filteredFiles = filterUndefined(files);
370
382
  const base = {
371
383
  url: currentUrl,
372
384
  pathname: currentUrl.pathname,
373
385
  searchParams: currentUrl.searchParams,
374
386
  params: this.params ?? {},
375
- files: files.html || files.md || files.css ? files : void 0
387
+ ...filteredFiles ? { files: filteredFiles } : {}
376
388
  };
377
389
  this.context = _ComponentElement.extendContext ? _ComponentElement.extendContext(base) : base;
378
390
  if (this.hasAttribute(SSR_ATTR)) {
@@ -459,7 +471,7 @@ var ComponentElement = class _ComponentElement extends HTMLElementBase {
459
471
  filePaths.md ? _ComponentElement.loadFile(filePaths.md) : void 0,
460
472
  filePaths.css ? _ComponentElement.loadFile(filePaths.css) : void 0
461
473
  ]);
462
- return { html, md, css };
474
+ return filterUndefined({ html, md, css }) ?? {};
463
475
  }
464
476
  async loadData() {
465
477
  if (this.params === null)
@@ -470,7 +482,7 @@ var ComponentElement = class _ComponentElement extends HTMLElementBase {
470
482
  try {
471
483
  const promise = this.component.getData({
472
484
  params: this.params,
473
- signal,
485
+ ...signal ? { signal } : {},
474
486
  context: this.context
475
487
  });
476
488
  this.dataPromise = promise;
@@ -549,7 +561,7 @@ var WidgetRegistry = class {
549
561
  name,
550
562
  modulePath: name,
551
563
  tagName: `widget-${name}`,
552
- files: widget.files
564
+ ...widget.files ? { files: widget.files } : {}
553
565
  };
554
566
  widgets.push(entry);
555
567
  moduleLoaders[name] = () => Promise.resolve({ default: widget.constructor });
@@ -585,7 +597,7 @@ function toRouteConfig(resolved) {
585
597
  pattern: resolved.pattern,
586
598
  type: node.redirect ? "redirect" : "page",
587
599
  modulePath: node.redirect ?? node.files?.ts ?? node.files?.js ?? node.files?.html ?? node.files?.md ?? "",
588
- files: node.files
600
+ ...node.files ? { files: node.files } : {}
589
601
  };
590
602
  }
591
603
  var RouteCore = class {
@@ -659,7 +671,7 @@ var RouteCore = class {
659
671
  pattern: `/${status}`,
660
672
  type: "page",
661
673
  modulePath: node.files?.ts ?? node.files?.js ?? node.files?.html ?? node.files?.md ?? "",
662
- files: node.files
674
+ ...node.files ? { files: node.files } : {}
663
675
  };
664
676
  }
665
677
  /** Get global error handler (root errorBoundary). */
@@ -692,7 +704,7 @@ var RouteCore = class {
692
704
  pattern,
693
705
  type: node.redirect ? "redirect" : "page",
694
706
  modulePath: node.redirect ?? node.files?.ts ?? node.files?.js ?? node.files?.html ?? node.files?.md ?? "",
695
- files: node.files
707
+ ...node.files ? { files: node.files } : {}
696
708
  };
697
709
  }
698
710
  /**
@@ -772,7 +784,14 @@ var RouteCore = class {
772
784
  widgetFiles.md ? load(widgetFiles.md) : void 0,
773
785
  widgetFiles.css ? load(widgetFiles.css) : void 0
774
786
  ]);
775
- return { html, md, css };
787
+ const result = {};
788
+ if (html != null)
789
+ result.html = html;
790
+ if (md != null)
791
+ result.md = md;
792
+ if (css != null)
793
+ result.css = css;
794
+ return result;
776
795
  }
777
796
  /**
778
797
  * Build a RouteInfo from a matched route and the resolved URL pathname.
@@ -822,13 +841,20 @@ var RouteCore = class {
822
841
  rf?.css ? fetchFile(rf.css) : void 0
823
842
  ]);
824
843
  }
844
+ const files = {};
845
+ if (html != null)
846
+ files.html = html;
847
+ if (md != null)
848
+ files.md = md;
849
+ if (css != null)
850
+ files.css = css;
825
851
  const base = {
826
852
  ...routeInfo,
827
853
  pathname: routeInfo.url.pathname,
828
854
  searchParams: routeInfo.url.searchParams,
829
- files: { html, md, css },
830
- signal,
831
- isLeaf
855
+ files,
856
+ ...signal ? { signal } : {},
857
+ ...isLeaf != null ? { isLeaf } : {}
832
858
  };
833
859
  return this.contextProvider ? this.contextProvider(base) : base;
834
860
  }
@@ -1051,7 +1077,7 @@ function resolveWidgetTags(html, registry, routeInfo, loadFiles, contextProvider
1051
1077
  ...routeInfo,
1052
1078
  pathname: routeInfo.url.pathname,
1053
1079
  searchParams: routeInfo.url.searchParams,
1054
- files
1080
+ ...files ? { files } : {}
1055
1081
  };
1056
1082
  const context = contextProvider ? contextProvider(baseContext) : baseContext;
1057
1083
  const data = await widget.getData({ params, context });
@@ -1274,7 +1300,7 @@ var SsrRenderer = class _SsrRenderer {
1274
1300
  try {
1275
1301
  const ri = { url, params: {} };
1276
1302
  const result = await this.renderRouteContent(ri, statusPage, void 0, signal);
1277
- return { content: this.stripSlots(result.content), status: 404, title: result.title };
1303
+ return { content: this.stripSlots(result.content), status: 404, ...result.title != null ? { title: result.title } : {} };
1278
1304
  } catch (e) {
1279
1305
  logger.error(`[${this.label}] Failed to render 404 status page for ${url.pathname}`, e instanceof Error ? e : void 0);
1280
1306
  }
@@ -1294,7 +1320,7 @@ var SsrRenderer = class _SsrRenderer {
1294
1320
  const routeInfo = this.core.toRouteInfo(matched, url);
1295
1321
  try {
1296
1322
  const { content, title } = await this.renderPage(routeInfo, matched, signal);
1297
- return { content, status: 200, title };
1323
+ return { content, status: 200, ...title != null ? { title } : {} };
1298
1324
  } catch (error) {
1299
1325
  if (error instanceof Response) {
1300
1326
  const statusPage = this.core.getStatusPage(error.status);
@@ -1305,7 +1331,7 @@ var SsrRenderer = class _SsrRenderer {
1305
1331
  return {
1306
1332
  content: this.stripSlots(result.content),
1307
1333
  status: error.status,
1308
- title: result.title
1334
+ ...result.title != null ? { title: result.title } : {}
1309
1335
  };
1310
1336
  } catch (e) {
1311
1337
  logger.error(`[${this.label}] Failed to render ${error.status} status page for ${url.pathname}`, e instanceof Error ? e : void 0);
@@ -1368,7 +1394,7 @@ var SsrRenderer = class _SsrRenderer {
1368
1394
  lastRenderedPattern = segments[i].route.pattern;
1369
1395
  }
1370
1396
  result = this.stripSlots(result);
1371
- return { content: result, title: pageTitle };
1397
+ return { content: result, ...pageTitle != null ? { title: pageTitle } : {} };
1372
1398
  }
1373
1399
  /** Load component, build context, get data, render content, get title. */
1374
1400
  async loadRouteContent(routeInfo, route, isLeaf, signal) {
@@ -1376,10 +1402,10 @@ var SsrRenderer = class _SsrRenderer {
1376
1402
  const tsModule = files.ts ?? files.js;
1377
1403
  const component = tsModule ? (await this.core.loadModule(tsModule)).default : page_component_default;
1378
1404
  const context = await this.core.buildComponentContext(routeInfo, route, signal, isLeaf);
1379
- const data = await component.getData({ params: routeInfo.params, signal, context });
1405
+ const data = await component.getData({ params: routeInfo.params, ...signal ? { signal } : {}, context });
1380
1406
  const content = this.renderContent(component, { data, params: routeInfo.params, context });
1381
1407
  const title = component.getTitle({ data, params: routeInfo.params, context });
1382
- return { content, title };
1408
+ return { content, ...title != null ? { title } : {} };
1383
1409
  }
1384
1410
  /** Render a component for error boundary/handler with minimal context. */
1385
1411
  renderComponent(component, data, context) {
@@ -1443,7 +1469,7 @@ var SsrHtmlRouter = class extends SsrRenderer {
1443
1469
  return files ? this.core.loadWidgetFiles(files) : Promise.resolve({});
1444
1470
  }, this.core.contextProvider);
1445
1471
  }
1446
- return { content, title };
1472
+ return { content, ...title != null ? { title } : {} };
1447
1473
  }
1448
1474
  renderContent(component, args) {
1449
1475
  return component.renderHTML(args);
@@ -1565,7 +1591,7 @@ var SsrMdRouter = class extends SsrRenderer {
1565
1591
  if (this.widgets) {
1566
1592
  content = await this.resolveWidgets(content, routeInfo);
1567
1593
  }
1568
- return { content, title };
1594
+ return { content, ...title != null ? { title } : {} };
1569
1595
  }
1570
1596
  renderContent(component, args) {
1571
1597
  return component.renderMarkdown(args);
@@ -1606,7 +1632,7 @@ Path: \`${url.pathname}\``;
1606
1632
  ...routeInfo,
1607
1633
  pathname: routeInfo.url.pathname,
1608
1634
  searchParams: routeInfo.url.searchParams,
1609
- files
1635
+ ...files ? { files } : {}
1610
1636
  };
1611
1637
  const context = this.core.contextProvider ? this.core.contextProvider(baseContext) : baseContext;
1612
1638
  const data = await widget.getData({ params: block.params, context });
@@ -1660,8 +1686,10 @@ function resolveTargetNode(node, name, isRoot) {
1660
1686
  // dist/runtime/abstract.runtime.js
1661
1687
  var DEFAULT_ROUTES_DIR = "/routes";
1662
1688
  var DEFAULT_WIDGETS_DIR = "/widgets";
1689
+ var DEFAULT_ELEMENTS_DIR = "/elements";
1663
1690
  var ROUTES_MANIFEST_PATH = "/routes.manifest.json";
1664
1691
  var WIDGETS_MANIFEST_PATH = "/widgets.manifest.json";
1692
+ var ELEMENTS_MANIFEST_PATH = "/elements.manifest.json";
1665
1693
  var Runtime = class {
1666
1694
  config;
1667
1695
  constructor(config = {}) {
@@ -1743,10 +1771,12 @@ var Runtime = class {
1743
1771
  // ── Manifest resolution ─────────────────────────────────────────────
1744
1772
  routesManifestCache = null;
1745
1773
  widgetsManifestCache = null;
1774
+ elementsManifestCache = null;
1746
1775
  /** Clear cached manifests so the next query triggers a fresh scan. */
1747
1776
  invalidateManifests() {
1748
1777
  this.routesManifestCache = null;
1749
1778
  this.widgetsManifestCache = null;
1779
+ this.elementsManifestCache = null;
1750
1780
  }
1751
1781
  /**
1752
1782
  * Resolve the routes manifest. Called when the concrete runtime returns
@@ -1780,6 +1810,22 @@ var Runtime = class {
1780
1810
  this.widgetsManifestCache = Response.json(entries);
1781
1811
  return this.widgetsManifestCache.clone();
1782
1812
  }
1813
+ /**
1814
+ * Resolve the elements manifest. Called when the concrete runtime returns
1815
+ * 404 for ELEMENTS_MANIFEST_PATH. Scans `config.elementsDir` (or default).
1816
+ */
1817
+ async resolveElementsManifest() {
1818
+ if (this.elementsManifestCache)
1819
+ return this.elementsManifestCache.clone();
1820
+ const elementsDir = this.config.elementsDir ?? DEFAULT_ELEMENTS_DIR;
1821
+ const dirResponse = await this.query(elementsDir + "/");
1822
+ if (dirResponse.status === 404) {
1823
+ return new Response("Not Found", { status: 404 });
1824
+ }
1825
+ const entries = await this.scanElements(elementsDir, elementsDir.replace(/^\//, ""));
1826
+ this.elementsManifestCache = Response.json(entries);
1827
+ return this.elementsManifestCache.clone();
1828
+ }
1783
1829
  // ── Scanning ──────────────────────────────────────────────────────────
1784
1830
  async *walkDirectory(dir) {
1785
1831
  const trailingDir = dir.endsWith("/") ? dir : dir + "/";
@@ -1880,6 +1926,37 @@ var Runtime = class {
1880
1926
  entries.sort((a, b) => a.name.localeCompare(b.name));
1881
1927
  return entries;
1882
1928
  }
1929
+ async scanElements(elementsDir, pathPrefix) {
1930
+ const entries = [];
1931
+ const trailingDir = elementsDir.endsWith("/") ? elementsDir : elementsDir + "/";
1932
+ const response = await this.query(trailingDir);
1933
+ const listing = await response.json();
1934
+ for (const item of listing) {
1935
+ if (!item.endsWith("/"))
1936
+ continue;
1937
+ const name = item.slice(0, -1);
1938
+ if (!name.includes("-")) {
1939
+ console.warn(`[emroute] Skipping element "${name}": custom element names must contain a hyphen (e.g. "my-element")`);
1940
+ continue;
1941
+ }
1942
+ let moduleFile = `${name}.element.ts`;
1943
+ let modulePath = `${trailingDir}${name}/${moduleFile}`;
1944
+ if ((await this.query(modulePath)).status === 404) {
1945
+ moduleFile = `${name}.element.js`;
1946
+ modulePath = `${trailingDir}${name}/${moduleFile}`;
1947
+ if ((await this.query(modulePath)).status === 404)
1948
+ continue;
1949
+ }
1950
+ const prefix = pathPrefix ? `${pathPrefix}/` : "";
1951
+ entries.push({
1952
+ name,
1953
+ modulePath: `${prefix}${name}/${moduleFile}`,
1954
+ tagName: name
1955
+ });
1956
+ }
1957
+ entries.sort((a, b) => a.name.localeCompare(b.name));
1958
+ return entries;
1959
+ }
1883
1960
  };
1884
1961
 
1885
1962
  // dist/server/emroute.server.js
@@ -2018,6 +2095,11 @@ async function createEmrouteServer(config, runtime) {
2018
2095
  widgetFiles = imported.widgetFiles;
2019
2096
  }
2020
2097
  }
2098
+ let discoveredElementEntries = [];
2099
+ const elementsResponse = await runtime.query(ELEMENTS_MANIFEST_PATH);
2100
+ if (elementsResponse.status !== 404) {
2101
+ discoveredElementEntries = await elementsResponse.json();
2102
+ }
2021
2103
  let ssrHtmlRouter = null;
2022
2104
  let ssrMdRouter = null;
2023
2105
  function buildSsrRouters() {
@@ -2029,22 +2111,23 @@ async function createEmrouteServer(config, runtime) {
2029
2111
  ssrHtmlRouter = new SsrHtmlRouter(resolver, {
2030
2112
  fileReader: (path) => runtime.query(path, { as: "text" }),
2031
2113
  moduleLoaders,
2032
- markdownRenderer: config.markdownRenderer,
2033
- extendContext: config.extendContext,
2034
- widgets,
2114
+ ...config.markdownRenderer ? { markdownRenderer: config.markdownRenderer } : {},
2115
+ ...config.extendContext ? { extendContext: config.extendContext } : {},
2116
+ ...widgets ? { widgets } : {},
2035
2117
  widgetFiles
2036
2118
  });
2037
2119
  ssrMdRouter = new SsrMdRouter(resolver, {
2038
2120
  fileReader: (path) => runtime.query(path, { as: "text" }),
2039
2121
  moduleLoaders,
2040
- extendContext: config.extendContext,
2041
- widgets,
2122
+ ...config.extendContext ? { extendContext: config.extendContext } : {},
2123
+ ...widgets ? { widgets } : {},
2042
2124
  widgetFiles
2043
2125
  });
2044
2126
  }
2045
2127
  buildSsrRouters();
2046
2128
  const title = config.title ?? "emroute";
2047
- let shell = await resolveShell(runtime, title, htmlBase);
2129
+ const shellBase = spa === "root" || spa === "only" ? appBase : htmlBase;
2130
+ let shell = await resolveShell(runtime, title, shellBase);
2048
2131
  if ((await runtime.query("/main.css")).status !== 404) {
2049
2132
  shell = shell.replace("</head>", ' <link rel="stylesheet" href="/main.css">\n</head>');
2050
2133
  }
@@ -2137,6 +2220,9 @@ async function createEmrouteServer(config, runtime) {
2137
2220
  get widgetEntries() {
2138
2221
  return discoveredWidgetEntries;
2139
2222
  },
2223
+ get elementEntries() {
2224
+ return discoveredElementEntries;
2225
+ },
2140
2226
  get shell() {
2141
2227
  return shell;
2142
2228
  }
@@ -2321,20 +2407,36 @@ async function bootEmrouteApp(options) {
2321
2407
  const routeTree = await routesResponse.json();
2322
2408
  const widgetsResponse = await runtime.handle(WIDGETS_MANIFEST_PATH);
2323
2409
  const widgetEntries = widgetsResponse.ok ? await widgetsResponse.json() : [];
2324
- const moduleLoaders = buildLazyLoaders(routeTree, widgetEntries, runtime);
2410
+ const elementsResponse = await runtime.handle(ELEMENTS_MANIFEST_PATH);
2411
+ const elementEntries = elementsResponse.ok ? await elementsResponse.json() : [];
2412
+ const moduleLoaders = buildLazyLoaders(routeTree, widgetEntries, elementEntries, runtime);
2325
2413
  const widgets = new WidgetRegistry();
2326
2414
  for (const entry of widgetEntries) {
2327
2415
  ComponentElement.registerLazy(entry.name, entry.files, moduleLoaders[entry.modulePath]);
2328
2416
  }
2417
+ for (const entry of elementEntries) {
2418
+ const loader = moduleLoaders[entry.modulePath];
2419
+ if (loader) {
2420
+ loader().then((mod) => {
2421
+ const cls = mod.default;
2422
+ if (typeof cls === "function" && !customElements.get(entry.tagName)) {
2423
+ customElements.define(entry.tagName, cls);
2424
+ }
2425
+ }).catch((e) => {
2426
+ console.error(`[emroute] Failed to load element ${entry.tagName}:`, e);
2427
+ });
2428
+ }
2429
+ }
2430
+ const mdRenderer = MarkdownElement.getConfiguredRenderer();
2329
2431
  const server = await createEmrouteServer({
2330
2432
  routeTree,
2331
2433
  widgets,
2332
2434
  moduleLoaders,
2333
- markdownRenderer: MarkdownElement.getConfiguredRenderer() ?? void 0
2435
+ ...mdRenderer ? { markdownRenderer: mdRenderer } : {}
2334
2436
  }, runtime);
2335
2437
  return createEmrouteApp(server, options);
2336
2438
  }
2337
- function buildLazyLoaders(tree, widgetEntries, runtime) {
2439
+ function buildLazyLoaders(tree, widgetEntries, elementEntries, runtime) {
2338
2440
  const paths = /* @__PURE__ */ new Set();
2339
2441
  function walk(node) {
2340
2442
  const modulePath = node.files?.ts ?? node.files?.js;
@@ -2356,6 +2458,8 @@ function buildLazyLoaders(tree, widgetEntries, runtime) {
2356
2458
  walk(tree);
2357
2459
  for (const entry of widgetEntries)
2358
2460
  paths.add(entry.modulePath);
2461
+ for (const entry of elementEntries)
2462
+ paths.add(entry.modulePath);
2359
2463
  const loaders = {};
2360
2464
  for (const path of paths) {
2361
2465
  const absolute = path.startsWith("/") ? path : "/" + path;