xpine 0.0.29 → 0.0.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.
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  // src/runDevServer.ts
2
2
  import expressWs from "express-ws";
3
3
  import http from "http";
4
- import express from "express";
5
- import EventEmitter from "events";
4
+ import express2 from "express";
5
+ import EventEmitter2 from "events";
6
6
  import chokidar from "chokidar";
7
7
 
8
8
  // src/scripts/build.ts
9
- import path5 from "path";
10
- import fs5 from "fs-extra";
9
+ import path6 from "path";
10
+ import fs6 from "fs-extra";
11
11
  import { build } from "esbuild";
12
12
 
13
13
  // src/build/typescript-builder.ts
@@ -121,10 +121,12 @@ function createContext(value) {
121
121
  },
122
122
  runArrayQueue() {
123
123
  Object.keys(arrayQueue).forEach((key) => {
124
- arrayQueue[key].sort((a, b) => {
125
- return (a?.position ?? Infinity) - (b.position ?? Infinity);
126
- });
127
- for (const item of arrayQueue[key]) {
124
+ const dates = arrayQueue[key].filter((item) => item?.position instanceof Date);
125
+ const numbers = arrayQueue[key].filter((item) => typeof item?.position === "number" || !item?.position);
126
+ const sortedDates = dates.toSorted((a, b) => b?.position.getTime() - a?.position.getTime());
127
+ const sortedNumbers = numbers.toSorted((a, b) => (a?.position ?? Infinity) - (b.position ?? Infinity));
128
+ const output = sortedNumbers.concat(sortedDates);
129
+ for (const item of output) {
128
130
  this.set(key, item.value, []);
129
131
  }
130
132
  });
@@ -283,7 +285,7 @@ async function triggerXPineOnLoad(noCache = false) {
283
285
  }
284
286
 
285
287
  // src/scripts/build.ts
286
- import { globSync } from "glob";
288
+ import { globSync as globSync2 } from "glob";
287
289
  import postcss from "postcss";
288
290
  import tailwindPostcss from "@tailwindcss/postcss";
289
291
 
@@ -324,7 +326,9 @@ var regex_default = {
324
326
  dynamicRoutes: /(\[)(.*?)(\])/g,
325
327
  isDynamicRoute: /\[(.*)\]/g,
326
328
  endsWithTSX: /\.tsx$/,
327
- endsWithJSX: /\.jsx$/
329
+ endsWithJSX: /\.jsx$/,
330
+ endsWithFileName: /\.(html|tsx|jsx|js|ts)$/,
331
+ indexFile: /index\.(html|tsx|jsx|js|ts)$/g
328
332
  };
329
333
 
330
334
  // src/util/config-file.ts
@@ -447,8 +451,227 @@ var staticComment = "<!-- static -->";
447
451
 
448
452
  // src/scripts/build.ts
449
453
  import ts3 from "typescript";
454
+
455
+ // src/express.ts
456
+ import express from "express";
457
+ import { globSync } from "glob";
458
+
459
+ // src/auth.ts
460
+ import jsonwebtoken from "jsonwebtoken";
461
+ var { verify, sign } = jsonwebtoken;
462
+ async function signUser(email, username) {
463
+ return new Promise((resolve, reject) => {
464
+ sign(
465
+ {
466
+ user: {
467
+ email,
468
+ username
469
+ }
470
+ },
471
+ // @ts-ignore
472
+ process.env.JWT_PRIVATE_KEY,
473
+ { expiresIn: "30d" },
474
+ (err, token) => {
475
+ if (err) reject(err);
476
+ resolve(token);
477
+ }
478
+ );
479
+ });
480
+ }
481
+ async function verifyUser(token) {
482
+ return new Promise((resolve, reject) => {
483
+ verify(token, process.env.JWT_PRIVATE_KEY, (err, authorizedData) => {
484
+ if (err) reject(err);
485
+ resolve(authorizedData);
486
+ });
487
+ });
488
+ }
489
+ function getTokenFromRequest(req) {
490
+ const { authorization } = req.headers;
491
+ if (!authorization) return null;
492
+ const token = authorization.split(" ").pop() || "";
493
+ return token || null;
494
+ }
495
+
496
+ // src/express.ts
497
+ import requestIP from "request-ip";
498
+ import fs5 from "fs-extra";
499
+ import path5 from "path";
500
+ import EventEmitter from "events";
501
+ var OnInitEmitter = class extends EventEmitter {
502
+ };
503
+ var onInitEmitter = new OnInitEmitter();
504
+ onInitEmitter.on("triggerOnInit", async (paths) => {
505
+ for (const routePath of paths) {
506
+ const pathImport = await import(routePath.path + `?cache=${Date.now()}`);
507
+ if (pathImport?.config?.onInit) await pathImport.config.onInit();
508
+ }
509
+ });
510
+ function getAllBuiltRoutes() {
511
+ const routes = globSync(config.pagesDir + "/**/*.{tsx,ts}");
512
+ return routes.map((route) => {
513
+ const routeFormatted = route.split(config.pagesDir).pop().replace(".tsx", "").replace(".js", "").replace(".ts", "");
514
+ if (routeFormatted.endsWith("+config")) return;
515
+ const routeFormattedWithIndex = routeFormatted.replace(/\/index$/g, "");
516
+ return {
517
+ route: routeFormattedWithIndex,
518
+ path: route.replace(config.srcDir, config.distDir).replace(".tsx", ".js").replace(".ts", ".js"),
519
+ originalRoute: route
520
+ };
521
+ }).filter(Boolean);
522
+ }
523
+ async function createRouter() {
524
+ const isDev = process.env.NODE_ENV === "development";
525
+ const methods = ["get", "post", "put", "patch", "delete"];
526
+ const router = express.Router();
527
+ const routeMap = getAllBuiltRoutes();
528
+ const routeResults = [];
529
+ const configFiles = globSync(config.pagesDir + "/**/+config.{tsx,ts}");
530
+ await triggerXPineOnLoad();
531
+ for (const route of routeMap) {
532
+ const isJSX = route.originalRoute.endsWith(".tsx") || route.originalRoute.endsWith(".jsx");
533
+ const slugRoute = route.route.replace(/[ ]/g, "");
534
+ const foundMethod = methods.find((method) => slugRoute.endsWith(`.${method}`));
535
+ const isDynamicRoute = slugRoute.match(regex_default.isDynamicRoute);
536
+ let formattedRouteItem = slugRoute;
537
+ if (foundMethod) formattedRouteItem = formattedRouteItem.split(".").shift();
538
+ if (isDynamicRoute) {
539
+ const result = [...formattedRouteItem.matchAll(regex_default.dynamicRoutes)];
540
+ for (const match of result) {
541
+ formattedRouteItem = formattedRouteItem.replace(match[0], ":" + match[2]);
542
+ }
543
+ }
544
+ const componentImport = await import(route.path);
545
+ const componentFn = isDev ? null : componentImport?.default;
546
+ if (componentImport?.config?.onInit) {
547
+ await componentImport.config?.onInit();
548
+ }
549
+ let config2 = {};
550
+ const configFilePaths = getConfigFiles(route.originalRoute, configFiles);
551
+ if (!isDev) {
552
+ config2 = configFilePaths && await getCompleteConfig(configFilePaths, Date.now());
553
+ if (componentImport?.config) {
554
+ config2 = {
555
+ ...config2,
556
+ ...componentImport.config
557
+ };
558
+ }
559
+ }
560
+ routeResults.push({
561
+ formattedRouteItem,
562
+ foundMethod,
563
+ route
564
+ });
565
+ router[foundMethod || "get"](formattedRouteItem, async (req, res) => {
566
+ const urlPath = req?.route?.path || "/";
567
+ try {
568
+ const staticPath = routeHasStaticPath(formattedRouteItem, req.params);
569
+ if (staticPath && !isDev) {
570
+ res.sendFile(staticPath);
571
+ return;
572
+ }
573
+ if (componentFn && !isDev) {
574
+ if (isJSX) {
575
+ const data = config2?.data ? await config2.data(req) : null;
576
+ const originalResult = await componentFn({ req, res, data, path: urlPath });
577
+ const output = config2?.wrapper ? await config2.wrapper({ req, children: originalResult, config: config2, data, path: urlPath }) : originalResult;
578
+ res.send(doctypeHTML + output);
579
+ } else {
580
+ await componentFn(req, res);
581
+ }
582
+ return;
583
+ }
584
+ await triggerXPineOnLoad(true);
585
+ const componentImportDev = await import(route.path + `?cache=${Date.now()}`);
586
+ const componentFnDev = componentImportDev.default;
587
+ onInitEmitter.emit("triggerOnInit", getAllBuiltRoutes());
588
+ if (isJSX) {
589
+ let config3 = configFilePaths && await getCompleteConfig(configFilePaths, Date.now());
590
+ if (componentImportDev?.config) {
591
+ config3 = {
592
+ ...config3,
593
+ ...componentImportDev.config
594
+ };
595
+ }
596
+ const data = config3?.data ? await config3.data(req) : null;
597
+ const originalResult = await componentFnDev({ req, res, data, config: config3, path: urlPath });
598
+ const output = config3?.wrapper ? await config3.wrapper({ req, children: originalResult, config: config3, data, path: urlPath }) : originalResult;
599
+ context.clear();
600
+ res.send(doctypeHTML + output);
601
+ } else {
602
+ await componentFnDev(req, res);
603
+ }
604
+ } catch (err) {
605
+ console.error(err);
606
+ res.status(err?.status || 500).send(err?.message || "Error");
607
+ }
608
+ });
609
+ }
610
+ return {
611
+ router,
612
+ routeResults
613
+ };
614
+ }
615
+ async function verifyUserMiddleware(req, _res, next) {
616
+ const { usertoken } = req.cookies;
617
+ if (!usertoken) {
618
+ req.user = null;
619
+ }
620
+ try {
621
+ const { user } = await verifyUser(usertoken);
622
+ req.user = user;
623
+ } catch (err) {
624
+ req.user = null;
625
+ }
626
+ next();
627
+ }
628
+ async function createXPineRouter(app, beforeErrorRoute) {
629
+ app.use(express.static(config.distPublicDir));
630
+ app.use(verifyUserMiddleware);
631
+ app.use(requestIP.mw());
632
+ const { router, routeResults } = await createRouter();
633
+ app.use(function replaceableRouter(req, res, next) {
634
+ router(req, res, next);
635
+ });
636
+ const found404 = routeResults?.find((item) => item?.formattedRouteItem === "/404");
637
+ const import404 = process.env.NODE_ENV === "development" || !found404 ? null : (await import(found404.route.path)).default;
638
+ if (beforeErrorRoute) beforeErrorRoute(app);
639
+ app.use(async function(req, res) {
640
+ res.status(404);
641
+ if (import404) {
642
+ res.send(doctypeHTML + await import404(req, res));
643
+ } else if (found404 && process.env.NODE_ENV === "development") {
644
+ const import404Item = (await import(found404.route.path + `?cache=${Date.now()}`)).default;
645
+ res.send(doctypeHTML + await import404Item(req, res));
646
+ } else {
647
+ res.send("Error");
648
+ }
649
+ });
650
+ }
651
+ function routeHasStaticPath(route, params) {
652
+ const paramEntries = Object.entries(params);
653
+ let routeToStaticPath = route;
654
+ for (const [key, value] of paramEntries) {
655
+ routeToStaticPath = routeToStaticPath.replace(`:${key}`, value);
656
+ }
657
+ routeToStaticPath += "/index.html";
658
+ const outputPath = path5.join(config.distPagesDir, routeToStaticPath);
659
+ if (fs5.existsSync(outputPath)) return outputPath;
660
+ return false;
661
+ }
662
+ function filePathToURLPath(pathName, isDist = true) {
663
+ const result = pathName.split(isDist ? config.distPagesDir : config.pagesDir).pop().replace(regex_default.indexFile, "").replace(regex_default.endsWithFileName, "");
664
+ if (result.endsWith("/")) {
665
+ const cleanedResult = result.slice(0, -1);
666
+ if (!cleanedResult) return "/";
667
+ return cleanedResult;
668
+ }
669
+ return result;
670
+ }
671
+
672
+ // src/scripts/build.ts
450
673
  var extensions = [".ts", ".tsx"];
451
- var packageJson = JSON.parse(fs5.readFileSync(config.packageJsonPath, "utf-8"));
674
+ var packageJson = JSON.parse(fs6.readFileSync(config.packageJsonPath, "utf-8"));
452
675
  var allPackages = Object.keys(packageJson.devDependencies).concat(Object.keys(packageJson.dependencies));
453
676
  var xpineDistDir = getXPineDistDir();
454
677
  async function buildApp(args) {
@@ -456,12 +679,12 @@ async function buildApp(args) {
456
679
  const removePreviousBuild = args?.removePreviousBuild || false;
457
680
  const disableTailwind = args?.disableTailwind || false;
458
681
  try {
459
- if (removePreviousBuild) fs5.removeSync(config.distDir);
460
- const srcDirFiles = globSync(config.srcDir + "/**/*.{js,ts,tsx,jsx}");
682
+ if (removePreviousBuild) fs6.removeSync(config.distDir);
683
+ const srcDirFiles = globSync2(config.srcDir + "/**/*.{js,ts,tsx,jsx}");
461
684
  const { componentData, dataFiles } = await buildAppFiles(srcDirFiles, isDev);
462
685
  const alpineDataFile = await buildAlpineDataFile(componentData, dataFiles);
463
686
  await buildClientSideFiles([alpineDataFile], isDev);
464
- fs5.removeSync(config.distTempFolder);
687
+ fs6.removeSync(config.distTempFolder);
465
688
  await buildCSS(disableTailwind);
466
689
  await buildPublicFolderSymlinks();
467
690
  await buildOnLoadFile(componentData, isDev);
@@ -481,7 +704,7 @@ async function buildAppFiles(files, isDev) {
481
704
  return fileName === "+config";
482
705
  });
483
706
  const backendFiles = files.filter((file) => extensions.find((ext) => file.endsWith(ext))).filter((file) => !file.startsWith(config.publicDir));
484
- fs5.ensureDirSync(config.distDir);
707
+ fs6.ensureDirSync(config.distDir);
485
708
  await build({
486
709
  entryPoints: backendFiles,
487
710
  format: "esm",
@@ -505,10 +728,10 @@ async function buildAppFiles(files, isDev) {
505
728
  };
506
729
  }
507
730
  async function buildClientSideFiles(alpineDataFiles = [], isDev) {
508
- const tempFilePath = path5.join(config.distTempFolder, "./app.ts");
509
- fs5.ensureFileSync(tempFilePath);
731
+ const tempFilePath = path6.join(config.distTempFolder, "./app.ts");
732
+ fs6.ensureFileSync(tempFilePath);
510
733
  const pagesScriptsGlob = config.publicDir + "/scripts/pages/**/*.{js,ts}";
511
- const clientFiles = globSync(
734
+ const clientFiles = globSync2(
512
735
  config.publicDir + "/**/*.{js,ts}",
513
736
  {
514
737
  ignore: pagesScriptsGlob
@@ -524,7 +747,7 @@ async function buildClientSideFiles(alpineDataFiles = [], isDev) {
524
747
  minify: !isDev,
525
748
  sourcemap: isDev ? "inline" : false
526
749
  });
527
- const pagesFiles = globSync(pagesScriptsGlob);
750
+ const pagesFiles = globSync2(pagesScriptsGlob);
528
751
  await build({
529
752
  entryPoints: pagesFiles || [],
530
753
  bundle: true,
@@ -535,14 +758,14 @@ async function buildClientSideFiles(alpineDataFiles = [], isDev) {
535
758
  await logSize(config.distPublicDir, "client");
536
759
  }
537
760
  function writeDevServerClientSideCode(tempFilePath) {
538
- const devServerPath = path5.join(xpineDistDir, "./src/static/dev-server.js");
539
- const content = fs5.readFileSync(devServerPath, "utf-8");
540
- fs5.appendFileSync(tempFilePath, "\n" + content);
761
+ const devServerPath = path6.join(xpineDistDir, "./src/static/dev-server.js");
762
+ const content = fs6.readFileSync(devServerPath, "utf-8");
763
+ fs6.appendFileSync(tempFilePath, "\n" + content);
541
764
  }
542
765
  function writeSpaClientSideCode(tempFilePath) {
543
- const spaPath = path5.join(xpineDistDir, "./src/static/spa.js");
544
- const content = fs5.readFileSync(spaPath, "utf-8");
545
- fs5.appendFileSync(tempFilePath, "\n" + content);
766
+ const spaPath = path6.join(xpineDistDir, "./src/static/spa.js");
767
+ const content = fs6.readFileSync(spaPath, "utf-8");
768
+ fs6.appendFileSync(tempFilePath, "\n" + content);
546
769
  }
547
770
  async function buildAlpineDataFile(componentData, dataFiles) {
548
771
  const output = {
@@ -588,23 +811,23 @@ async function buildAlpineDataFile(componentData, dataFiles) {
588
811
  output.code.push(`Alpine.data('${dataFunction.name}', ${dataFunction.name});`);
589
812
  }
590
813
  const result = output.imports.join("\n") + "\n" + output.code.join("\n") + "\n" + output.end.join("\n");
591
- fs5.ensureFileSync(config.alpineDataPath);
592
- fs5.writeFileSync(config.alpineDataPath, result);
814
+ fs6.ensureFileSync(config.alpineDataPath);
815
+ fs6.writeFileSync(config.alpineDataPath, result);
593
816
  return config.alpineDataPath;
594
817
  }
595
818
  async function buildCSS(disableTailwind) {
596
- const cssFiles = globSync(config.srcDir + "/**/*.css");
819
+ const cssFiles = globSync2(config.srcDir + "/**/*.css");
597
820
  for (const file of cssFiles) {
598
- const fileContents = fs5.readFileSync(file, "utf-8");
821
+ const fileContents = fs6.readFileSync(file, "utf-8");
599
822
  const result = disableTailwind ? fileContents : await postcss([tailwindPostcss(), remove_layers_default()]).process(fileContents, { from: file });
600
823
  const newPath = file.replace(config.srcDir, config.distDir);
601
- fs5.ensureFileSync(newPath);
602
- fs5.writeFileSync(newPath, result.css);
824
+ fs6.ensureFileSync(newPath);
825
+ fs6.writeFileSync(newPath, result.css);
603
826
  }
604
827
  logSize(config.distPublicDir, "css");
605
828
  }
606
829
  async function buildPublicFolderSymlinks() {
607
- const files = globSync(config.publicDir + "/**/*.*", {
830
+ const files = globSync2(config.publicDir + "/**/*.*", {
608
831
  ignore: "/**/*.{css,js,ts,tsx,jsx}"
609
832
  });
610
833
  for (const file of files) {
@@ -613,19 +836,19 @@ async function buildPublicFolderSymlinks() {
613
836
  const splitNewPath = newPath.split("/");
614
837
  splitNewPath.pop();
615
838
  const newDir = splitNewPath.join("/");
616
- fs5.ensureDirSync(newDir);
617
- fs5.symlinkSync(file, newPath);
839
+ fs6.ensureDirSync(newDir);
840
+ fs6.symlinkSync(file, newPath);
618
841
  } catch {
619
842
  }
620
843
  }
621
844
  }
622
845
  async function logSize(pathName, type, validExtensions = [".js", ".css"]) {
623
- const files = globSync(pathName + "/**/*" + (type === "css" ? ".css" : ""));
846
+ const files = globSync2(pathName + "/**/*" + (type === "css" ? ".css" : ""));
624
847
  const fileSizes = files.map((file) => {
625
848
  if (!validExtensions.find((ext) => file.endsWith(ext))) return false;
626
849
  return {
627
850
  file,
628
- size: fs5.statSync(file).size / (1024 * 1e3)
851
+ size: fs6.statSync(file).size / (1024 * 1e3)
629
852
  };
630
853
  }).filter(Boolean);
631
854
  const totalSize = fileSizes.reduce((total, current) => {
@@ -661,15 +884,16 @@ async function buildStaticFiles(config2, component, componentImport, builtCompon
661
884
  if (componentImport?.onInit) await componentImport.onInit();
662
885
  const outputPath = componentDynamicPaths?.length ? componentDynamicPaths.reduce((total, current) => {
663
886
  return total.replace(`/[${current}]`, "");
664
- }, path5.dirname(builtComponentPath)) : path5.dirname(builtComponentPath);
887
+ }, path6.dirname(builtComponentPath)) : path6.dirname(builtComponentPath);
665
888
  if (typeof config2?.staticPaths === "boolean") {
889
+ const urlPath = filePathToURLPath(outputPath);
666
890
  try {
667
891
  const req = { params: {} };
668
892
  const data = config2?.data ? await config2.data(req) : null;
669
- const staticComponentOutput = await componentFn({ data });
670
- fs5.writeFileSync(
671
- path5.join(outputPath, "./index.html"),
672
- doctypeHTML + (config2?.wrapper ? await config2.wrapper({ req, children: staticComponentOutput, config: config2, data }) : staticComponentOutput) + staticComment
893
+ const staticComponentOutput = await componentFn({ data, path: urlPath });
894
+ fs6.writeFileSync(
895
+ path6.join(outputPath, "./index.html"),
896
+ doctypeHTML + (config2?.wrapper ? await config2.wrapper({ req, children: staticComponentOutput, config: config2, data, path: urlPath }) : staticComponentOutput) + staticComment
673
897
  );
674
898
  } catch (err) {
675
899
  console.error(err);
@@ -684,13 +908,14 @@ async function buildStaticFiles(config2, component, componentImport, builtCompon
684
908
  ...componentDynamicPaths?.length ? dynamicPath : {}
685
909
  }
686
910
  };
911
+ const updatedOutDir = path6.join(outputPath, `./${componentDynamicPaths.map((key) => dynamicPath[key]).join("/")}`);
912
+ const urlPath = filePathToURLPath(updatedOutDir);
687
913
  const data = config2?.data ? await config2.data(req) : null;
688
- const staticComponentOutput = await componentFn({ req, data });
689
- const updatedOutDir = path5.join(outputPath, `./${componentDynamicPaths.map((key) => dynamicPath[key]).join("/")}`);
690
- fs5.ensureDirSync(updatedOutDir);
691
- fs5.writeFileSync(
692
- path5.join(updatedOutDir, "./index.html"),
693
- doctypeHTML + (config2?.wrapper ? await config2.wrapper({ req, children: staticComponentOutput, config: config2, data }) : staticComponentOutput) + staticComment
914
+ const staticComponentOutput = await componentFn({ req, data, path: urlPath });
915
+ fs6.ensureDirSync(updatedOutDir);
916
+ fs6.writeFileSync(
917
+ path6.join(updatedOutDir, "./index.html"),
918
+ doctypeHTML + (config2?.wrapper ? await config2.wrapper({ req, children: staticComponentOutput, config: config2, data, path: urlPath }) : staticComponentOutput) + staticComment
694
919
  );
695
920
  } catch (err) {
696
921
  console.log("Could not build static component", component.path);
@@ -738,8 +963,8 @@ async function buildOnLoadFile(componentData, isDev) {
738
963
  context.runArrayQueue();
739
964
  }
740
965
  `;
741
- const onLoadFilePath = path5.join(config.distDir, "./__xpineOnLoad.ts");
742
- fs5.writeFileSync(onLoadFilePath, output);
966
+ const onLoadFilePath = path6.join(config.distDir, "./__xpineOnLoad.ts");
967
+ fs6.writeFileSync(onLoadFilePath, output);
743
968
  await build({
744
969
  entryPoints: [onLoadFilePath],
745
970
  format: "esm",
@@ -757,15 +982,15 @@ async function buildOnLoadFile(componentData, isDev) {
757
982
  }
758
983
 
759
984
  // src/runDevServer.ts
760
- import path7 from "path";
985
+ import path8 from "path";
761
986
 
762
987
  // src/util/env.ts
763
988
  import dotenv from "dotenv";
764
- import path6 from "path";
989
+ import path7 from "path";
765
990
  import { GetSecretValueCommand, SecretsManagerClient } from "@aws-sdk/client-secrets-manager";
766
991
  async function setupEnv() {
767
992
  if (process.env.HAS_SETUP_ENV) return;
768
- dotenv.config({ path: path6.join(config.rootDir, `./.env.${process.env.STAGE || "dev"}`) });
993
+ dotenv.config({ path: path7.join(config.rootDir, `./.env.${process.env.STAGE || "dev"}`) });
769
994
  await loadSecretsManagerSecrets();
770
995
  process.env.HAS_SETUP_ENV = "true";
771
996
  }
@@ -801,7 +1026,7 @@ async function runDevServer() {
801
1026
  const watcher = chokidar.watch(config.srcDir, {
802
1027
  ignoreInitial: true,
803
1028
  // Ignore map and prisma files
804
- ignored: (pathName) => pathName.endsWith(".map") || pathName.startsWith(path7.join(config.serverDir, "./prisma"))
1029
+ ignored: (pathName) => pathName.endsWith(".map") || pathName.startsWith(path8.join(config.serverDir, "./prisma"))
805
1030
  });
806
1031
  watcher.on("all", async (event, path9) => {
807
1032
  const shouldReloadServer = path9.startsWith(config.serverDir) && !path9.startsWith(config.runDir) || ["add", "unlink"].includes(event) && path9.startsWith(config.pagesDir);
@@ -821,10 +1046,10 @@ async function runDevServer() {
821
1046
  const startServer2 = (await import(config.serverDistAppPath + `?cache=${Date.now()}`)).default;
822
1047
  appServer = await startServer2();
823
1048
  }
824
- const wsApp = express();
1049
+ const wsApp = express2();
825
1050
  const wsServer = http.createServer(wsApp);
826
1051
  expressWs(wsApp, wsServer);
827
- class RefreshEmitter extends EventEmitter {
1052
+ class RefreshEmitter extends EventEmitter2 {
828
1053
  }
829
1054
  ;
830
1055
  const refreshEmitter = new RefreshEmitter();
@@ -847,7 +1072,7 @@ function asyncServerClose(server) {
847
1072
  });
848
1073
  }
849
1074
  function createRebuildEmitter(delay = 500) {
850
- class RebuildEmitter extends EventEmitter {
1075
+ class RebuildEmitter extends EventEmitter2 {
851
1076
  }
852
1077
  ;
853
1078
  const rebuildEmitter = new RebuildEmitter();
@@ -872,213 +1097,6 @@ function createRebuildEmitter(delay = 500) {
872
1097
  return rebuildEmitter;
873
1098
  }
874
1099
 
875
- // src/express.ts
876
- import express2 from "express";
877
- import { globSync as globSync2 } from "glob";
878
-
879
- // src/auth.ts
880
- import jsonwebtoken from "jsonwebtoken";
881
- var { verify, sign } = jsonwebtoken;
882
- async function signUser(email, username) {
883
- return new Promise((resolve, reject) => {
884
- sign(
885
- {
886
- user: {
887
- email,
888
- username
889
- }
890
- },
891
- // @ts-ignore
892
- process.env.JWT_PRIVATE_KEY,
893
- { expiresIn: "30d" },
894
- (err, token) => {
895
- if (err) reject(err);
896
- resolve(token);
897
- }
898
- );
899
- });
900
- }
901
- async function verifyUser(token) {
902
- return new Promise((resolve, reject) => {
903
- verify(token, process.env.JWT_PRIVATE_KEY, (err, authorizedData) => {
904
- if (err) reject(err);
905
- resolve(authorizedData);
906
- });
907
- });
908
- }
909
- function getTokenFromRequest(req) {
910
- const { authorization } = req.headers;
911
- if (!authorization) return null;
912
- const token = authorization.split(" ").pop() || "";
913
- return token || null;
914
- }
915
-
916
- // src/express.ts
917
- import requestIP from "request-ip";
918
- import fs6 from "fs-extra";
919
- import path8 from "path";
920
- import EventEmitter2 from "events";
921
- var OnInitEmitter = class extends EventEmitter2 {
922
- };
923
- var onInitEmitter = new OnInitEmitter();
924
- onInitEmitter.on("triggerOnInit", async (paths) => {
925
- for (const routePath of paths) {
926
- const pathImport = await import(routePath.path + `?cache=${Date.now()}`);
927
- if (pathImport?.config?.onInit) await pathImport.config.onInit();
928
- }
929
- });
930
- function getAllBuiltRoutes() {
931
- const routes = globSync2(config.pagesDir + "/**/*.{tsx,ts}");
932
- return routes.map((route) => {
933
- const routeFormatted = route.split(config.pagesDir).pop().replace(".tsx", "").replace(".js", "").replace(".ts", "");
934
- if (routeFormatted.endsWith("+config")) return;
935
- const routeFormattedWithIndex = routeFormatted.replace(/\/index$/g, "");
936
- return {
937
- route: routeFormattedWithIndex,
938
- path: route.replace(config.srcDir, config.distDir).replace(".tsx", ".js").replace(".ts", ".js"),
939
- originalRoute: route
940
- };
941
- }).filter(Boolean);
942
- }
943
- async function createRouter() {
944
- const isDev = process.env.NODE_ENV === "development";
945
- const methods = ["get", "post", "put", "patch", "delete"];
946
- const router = express2.Router();
947
- const routeMap = getAllBuiltRoutes();
948
- const routeResults = [];
949
- const configFiles = globSync2(config.pagesDir + "/**/+config.{tsx,ts}");
950
- await triggerXPineOnLoad();
951
- for (const route of routeMap) {
952
- const isJSX = route.originalRoute.endsWith(".tsx") || route.originalRoute.endsWith(".jsx");
953
- const slugRoute = route.route.replace(/[ ]/g, "");
954
- const foundMethod = methods.find((method) => slugRoute.endsWith(`.${method}`));
955
- const isDynamicRoute = slugRoute.match(regex_default.isDynamicRoute);
956
- let formattedRouteItem = slugRoute;
957
- if (foundMethod) formattedRouteItem = formattedRouteItem.split(".").shift();
958
- if (isDynamicRoute) {
959
- const result = [...formattedRouteItem.matchAll(regex_default.dynamicRoutes)];
960
- for (const match of result) {
961
- formattedRouteItem = formattedRouteItem.replace(match[0], ":" + match[2]);
962
- }
963
- }
964
- const componentImport = await import(route.path);
965
- const componentFn = isDev ? null : componentImport?.default;
966
- if (componentImport?.config?.onInit) {
967
- await componentImport.config?.onInit();
968
- }
969
- let config2 = {};
970
- const configFilePaths = getConfigFiles(route.originalRoute, configFiles);
971
- if (!isDev) {
972
- config2 = configFilePaths && await getCompleteConfig(configFilePaths, Date.now());
973
- if (componentImport?.config) {
974
- config2 = {
975
- ...config2,
976
- ...componentImport.config
977
- };
978
- }
979
- }
980
- routeResults.push({
981
- formattedRouteItem,
982
- foundMethod,
983
- route
984
- });
985
- router[foundMethod || "get"](formattedRouteItem, async (req, res) => {
986
- try {
987
- const staticPath = routeHasStaticPath(formattedRouteItem, req.params);
988
- if (staticPath && !isDev) {
989
- res.sendFile(staticPath);
990
- return;
991
- }
992
- if (componentFn && !isDev) {
993
- if (isJSX) {
994
- const data = config2?.data ? await config2.data(req) : null;
995
- const originalResult = await componentFn({ req, res, data });
996
- const output = config2?.wrapper ? await config2.wrapper({ req, children: originalResult, config: config2, data }) : originalResult;
997
- res.send(doctypeHTML + output);
998
- } else {
999
- await componentFn(req, res);
1000
- }
1001
- return;
1002
- }
1003
- await triggerXPineOnLoad(true);
1004
- const componentImportDev = await import(route.path + `?cache=${Date.now()}`);
1005
- const componentFnDev = componentImportDev.default;
1006
- onInitEmitter.emit("triggerOnInit", getAllBuiltRoutes());
1007
- if (isJSX) {
1008
- let config3 = configFilePaths && await getCompleteConfig(configFilePaths, Date.now());
1009
- if (componentImportDev?.config) {
1010
- config3 = {
1011
- ...config3,
1012
- ...componentImportDev.config
1013
- };
1014
- }
1015
- const data = config3?.data ? await config3.data(req) : null;
1016
- const originalResult = await componentFnDev({ req, res, data, config: config3 });
1017
- const output = config3?.wrapper ? await config3.wrapper({ req, children: originalResult, config: config3, data }) : originalResult;
1018
- context.clear();
1019
- res.send(doctypeHTML + output);
1020
- } else {
1021
- await componentFnDev(req, res);
1022
- }
1023
- } catch (err) {
1024
- console.error(err);
1025
- res.status(err?.status || 500).send(err?.message || "Error");
1026
- }
1027
- });
1028
- }
1029
- return {
1030
- router,
1031
- routeResults
1032
- };
1033
- }
1034
- async function verifyUserMiddleware(req, _res, next) {
1035
- const { usertoken } = req.cookies;
1036
- if (!usertoken) {
1037
- req.user = null;
1038
- }
1039
- try {
1040
- const { user } = await verifyUser(usertoken);
1041
- req.user = user;
1042
- } catch (err) {
1043
- req.user = null;
1044
- }
1045
- next();
1046
- }
1047
- async function createXPineRouter(app, beforeErrorRoute) {
1048
- app.use(express2.static(config.distPublicDir));
1049
- app.use(verifyUserMiddleware);
1050
- app.use(requestIP.mw());
1051
- const { router, routeResults } = await createRouter();
1052
- app.use(function replaceableRouter(req, res, next) {
1053
- router(req, res, next);
1054
- });
1055
- const found404 = routeResults?.find((item) => item?.formattedRouteItem === "/404");
1056
- const import404 = process.env.NODE_ENV === "development" || !found404 ? null : (await import(found404.route.path)).default;
1057
- if (beforeErrorRoute) beforeErrorRoute(app);
1058
- app.use(async function(req, res) {
1059
- res.status(404);
1060
- if (import404) {
1061
- res.send(doctypeHTML + await import404(req, res));
1062
- } else if (found404 && process.env.NODE_ENV === "development") {
1063
- const import404Item = (await import(found404.route.path + `?cache=${Date.now()}`)).default;
1064
- res.send(doctypeHTML + await import404Item(req, res));
1065
- } else {
1066
- res.send("Error");
1067
- }
1068
- });
1069
- }
1070
- function routeHasStaticPath(route, params) {
1071
- const paramEntries = Object.entries(params);
1072
- let routeToStaticPath = route;
1073
- for (const [key, value] of paramEntries) {
1074
- routeToStaticPath = routeToStaticPath.replace(`:${key}`, value);
1075
- }
1076
- routeToStaticPath += "/index.html";
1077
- const outputPath = path8.join(config.distPagesDir, routeToStaticPath);
1078
- if (fs6.existsSync(outputPath)) return outputPath;
1079
- return false;
1080
- }
1081
-
1082
1100
  // src/util/html.ts
1083
1101
  var html = class {
1084
1102
  static attributeObjectToString(props) {
@@ -1118,6 +1136,7 @@ export {
1118
1136
  createContext,
1119
1137
  createRouter,
1120
1138
  createXPineRouter,
1139
+ filePathToURLPath,
1121
1140
  fromRoot,
1122
1141
  getComponentDynamicPaths,
1123
1142
  getTokenFromRequest,