GitFOSS
move to latest version of react-monolith
+ 532
- 78
@@ -1,10 +1,22 @@
 {
-  "_generatedAtUnix": 1702173824643,
+  "_generatedAtUnix": 1702180342118,
   "_hashAlgorithm": "sha1",
   "_version": 2,
+  "assets": {
+    "IslandsRuntime": {
+      "kind": "generated",
+      "hash": "81cd1baaa8b7c287f98b563607aaeeaa2884158a",
+      "path": "./public/instant-router.js"
+    },
+    "InstantRouter": {
+      "kind": "generated",
+      "hash": "3d08c09ed073afa4560e7b9943914bf3ddc6098d",
+      "path": "./public/islands-runtime.js"
+    }
+  },
   "islands": {
     "Code": {
-      "hash": "637cb859750ff563dc8156f17615d9864f95f561",
+      "hash": "c3c638cfcd010020f6ca251f7a3984721b60048d",
       "pathSource": "./app/islands/Code.tsx",
       "pathBundle": "./public/.islands/Code.bundle.js",
       "pathSourceMap": "./public/.islands/Code.bundle.js.map"

app/controllers/repository/getRepositoryBrowserView.ts
@@ -21,7 +21,8 @@ const getRepositoryBrowserView: ReqHandler<
   AppRouteParams,
   AppRoute.REPOSITORY_BROWSER
 > = async (request, reply) => {
-  const { orgSlug, repoSlug, currentRef: currRef, "*": path } = request.params;
+  const { orgSlug, repoSlug, currentRef: currRef } = request.params;
+  const path = request.params["*"] || "";
   const currentRef = currRef || Const.DEFAULT_HEAD_REF;
 
   const orgService = makeOrganizationService({ request });

app/controllers/repository/postRepositoryForkAction.ts
@@ -33,7 +33,6 @@ const postRepositoryForkAction: ReqHandler<
 
   const { body, params, validationError } = request;
   const { orgSlug: sourceOrgSlug, repoSlug: sourceRepoSlug } = params;
-
   const {
     target_org_slug: targetOrgSlug,
     target_repo_slug: targetRepoSlug,

...
@@ -77,8 +76,7 @@ const postRepositoryForkAction: ReqHandler<
       sourceParentOrg,
       sourceRepo,
       errorMessage,
-      initialValues:
-        body as AppRouteParams[AppRoute.REPOSITORY_FORK_ACTION]["body"],
+      initialValues: body,
     });
   }
 

...
@@ -112,8 +110,7 @@ const postRepositoryForkAction: ReqHandler<
       sourceParentOrg,
       sourceRepo,
       errorMessage: (err as Error).message,
-      initialValues:
-        body as AppRouteParams[AppRoute.REPOSITORY_FORK_ACTION]["body"],
+      initialValues: body,
     });
   }
 };

@@ -1,5 +1,3 @@
-// 1st-party
-import type { IRouteParams } from "@ethicdevs/react-monolith";
 // 3rd-party
 import type { FastifySchema } from "fastify";
 // generated via script[generate:prisma]

...
@@ -94,7 +92,8 @@ export const AppRoutePaths: Record<AppRoute, string> = {
   [AppRoute.USER_DETAILS]: "/@:username",
 };
 
-export interface AppRouteParams extends IRouteParams {
+export interface AppRouteParams {
+  [x: string]: any;
   [AppRoute.HOME]: undefined;
   [AppRoute.THEME_SET_SCHEME_ACTION]: {
     params: {

@@ -1,9 +1,22 @@
 // 1st-party
-import { AppRouter, AppRouterGroup, Router } from "@ethicdevs/react-monolith";
+import {
+  AppRouter,
+  AppRouterGroup,
+  AppRouterRoot,
+  AppRouterRoute,
+  AppRouterRouteGroup,
+  IRouteParams,
+  Router,
+} from "@ethicdevs/react-monolith";
 // 3rd-party
 import React from "react";
 // app
-import { AppRoute, AppRoutePaths, AppRouteSchemas } from "./routes.defs";
+import {
+  AppRoute,
+  AppRouteParams,
+  AppRoutePaths,
+  AppRouteSchemas,
+} from "./routes.defs";
 import { authenticatedOrLogin, guestOrRedirect } from "./utils/server";
 // app controllers
 import {

...
@@ -17,17 +30,27 @@ import {
   UserController,
 } from "./controllers";
 
-const RootAppRouter: AppRouter = () => {
+function getTypedRouter<RoutesParams extends IRouteParams = IRouteParams>() {
+  return {
+    Root: Router.Root as AppRouterRoot<RoutesParams>,
+    Group: Router.Group as AppRouterRouteGroup<RoutesParams>,
+    Route: Router.Route as AppRouterRoute<RoutesParams>,
+  };
+}
+
+const RootAppRouter: AppRouter<AppRouteParams> = () => {
   const loggedOrLoginRedirect = authenticatedOrLogin();
   const guestOrDashboardRedirect = guestOrRedirect(
     AppRoutePaths[AppRoute.USER_DASHBOARD]
   );
 
+  const { Root, Group, Route } = getTypedRouter<AppRouteParams>();
+
   return (
-    <Router.Root>
+    <Root>
       <></>
-      <Router.Group type={AppRouterGroup.API}>
-        <Router.Route
+      <Group type={AppRouterGroup.API}>
+        <Route
           name={AppRoute.THEME_SET_SCHEME_ACTION}
           method={"GET"}
           path={AppRoutePaths[AppRoute.THEME_SET_SCHEME_ACTION]}

...
@@ -35,7 +58,7 @@ const RootAppRouter: AppRouter = () => {
           handler={ThemeController.setThemeSchemeAction}
         />
         {/* --- */}
-        <Router.Route
+        <Route
           name={AppRoute.HOME}
           method={"GET"}
           path={AppRoutePaths[AppRoute.HOME]}

...
@@ -43,14 +66,14 @@ const RootAppRouter: AppRouter = () => {
           handler={HomeController.getHomeView}
         />
         {/* --- */}
-        <Router.Route
+        <Route
           name={AppRoute.AUTH_REGISTER}
           method={"GET"}
           path={AppRoutePaths[AppRoute.AUTH_REGISTER]}
           preHandler={guestOrDashboardRedirect}
           handler={AuthController.getRegisterView}
         />
-        <Router.Route
+        <Route
           name={AppRoute.AUTH_REGISTER_ACTION}
           method={"POST"}
           path={AppRoutePaths[AppRoute.AUTH_REGISTER_ACTION]}

...
@@ -59,7 +82,7 @@ const RootAppRouter: AppRouter = () => {
           handler={AuthController.postRegisterAction}
         />
         {/* --- */}
-        <Router.Route
+        <Route
           name={AppRoute.AUTH_LOGIN}
           method={"GET"}
           path={AppRoutePaths[AppRoute.AUTH_LOGIN]}

...
@@ -67,7 +90,7 @@ const RootAppRouter: AppRouter = () => {
           schema={AppRouteSchemas[AppRoute.AUTH_LOGIN]}
           handler={AuthController.getLoginView}
         />
-        <Router.Route
+        <Route
           name={AppRoute.AUTH_LOGIN_ACTION}
           method={"POST"}
           path={AppRoutePaths[AppRoute.AUTH_LOGIN_ACTION]}

...
@@ -75,7 +98,7 @@ const RootAppRouter: AppRouter = () => {
           schema={AppRouteSchemas[AppRoute.AUTH_LOGIN_ACTION]}
           handler={AuthController.postLoginAction}
         />
-        <Router.Route
+        <Route
           name={AppRoute.AUTH_LOGOUT_ACTION}
           method={"GET"}
           path={AppRoutePaths[AppRoute.AUTH_LOGOUT_ACTION]}

...
@@ -84,21 +107,21 @@ const RootAppRouter: AppRouter = () => {
           handler={AuthController.getLogoutAction}
         />
         {/* --- */}
-        <Router.Route
+        <Route
           name={AppRoute.USER_DASHBOARD}
           method={"GET"}
           path={AppRoutePaths[AppRoute.USER_DASHBOARD]}
           preHandler={loggedOrLoginRedirect}
           handler={UserController.getUserDashboardView}
         />
-        <Router.Route
+        <Route
           name={AppRoute.USER_DETAILS}
           method={"GET"}
           path={AppRoutePaths[AppRoute.USER_DETAILS]}
           handler={UserController.getUserDetailsView}
         />
         {/* --- */}
-        <Router.Route
+        <Route
           name={AppRoute.ORGANIZATION_DETAILS}
           method={"GET"}
           path={AppRoutePaths[AppRoute.ORGANIZATION_DETAILS]}

...
@@ -106,42 +129,42 @@ const RootAppRouter: AppRouter = () => {
           handler={OrganizationController.getOrganizationDetailsView}
         />
         {/* --- */}
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_BROWSER}
           method={"GET"}
           path={AppRoutePaths[AppRoute.REPOSITORY_BROWSER]}
           schema={AppRouteSchemas[AppRoute.REPOSITORY_BROWSER]}
           handler={RepositoryController.getRepositoryBrowserView}
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_BROWSER_WITH_PATH}
           method={"GET"}
           path={AppRoutePaths[AppRoute.REPOSITORY_BROWSER_WITH_PATH]}
           schema={AppRouteSchemas[AppRoute.REPOSITORY_BROWSER]}
           handler={RepositoryController.getRepositoryBrowserView}
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_COMMITS_LOG}
           method={"GET"}
           path={AppRoutePaths[AppRoute.REPOSITORY_COMMITS_LOG]}
           schema={AppRouteSchemas[AppRoute.REPOSITORY_COMMITS_LOG]}
           handler={RepositoryController.getRepositoryCommitsLogView}
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_COMPARE}
           method={"GET"}
           path={AppRoutePaths[AppRoute.REPOSITORY_COMPARE]}
           schema={AppRouteSchemas[AppRoute.REPOSITORY_COMPARE]}
           handler={RepositoryController.getRepositoryCompareView}
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_CREATE}
           method={"GET"}
           path={AppRoutePaths[AppRoute.REPOSITORY_CREATE]}
           preHandler={loggedOrLoginRedirect}
           handler={RepositoryController.getRepositoryCreateView}
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_CREATE_ACTION}
           method={"POST"}
           path={AppRoutePaths[AppRoute.REPOSITORY_CREATE_ACTION]}

...
@@ -149,41 +172,41 @@ const RootAppRouter: AppRouter = () => {
           schema={AppRouteSchemas[AppRoute.REPOSITORY_CREATE_ACTION]}
           handler={RepositoryController.postRepositoryCreateAction}
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_DETAILS}
           method={"GET"}
           path={AppRoutePaths[AppRoute.REPOSITORY_DETAILS]}
           schema={AppRouteSchemas[AppRoute.REPOSITORY_DETAILS]}
           handler={RepositoryController.getRepositoryDetailsView}
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_DETAILS_WITH_TRAILING_SLASH}
           method={"GET"}
           path={AppRoutePaths[AppRoute.REPOSITORY_DETAILS_WITH_TRAILING_SLASH]}
           schema={AppRouteSchemas[AppRoute.REPOSITORY_DETAILS]}
           handler={RepositoryController.getRepositoryDetailsView}
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_EXPLORE}
           method={"GET"}
           path={AppRoutePaths[AppRoute.REPOSITORY_EXPLORE]}
           handler={RepositoryController.getRepositoryExploreView}
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_FORK}
           method={"GET"}
           path={AppRoutePaths[AppRoute.REPOSITORY_FORK]}
           preHandler={loggedOrLoginRedirect}
           handler={RepositoryController.getRepositoryForkView}
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_FORK_ACTION}
           method={"POST"}
           path={AppRoutePaths[AppRoute.REPOSITORY_FORK_ACTION]}
           preHandler={loggedOrLoginRedirect}
           handler={RepositoryController.postRepositoryForkAction}
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_PULL_REQUEST_CLOSE_ACTION}
           method={"POST"}
           path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUEST_CLOSE_ACTION]}

...
@@ -195,7 +218,7 @@ const RootAppRouter: AppRouter = () => {
             RepositoryPullRequestsController.getRepositoryPullRequestCloseAction
           }
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_CREATE_ACTION}
           method={"POST"}
           path={

...
@@ -213,7 +236,7 @@ const RootAppRouter: AppRouter = () => {
             RepositoryPullRequestsController.getRepositoryPullRequestCommentCreateAction
           }
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_DELETE_ACTION}
           method={"POST"}
           path={

...
@@ -231,7 +254,7 @@ const RootAppRouter: AppRouter = () => {
             RepositoryPullRequestsController.getRepositoryPullRequestCommentDeleteAction
           }
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_UPDATE_ACTION}
           method={"POST"}
           path={

...
@@ -249,7 +272,7 @@ const RootAppRouter: AppRouter = () => {
             RepositoryPullRequestsController.getRepositoryPullRequestCommentUpdateAction
           }
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_PULL_REQUEST_CREATE}
           method={"GET"}
           path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUEST_CREATE]}

...
@@ -259,7 +282,7 @@ const RootAppRouter: AppRouter = () => {
             RepositoryPullRequestsController.getRepositoryPullRequestCreateView
           }
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION}
           method={"POST"}
           path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION]}

...
@@ -271,7 +294,7 @@ const RootAppRouter: AppRouter = () => {
             RepositoryPullRequestsController.postRepositoryPullRequestCreateAction
           }
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_PULL_REQUEST_DELETE_ACTION}
           method={"POST"}
           path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUEST_DELETE_ACTION]}

...
@@ -283,7 +306,7 @@ const RootAppRouter: AppRouter = () => {
             RepositoryPullRequestsController.getRepositoryPullRequestDeleteAction
           }
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_PULL_REQUEST_DETAILS}
           method={"GET"}
           path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUEST_DETAILS]}

...
@@ -293,7 +316,7 @@ const RootAppRouter: AppRouter = () => {
             RepositoryPullRequestsController.getRepositoryPullRequestDetailsView
           }
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION}
           method={"POST"}
           path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION]}

...
@@ -305,7 +328,7 @@ const RootAppRouter: AppRouter = () => {
             RepositoryPullRequestsController.postRepositoryPullRequestMergeAction
           }
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION}
           method={"POST"}
           path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION]}

...
@@ -317,7 +340,7 @@ const RootAppRouter: AppRouter = () => {
             RepositoryPullRequestsController.getRepositoryPullRequestUpdateAction
           }
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_PULL_REQUESTS}
           method={"GET"}
           path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUESTS]}

...
@@ -326,7 +349,7 @@ const RootAppRouter: AppRouter = () => {
             RepositoryPullRequestsController.getRepositoryPullRequestsView
           }
         />
-        <Router.Route
+        <Route
           name={AppRoute.REPOSITORY_SHOW_OBJECT}
           method={"GET"}
           path={AppRoutePaths[AppRoute.REPOSITORY_SHOW_OBJECT]}

...
@@ -334,7 +357,7 @@ const RootAppRouter: AppRouter = () => {
           handler={RepositoryController.getRepositoryShowObjectView}
         />
         {/* --- */}
-        <Router.Route
+        <Route
           name={AppRoute.SYNTAX_HIGHLIGHT_HIGHLIGHT_CODE_ACTION}
           method={"POST"}
           path={AppRoutePaths[AppRoute.SYNTAX_HIGHLIGHT_HIGHLIGHT_CODE_ACTION]}

...
@@ -343,8 +366,8 @@ const RootAppRouter: AppRouter = () => {
           }
           handler={SyntaxHighlightController.highlightCodeAction}
         />
-      </Router.Group>
-    </Router.Root>
+      </Group>
+    </Root>
   );
 };
 

@@ -1,5 +1,5 @@
 // 1st-party
-import { InMemoryCacheAdapter } from "@ethicdevs/fastify-stream-react-views";
+// import { InMemoryCacheAdapter } from "@ethicdevs/fastify-stream-react-views";
 import {
   AppServer,
   makeAppServer,

...
@@ -69,9 +69,9 @@ async function main(): Promise<AppServer> {
       depsFolder: Paths.ASSET_DEPS_FOLDER_NAME,
       importPrefix: publicBaseUrl,
     },
-    cacheAdapter: new InMemoryCacheAdapter({
-      maxSize: Const.SSR_CACHE_MAX_SIZE_BYTES,
-    }),
+    // cacheAdapter: new InMemoryCacheAdapter({
+    //   maxSize: Const.SSR_CACHE_MAX_SIZE_BYTES,
+    // }),
     featureFlags: {
       withIncrementalBuild: true,
       withImportsMap: true,

app/services/repository/getRepositoryCommitLog.ts
@@ -58,14 +58,14 @@ const makeGetRepositoryCommitLog: ServiceMethodFactory<
       path != null && path.trim() !== "" ? `${path}` : null,
     ].filter((x): x is string => x != null);
 
-    const gitLogProcess = spawn("git", args, {
-      cwd: repoPath,
-      env: {
-        LANG: "C",
-      },
-    });
-
     try {
+      const gitLogProcess = spawn("git", args, {
+        cwd: repoPath,
+        env: {
+          LANG: "C",
+        },
+      });
+
       const gitLogResult = await new Promise<RepositoryLog[]>(
         (resolve, reject) => {
           let buffer = [] as string[];

@@ -1,6 +1,6 @@
 version: "3"
 services:
-  gitfoss_db:
+  db:
     container_name: gitfoss_db
     image: postgres:14
     environment:

...
@@ -11,23 +11,24 @@ services:
     volumes:
       - ./data/postgres_data:/var/lib/postgresql/data
   web:
+    container_name: gitfoss_web
     build:
       context: .
       dockerfile: Dockerfile
       args:
         - HOST=0.0.0.0
         - PORT=1337
-    container_name: gitfoss_web
     depends_on:
-      - gitfoss_db
-    environment:
-      - COOKIE_NAME=gitfoss_ssid
-      - COOKIE_SECRET=gitfoss-cookie-secret
-      - DATABASE_URL=postgresql://postgres:postgres@gitfoss_db:5432/gitfoss_local?sslmode=disable&connection_limit=3
-      - DEPLOYMENT_DOMAIN=local-app.localhost
-      - DEPLOYMENT_SCHEME=http
-      - GIT_REPOSITORIES_ROOT=/var/lib/gitfoss/repos
+      - db
     ports:
       - 1337:1337
     volumes:
       - ./data/gitfoss_repos:/var/lib/gitfoss/repos
+    env_file: .env.local
+    # environment:
+    #   - COOKIE_NAME=gitfoss_ssid
+    #   - COOKIE_SECRET=gitfoss-cookie-secret
+    #   - DATABASE_URL=postgresql://postgres:postgres@gitfoss_db:5432/gitfoss_local?sslmode=disable&connection_limit=3
+    #   - DEPLOYMENT_DOMAIN=local-app.localhost
+    #   - DEPLOYMENT_SCHEME=http
+    #   - GIT_REPOSITORIES_ROOT=/var/lib/gitfoss/repos

@@ -31,7 +31,7 @@
     "@ethicdevs/fastify-custom-session": "^0.6.0",
     "@ethicdevs/fastify-git-server": "^1.6.1",
     "@ethicdevs/fastify-stream-react-views": "^1.11.3",
-    "@ethicdevs/react-monolith": "^1.9.8",
+    "@ethicdevs/react-monolith": "^1.9.12",
     "@fastify/cookie": "6.0.0",
     "@fastify/formbody": "6.0.0",
     "@prisma/client": "^4.9.0",

new file
public/instant-router.js.old
@@ -0,0 +1,421 @@
+/* InstantRouter */var __defProp = Object.defineProperty;
+var __defProps = Object.defineProperties;
+var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
+var __getOwnPropSymbols = Object.getOwnPropertySymbols;
+var __hasOwnProp = Object.prototype.hasOwnProperty;
+var __propIsEnum = Object.prototype.propertyIsEnumerable;
+
+var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
+  enumerable: true,
+  configurable: true,
+  writable: true,
+  value
+}) : obj[key] = value;
+
+var __spreadValues = (a, b) => {
+  for (var prop in b || (b = {})) if (__hasOwnProp.call(b, prop)) __defNormalProp(a, prop, b[prop]);
+
+  if (__getOwnPropSymbols) for (var prop of __getOwnPropSymbols(b)) {
+    if (__propIsEnum.call(b, prop)) __defNormalProp(a, prop, b[prop]);
+  }
+  return a;
+};
+
+var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
+
+var __name = (target, value) => __defProp(target, "name", {
+  value,
+  configurable: true
+});
+
+var __async = (__this, __arguments, generator) => {
+  return new Promise((resolve, reject) => {
+    var fulfilled = value => {
+      try {
+        step(generator.next(value));
+      } catch (e) {
+        reject(e);
+      }
+    };
+
+    var rejected = value => {
+      try {
+        step(generator.throw(value));
+      } catch (e) {
+        reject(e);
+      }
+    };
+
+    var step = x => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
+
+    step((generator = generator.apply(__this, __arguments)).next());
+  });
+}; // node_modules/@ethicdevs/react-monolith/dist/core/instant-router.js
+
+
+var domParser = new DOMParser();
+
+function fetchAnchorHref(anchorHref, currentLocationHref, method = "get", body = void 0, headers = void 0) {
+  return __async(this, null, function* () {
+    const url = method.toLowerCase() === "get" && body != null ? `${anchorHref}?${body}` : anchorHref;
+    const res = yield fetch(url, {
+      method,
+      body: method.toLowerCase() !== "get" ? body : void 0,
+      headers: __spreadProps(__spreadValues(__spreadValues({}, headers || {}), anchorHref !== currentLocationHref ? {
+        referer: currentLocationHref
+      } : {}), {
+        accept: "text/html",
+        "accept-charset": "utf-8",
+        "x-requested-with": "XMLHttpRequest"
+      })
+    });
+    return res;
+  });
+}
+
+__name(fetchAnchorHref, "fetchAnchorHref");
+
+function fetchAndPushState(targetHref, refererHref, method = "get", body = void 0, headers = void 0, withAutoScroll = true) {
+  return __async(this, null, function* () {
+    let targetHtml = null;
+
+    try {
+      document.dispatchEvent(new CustomEvent(ClientSideRouterEvents.LOADING, {
+        detail: {
+          request: {
+            method,
+            url: targetHref,
+            body,
+            headers,
+            referer: refererHref
+          }
+        }
+      }));
+      let res = yield fetchAnchorHref(targetHref, refererHref, method, body, headers);
+
+      if (res.status >= 301 && res.status <= 308) {
+        const locationHeaderHref = res.headers.get("location");
+
+        if (locationHeaderHref != null) {
+          targetHref = locationHeaderHref;
+          res = yield fetchAnchorHref(targetHref, refererHref, method, body, headers);
+        }
+      } else {
+        targetHtml = yield res.text();
+        targetHref = res.url;
+      }
+
+      document.dispatchEvent(new CustomEvent(ClientSideRouterEvents.LOADED, {
+        detail: {
+          request: {
+            method,
+            url: targetHref,
+            body,
+            headers,
+            referer: refererHref
+          },
+          response: {
+            html: targetHtml
+          }
+        }
+      }));
+    } catch (err) {
+      const error = err;
+      document.dispatchEvent(new CustomEvent(ClientSideRouterEvents.LOAD_ERROR, {
+        detail: {
+          request: {
+            method,
+            url: targetHref,
+            body,
+            headers,
+            referer: refererHref
+          },
+          response: {
+            error
+          }
+        }
+      }));
+    }
+
+    if (targetHtml == null) {
+      document.dispatchEvent(new CustomEvent(ClientSideRouterEvents.LOAD_ERROR, {
+        detail: {
+          request: {
+            method,
+            url: targetHref,
+            body,
+            headers,
+            referer: refererHref
+          },
+          response: {
+            error: new Error("Could not retrieve HTML to display, it was null.")
+          }
+        }
+      }));
+      return () => void 0;
+    }
+
+    const targetDoc = domParser.parseFromString(targetHtml, "text/html");
+    const {
+      body: targetBody,
+      head: targetHead,
+      title: targetTitle
+    } = targetDoc;
+    const targetStyles = [];
+    targetHead.childNodes.forEach(node => {
+      if (node.nodeType === 1 && node.nodeName.toLowerCase() === "style") {
+        targetStyles.push(node);
+      }
+    });
+    return () => {
+      var _a;
+
+      try {
+        document.dispatchEvent(new CustomEvent(ClientSideRouterEvents.NAVIGATING, {
+          detail: {
+            request: {
+              url: targetHref,
+              referer: refererHref,
+              body: targetBody,
+              head: targetHead,
+              title: targetTitle
+            }
+          }
+        }));
+        document.title = targetTitle;
+        document.body.innerHTML = targetBody.innerHTML || document.body.innerHTML;
+
+        if (document.scrollingElement != null && withAutoScroll === true) {
+          document.scrollingElement.scrollTo({
+            behavior: "smooth",
+            top: 0
+          });
+        }
+
+        if (typeof window.history !== "undefined" && targetHref !== ((_a = history.state) === null || _a === void 0 ? void 0 : _a.targetHref) && targetHref !== refererHref) {
+          const targetUrl = new URL(targetHref);
+          window.history.pushState({
+            targetHref
+          }, "", method.toLowerCase() === "get" && body != null ? [targetUrl.pathname, body].join("?") : targetUrl.pathname);
+        }
+
+        document.dispatchEvent(new CustomEvent(ClientSideRouterEvents.NAVIGATED, {
+          detail: {
+            request: {
+              url: targetHref,
+              referer: refererHref,
+              body: targetBody,
+              head: targetHead,
+              title: targetTitle
+            },
+            response: true
+          }
+        }));
+      } catch (err) {
+        const error = err;
+        document.dispatchEvent(new CustomEvent(ClientSideRouterEvents.NAVIGATION_ERROR, {
+          detail: {
+            request: {
+              url: targetHref,
+              referer: refererHref,
+              body: targetBody,
+              head: targetHead,
+              title: targetTitle
+            },
+            response: {
+              error
+            }
+          }
+        }));
+      }
+    };
+  });
+}
+
+__name(fetchAndPushState, "fetchAndPushState");
+
+function clientSideRouter() {
+  return __async(this, arguments, function* (opts = {
+    fetchAnchorsOn: "mousedown"
+  }) {
+    const pageHref = window.location.href;
+
+    function onClientSideRouterMouseDown(ev) {
+      return __async(this, null, function* () {
+        const targetEl = ev.target;
+
+        if (ev == null || ev.button !== 0 || targetEl == null || targetEl.tagName.toLowerCase() !== "a" || "href" in targetEl === false || targetEl.href == null || targetEl.href.trim() === "") {
+          return false;
+        }
+
+        const targetDataset = targetEl.dataset;
+        const baseUrl = new URL(document.baseURI);
+        const targetUrl = new URL(targetEl.href, document.baseURI);
+        const isExternalUrl = baseUrl.origin !== targetUrl.origin;
+
+        if (isExternalUrl || targetDataset["externalLink"] === "true") {
+          return false;
+        }
+
+        const targetHash = targetUrl.hash;
+        const isHashChange = !!(targetHash != null && targetHash.trim() !== "" && targetHash.startsWith("#"));
+
+        if (isHashChange) {
+          const hashEl = document.querySelector(targetHash);
+
+          if (hashEl != null) {
+            ev.preventDefault();
+
+            if (targetDataset["smoothScroll"] !== "disabled") {
+              hashEl.scrollIntoView({
+                behavior: "smooth"
+              });
+            }
+
+            window.location.hash = targetHash;
+            return true;
+          }
+
+          return false;
+        }
+
+        let doNavigate = null;
+        let pollWaitFetchDoneIntervalId = null;
+
+        const navigateOrWait = /* @__PURE__ */__name(() => {
+          if (doNavigate != null) {
+            doNavigate();
+
+            if (pollWaitFetchDoneIntervalId != null) {
+              clearTimeout(pollWaitFetchDoneIntervalId);
+              pollWaitFetchDoneIntervalId = null;
+            }
+
+            if (targetEl != null && onClickHandler != null) {
+              targetEl.removeEventListener("click", onClickHandler);
+              onClickHandler = null;
+            }
+          } else {
+            pollWaitFetchDoneIntervalId = setTimeout(() => {
+              if (pollWaitFetchDoneIntervalId != null) {
+                clearTimeout(pollWaitFetchDoneIntervalId);
+                pollWaitFetchDoneIntervalId = null;
+              }
+
+              navigateOrWait();
+            }, 10);
+          }
+        }, "navigateOrWait");
+
+        let onClickHandler = /* @__PURE__ */__name(subEv => {
+          subEv.preventDefault();
+          navigateOrWait();
+          return true;
+        }, "onClickHandler");
+
+        try {
+          targetEl.addEventListener("click", onClickHandler);
+          doNavigate = yield fetchAndPushState(targetEl.href, pageHref, void 0, void 0, void 0, targetDataset["smoothScroll"] !== "disabled");
+        } catch (_) {
+          targetEl.removeEventListener("click", onClickHandler);
+          onClickHandler = null;
+          doNavigate = /* @__PURE__ */__name(() => {
+            window.location.href = targetEl.href;
+          }, "doNavigate");
+        }
+
+        return true;
+      });
+    }
+
+    __name(onClientSideRouterMouseDown, "onClientSideRouterMouseDown");
+
+    function onClientSideRouterSubmit(ev) {
+      return __async(this, null, function* () {
+        const targetEl = ev.target;
+
+        if (targetEl == null || targetEl.tagName.toLowerCase() !== "form") {
+          return false;
+        }
+
+        const targetAction = targetEl.action;
+        const targetMethod = targetEl.method;
+
+        if (targetAction == null || targetAction.trim() === "" || targetMethod == null || ["get", "post"].includes(targetMethod.toLowerCase()) === false) {
+          return false;
+        }
+
+        ev.preventDefault();
+        const headers = {
+          "content-type": "application/x-www-form-urlencoded"
+        };
+        const targetFormData = new FormData(targetEl);
+        let targetFormDataEntries = {};
+        targetFormData.forEach((v, k) => {
+          targetFormDataEntries = __spreadProps(__spreadValues({}, targetFormDataEntries), {
+            [k]: v
+          });
+        });
+        const bodyFormEncoded = Object.entries(targetFormDataEntries).map(([k, v]) => `${k}=${v}`).join("&");
+
+        let doNavigate = /* @__PURE__ */__name(() => {
+          window.location.href = targetAction;
+        }, "doNavigate");
+
+        try {
+          doNavigate = yield fetchAndPushState(targetAction, pageHref, targetMethod, bodyFormEncoded, headers);
+        } catch (_) {}
+
+        doNavigate();
+        return true;
+      });
+    }
+
+    __name(onClientSideRouterSubmit, "onClientSideRouterSubmit");
+
+    document.addEventListener(opts.fetchAnchorsOn, onClientSideRouterMouseDown);
+    document.addEventListener("submit", onClientSideRouterSubmit);
+    window.addEventListener("popstate", event => setTimeout(() => __async(this, null, function* () {
+      if (event.state) {
+        if (event.state.targetHref != null) {
+          let doNavigate = /* @__PURE__ */__name(() => {
+            window.location.href = event.state.targetHref;
+          }, "doNavigate");
+
+          try {
+            doNavigate = yield fetchAndPushState(event.state.targetHref, pageHref, void 0, void 0, void 0, false);
+          } catch (_) {}
+
+          doNavigate();
+          return true;
+        }
+
+        return false;
+      } else {
+        return false;
+      }
+    }), 0));
+  });
+}
+
+__name(clientSideRouter, "clientSideRouter");
+
+var ClientSideRouterEventPrefix = `instantroute_`;
+var ClientSideRouterEvents = {
+  LOADING: `${ClientSideRouterEventPrefix}loading`,
+  LOADED: `${ClientSideRouterEventPrefix}loaded`,
+  LOAD_ERROR: `${ClientSideRouterEventPrefix}load_error`,
+  NAVIGATING: `${ClientSideRouterEventPrefix}navigating`,
+  NAVIGATED: `${ClientSideRouterEventPrefix}navigated`,
+  NAVIGATION_ERROR: `${ClientSideRouterEventPrefix}navigation_error`
+};
+window.location["hardReplace"] = window.location.replace;
+window.location.replace = /* @__PURE__ */__name(function replace(url) {
+  const pageHref = window.location.href;
+  fetchAndPushState(url.toString(), pageHref).then(doNavigate => doNavigate()).catch(() => {
+    window.location["hardReplace"](url.toString());
+  });
+}, "replace");
+clientSideRouter({
+  fetchAnchorsOn: "mousedown"
+});

@@ -346,10 +346,10 @@
     terser "^5.14.1"
     transform-modules-eumd "^1.0.0"
 
-"@ethicdevs/react-monolith@^1.9.8":
-  version "1.9.8"
-  resolved "https://registry.yarnpkg.com/@ethicdevs/react-monolith/-/react-monolith-1.9.8.tgz#b34979df052066aef8672b5127ec98777999b2d4"
-  integrity sha512-iwiAz550lyaOB0N1sB4V7WQY69NSWFXDimvQI5Xx4B53EhhbI67TQ2asbDuG6e7+b724a04Njuo9lVLdeCFMvA==
+"@ethicdevs/react-monolith@^1.9.12":
+  version "1.9.12"
+  resolved "https://registry.yarnpkg.com/@ethicdevs/react-monolith/-/react-monolith-1.9.12.tgz#4239336cbd000c0bf8e53be2a9dbc6b8b01b7f56"
+  integrity sha512-pdnbTWsuX/0JjKMorVFArFDMclx0YrpQ0kcUDWaKsKjrr6NQDdmEU/8JkWWWf8wW/VBmnHiOOWR6a8lMiHPTWg==
   dependencies:
     deepest-merge "^1.0.0"
     react-ssr-prepass "^1.5.0"