@blinkk/root 1.0.0-rc.2 → 1.0.0-rc.21

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.
@@ -4,6 +4,7 @@ import {
4
4
  trailingSlashMiddleware
5
5
  } from "./chunk-WNXIRMFF.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,31 @@ 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
+ function reloadPublicDirCache() {
1051
+ handler = sirv(publicDir, sirvOptions);
1052
+ }
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(
1059
+ "all",
1060
+ debounce((event, filepath) => {
1061
+ if (isInPublicDir(filepath)) {
1062
+ reloadPublicDirCache();
1063
+ }
1064
+ }, 1e3)
1065
+ );
1066
+ return (req, res, next) => {
1067
+ handler(req, res, next);
1068
+ };
965
1069
  }
966
1070
  function rootDevServerMiddleware() {
967
1071
  return async (req, res, next) => {
@@ -1010,6 +1114,17 @@ function rootDevServer500Middleware() {
1010
1114
  next(err);
1011
1115
  };
1012
1116
  }
1117
+ function testCmsEnabled(rootConfig) {
1118
+ const plugins = rootConfig.plugins || [];
1119
+ return Boolean(plugins.find((plugin) => plugin.name === "root-cms"));
1120
+ }
1121
+ function debounce(fn, timeout) {
1122
+ let timer;
1123
+ return (...args) => {
1124
+ clearTimeout(timer);
1125
+ timer = setTimeout(() => fn(...args), timeout);
1126
+ };
1127
+ }
1013
1128
 
1014
1129
  // src/cli/commands/preview.ts
1015
1130
  import path6 from "node:path";
@@ -1034,7 +1149,7 @@ async function preview(rootProjectDir, options) {
1034
1149
  async function createPreviewServer(options) {
1035
1150
  var _a;
1036
1151
  const rootDir = options.rootDir;
1037
- const rootConfig = await loadRootConfig(rootDir, { command: "preview" });
1152
+ const rootConfig = await loadBundledConfig(rootDir, { command: "preview" });
1038
1153
  const distDir = path6.join(rootDir, "dist");
1039
1154
  const server = express2();
1040
1155
  server.disable("x-powered-by");
@@ -1049,11 +1164,16 @@ async function createPreviewServer(options) {
1049
1164
  configureServerPlugins(
1050
1165
  server,
1051
1166
  async () => {
1052
- var _a2;
1167
+ var _a2, _b;
1053
1168
  const userMiddlewares = ((_a2 = rootConfig.server) == null ? void 0 : _a2.middlewares) || [];
1054
1169
  userMiddlewares.forEach((middleware) => {
1055
1170
  server.use(middleware);
1056
1171
  });
1172
+ if ((_b = rootConfig.server) == null ? void 0 : _b.redirects) {
1173
+ server.use(
1174
+ redirectsMiddleware({ redirects: rootConfig.server.redirects })
1175
+ );
1176
+ }
1057
1177
  const publicDir = path6.join(distDir, "html");
1058
1178
  server.use(sirv2(publicDir, { dev: false }));
1059
1179
  server.use(trailingSlashMiddleware({ rootConfig }));
@@ -1069,19 +1189,16 @@ async function createPreviewServer(options) {
1069
1189
  async function rootPreviewRendererMiddleware(options) {
1070
1190
  const { distDir, rootConfig } = options;
1071
1191
  const render = await import(path6.join(distDir, "server/render.js"));
1072
- const manifestPath = path6.join(distDir, "client/root-manifest.json");
1192
+ const manifestPath = path6.join(distDir, ".root/manifest.json");
1073
1193
  if (!await fileExists(manifestPath)) {
1074
1194
  throw new Error(
1075
1195
  `could not find ${manifestPath}. run \`root build\` before \`root preview\`.`
1076
1196
  );
1077
1197
  }
1078
- const elementGraphJsonPath = path6.join(
1079
- distDir,
1080
- "client/root-element-graph.json"
1081
- );
1198
+ const elementGraphJsonPath = path6.join(distDir, ".root/elements.json");
1082
1199
  if (!await fileExists(elementGraphJsonPath)) {
1083
1200
  throw new Error(
1084
- `could not find ${elementGraphJsonPath}. run \`root build\` before \`root start\`.`
1201
+ `could not find ${elementGraphJsonPath}. run \`root build\` before \`root preview\`.`
1085
1202
  );
1086
1203
  }
1087
1204
  const rootManifest = await loadJson(manifestPath);
@@ -1103,7 +1220,7 @@ function rootPreviewServerMiddleware() {
1103
1220
  try {
1104
1221
  console.error(`error rendering ${req.originalUrl}`);
1105
1222
  console.error(e.stack || e);
1106
- const { html } = await renderer.renderError(e);
1223
+ const { html } = await renderer.renderDevServer500(req, e);
1107
1224
  res.status(500).set({ "Content-Type": "text/html" }).end(html);
1108
1225
  } catch (e2) {
1109
1226
  console.error("failed to render custom error");
@@ -1172,7 +1289,7 @@ async function start(rootProjectDir, options) {
1172
1289
  async function createProdServer(options) {
1173
1290
  var _a;
1174
1291
  const rootDir = options.rootDir;
1175
- const rootConfig = await loadRootConfig(rootDir, { command: "start" });
1292
+ const rootConfig = await loadBundledConfig(rootDir, { command: "start" });
1176
1293
  const distDir = path7.join(rootDir, "dist");
1177
1294
  const server = express3();
1178
1295
  server.disable("x-powered-by");
@@ -1187,11 +1304,16 @@ async function createProdServer(options) {
1187
1304
  configureServerPlugins(
1188
1305
  server,
1189
1306
  async () => {
1190
- var _a2;
1307
+ var _a2, _b;
1191
1308
  const userMiddlewares = ((_a2 = rootConfig.server) == null ? void 0 : _a2.middlewares) || [];
1192
1309
  userMiddlewares.forEach((middleware) => {
1193
1310
  server.use(middleware);
1194
1311
  });
1312
+ if ((_b = rootConfig.server) == null ? void 0 : _b.redirects) {
1313
+ server.use(
1314
+ redirectsMiddleware({ redirects: rootConfig.server.redirects })
1315
+ );
1316
+ }
1195
1317
  const publicDir = path7.join(distDir, "html");
1196
1318
  server.use(sirv3(publicDir, { dev: false }));
1197
1319
  server.use(trailingSlashMiddleware({ rootConfig }));
@@ -1207,16 +1329,13 @@ async function createProdServer(options) {
1207
1329
  async function rootProdRendererMiddleware(options) {
1208
1330
  const { distDir, rootConfig } = options;
1209
1331
  const render = await import(path7.join(distDir, "server/render.js"));
1210
- const manifestPath = path7.join(distDir, "client/root-manifest.json");
1332
+ const manifestPath = path7.join(distDir, ".root/manifest.json");
1211
1333
  if (!await fileExists(manifestPath)) {
1212
1334
  throw new Error(
1213
1335
  `could not find ${manifestPath}. run \`root build\` before \`root start\`.`
1214
1336
  );
1215
1337
  }
1216
- const elementGraphJsonPath = path7.join(
1217
- distDir,
1218
- "client/root-element-graph.json"
1219
- );
1338
+ const elementGraphJsonPath = path7.join(distDir, ".root/elements.json");
1220
1339
  if (!await fileExists(elementGraphJsonPath)) {
1221
1340
  throw new Error(
1222
1341
  `could not find ${elementGraphJsonPath}. run \`root build\` before \`root start\`.`
@@ -1296,4 +1415,4 @@ export {
1296
1415
  start,
1297
1416
  createProdServer
1298
1417
  };
1299
- //# sourceMappingURL=chunk-CY3DVKXO.js.map
1418
+ //# sourceMappingURL=chunk-PICVEUBV.js.map