~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 type { FastifySchema } from "fastify";
import React from "react";
// generated via script[generate:prisma]
import { ResourceVisibility } from "@prisma/client";
// app
import { authenticatedOrLogin, guestOrRedirect } from "./utils/server";
// app controllers
import { AuthController } from "./controllers/auth";
import { OrganizationController } from "./controllers/organization";
import { RepositoryController } from "./controllers/repository";
import { UserController } from "./controllers/user";
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",
  AUTH_LOGOUT_ACTION = "auth.logout.action",
  USER_DASHBOARD = "user.dashboard",
  USER_DETAILS = "user.details",
  ORGANIZATION_DETAILS = "organization.details",
  REPOSITORY_BROWSER = "repository.browser",
  REPOSITORY_COMMITS_LOG = "repository.commits_log",
  REPOSITORY_COMPARE = "repository.compare",
  REPOSITORY_CREATE = "repository.create",
  REPOSITORY_CREATE_ACTION = "repository.create.action",
  REPOSITORY_DETAILS = "repository.details",
  REPOSITORY_EXPLORE = "repository.explore",
  REPOSITORY_FORK = "repository.fork",
  REPOSITORY_FORK_ACTION = "repository.fork.action",
  REPOSITORY_PULL_REQUESTS = "repository.pull_requests",
  REPOSITORY_SHOW_OBJECT = "repository.show_object",
}

export interface AppRoutesParams extends IRouteParams {
  [AppRoute.HOME]: undefined;
  [AppRoute.SET_THEME]: {
    params: {
      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.AUTH_LOGOUT_ACTION]: undefined;
  [AppRoute.USER_DASHBOARD]: undefined;
  [AppRoute.USER_DETAILS]: {
    params: {
      username: string;
    };
  };
  [AppRoute.ORGANIZATION_DETAILS]: {
    params: {
      orgSlug: string;
    };
  };
  [AppRoute.REPOSITORY_BROWSER]: {
    params: {
      orgSlug: string;
      repoSlug: string;
      currentRef: string;
      "*": string;
    };
  };
  [AppRoute.REPOSITORY_COMMITS_LOG]: {
    params: {
      orgSlug: string;
      repoSlug: string;
      currentRef: string;
    };
  };
  [AppRoute.REPOSITORY_COMPARE]: {
    params: {
      orgSlug: string;
      repoSlug: string;
      refA: string;
      refB: string;
    };
  };
  [AppRoute.REPOSITORY_CREATE]: undefined;
  [AppRoute.REPOSITORY_CREATE_ACTION]: {
    body: {
      parent_org_slug: string;
      repo_display_name: string;
      repo_init_license_file: "on" | "off";
      repo_init_license_kind: string;
      repo_init_readme_file: "on" | "off";
      repo_keywords: string;
      repo_keywords_add: string;
      repo_short_description: string;
      repo_slug: string;
      repo_visibility: ResourceVisibility;
      repo_website_url: string;
    };
  };
  [AppRoute.REPOSITORY_DETAILS]: {
    params: {
      orgSlug: string;
      repoSlug: string;
    };
  };
  [AppRoute.REPOSITORY_EXPLORE]: undefined;
  [AppRoute.REPOSITORY_FORK]: {
    params: {
      orgSlug: string;
      repoSlug: string;
    };
  };
  [AppRoute.REPOSITORY_FORK_ACTION]: {
    params: {
      orgSlug: string;
      repoSlug: string;
    };
    body: {
      target_org_slug: string;
      target_repo_display_name: string;
      target_repo_slug: string;
      target_repo_visibility: ResourceVisibility;
    };
  };
  [AppRoute.REPOSITORY_PULL_REQUESTS]: {
    params: {
      orgSlug: string;
      repoSlug: string;
    };
  };
  [AppRoute.REPOSITORY_SHOW_OBJECT]: {
    params: {
      orgSlug: string;
      repoSlug: string;
      objectId: string;
    };
  };
}

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.AUTH_LOGOUT_ACTION]: undefined,
  [AppRoute.USER_DASHBOARD]: undefined,
  [AppRoute.USER_DETAILS]: {
    params: {
      type: "object",
      required: ["username"],
      additionalProperties: false,
      properties: {
        username: {
          type: "string",
        },
      },
    },
  },
  [AppRoute.ORGANIZATION_DETAILS]: {
    params: {
      type: "object",
      required: ["orgSlug"],
      additionalProperties: false,
      properties: {
        orgSlug: {
          type: "string",
        },
      },
    },
  },
  [AppRoute.REPOSITORY_BROWSER]: {
    params: {
      type: "object",
      required: ["orgSlug", "repoSlug", "ref", "*"],
      additionalProperties: false,
      properties: {
        orgSlug: {
          type: "string",
        },
        repoSlug: {
          type: "string",
        },
        ref: {
          type: "string",
        },
        "*": {
          type: "string",
        },
      },
    },
  },
  [AppRoute.REPOSITORY_COMMITS_LOG]: {
    params: {
      type: "object",
      required: ["orgSlug", "repoSlug", "currentRef"],
      additionalProperties: false,
      properties: {
        orgSlug: {
          type: "string",
        },
        repoSlug: {
          type: "string",
        },
        currentRef: {
          type: "string",
        },
      },
    },
  },
  [AppRoute.REPOSITORY_COMPARE]: {
    params: {
      type: "object",
      required: ["orgSlug", "repoSlug", "refA", "refB"],
      additionalProperties: false,
      properties: {
        orgSlug: {
          type: "string",
        },
        repoSlug: {
          type: "string",
        },
        refA: {
          type: "string",
        },
        refB: {
          type: "string",
        },
      },
    },
  },
  [AppRoute.REPOSITORY_CREATE]: undefined,
  [AppRoute.REPOSITORY_CREATE_ACTION]: {
    body: {
      type: "object",
      required: [
        "parent_org_slug",
        "repo_display_name",
        "repo_init_license_file",
        "repo_init_license_kind",
        "repo_init_readme_file",
        "repo_keywords",
        "repo_keywords_add",
        "repo_short_description",
        "repo_slug",
        "repo_visibility",
        "repo_website_url",
      ],
      additionalProperties: false,
      properties: {
        parent_org_slug: {
          type: "string",
        },
        repo_display_name: {
          type: "string",
          minLength: 3,
          maxLength: 64,
        },
        repo_init_license_file: {
          type: "string",
          enum: ["on", "off"],
        },
        repo_init_license_kind: {
          type: "string",
        },
        repo_init_readme_file: {
          type: "string",
          enum: ["on", "off"],
        },
        repo_keywords: {
          type: "string",
        },
        repo_keywords_add: {
          type: "string",
        },
        repo_short_description: {
          type: "string",
          minLength: 10,
          maxLength: 140,
        },
        repo_slug: {
          type: "string",
          minLength: 3,
          maxLength: 64,
        },
        repo_visibility: {
          type: "string",
          enum: Object.values(ResourceVisibility),
        },
        repo_website_url: {
          type: "string",
          format: "uri",
        },
      },
    },
  },
  [AppRoute.REPOSITORY_DETAILS]: {
    params: {
      type: "object",
      required: ["orgSlug", "repoSlug"],
      additionalProperties: false,
      properties: {
        orgSlug: {
          type: "string",
        },
        repoSlug: {
          type: "string",
        },
      },
    },
  },
  [AppRoute.REPOSITORY_EXPLORE]: undefined,
  [AppRoute.REPOSITORY_FORK]: {
    params: {
      type: "object",
      required: ["orgSlug", "repoSlug"],
      additionalProperties: false,
      properties: {
        orgSlug: {
          type: "string",
        },
        repoSlug: {
          type: "string",
        },
      },
    },
    body: {
      type: "object",
      required: [
        "target_org_slug",
        "target_repo_display_name",
        "target_repo_slug",
        "target_repo_visibility",
      ],
      additionalProperties: false,
      properties: {
        target_org_slug: {
          type: "string",
        },
        target_repo_display_name: {
          type: "string",
        },
        target_repo_slug: {
          type: "string",
        },
        target_repo_visibility: {
          type: "string",
          enum: Object.values(ResourceVisibility),
        },
      },
    },
  },
  [AppRoute.REPOSITORY_FORK_ACTION]: {
    params: {
      type: "object",
      required: ["orgSlug", "repoSlug"],
      additionalProperties: false,
      properties: {
        orgSlug: {
          type: "string",
        },
        repoSlug: {
          type: "string",
        },
      },
    },
  },
  [AppRoute.REPOSITORY_PULL_REQUESTS]: {
    params: {
      type: "object",
      required: ["orgSlug", "repoSlug"],
      additionalProperties: false,
      properties: {
        orgSlug: {
          type: "string",
        },
        repoSlug: {
          type: "string",
        },
      },
    },
  },
  [AppRoute.REPOSITORY_SHOW_OBJECT]: {
    params: {
      type: "object",
      required: ["orgSlug", "repoSlug", "objectId"],
      additionalProperties: false,
      properties: {
        orgSlug: {
          type: "string",
        },
        repoSlug: {
          type: "string",
        },
        objectId: {
          type: "string",
        },
      },
    },
  },
};

const RootAppRouter: AppRouter = () => {
  const guestOrDashboardRedirect = guestOrRedirect("/dashboard");
  const loggedOrLoginRedirect = authenticatedOrLogin();
  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"}
          preHandler={guestOrDashboardRedirect}
          schema={AppRoutesSchemas[AppRoute.AUTH_REGISTER_ACTION]}
          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"}
          preHandler={guestOrDashboardRedirect}
          schema={AppRoutesSchemas[AppRoute.AUTH_LOGIN_ACTION]}
          handler={AuthController.postLoginAction}
        />
        <Router.Route
          name={AppRoute.AUTH_LOGOUT_ACTION}
          method={"GET"}
          path={"/auth/logout"}
          preHandler={loggedOrLoginRedirect}
          schema={AppRoutesSchemas[AppRoute.AUTH_LOGOUT_ACTION]}
          handler={AuthController.getLogoutAction}
        />
        {/* --- */}
        <Router.Route
          name={AppRoute.USER_DASHBOARD}
          method={"GET"}
          path={"/dashboard"}
          preHandler={loggedOrLoginRedirect}
          handler={UserController.getUserDashboardView}
        />
        <Router.Route
          name={AppRoute.USER_DETAILS}
          method={"GET"}
          path={"/@:username"}
          handler={UserController.getUserDetailsView}
        />
        {/* --- */}
        <Router.Route
          name={AppRoute.ORGANIZATION_DETAILS}
          method={"GET"}
          path={"/:orgSlug"}
          schema={AppRoutesSchemas[AppRoute.ORGANIZATION_DETAILS]}
          handler={OrganizationController.getOrganizationDetailsView}
        />
        {/* --- */}
        <Router.Route
          name={AppRoute.REPOSITORY_BROWSER}
          method={"GET"}
          path={"/:orgSlug/:repoSlug/:currentRef/tree"}
          schema={AppRoutesSchemas[AppRoute.REPOSITORY_BROWSER]}
          handler={RepositoryController.getRepositoryBrowserView}
        />
        <Router.Route
          name={AppRoute.REPOSITORY_BROWSER}
          method={"GET"}
          path={"/:orgSlug/:repoSlug/:currentRef/tree/*"}
          schema={AppRoutesSchemas[AppRoute.REPOSITORY_BROWSER]}
          handler={RepositoryController.getRepositoryBrowserView}
        />
        <Router.Route
          name={AppRoute.REPOSITORY_COMMITS_LOG}
          method={"GET"}
          path={"/:orgSlug/:repoSlug/:currentRef/commits"}
          schema={AppRoutesSchemas[AppRoute.REPOSITORY_COMMITS_LOG]}
          handler={RepositoryController.getRepositoryCommitsLogView}
        />
        <Router.Route
          name={AppRoute.REPOSITORY_COMPARE}
          method={"GET"}
          path={"/:orgSlug/:repoSlug/compare/:refA..:refB"}
          schema={AppRoutesSchemas[AppRoute.REPOSITORY_COMPARE]}
          handler={RepositoryController.getRepositoryCompareView}
        />
        <Router.Route
          name={AppRoute.REPOSITORY_CREATE}
          method={"GET"}
          path={"/repo/new"}
          preHandler={loggedOrLoginRedirect}
          handler={RepositoryController.getRepositoryCreateView}
        />
        <Router.Route
          name={AppRoute.REPOSITORY_CREATE_ACTION}
          method={"POST"}
          path={"/repo/new"}
          preHandler={loggedOrLoginRedirect}
          schema={AppRoutesSchemas[AppRoute.REPOSITORY_CREATE_ACTION]}
          handler={RepositoryController.postRepositoryCreateAction}
        />
        <Router.Route
          name={AppRoute.REPOSITORY_DETAILS}
          method={"GET"}
          path={"/:orgSlug/:repoSlug"}
          schema={AppRoutesSchemas[AppRoute.REPOSITORY_DETAILS]}
          handler={RepositoryController.getRepositoryDetailsView}
        />
        <Router.Route
          name={AppRoute.REPOSITORY_DETAILS}
          method={"GET"}
          path={"/:orgSlug/:repoSlug/"}
          schema={AppRoutesSchemas[AppRoute.REPOSITORY_DETAILS]}
          handler={RepositoryController.getRepositoryDetailsView}
        />
        <Router.Route
          name={AppRoute.REPOSITORY_EXPLORE}
          method={"GET"}
          path={"/repo/explore"}
          handler={RepositoryController.getRepositoryExploreView}
        />
        <Router.Route
          name={AppRoute.REPOSITORY_FORK}
          method={"GET"}
          path={"/:orgSlug/:repoSlug/fork"}
          handler={RepositoryController.getRepositoryForkView}
        />
        <Router.Route
          name={AppRoute.REPOSITORY_FORK_ACTION}
          method={"POST"}
          path={"/:orgSlug/:repoSlug/fork"}
          handler={RepositoryController.postRepositoryForkAction}
        />
        <Router.Route
          name={AppRoute.REPOSITORY_PULL_REQUESTS}
          method={"GET"}
          path={"/:orgSlug/:repoSlug/pulls"}
          schema={AppRoutesSchemas[AppRoute.REPOSITORY_PULL_REQUESTS]}
          handler={RepositoryController.getRepositoryPullRequestsView}
        />
        <Router.Route
          name={AppRoute.REPOSITORY_SHOW_OBJECT}
          method={"GET"}
          path={"/:orgSlug/:repoSlug/show/:objectId"}
          schema={AppRoutesSchemas[AppRoute.REPOSITORY_SHOW_OBJECT]}
          handler={RepositoryController.getRepositoryShowObjectView}
        />
      </Router.Group>
    </Router.Root>
  );
};

export default RootAppRouter;