@blinkk/root 1.0.0-rc.3 → 1.0.0-rc.31

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.
@@ -2,8 +2,9 @@ import {
2
2
  rootProjectMiddleware,
3
3
  sessionMiddleware,
4
4
  trailingSlashMiddleware
5
- } from "./chunk-WNXIRMFF.js";
5
+ } from "./chunk-O74GNZTB.js";
6
6
  import {
7
+ bundleRootConfig,
7
8
  copyGlob,
8
9
  createViteServer,
9
10
  dirExists,
@@ -11,22 +12,24 @@ import {
11
12
  fileExists,
12
13
  isDirectory,
13
14
  isJsFile,
15
+ loadBundledConfig,
14
16
  loadJson,
15
17
  loadRootConfig,
16
18
  makeDir,
17
19
  rmDir,
18
20
  writeFile
19
- } from "./chunk-J2ANSYAE.js";
21
+ } from "./chunk-JH33OQEK.js";
20
22
  import {
21
23
  configureServerPlugins,
22
24
  getVitePlugins
23
25
  } from "./chunk-QKBMWK5B.js";
24
26
  import {
27
+ RouteTrie,
25
28
  htmlMinify,
26
29
  htmlPretty,
27
30
  isValidTagName,
28
31
  parseTagNames
29
- } from "./chunk-DFBTOMQF.js";
32
+ } from "./chunk-IUQLRDFW.js";
30
33
 
31
34
  // src/cli/commands/build.ts
32
35
  import path3 from "node:path";
@@ -415,7 +418,7 @@ async function build(rootProjectDir, options) {
415
418
  ssr: {
416
419
  ...viteConfig.ssr,
417
420
  target: "node",
418
- noExternal: ["@blinkk/root", ...noExternal]
421
+ noExternal: ["@blinkk/root", "@blinkk/root-cms/richtext", ...noExternal]
419
422
  }
420
423
  });
421
424
  await viteBuild({
@@ -435,9 +438,9 @@ async function build(rootProjectDir, options) {
435
438
  ...(_e = (_d = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _d.rollupOptions) == null ? void 0 : _e.output
436
439
  }
437
440
  },
438
- outDir: path3.join(distDir, "routes"),
441
+ outDir: path3.join(distDir, ".build/routes"),
439
442
  ssr: true,
440
- ssrManifest: true,
443
+ ssrManifest: false,
441
444
  ssrEmitAssets: true,
442
445
  manifest: true,
443
446
  cssCodeSplit: true,
@@ -466,7 +469,7 @@ async function build(rootProjectDir, options) {
466
469
  ...(_h = (_g = viteConfig == null ? void 0 : viteConfig.build) == null ? void 0 : _g.rollupOptions) == null ? void 0 : _h.output
467
470
  }
468
471
  },
469
- outDir: path3.join(distDir, "client"),
472
+ outDir: path3.join(distDir, ".build/client"),
470
473
  ssr: false,
471
474
  ssrManifest: false,
472
475
  manifest: true,
@@ -478,18 +481,22 @@ async function build(rootProjectDir, options) {
478
481
  }
479
482
  });
480
483
  } else {
481
- await writeFile(path3.join(distDir, "client/manifest.json"), "{}");
484
+ await writeFile(
485
+ path3.join(distDir, ".build/client/.vite/manifest.json"),
486
+ "{}"
487
+ );
482
488
  }
489
+ await bundleRootConfig(rootDir, path3.join(distDir, "root.config.js"));
483
490
  await copyGlob(
484
491
  "**/*.css",
485
- path3.join(distDir, "routes"),
486
- path3.join(distDir, "client")
492
+ path3.join(distDir, ".build/routes"),
493
+ path3.join(distDir, ".build/client")
487
494
  );
488
495
  const routesManifest = await loadJson(
489
- path3.join(distDir, "routes/manifest.json")
496
+ path3.join(distDir, ".build/routes/.vite/manifest.json")
490
497
  );
491
498
  const clientManifest = await loadJson(
492
- path3.join(distDir, "client/manifest.json")
499
+ path3.join(distDir, ".build/client/.vite/manifest.json")
493
500
  );
494
501
  function collectRouteCss(asset, cssDeps, visited) {
495
502
  if (!asset || !asset.file || visited.has(asset.file)) {
@@ -525,12 +532,12 @@ async function build(rootProjectDir, options) {
525
532
  );
526
533
  const rootManifest = assetMap.toJson();
527
534
  await writeFile(
528
- path3.join(distDir, "client/root-manifest.json"),
535
+ path3.join(distDir, ".root/manifest.json"),
529
536
  JSON.stringify(rootManifest, null, 2)
530
537
  );
531
538
  const elementGraphJson = elementGraph.toJson();
532
539
  await writeFile(
533
- path3.join(distDir, "client/root-element-graph.json"),
540
+ path3.join(distDir, ".root/elements.json"),
534
541
  JSON.stringify(elementGraphJson, null, 2)
535
542
  );
536
543
  const buildDir = path3.join(distDir, "html");
@@ -540,25 +547,37 @@ async function build(rootProjectDir, options) {
540
547
  } else {
541
548
  await makeDir(buildDir);
542
549
  }
550
+ const seenAssets = /* @__PURE__ */ new Set();
551
+ async function copyAssetToDistHtml(assetUrl) {
552
+ if (seenAssets.has(assetUrl)) {
553
+ return;
554
+ }
555
+ seenAssets.add(assetUrl);
556
+ const assetRelPath = assetUrl.slice(1);
557
+ const assetFrom = path3.join(distDir, ".build/client", assetRelPath);
558
+ const assetTo = path3.join(buildDir, assetRelPath);
559
+ if (!await fileExists(assetFrom)) {
560
+ console.log(`${assetFrom} does not exist`);
561
+ return;
562
+ }
563
+ await fsExtra.copy(assetFrom, assetTo);
564
+ printFileOutput(fileSize(assetTo), "dist/html/", assetRelPath);
565
+ }
543
566
  console.log("\njs/css output:");
544
567
  await Promise.all(
545
568
  Object.keys(rootManifest).map(async (src) => {
569
+ const assetData = rootManifest[src];
546
570
  if (isRouteFile(src)) {
571
+ const importedCss = assetData.importedCss || [];
572
+ for (const cssAssetUrl of importedCss) {
573
+ await copyAssetToDistHtml(cssAssetUrl);
574
+ }
547
575
  return;
548
576
  }
549
- const assetData = rootManifest[src];
550
577
  if (!assetData.assetUrl) {
551
578
  return;
552
579
  }
553
- const assetRelPath = assetData.assetUrl.slice(1);
554
- const assetFrom = path3.join(distDir, "client", assetRelPath);
555
- const assetTo = path3.join(buildDir, assetRelPath);
556
- if (!await fileExists(assetFrom)) {
557
- console.log(`${assetFrom} does not exist`);
558
- return;
559
- }
560
- await fsExtra.copy(assetFrom, assetTo);
561
- printFileOutput(fileSize(assetTo), "dist/html/", assetRelPath);
580
+ await copyAssetToDistHtml(assetData.assetUrl);
562
581
  })
563
582
  );
564
583
  if (!ssrOnly) {
@@ -683,6 +702,51 @@ var Hooks = class {
683
702
  }
684
703
  };
685
704
 
705
+ // src/middleware/redirects.ts
706
+ function redirectsMiddleware(options) {
707
+ const routeTrie = new RouteTrie();
708
+ const redirects = options.redirects || [];
709
+ redirects.forEach((redirect) => {
710
+ if (!verifyRedirectConfig(redirect)) {
711
+ console.warn("ignoring invalid redirect config:", redirect);
712
+ return;
713
+ }
714
+ routeTrie.add(redirect.source, redirect);
715
+ });
716
+ return (req, res, next) => {
717
+ const [redirect, params] = routeTrie.get(req.path);
718
+ if (redirect) {
719
+ const destination = replaceParams(redirect.destination, params);
720
+ const code = redirect.type || 302;
721
+ res.redirect(code, destination);
722
+ return;
723
+ }
724
+ next();
725
+ };
726
+ }
727
+ function verifyRedirectConfig(redirect) {
728
+ if (!redirect.source) {
729
+ return false;
730
+ }
731
+ if (!redirect.destination) {
732
+ return false;
733
+ }
734
+ return true;
735
+ }
736
+ function replaceParams(urlPathFormat, params) {
737
+ const urlPath = urlPathFormat.replaceAll(
738
+ /\[\[?(\.\.\.)?([\w\-_]*)\]?\]/g,
739
+ (match, _wildcard, key) => {
740
+ const val = params[key];
741
+ if (!val) {
742
+ throw new Error(`unreplaced param ${match} in url: ${urlPathFormat}`);
743
+ }
744
+ return val;
745
+ }
746
+ );
747
+ return urlPath;
748
+ }
749
+
686
750
  // src/render/asset-map/dev-asset-map.ts
687
751
  import path4 from "node:path";
688
752
  import { searchForWorkspaceRoot as searchForWorkspaceRoot2 } from "vite";
@@ -862,12 +926,17 @@ async function dev(rootProjectDir, options) {
862
926
  const defaultPort = parseInt(process.env.PORT || "4007");
863
927
  const host = (options == null ? void 0 : options.host) || "localhost";
864
928
  const port = await findOpenPort(defaultPort, defaultPort + 10);
929
+ const server = await createDevServer({ rootDir, port });
930
+ const rootConfig = server.get("rootConfig");
931
+ const basePath = rootConfig.base || "";
865
932
  console.log();
866
933
  console.log(`${dim2("\u2503")} project: ${rootDir}`);
867
- console.log(`${dim2("\u2503")} server: http://${host}:${port}`);
934
+ console.log(`${dim2("\u2503")} server: http://${host}:${port}${basePath}`);
935
+ if (testCmsEnabled(rootConfig)) {
936
+ console.log(`${dim2("\u2503")} cms: http://${host}:${port}/cms/`);
937
+ }
868
938
  console.log(`${dim2("\u2503")} mode: development`);
869
939
  console.log();
870
- const server = await createDevServer({ rootDir, port });
871
940
  server.listen(port, host);
872
941
  }
873
942
  async function createDevServer(options) {
@@ -876,9 +945,14 @@ async function createDevServer(options) {
876
945
  const rootConfig = await loadRootConfig(rootDir, { command: "dev" });
877
946
  const port = options == null ? void 0 : options.port;
878
947
  const server = express();
948
+ server.set("rootConfig", rootConfig);
879
949
  server.disable("x-powered-by");
950
+ const { viteServer, viteMiddleware } = await createViteMiddleware({
951
+ rootConfig,
952
+ port
953
+ });
880
954
  server.use(rootProjectMiddleware({ rootConfig }));
881
- server.use(await viteServerMiddleware({ rootConfig, port }));
955
+ server.use(viteMiddleware);
882
956
  server.use(hooksMiddleware());
883
957
  const sessionCookieSecret = ((_a = rootConfig.server) == null ? void 0 : _a.sessionCookieSecret) || randString(36);
884
958
  server.use(cookieParser(sessionCookieSecret));
@@ -887,14 +961,19 @@ async function createDevServer(options) {
887
961
  await configureServerPlugins(
888
962
  server,
889
963
  async () => {
890
- var _a2;
964
+ var _a2, _b;
891
965
  const userMiddlewares = ((_a2 = rootConfig.server) == null ? void 0 : _a2.middlewares) || [];
892
966
  for (const middleware of userMiddlewares) {
893
967
  server.use(middleware);
894
968
  }
969
+ if ((_b = rootConfig.server) == null ? void 0 : _b.redirects) {
970
+ server.use(
971
+ redirectsMiddleware({ redirects: rootConfig.server.redirects })
972
+ );
973
+ }
895
974
  const publicDir = path5.join(rootDir, "public");
896
975
  if (await dirExists(publicDir)) {
897
- server.use(sirv(publicDir, { dev: false }));
976
+ server.use(rootPublicDirMiddleware({ publicDir, viteServer }));
898
977
  }
899
978
  server.use(trailingSlashMiddleware({ rootConfig }));
900
979
  server.use(rootDevServerMiddleware());
@@ -906,7 +985,7 @@ async function createDevServer(options) {
906
985
  );
907
986
  return server;
908
987
  }
909
- async function viteServerMiddleware(options) {
988
+ async function createViteMiddleware(options) {
910
989
  const rootConfig = options.rootConfig;
911
990
  const rootDir = rootConfig.rootDir;
912
991
  let elementGraph = await getElements(rootConfig);
@@ -945,7 +1024,7 @@ async function viteServerMiddleware(options) {
945
1024
  console.log(`element deleted: ${filePath}`);
946
1025
  }
947
1026
  });
948
- return async (req, res, next) => {
1027
+ const viteMiddleware = async (req, res, next) => {
949
1028
  try {
950
1029
  req.viteServer = viteServer;
951
1030
  const renderModulePath = path5.resolve(__dirname2, "./render.js");
@@ -962,6 +1041,28 @@ async function viteServerMiddleware(options) {
962
1041
  next(e);
963
1042
  }
964
1043
  };
1044
+ return { viteServer, viteMiddleware };
1045
+ }
1046
+ function rootPublicDirMiddleware(options) {
1047
+ const publicDir = options.publicDir;
1048
+ const sirvOptions = { dev: false };
1049
+ let handler = sirv(publicDir, sirvOptions);
1050
+ const reloadPublicDirCache = debounce(() => {
1051
+ handler = sirv(publicDir, sirvOptions);
1052
+ }, 1e3);
1053
+ function isInPublicDir(changedFilePath) {
1054
+ const filePath = path5.resolve(changedFilePath);
1055
+ return filePath.startsWith(publicDir);
1056
+ }
1057
+ const watcher = options.viteServer.watcher;
1058
+ watcher.on("all", (event, filepath) => {
1059
+ if (isInPublicDir(filepath)) {
1060
+ reloadPublicDirCache();
1061
+ }
1062
+ });
1063
+ return (req, res, next) => {
1064
+ handler(req, res, next);
1065
+ };
965
1066
  }
966
1067
  function rootDevServerMiddleware() {
967
1068
  return async (req, res, next) => {
@@ -1010,6 +1111,17 @@ function rootDevServer500Middleware() {
1010
1111
  next(err);
1011
1112
  };
1012
1113
  }
1114
+ function testCmsEnabled(rootConfig) {
1115
+ const plugins = rootConfig.plugins || [];
1116
+ return Boolean(plugins.find((plugin) => plugin.name === "root-cms"));
1117
+ }
1118
+ function debounce(fn, timeout) {
1119
+ let timer;
1120
+ return (...args) => {
1121
+ clearTimeout(timer);
1122
+ timer = setTimeout(() => fn(...args), timeout);
1123
+ };
1124
+ }
1013
1125
 
1014
1126
  // src/cli/commands/preview.ts
1015
1127
  import path6 from "node:path";
@@ -1034,7 +1146,7 @@ async function preview(rootProjectDir, options) {
1034
1146
  async function createPreviewServer(options) {
1035
1147
  var _a;
1036
1148
  const rootDir = options.rootDir;
1037
- const rootConfig = await loadRootConfig(rootDir, { command: "preview" });
1149
+ const rootConfig = await loadBundledConfig(rootDir, { command: "preview" });
1038
1150
  const distDir = path6.join(rootDir, "dist");
1039
1151
  const server = express2();
1040
1152
  server.disable("x-powered-by");
@@ -1049,11 +1161,16 @@ async function createPreviewServer(options) {
1049
1161
  configureServerPlugins(
1050
1162
  server,
1051
1163
  async () => {
1052
- var _a2;
1164
+ var _a2, _b;
1053
1165
  const userMiddlewares = ((_a2 = rootConfig.server) == null ? void 0 : _a2.middlewares) || [];
1054
1166
  userMiddlewares.forEach((middleware) => {
1055
1167
  server.use(middleware);
1056
1168
  });
1169
+ if ((_b = rootConfig.server) == null ? void 0 : _b.redirects) {
1170
+ server.use(
1171
+ redirectsMiddleware({ redirects: rootConfig.server.redirects })
1172
+ );
1173
+ }
1057
1174
  const publicDir = path6.join(distDir, "html");
1058
1175
  server.use(sirv2(publicDir, { dev: false }));
1059
1176
  server.use(trailingSlashMiddleware({ rootConfig }));
@@ -1069,19 +1186,16 @@ async function createPreviewServer(options) {
1069
1186
  async function rootPreviewRendererMiddleware(options) {
1070
1187
  const { distDir, rootConfig } = options;
1071
1188
  const render = await import(path6.join(distDir, "server/render.js"));
1072
- const manifestPath = path6.join(distDir, "client/root-manifest.json");
1189
+ const manifestPath = path6.join(distDir, ".root/manifest.json");
1073
1190
  if (!await fileExists(manifestPath)) {
1074
1191
  throw new Error(
1075
1192
  `could not find ${manifestPath}. run \`root build\` before \`root preview\`.`
1076
1193
  );
1077
1194
  }
1078
- const elementGraphJsonPath = path6.join(
1079
- distDir,
1080
- "client/root-element-graph.json"
1081
- );
1195
+ const elementGraphJsonPath = path6.join(distDir, ".root/elements.json");
1082
1196
  if (!await fileExists(elementGraphJsonPath)) {
1083
1197
  throw new Error(
1084
- `could not find ${elementGraphJsonPath}. run \`root build\` before \`root start\`.`
1198
+ `could not find ${elementGraphJsonPath}. run \`root build\` before \`root preview\`.`
1085
1199
  );
1086
1200
  }
1087
1201
  const rootManifest = await loadJson(manifestPath);
@@ -1103,7 +1217,7 @@ function rootPreviewServerMiddleware() {
1103
1217
  try {
1104
1218
  console.error(`error rendering ${req.originalUrl}`);
1105
1219
  console.error(e.stack || e);
1106
- const { html } = await renderer.renderError(e);
1220
+ const { html } = await renderer.renderDevServer500(req, e);
1107
1221
  res.status(500).set({ "Content-Type": "text/html" }).end(html);
1108
1222
  } catch (e2) {
1109
1223
  console.error("failed to render custom error");
@@ -1172,7 +1286,7 @@ async function start(rootProjectDir, options) {
1172
1286
  async function createProdServer(options) {
1173
1287
  var _a;
1174
1288
  const rootDir = options.rootDir;
1175
- const rootConfig = await loadRootConfig(rootDir, { command: "start" });
1289
+ const rootConfig = await loadBundledConfig(rootDir, { command: "start" });
1176
1290
  const distDir = path7.join(rootDir, "dist");
1177
1291
  const server = express3();
1178
1292
  server.disable("x-powered-by");
@@ -1187,11 +1301,16 @@ async function createProdServer(options) {
1187
1301
  configureServerPlugins(
1188
1302
  server,
1189
1303
  async () => {
1190
- var _a2;
1304
+ var _a2, _b;
1191
1305
  const userMiddlewares = ((_a2 = rootConfig.server) == null ? void 0 : _a2.middlewares) || [];
1192
1306
  userMiddlewares.forEach((middleware) => {
1193
1307
  server.use(middleware);
1194
1308
  });
1309
+ if ((_b = rootConfig.server) == null ? void 0 : _b.redirects) {
1310
+ server.use(
1311
+ redirectsMiddleware({ redirects: rootConfig.server.redirects })
1312
+ );
1313
+ }
1195
1314
  const publicDir = path7.join(distDir, "html");
1196
1315
  server.use(sirv3(publicDir, { dev: false }));
1197
1316
  server.use(trailingSlashMiddleware({ rootConfig }));
@@ -1207,16 +1326,13 @@ async function createProdServer(options) {
1207
1326
  async function rootProdRendererMiddleware(options) {
1208
1327
  const { distDir, rootConfig } = options;
1209
1328
  const render = await import(path7.join(distDir, "server/render.js"));
1210
- const manifestPath = path7.join(distDir, "client/root-manifest.json");
1329
+ const manifestPath = path7.join(distDir, ".root/manifest.json");
1211
1330
  if (!await fileExists(manifestPath)) {
1212
1331
  throw new Error(
1213
1332
  `could not find ${manifestPath}. run \`root build\` before \`root start\`.`
1214
1333
  );
1215
1334
  }
1216
- const elementGraphJsonPath = path7.join(
1217
- distDir,
1218
- "client/root-element-graph.json"
1219
- );
1335
+ const elementGraphJsonPath = path7.join(distDir, ".root/elements.json");
1220
1336
  if (!await fileExists(elementGraphJsonPath)) {
1221
1337
  throw new Error(
1222
1338
  `could not find ${elementGraphJsonPath}. run \`root build\` before \`root start\`.`
@@ -1296,4 +1412,4 @@ export {
1296
1412
  start,
1297
1413
  createProdServer
1298
1414
  };
1299
- //# sourceMappingURL=chunk-CY3DVKXO.js.map
1415
+ //# sourceMappingURL=chunk-QQOTOKPH.js.map