@blinkk/root 1.0.0-alpha.8 → 1.0.0-beta.0

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/render.js CHANGED
@@ -1,10 +1,14 @@
1
1
  import {
2
- ErrorPage,
3
- HEAD_CONTEXT,
2
+ htmlMinify,
3
+ htmlPretty,
4
+ parseTagNames
5
+ } from "./chunk-GGQGZ7ZE.js";
6
+ import {
7
+ HTML_CONTEXT,
4
8
  I18N_CONTEXT,
5
- SCRIPT_CONTEXT,
9
+ REQUEST_CONTEXT,
6
10
  getTranslations
7
- } from "./chunk-ZV52A6YZ.js";
11
+ } from "./chunk-WTSNW7BB.js";
8
12
 
9
13
  // src/render/render.tsx
10
14
  import renderToString from "preact-render-to-string";
@@ -149,8 +153,9 @@ function getRoutes(config) {
149
153
  }
150
154
  );
151
155
  const trie = new RouteTrie();
152
- Object.keys(routes).forEach((filePath) => {
153
- let routePath = filePath.replace(/^\/routes/, "");
156
+ Object.keys(routes).forEach((modulePath) => {
157
+ const src = modulePath.slice(1);
158
+ let routePath = modulePath.replace(/^\/routes/, "");
154
159
  const parts = path.parse(routePath);
155
160
  if (parts.name.startsWith("_")) {
156
161
  return;
@@ -160,18 +165,23 @@ function getRoutes(config) {
160
165
  } else {
161
166
  routePath = path.join(parts.dir, parts.name);
162
167
  }
168
+ const localeRoutePath = i18nUrlFormat.replace("{locale}", "[locale]").replace("{path}", routePath.replace(/^\/*/, ""));
163
169
  trie.add(routePath, {
164
- modulePath: filePath,
165
- module: routes[filePath],
166
- locale: defaultLocale
170
+ src,
171
+ module: routes[modulePath],
172
+ locale: defaultLocale,
173
+ routePath,
174
+ localeRoutePath
167
175
  });
168
176
  locales.forEach((locale) => {
169
- const localeRoutePath = i18nUrlFormat.replace("{locale}", locale).replace("{path}", routePath.replace(/^\/*/, ""));
170
- if (localeRoutePath !== routePath) {
171
- trie.add(localeRoutePath, {
172
- modulePath: filePath,
173
- module: routes[filePath],
174
- locale
177
+ const localePath = localeRoutePath.replace("[locale]", locale);
178
+ if (localePath !== routePath) {
179
+ trie.add(localePath, {
180
+ src,
181
+ module: routes[modulePath],
182
+ locale,
183
+ routePath,
184
+ localeRoutePath
175
185
  });
176
186
  }
177
187
  });
@@ -179,17 +189,33 @@ function getRoutes(config) {
179
189
  return trie;
180
190
  }
181
191
  async function getAllPathsForRoute(urlPathFormat, route) {
182
- const urlPaths = [];
183
192
  const routeModule = route.module;
193
+ if (!routeModule.default) {
194
+ return [];
195
+ }
196
+ const urlPaths = [];
184
197
  if (routeModule.getStaticPaths) {
185
198
  const staticPaths = await routeModule.getStaticPaths();
186
- staticPaths.paths.forEach(
187
- (pathParams) => {
188
- urlPaths.push({
189
- urlPath: replaceParams(urlPathFormat, pathParams.params),
190
- params: pathParams.params || {}
191
- });
192
- }
199
+ if (staticPaths.paths) {
200
+ staticPaths.paths.forEach(
201
+ (pathParams) => {
202
+ const urlPath = replaceParams(urlPathFormat, pathParams.params || {});
203
+ if (pathContainsPlaceholders(urlPath)) {
204
+ console.warn(
205
+ `path contains placeholders: ${urlPathFormat}, double check getStaticPaths() and ensure all params are returned. more info: https://rootjs.dev/guide/routes#getStaticPaths`
206
+ );
207
+ } else {
208
+ urlPaths.push({
209
+ urlPath: replaceParams(urlPathFormat, pathParams.params),
210
+ params: pathParams.params || {}
211
+ });
212
+ }
213
+ }
214
+ );
215
+ }
216
+ } else if (pathContainsPlaceholders(urlPathFormat)) {
217
+ console.warn(
218
+ `path contains placeholders: ${urlPathFormat}, did you forget to define getStaticPaths()? more info: https://rootjs.dev/guide/routes#getStaticPaths`
193
219
  );
194
220
  } else {
195
221
  urlPaths.push({ urlPath: urlPathFormat, params: {} });
@@ -209,189 +235,352 @@ function replaceParams(urlPathFormat, params) {
209
235
  );
210
236
  return urlPath;
211
237
  }
238
+ function pathContainsPlaceholders(urlPath) {
239
+ const segments = urlPath.split("/");
240
+ return segments.some((segment) => {
241
+ return segment.startsWith("[") && segment.endsWith("]");
242
+ });
243
+ }
212
244
 
213
- // src/render/render.tsx
214
- import { elementsMap } from "virtual:root-elements";
215
-
216
- // src/core/components/dev-not-found-page.tsx
245
+ // src/core/pages/ErrorPage.tsx
217
246
  import { Fragment, jsx, jsxs } from "preact/jsx-runtime";
218
247
  var STYLES = `
248
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap');
249
+
250
+ :root {
251
+ --font-family-text: "Inter", sans-serif;
252
+ }
253
+
219
254
  body {
220
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;
255
+ font-family: var(--font-family-text);
256
+ background: #F5F5F5;
257
+ padding: 40px 16px;
258
+ }
259
+
260
+ .root {
261
+ max-width: 1200px;
262
+ margin: 0 auto;
221
263
  }
222
264
 
223
265
  h1 {
224
266
  margin-bottom: 40px;
225
267
  }
226
268
 
227
- .route-list {
228
- display: grid;
229
- grid-template-columns: auto 1fr;
230
- align-items: center;
231
- column-gap: 24px;
232
- row-gap: 8px;
233
- padding: 0 40px;
269
+ h2 {
270
+ margin-top: 30px;
234
271
  }
235
272
 
236
- .route-module {
237
- text-align: right;
273
+ .box {
274
+ padding: 16px;
275
+ border-radius: 12px;
276
+ background: #ffffff;
238
277
  }
239
278
 
240
- hr {
241
- margin: 60px 0;
279
+ pre.box {
280
+ overflow: scroll;
281
+ }
282
+
283
+ @media (min-width: 500px) {
284
+ body {
285
+ padding: 40px;
286
+ }
287
+
288
+ .box {
289
+ padding: 24px;
290
+ }
291
+ }
292
+
293
+ @media (min-width: 1024px) {
294
+ body {
295
+ padding: 100px;
296
+ }
242
297
  }
243
298
  `;
244
- function DevNotFoundPage(props) {
245
- const routesList = [];
246
- Object.keys(props.routes).forEach((urlPath) => {
247
- routesList.push(Object.assign({}, props.routes[urlPath], { urlPath }));
248
- });
299
+ function ErrorPage(props) {
300
+ const { code, message } = props;
301
+ const title = props.title ? `${code} | ${props.title}` : code;
249
302
  return /* @__PURE__ */ jsxs(Fragment, {
250
303
  children: [
251
304
  /* @__PURE__ */ jsx("style", {
252
305
  dangerouslySetInnerHTML: { __html: STYLES }
253
306
  }),
254
307
  /* @__PURE__ */ jsxs("div", {
308
+ className: "root",
255
309
  children: [
256
- /* @__PURE__ */ jsxs("h1", {
257
- children: [
258
- /* @__PURE__ */ jsx("strong", {
259
- children: "404:"
260
- }),
261
- " Not Found"
262
- ]
310
+ /* @__PURE__ */ jsx("h1", {
311
+ children: title
263
312
  }),
264
- routesList.length > 0 ? /* @__PURE__ */ jsxs(Fragment, {
265
- children: [
266
- /* @__PURE__ */ jsx("h2", {
267
- children: "Routes found in the project:"
268
- }),
269
- /* @__PURE__ */ jsx("div", {
270
- class: "route-list",
271
- children: routesList.map((route) => /* @__PURE__ */ jsxs(Fragment, {
272
- children: [
273
- /* @__PURE__ */ jsx("div", {
274
- class: "route-module",
275
- children: route.modulePath
276
- }),
277
- /* @__PURE__ */ jsx("a", {
278
- class: "route-url",
279
- href: route.urlPath,
280
- children: route.urlPath
281
- })
282
- ]
283
- }))
284
- })
285
- ]
286
- }) : /* @__PURE__ */ jsxs(Fragment, {
287
- children: [
288
- /* @__PURE__ */ jsx("h2", {
289
- children: "No routes found in the project"
290
- }),
291
- /* @__PURE__ */ jsxs("p", {
292
- children: [
293
- "Add your first route at ",
294
- /* @__PURE__ */ jsx("code", {
295
- children: "/routes/index.tsx"
296
- })
297
- ]
298
- })
299
- ]
313
+ message && /* @__PURE__ */ jsx("p", {
314
+ children: message
315
+ }),
316
+ props.children
317
+ ]
318
+ })
319
+ ]
320
+ });
321
+ }
322
+
323
+ // src/core/pages/DevNotFoundPage.tsx
324
+ import { jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
325
+ function DevNotFoundPage(props) {
326
+ const req = props.req;
327
+ const routesList = [];
328
+ let maxUrlLen = 0;
329
+ Object.keys(props.sitemap).forEach((urlPath) => {
330
+ const route = props.sitemap[urlPath].route;
331
+ routesList.push(Object.assign({}, route, { urlPath }));
332
+ if (urlPath.length > maxUrlLen) {
333
+ maxUrlLen = urlPath.length;
334
+ }
335
+ });
336
+ const routesListString = routesList.map((route) => {
337
+ return `${route.urlPath.padEnd(maxUrlLen, " ")} => ${route.src}`;
338
+ }).join("\n");
339
+ return /* @__PURE__ */ jsxs2(ErrorPage, {
340
+ code: 404,
341
+ title: "Root.js",
342
+ children: [
343
+ /* @__PURE__ */ jsx2("h2", {
344
+ children: "Routes"
345
+ }),
346
+ routesList.length > 0 ? /* @__PURE__ */ jsx2("pre", {
347
+ className: "box",
348
+ children: /* @__PURE__ */ jsx2("code", {
349
+ children: routesListString
350
+ })
351
+ }) : /* @__PURE__ */ jsxs2("div", {
352
+ className: "box",
353
+ children: [
354
+ "Add your first route at ",
355
+ /* @__PURE__ */ jsx2("code", {
356
+ children: "/routes/index.tsx"
357
+ })
358
+ ]
359
+ }),
360
+ /* @__PURE__ */ jsx2("h2", {
361
+ children: "Debug Info"
362
+ }),
363
+ /* @__PURE__ */ jsx2("pre", {
364
+ className: "box",
365
+ children: /* @__PURE__ */ jsx2("code", {
366
+ children: `url: ${req.originalUrl}`
367
+ })
368
+ })
369
+ ]
370
+ });
371
+ }
372
+
373
+ // src/core/pages/DevErrorPage.tsx
374
+ import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "preact/jsx-runtime";
375
+ function DevErrorPage(props) {
376
+ var _a;
377
+ const req = props.req;
378
+ const err = props.error;
379
+ const route = props.route;
380
+ const routeParams = props.routeParams;
381
+ let errMsg = String(err);
382
+ if (err && err.stack) {
383
+ errMsg = err.stack.replace(/\(.*node_modules/g, "(node_modules").replace(/at \/.*node_modules/g, "at node_modules");
384
+ if ((_a = req.rootConfig) == null ? void 0 : _a.rootDir) {
385
+ errMsg = errMsg.replaceAll(req.rootConfig.rootDir, "<root>");
386
+ }
387
+ if (process.env.HOME) {
388
+ errMsg = errMsg.replaceAll(process.env.HOME, "$HOME");
389
+ }
390
+ }
391
+ return /* @__PURE__ */ jsxs3(ErrorPage, {
392
+ code: 500,
393
+ title: "Root.js",
394
+ children: [
395
+ errMsg && /* @__PURE__ */ jsxs3(Fragment2, {
396
+ children: [
397
+ /* @__PURE__ */ jsx3("h2", {
398
+ children: "Error"
300
399
  }),
301
- /* @__PURE__ */ jsx("hr", {}),
302
- /* @__PURE__ */ jsx("p", {
303
- children: "Note: This page could use some love! If you're interested in helping to style this page, please reach out to the root.js developers!"
400
+ /* @__PURE__ */ jsx3("pre", {
401
+ className: "box",
402
+ children: /* @__PURE__ */ jsx3("code", {
403
+ children: errMsg
404
+ })
304
405
  })
305
406
  ]
407
+ }),
408
+ /* @__PURE__ */ jsx3("h2", {
409
+ children: "Debug Info"
410
+ }),
411
+ /* @__PURE__ */ jsx3("pre", {
412
+ className: "box",
413
+ children: /* @__PURE__ */ jsx3("code", {
414
+ children: `url: ${req.originalUrl}
415
+ route: ${(route == null ? void 0 : route.src) || "null"}
416
+ routeParams: ${routeParams && JSON.stringify(routeParams) || "null"}`
417
+ })
306
418
  })
307
419
  ]
308
420
  });
309
421
  }
310
422
 
311
423
  // src/render/render.tsx
312
- import { jsx as jsx2, jsxs as jsxs2 } from "preact/jsx-runtime";
424
+ import { jsx as jsx4, jsxs as jsxs4 } from "preact/jsx-runtime";
313
425
  var Renderer = class {
314
- constructor(config) {
315
- this.routes = getRoutes(config);
426
+ constructor(rootConfig, options) {
427
+ this.rootConfig = rootConfig;
428
+ this.routes = getRoutes(this.rootConfig);
429
+ this.assetMap = options.assetMap;
430
+ this.elementGraph = options.elementGraph;
316
431
  }
317
- async render(url, options) {
318
- const assetMap = options.assetMap;
432
+ async handle(req, res, next) {
433
+ const url = req.path;
319
434
  const [route, routeParams] = this.routes.get(url);
320
- if (route && route.module && route.module.default) {
321
- return await this.renderRoute(route, { routeParams, assetMap });
435
+ if (!route) {
436
+ next();
437
+ return;
322
438
  }
323
- return { notFound: true };
324
- }
325
- async renderRoute(route, options) {
326
- const routeParams = options.routeParams;
327
- const assetMap = options.assetMap;
328
- const Component = route.module.default;
329
- if (!Component) {
330
- throw new Error(
331
- "unable to render route. the route should have a default export that renders a jsx component."
332
- );
439
+ const render404 = async () => {
440
+ next();
441
+ };
442
+ const render = async (props2) => {
443
+ if (!route.module.default) {
444
+ console.error(`no default component exported in route: ${route.src}`);
445
+ render404();
446
+ return;
447
+ }
448
+ const output = await this.renderComponent(route.module.default, props2, {
449
+ route,
450
+ routeParams
451
+ });
452
+ let html = output.html;
453
+ if (this.rootConfig.prettyHtml) {
454
+ html = await htmlPretty(html, this.rootConfig.prettyHtmlOptions);
455
+ } else if (this.rootConfig.minifyHtml !== false) {
456
+ html = await htmlMinify(html, this.rootConfig.minifyHtmlOptions);
457
+ }
458
+ res.status(200).set({ "Content-Type": "text/html" }).end(html);
459
+ };
460
+ if (route.module.handle) {
461
+ const handlerContext = {
462
+ route,
463
+ params: routeParams,
464
+ render,
465
+ render404
466
+ };
467
+ req.handlerContext = handlerContext;
468
+ return route.module.handle(req, res, next);
333
469
  }
334
470
  let props = {};
335
471
  if (route.module.getStaticProps) {
336
472
  const propsData = await route.module.getStaticProps({
473
+ rootConfig: this.rootConfig,
337
474
  params: routeParams
338
475
  });
339
476
  if (propsData.notFound) {
340
- return this.render404();
477
+ return render404();
341
478
  }
342
479
  if (propsData.props) {
343
480
  props = propsData.props;
344
481
  }
345
482
  }
483
+ await render(props);
484
+ }
485
+ async renderComponent(Component, props, options) {
486
+ const { route, routeParams } = options;
346
487
  const locale = route.locale;
347
488
  const translations = getTranslations(locale);
348
- const headComponents = [];
349
- const userScripts = [];
350
- const vdom = /* @__PURE__ */ jsx2(I18N_CONTEXT.Provider, {
351
- value: { locale, translations },
352
- children: /* @__PURE__ */ jsx2(SCRIPT_CONTEXT.Provider, {
353
- value: userScripts,
354
- children: /* @__PURE__ */ jsx2(HEAD_CONTEXT.Provider, {
355
- value: headComponents,
356
- children: /* @__PURE__ */ jsx2(Component, {
489
+ const ctx = {
490
+ route,
491
+ props,
492
+ routeParams,
493
+ locale,
494
+ translations
495
+ };
496
+ const htmlContext = {
497
+ htmlAttrs: {},
498
+ headAttrs: {},
499
+ headComponents: [],
500
+ bodyAttrs: {},
501
+ scriptDeps: []
502
+ };
503
+ const vdom = /* @__PURE__ */ jsx4(REQUEST_CONTEXT.Provider, {
504
+ value: ctx,
505
+ children: /* @__PURE__ */ jsx4(I18N_CONTEXT.Provider, {
506
+ value: { locale, translations },
507
+ children: /* @__PURE__ */ jsx4(HTML_CONTEXT.Provider, {
508
+ value: htmlContext,
509
+ children: /* @__PURE__ */ jsx4(Component, {
357
510
  ...props
358
511
  })
359
512
  })
360
513
  })
361
514
  });
362
- const mainHtml = renderToString(vdom, {}, { pretty: true });
363
- const pageAsset = await assetMap.get(route.modulePath);
364
- const cssDeps = await (pageAsset == null ? void 0 : pageAsset.getCssDeps());
365
- if (cssDeps) {
366
- cssDeps.forEach((cssUrl) => {
367
- headComponents.push(/* @__PURE__ */ jsx2("link", {
368
- rel: "stylesheet",
369
- href: cssUrl
370
- }));
371
- });
515
+ const mainHtml = renderToString(vdom);
516
+ const jsDeps = /* @__PURE__ */ new Set();
517
+ const cssDeps = /* @__PURE__ */ new Set();
518
+ const routeAsset = await this.assetMap.get(route.src);
519
+ if (routeAsset) {
520
+ const routeCssDeps = await routeAsset.getCssDeps();
521
+ routeCssDeps.forEach((dep) => cssDeps.add(dep));
372
522
  }
373
- const scriptDeps = await this.getScriptDeps(mainHtml, { assetMap });
374
- scriptDeps.forEach((jsUrls) => {
375
- headComponents.push(/* @__PURE__ */ jsx2("script", {
376
- type: "module",
377
- src: jsUrls
378
- }));
379
- });
523
+ await this.collectElementDeps(mainHtml, jsDeps, cssDeps);
380
524
  await Promise.all(
381
- userScripts.map(async (scriptDep) => {
382
- const scriptAsset = await assetMap.get(scriptDep.src);
525
+ htmlContext.scriptDeps.map(async (scriptDep) => {
526
+ if (!scriptDep.src) {
527
+ return;
528
+ }
529
+ const scriptAsset = await this.assetMap.get(scriptDep.src.slice(1));
383
530
  if (scriptAsset) {
384
- const scriptUrl = scriptAsset ? scriptAsset.assetUrl : scriptDep.src;
385
- headComponents.push(/* @__PURE__ */ jsx2("script", {
386
- type: "module",
387
- src: scriptUrl
388
- }));
531
+ jsDeps.add(scriptAsset.assetUrl);
532
+ const scriptJsDeps = await scriptAsset.getJsDeps();
533
+ scriptJsDeps.forEach((dep) => jsDeps.add(dep));
389
534
  }
390
535
  })
391
536
  );
392
- const html = await this.renderHtml({ mainHtml, locale, headComponents });
537
+ const styleTags = Array.from(cssDeps).map((cssUrl) => {
538
+ return /* @__PURE__ */ jsx4("link", {
539
+ rel: "stylesheet",
540
+ href: cssUrl
541
+ });
542
+ });
543
+ const scriptTags = Array.from(jsDeps).map((jsUrls) => {
544
+ return /* @__PURE__ */ jsx4("script", {
545
+ type: "module",
546
+ src: jsUrls
547
+ });
548
+ });
549
+ const html = await this.renderHtml(mainHtml, {
550
+ htmlAttrs: htmlContext.htmlAttrs,
551
+ headAttrs: htmlContext.headAttrs,
552
+ bodyAttrs: htmlContext.bodyAttrs,
553
+ headComponents: [
554
+ ...htmlContext.headComponents,
555
+ ...styleTags,
556
+ ...scriptTags
557
+ ]
558
+ });
393
559
  return { html };
394
560
  }
561
+ async renderRoute(route, options) {
562
+ const routeParams = options.routeParams;
563
+ const Component = route.module.default;
564
+ if (!Component) {
565
+ throw new Error(
566
+ "unable to render route. the route should have a default export that renders a jsx component."
567
+ );
568
+ }
569
+ let props = {};
570
+ if (route.module.getStaticProps) {
571
+ const propsData = await route.module.getStaticProps({
572
+ rootConfig: this.rootConfig,
573
+ params: routeParams
574
+ });
575
+ if (propsData.notFound) {
576
+ return { notFound: true };
577
+ }
578
+ if (propsData.props) {
579
+ props = propsData.props;
580
+ }
581
+ }
582
+ return this.renderComponent(Component, props, { route, routeParams });
583
+ }
395
584
  async getSitemap() {
396
585
  const sitemap = {};
397
586
  await this.routes.walk(async (urlPath, route) => {
@@ -405,86 +594,117 @@ var Renderer = class {
405
594
  });
406
595
  return sitemap;
407
596
  }
408
- async renderHtml(options) {
409
- const page = /* @__PURE__ */ jsxs2("html", {
410
- lang: options.locale,
597
+ async renderHtml(html, options) {
598
+ const htmlAttrs = (options == null ? void 0 : options.htmlAttrs) || {};
599
+ const headAttrs = (options == null ? void 0 : options.headAttrs) || {};
600
+ const bodyAttrs = (options == null ? void 0 : options.bodyAttrs) || {};
601
+ const page = /* @__PURE__ */ jsxs4("html", {
602
+ ...htmlAttrs,
411
603
  children: [
412
- /* @__PURE__ */ jsxs2("head", {
604
+ /* @__PURE__ */ jsxs4("head", {
605
+ ...headAttrs,
413
606
  children: [
414
- /* @__PURE__ */ jsx2("meta", {
607
+ /* @__PURE__ */ jsx4("meta", {
415
608
  charSet: "utf-8"
416
609
  }),
417
- options.headComponents
610
+ options == null ? void 0 : options.headComponents
418
611
  ]
419
612
  }),
420
- /* @__PURE__ */ jsx2("body", {
421
- dangerouslySetInnerHTML: { __html: options.mainHtml }
613
+ /* @__PURE__ */ jsx4("body", {
614
+ ...bodyAttrs,
615
+ dangerouslySetInnerHTML: { __html: html }
422
616
  })
423
617
  ]
424
618
  });
425
- const html = `<!doctype html>
426
- ${renderToString(
427
- page,
428
- {},
429
- { pretty: true }
430
- )}
619
+ return `<!doctype html>
620
+ ${renderToString(page)}
431
621
  `;
432
- return html;
433
622
  }
434
623
  async render404() {
435
- return {
436
- html: "<!doctype html><html><title>404 Not Found</title><h1>404 Not Found</h1>",
437
- notFound: true
438
- };
439
- }
440
- async renderError(error) {
441
- const mainHtml = renderToString(/* @__PURE__ */ jsx2(ErrorPage, {
442
- error
624
+ const mainHtml = renderToString(/* @__PURE__ */ jsx4(ErrorPage, {
625
+ code: 404,
626
+ title: "Not Found"
443
627
  }));
444
- const html = await this.renderHtml({ mainHtml, locale: "en" });
628
+ const html = await this.renderHtml(mainHtml, {
629
+ headComponents: [/* @__PURE__ */ jsx4("title", {
630
+ children: "404"
631
+ })]
632
+ });
445
633
  return { html };
446
634
  }
447
- async renderDevNotFound() {
448
- const routes = await this.getAllRoutes();
449
- const mainHtml = renderToString(/* @__PURE__ */ jsx2(DevNotFoundPage, {
450
- routes
451
- }));
452
- const html = await this.renderHtml({
453
- mainHtml,
454
- locale: "en",
455
- headComponents: [/* @__PURE__ */ jsx2("title", {
456
- children: "404: Not Found"
635
+ async renderError(err) {
636
+ const mainHtml = renderToString(
637
+ /* @__PURE__ */ jsx4(ErrorPage, {
638
+ code: 500,
639
+ title: "Error",
640
+ message: "An unknown error occurred."
641
+ })
642
+ );
643
+ const html = await this.renderHtml(mainHtml, {
644
+ headComponents: [/* @__PURE__ */ jsx4("title", {
645
+ children: "500"
457
646
  })]
458
647
  });
459
648
  return { html };
460
649
  }
461
- async getAllRoutes() {
462
- const routes = {};
463
- await this.routes.walk((urlPath, route) => {
464
- routes[urlPath] = route;
650
+ async renderDevServer404(req) {
651
+ const sitemap = await this.getSitemap();
652
+ const mainHtml = renderToString(
653
+ /* @__PURE__ */ jsx4(DevNotFoundPage, {
654
+ req,
655
+ sitemap
656
+ })
657
+ );
658
+ const html = await this.renderHtml(mainHtml, {
659
+ headComponents: [/* @__PURE__ */ jsx4("title", {
660
+ children: "404 | Root.js"
661
+ })]
465
662
  });
466
- return routes;
663
+ return { html };
467
664
  }
468
- async getScriptDeps(html, options) {
469
- const assetMap = options.assetMap;
470
- const deps = /* @__PURE__ */ new Set();
471
- const re = /<(\w[\w-]+\w)/g;
472
- const matches = Array.from(html.matchAll(re));
665
+ async renderDevServer500(req, error) {
666
+ const [route, routeParams] = this.routes.get(req.path);
667
+ const mainHtml = renderToString(
668
+ /* @__PURE__ */ jsx4(DevErrorPage, {
669
+ req,
670
+ route,
671
+ routeParams,
672
+ error
673
+ })
674
+ );
675
+ const html = await this.renderHtml(mainHtml, {
676
+ headComponents: [/* @__PURE__ */ jsx4("title", {
677
+ children: "500 | Root.js"
678
+ })]
679
+ });
680
+ return { html };
681
+ }
682
+ async collectElementDeps(html, jsDeps, cssDeps) {
683
+ const elementsMap = this.elementGraph.sourceFiles;
684
+ const assetMap = this.assetMap;
685
+ const tagNames = /* @__PURE__ */ new Set();
686
+ for (const tagName of parseTagNames(html)) {
687
+ if (tagName && tagName in elementsMap) {
688
+ tagNames.add(tagName);
689
+ for (const depTagName of this.elementGraph.getDeps(tagName)) {
690
+ tagNames.add(depTagName);
691
+ }
692
+ }
693
+ }
473
694
  await Promise.all(
474
- matches.map(async (match) => {
475
- const tagName = match[1];
476
- if (tagName && tagName.includes("-") && tagName in elementsMap) {
477
- const modulePath = elementsMap[tagName];
478
- const asset = await assetMap.get(modulePath);
479
- if (!asset) {
480
- return;
481
- }
482
- const assetJsDeps = await asset.getJsDeps();
483
- assetJsDeps.forEach((dep) => deps.add(dep));
695
+ Array.from(tagNames).map(async (tagName) => {
696
+ const elementModule = elementsMap[tagName];
697
+ const asset = await assetMap.get(elementModule.relPath);
698
+ if (!asset) {
699
+ return;
484
700
  }
701
+ const assetJsDeps = await asset.getJsDeps();
702
+ assetJsDeps.forEach((dep) => jsDeps.add(dep));
703
+ const assetCssDeps = await asset.getCssDeps();
704
+ assetCssDeps.forEach((dep) => cssDeps.add(dep));
485
705
  })
486
706
  );
487
- return Array.from(deps);
707
+ return { jsDeps, cssDeps };
488
708
  }
489
709
  };
490
710
  export {