GitFOSS
~app/routes.tsx
.ts
TypeScript
(application/typescript)
// 1st-party
import type { IRouteParams } from "@ethicdevs/react-monolith";
import { AppRouter, AppRouterGroup, Router } from "@ethicdevs/react-monolith";
// 3rd-party
import { FastifySchema } from "fastify";
import React from "react";
// app
import { authenticatedOrLogin, guestOrRedirect } from "./utils/server";
// app controllers
import { AuthController } from "./controllers/auth";
import { RepositoryController } from "./controllers/repository";
import * as HomeController from "./controllers/HomeController";
import * as ThemeController from "./controllers/ThemeController";

export enum AppRoute {
  HOME = "home",
  SET_THEME = "set_theme.action",
  AUTH_REGISTER = "auth.register",
  AUTH_REGISTER_ACTION = "auth.register.action",
  AUTH_LOGIN = "auth.login",
  AUTH_LOGIN_ACTION = "auth.login.action",
  USER_DASHBOARD = "user.dashboard",
  REPOSITORY_EXPLORE = "repository.explore",
}

export interface AppRoutesParams extends IRouteParams {
  [AppRoute.HOME]: undefined;
  [AppRoute.SET_THEME]: {
    themeScheme: string;
  };
  [AppRoute.AUTH_REGISTER]: undefined;
  [AppRoute.AUTH_REGISTER_ACTION]: {
    body: {
      email_address: string;
      username: string;
      password: string;
    };
  };
  [AppRoute.AUTH_LOGIN]: undefined;
  [AppRoute.AUTH_LOGIN_ACTION]: {
    body: {
      email_address: string;
      password: string;
    };
  };
  [AppRoute.USER_DASHBOARD]: undefined;
  [AppRoute.REPOSITORY_EXPLORE]: undefined;
}

export const AppRoutesSchemas: Record<AppRoute, undefined | FastifySchema> = {
  [AppRoute.HOME]: undefined,
  [AppRoute.SET_THEME]: {
    params: {
      type: "object",
      required: ["themeScheme"],
      additionalProperties: false,
      properties: {
        themeScheme: {
          type: "string",
          enum: ["light", "dark"],
        },
      },
    },
  },
  [AppRoute.AUTH_REGISTER]: undefined,
  [AppRoute.AUTH_REGISTER_ACTION]: {
    body: {
      type: "object",
      required: ["email_address", "username", "password"],
      additionalProperties: false,
      properties: {
        email_address: { type: "string" },
        username: { type: "string" },
        password: { type: "string" },
      },
    },
  },
  [AppRoute.AUTH_LOGIN]: undefined,
  [AppRoute.AUTH_LOGIN_ACTION]: {
    body: {
      type: "object",
      required: ["email_address", "password"],
      additionalProperties: false,
      properties: {
        email_address: { type: "string" },
        password: { type: "string" },
      },
    },
  },
  [AppRoute.USER_DASHBOARD]: undefined,
  [AppRoute.REPOSITORY_EXPLORE]: undefined,
};

const RootAppRouter: AppRouter = () => {
  const guestOrDashboardRedirect = guestOrRedirect("/dashboard");
  return (
    <Router.Root>
      <></>
      <Router.Group type={AppRouterGroup.API}>
        <Router.Route
          name={AppRoute.SET_THEME}
          method={"GET"}
          path={"/theme/:themeScheme"}
          schema={AppRoutesSchemas[AppRoute.SET_THEME]}
          handler={ThemeController.getTheme}
        />
        {/* --- */}
        <Router.Route
          name={AppRoute.HOME}
          method={"GET"}
          path={"/"}
          preHandler={guestOrDashboardRedirect}
          handler={HomeController.getHomeView}
        />
        {/* --- */}
        <Router.Route
          name={AppRoute.AUTH_REGISTER}
          method={"GET"}
          path={"/auth/register"}
          preHandler={guestOrDashboardRedirect}
          handler={AuthController.getRegisterView}
        />
        <Router.Route
          name={AppRoute.AUTH_REGISTER_ACTION}
          method={"POST"}
          path={"/auth/register"}
          schema={AppRoutesSchemas[AppRoute.AUTH_REGISTER_ACTION]}
          preHandler={guestOrDashboardRedirect}
          handler={AuthController.postRegisterAction}
        />
        {/* --- */}
        <Router.Route
          name={AppRoute.AUTH_LOGIN}
          method={"GET"}
          path={"/auth/login"}
          preHandler={guestOrDashboardRedirect}
          handler={AuthController.getLoginView}
        />
        <Router.Route
          name={AppRoute.AUTH_LOGIN_ACTION}
          method={"POST"}
          path={"/auth/login"}
          schema={AppRoutesSchemas[AppRoute.AUTH_LOGIN_ACTION]}
          preHandler={guestOrDashboardRedirect}
          handler={AuthController.postLoginAction}
        />
        {/* --- */}
        <Router.Route
          name={AppRoute.USER_DASHBOARD}
          method={"GET"}
          path={"/dashboard"}
          preHandler={authenticatedOrLogin()}
          handler={AuthController.getDashboardView}
        />
        {/* --- */}
        <Router.Route
          name={AppRoute.REPOSITORY_EXPLORE}
          method={"GET"}
          path={"/repositories/explore"}
          preHandler={authenticatedOrLogin()}
          handler={RepositoryController.getRepositoryExploreView}
        />
      </Router.Group>
    </Router.Root>
  );
};

export default RootAppRouter;