refactor(routes): make the Routes Paths + Params typesafe@@ -1,5 +1,5 @@
{
- "_generatedAtUnix": 1665676834248,
+ "_generatedAtUnix": 1665685521848,
"_hashAlgorithm": "sha1",
"_version": 2,
"islands": {
@@ -22,13 +22,13 @@
"pathSourceMap": "./public/.islands/PullRequestSourceSelect.bundle.js.map"
},
"RepositoriesList": {
- "hash": "123782350476918ef2f540ddaca91ef9c82bcc8f",
+ "hash": "4cf17af8826b391263e248be55ce4116eb7414d6",
"pathSource": "./app/islands/RepositoriesList.tsx",
"pathBundle": "./public/.islands/RepositoriesList.bundle.js",
"pathSourceMap": "./public/.islands/RepositoriesList.bundle.js.map"
},
"RepositoryCommitSummaryLine": {
- "hash": "7c1eee05085d4ec9ef48e6ecfe8f90408a814a16",
+ "hash": "e012ace9c8913084e366212f13bb7ae0156b31ab",
"pathSource": "./app/islands/RepositoryCommitSummaryLine.tsx",
"pathBundle": "./public/.islands/RepositoryCommitSummaryLine.bundle.js",
"pathSourceMap": "./public/.islands/RepositoryCommitSummaryLine.bundle.js.map"
@@ -40,7 +40,7 @@
"pathSourceMap": "./public/.islands/RepositoryCreateForm.bundle.js.map"
},
"RepositoryFilesDiffsList": {
- "hash": "3343a34118a771923801fa256372e534d8599f2c",
+ "hash": "3f25148b18ecf4be33cde9ba288d93f5f7f3fc53",
"pathSource": "./app/islands/RepositoryFilesDiffsList.tsx",
"pathBundle": "./public/.islands/RepositoryFilesDiffsList.bundle.js",
"pathSourceMap": "./public/.islands/RepositoryFilesDiffsList.bundle.js.map"
@@ -52,7 +52,7 @@
"pathSourceMap": "./public/.islands/RepositoryForkForm.bundle.js.map"
},
"RepositoryHero": {
- "hash": "8e3ab7bf7a0453764210ea7f352fafc688e8b905",
+ "hash": "81540baa6a726aa5046fbe1c4d09d1d926a7adb3",
"pathSource": "./app/islands/RepositoryHero.tsx",
"pathBundle": "./public/.islands/RepositoryHero.bundle.js",
"pathSourceMap": "./public/.islands/RepositoryHero.bundle.js.map"
@@ -64,13 +64,13 @@
"pathSourceMap": "./public/.islands/RepositoryInitialSetup.bundle.js.map"
},
"RepositoryPullRequestCreateForm": {
- "hash": "6ac90711334641e84db75f910431e086fc0d1e00",
+ "hash": "e0ca07f9a904abb40e812678f1a1efde5e3ae994",
"pathSource": "./app/islands/RepositoryPullRequestCreateForm.tsx",
"pathBundle": "./public/.islands/RepositoryPullRequestCreateForm.bundle.js",
"pathSourceMap": "./public/.islands/RepositoryPullRequestCreateForm.bundle.js.map"
},
"RepositoryTreeView": {
- "hash": "846a1f7c4654c973bd106763dee544eb2a485ab2",
+ "hash": "730ce2e7a8f5b705deb6fac8e506ebc0d4cc1458",
"pathSource": "./app/islands/RepositoryTreeView.tsx",
"pathBundle": "./public/.islands/RepositoryTreeView.bundle.js",
"pathSourceMap": "./public/.islands/RepositoryTreeView.bundle.js.map"
@@ -78,19 +78,19 @@
},
"views": {
"HomeView": {
- "hash": "98b1f0f9fe6b3f5a61b9ca5707459a8a32de0e6c",
+ "hash": "c1530f6ff4b764c99bd296ebdad53d6fd8f95fa2",
"pathSource": "./app/views/HomeView.tsx"
},
"InternalErrorView": {
- "hash": "63c8e65201adc83014dd9434569fb857d3888635",
+ "hash": "a155f3581f6ccadc5e7db619152490c65b7c4de5",
"pathSource": "./app/views/InternalErrorView.tsx"
},
"LoginView": {
- "hash": "86965d3c632c5b2b6f3ef5bbcab2ad73adea2de1",
+ "hash": "44c082512925027813f1f7d046ec43e5ac8d3f0d",
"pathSource": "./app/views/auth/LoginView.tsx"
},
"RegisterView": {
- "hash": "9ef9cd8f4c0e8402994277cf3d7191e3db765e6d",
+ "hash": "d703ac5d1bec1c1167c60b08fc4eb98f02cef139",
"pathSource": "./app/views/auth/RegisterView.tsx"
},
"OrganizationDetailsView": {
@@ -110,11 +110,11 @@
"pathSource": "./app/views/repository/RepositoryCompareView.tsx"
},
"RepositoryCreateView": {
- "hash": "79c276144349b6d0fbe3aeeb658fb1ae30daa9d5",
+ "hash": "83da3d43e76d51e0615ac1d3e22a27df9c43c584",
"pathSource": "./app/views/repository/RepositoryCreateView.tsx"
},
"RepositoryDetailsView": {
- "hash": "29d660c09e9ae686b6e7c4c16d171e27fbd9b13c",
+ "hash": "486e106dcc7ef2a7499b9702b9dd81ce3cf90b6d",
"pathSource": "./app/views/repository/RepositoryDetailsView.tsx"
},
"RepositoryExploreView": {
@@ -122,7 +122,7 @@
"pathSource": "./app/views/repository/RepositoryExploreView.tsx"
},
"RepositoryForkView": {
- "hash": "1a9509ad1a1a6f287f5ca7fd69ccbe5344d9f520",
+ "hash": "03cf6068a1eac864d44ca06a5bd729427ed73e6f",
"pathSource": "./app/views/repository/RepositoryForkView.tsx"
},
"RepositoryShowObjectView": {
@@ -134,11 +134,11 @@
"pathSource": "./app/views/repositoryPullRequests/RepositoryPullRequestCreateView.tsx"
},
"RepositoryPullRequestDetailsView": {
- "hash": "6c311e13f7cbbc00b502e0d4c1af30493433eb65",
+ "hash": "3be2cc6227dd14e4345c8ab2b38500a00c90df6d",
"pathSource": "./app/views/repositoryPullRequests/RepositoryPullRequestDetailsView.tsx"
},
"RepositoryPullRequestsView": {
- "hash": "1ad2fff2166e8417a428852f7f4579d4f2ece30d",
+ "hash": "15afac8b1953b882780b60c5b5abb75354ca6a88",
"pathSource": "./app/views/repositoryPullRequests/RepositoryPullRequestsView.tsx"
},
"UserDashboardView": {
@@ -3,8 +3,10 @@ import React, { useMemo, VFC } from "react";
import styled, { css } from "styled-components";
// app
import type { CommonProps, WithThemeSchemeProp } from "../types";
+import { AppRoute } from "../routes.defs";
import { Const } from "../const";
import { NamedColors } from "../utils/style";
+import { buildRouteLink } from "../utils/shared";
interface PageHeaderProps extends CommonProps {}
@@ -18,10 +20,17 @@ export const PageHeader: VFC<PageHeaderProps & WithThemeSchemeProp> = ({
if (commonProps.authenticated) {
return (
<>
- <a href={`/@${commonProps.currentUserUsername || "ghost"}`}>
+ <a
+ href={buildRouteLink(AppRoute.USER_DETAILS, {
+ username: commonProps.currentUserUsername || "ghost",
+ })}
+ >
{commonProps.currentUserUsername || "ghost"}
</a>
- <a aria-label={"Log off your account"} href={"/auth/logout"}>
+ <a
+ aria-label={"Log off your account"}
+ href={buildRouteLink(AppRoute.AUTH_LOGOUT_ACTION, null)}
+ >
Logout
</a>
</>
@@ -30,10 +39,16 @@ export const PageHeader: VFC<PageHeaderProps & WithThemeSchemeProp> = ({
return (
<>
- <a aria-label={"Register a new account"} href={"/auth/register"}>
+ <a
+ aria-label={"Register a new account"}
+ href={buildRouteLink(AppRoute.AUTH_REGISTER, null)}
+ >
Register
</a>
- <a aria-label={"Login to your account"} href={"/auth/login"}>
+ <a
+ aria-label={"Login to your account"}
+ href={buildRouteLink(AppRoute.AUTH_LOGIN, null)}
+ >
Login
</a>
</>
@@ -48,19 +63,27 @@ export const PageHeader: VFC<PageHeaderProps & WithThemeSchemeProp> = ({
</a>
</StyledLogoArea>
<StyledPageHeaderNav>
- <a aria-label={"Explore Repositories"} href={"/repo/explore"}>
+ <a
+ aria-label={"Explore Repositories"}
+ href={buildRouteLink(AppRoute.REPOSITORY_EXPLORE, null)}
+ >
Explore Repositories
</a>
</StyledPageHeaderNav>
<StyledActionsArea>
{commonProps.authenticated && (
- <a aria-label={"Create a new Repository"} href={"/repo/new"}>
+ <a
+ aria-label={"Create a new Repository"}
+ href={buildRouteLink(AppRoute.REPOSITORY_CREATE, null)}
+ >
New Repository
</a>
)}
<a
data-smooth-scroll={"disabled"}
- href={`/theme/${invertThemeScheme}`}
+ href={buildRouteLink(AppRoute.THEME_SET_SCHEME_ACTION, {
+ themeScheme: invertThemeScheme,
+ })}
style={{ color: NamedColors.TEXT_MUTED[themeScheme] }}
title={`Click to enable ${
themeScheme === "light" ? "dark" : "light"
@@ -1,7 +1,7 @@
// 3rd-party
import type { ReqHandler } from "@ethicdevs/react-monolith";
// app
-import { AppRoute } from "../../routes";
+import { AppRoute } from "../../routes.defs";
const getLogoutAction: ReqHandler = async (request, reply) => {
await request.session.destroy();
@@ -1,7 +1,7 @@
// 3rd-party
import type { ReqHandler } from "@ethicdevs/react-monolith";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
import LoginView, { LoginViewProps } from "../../views/auth/LoginView";
import { makeAuthService } from "../../services/auth";
@@ -1,7 +1,7 @@
// 3rd-party
import type { ReqHandler } from "@ethicdevs/react-monolith";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
import RegisterView, { RegisterViewProps } from "../../views/auth/RegisterView";
import { makeAuthService } from "../../services/auth";
@@ -8,7 +8,7 @@ import {
User,
} from "@prisma/client";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
// app views
@@ -3,7 +3,7 @@ import type { ReqHandler } from "@ethicdevs/react-monolith";
// generated via script[generate:prisma]
import { ResourceVisibility } from "@prisma/client";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
import { Const } from "../../const";
// app services
import { makeOrganizationService } from "../../services/organization";
@@ -2,7 +2,7 @@
import type { ReqHandler } from "@ethicdevs/react-monolith";
import { ResourceVisibility } from "@prisma/client";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
import { makeRepositoryService } from "../../services/repository";
@@ -2,7 +2,7 @@
import { ReqHandler } from "@ethicdevs/react-monolith";
// generated via script[generate:prisma]
import { ResourceVisibility } from "@prisma/client";
-import { AppRoute, AppRoutesParams } from "app/routes";
+import { AppRoute, AppRoutesParams } from "app/routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
import { makeRepositoryService } from "../../services/repository";
@@ -1,7 +1,7 @@
// 1st-party
import type { ReqHandler } from "@ethicdevs/react-monolith";
// app
-import { AppRoute } from "../../routes";
+import { AppRoute } from "../../routes.defs";
import { makeUsersService } from "../../services/user";
// app views
import RepositoryCreateView, {
@@ -1,7 +1,7 @@
// 1st-party
import type { ReqHandler } from "@ethicdevs/react-monolith";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
import { Const } from "../../const";
// app services
import { makeOrganizationService } from "../../services/organization";
@@ -1,7 +1,7 @@
// 1st-party
import type { ReqHandler } from "@ethicdevs/react-monolith";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
import { makeRepositoryService } from "../../services/repository";
@@ -2,7 +2,7 @@
import type { ReqHandler } from "@ethicdevs/react-monolith";
import { ResourceVisibility } from "@prisma/client";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
import { makeRepositoryService } from "../../services/repository";
@@ -3,7 +3,7 @@ import { join, resolve } from "node:path";
// 1st-party
import type { ReqHandler } from "@ethicdevs/react-monolith";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
import { Env } from "../../env";
// app services
import { makeRepositoryService } from "../../services/repository";
@@ -3,7 +3,7 @@ import { join, resolve } from "node:path";
// 1st-party
import type { ReqHandler } from "@ethicdevs/react-monolith";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
import { Env } from "../../env";
// app services
import { makeOrganizationService } from "../../services/organization";
@@ -2,7 +2,7 @@
import type { ReqHandler } from "@ethicdevs/react-monolith";
import { ResourceVisibility } from "@prisma/client";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
import { makePullRequestService } from "../../services/pullRequest";
@@ -2,7 +2,7 @@
import type { ReqHandler } from "@ethicdevs/react-monolith";
import { ResourceVisibility } from "@prisma/client";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
import { makePullRequestService } from "../../services/pullRequest";
@@ -2,7 +2,7 @@
import type { ReqHandler } from "@ethicdevs/react-monolith";
import { ResourceVisibility } from "@prisma/client";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
import { makePullRequestService } from "../../services/pullRequest";
@@ -2,7 +2,7 @@
import type { ReqHandler } from "@ethicdevs/react-monolith";
import { ResourceVisibility } from "@prisma/client";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
import { makePullRequestService } from "../../services/pullRequest";
@@ -3,7 +3,7 @@ import { ReqHandler } from "@ethicdevs/react-monolith";
// app
import type { RepositoryWithParentAndForkedFromRepos } from "../../types";
import { Const } from "../../const";
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
import { makeRepositoryService } from "../../services/repository";
@@ -2,7 +2,7 @@
import type { ReqHandler } from "@ethicdevs/react-monolith";
import { ResourceVisibility } from "@prisma/client";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
import { makePullRequestService } from "../../services/pullRequest";
@@ -3,7 +3,7 @@ import type { ReqHandler } from "@ethicdevs/react-monolith";
import { ResourceVisibility } from "@prisma/client";
// app
import type { RepositoryFileDiff } from "../../types";
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
import { makePullRequestService } from "../../services/pullRequest";
@@ -124,6 +124,7 @@ const getRepositoryPullRequestDetailsView: ReqHandler = async (
sourceRepo,
targetParentOrg,
targetRepo,
+ isCurrentUserAllowedToMerge: true,
}
);
};
@@ -2,7 +2,7 @@
import type { ReqHandler } from "@ethicdevs/react-monolith";
import { ResourceVisibility } from "@prisma/client";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
import { makePullRequestService } from "../../services/pullRequest";
@@ -2,7 +2,7 @@
import type { ReqHandler } from "@ethicdevs/react-monolith";
import { ResourceVisibility } from "@prisma/client";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
import { makePullRequestService } from "../../services/pullRequest";
@@ -2,7 +2,7 @@
import type { ReqHandler } from "@ethicdevs/react-monolith";
import { ResourceVisibility } from "@prisma/client";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app services
import { makeOrganizationService } from "../../services/organization";
import { makePullRequestService } from "../../services/pullRequest";
@@ -1,7 +1,7 @@
// 1st-party
import { ReqHandler } from "@ethicdevs/react-monolith";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
// app islands
import {
PullRequestFormState,
@@ -5,7 +5,7 @@ import Prism from "prismjs";
import { parse as parseHtmlToJson, TextNode, RealNode } from "himalaya";
// app
import type { AppThemeScheme } from "../../types";
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
import { escapeHtmlCode } from "../../utils/shared/escapeHtmlCode";
Prism.languages.prisma = Prism.languages.extend("javascript", {
@@ -1,7 +1,7 @@
// 1st-party
import { ReqHandler } from "@ethicdevs/react-monolith";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
const setThemeSchemeAction: ReqHandler = async (request, reply) => {
const { referer } = request.headers;
@@ -1,7 +1,7 @@
// 3rd-party
import type { ReqHandler } from "@ethicdevs/react-monolith";
// app
-import { AppRoute } from "../../routes";
+import { AppRoute } from "../../routes.defs";
import { makeUsersService } from "../../services/user";
// app views
import UserDashboardView, {
@@ -2,7 +2,7 @@
import type { ReqHandler } from "@ethicdevs/react-monolith";
import { User } from "@prisma/client";
// app
-import { AppRoute, AppRoutesParams } from "../../routes";
+import { AppRoute, AppRoutesParams } from "../../routes.defs";
import { makeUsersService } from "../../services/user";
// app views
import UserDetailsView, {
@@ -6,8 +6,10 @@ import React from "react";
import { Organization, Repository } from "@prisma/client";
// app
import type { WithThemeSchemeProp } from "../types";
+import { AppRoute } from "../routes.defs";
import { Card } from "../components/Card.styled";
import { Grid } from "../components/Grid";
+import { buildRouteLink } from "../utils/shared";
export interface RepositoriesListProps {
repositories: Array<Repository & { parentOrg: Organization }>;
@@ -26,7 +28,12 @@ const RepositoriesList: ReactIsland<
>
<Grid.Row fluid nowrap>
<h1 style={{ margin: 0, flex: 1 }}>
- <a href={`/${repo.parentOrg.slug}/${repo.slug}`}>
+ <a
+ href={buildRouteLink(AppRoute.REPOSITORY_DETAILS, {
+ orgSlug: repo.parentOrg.slug,
+ repoSlug: repo.slug,
+ })}
+ >
{repo.parentOrg.displayName || repo.parentOrg.slug}
{" / "}
{repo.displayName || repo.slug}
@@ -4,7 +4,9 @@ import type { ReactIsland } from "@ethicdevs/react-monolith";
import React, { useCallback, useMemo, useState } from "react";
// app
import type { RepositoryObject } from "../types";
+import { AppRoute } from "../routes.defs";
import { Grid } from "../components/Grid";
+import { buildRouteLink } from "../utils/shared";
export interface RepositoryCommitSummaryLineProps {
commit: RepositoryObject;
@@ -56,7 +58,13 @@ const RepositoryCommitSummaryLine: ReactIsland<RepositoryCommitSummaryLineProps>
<Grid.Col flex={"1 0 calc(100% - 220px)"} style={{ minWidth: 360 }}>
<strong>{commit.author.name}</strong>
<span style={{ marginTop: 8 }}>
- <a href={`/${orgSlug}/${repoSlug}/show/${commit.commit}`}>
+ <a
+ href={buildRouteLink(AppRoute.REPOSITORY_SHOW_OBJECT, {
+ orgSlug,
+ repoSlug,
+ objectId: commit.commit,
+ })}
+ >
{subject}
</a>
{isSubjectTooLongForDisplay ? (
@@ -76,11 +84,23 @@ const RepositoryCommitSummaryLine: ReactIsland<RepositoryCommitSummaryLineProps>
}}
>
<span>
- <a href={`/${orgSlug}/${repoSlug}/show/${commit.commit}`}>
+ <a
+ href={buildRouteLink(AppRoute.REPOSITORY_SHOW_OBJECT, {
+ orgSlug,
+ repoSlug,
+ objectId: commit.commit,
+ })}
+ >
{commit.abbreviated_commit}
</a>
{commit.abbreviated_parent.trim() != "" ? (
- <a href={`/${orgSlug}/${repoSlug}/show/${commit.parent}`}>
+ <a
+ href={buildRouteLink(AppRoute.REPOSITORY_SHOW_OBJECT, {
+ orgSlug,
+ repoSlug,
+ objectId: commit.parent,
+ })}
+ >
{` (parent ${commit.abbreviated_parent})`}
</a>
) : null}
@@ -8,9 +8,11 @@ import type {
RepositoryFileDiffChunk,
WithThemeSchemeProp,
} from "../types";
+import { AppRoute } from "../routes.defs";
import { Const } from "../const";
import { Card } from "../components/Card.styled";
import { Grid } from "../components/Grid";
+import { buildRouteLink } from "../utils/shared";
// app islands
import Code, { getThemedCodeCss } from "../islands/Code";
@@ -62,12 +64,28 @@ const RepositoryFilesDiffsList: ReactIsland<
</div>
<div style={{ marginLeft: 16 }}>
<a
- href={`/${orgSlug}/${repoSlug}/${commitHash}/tree/${diff.to}`}
+ href={buildRouteLink(
+ AppRoute.REPOSITORY_BROWSER_WITH_PATH,
+ {
+ orgSlug,
+ repoSlug,
+ currentRef: commitHash,
+ "*": diff.to,
+ }
+ )}
>
View file (current ref)
</a>
<a
- href={`/${orgSlug}/${repoSlug}/${Const.PRIMARY_BRANCH_REF}/tree/${diff.to}`}
+ href={buildRouteLink(
+ AppRoute.REPOSITORY_BROWSER_WITH_PATH,
+ {
+ orgSlug,
+ repoSlug,
+ currentRef: Const.PRIMARY_BRANCH_REF,
+ "*": diff.to,
+ }
+ )}
style={{ marginLeft: 16 }}
>
View file (${Const.PRIMARY_BRANCH_REF})
@@ -6,7 +6,9 @@ import React from "react";
import type { Organization, Repository } from "@prisma/client";
// app
import type { RepositoryForkedFromRepoMeta } from "../types";
+import { AppRoute } from "../routes.defs";
import { Grid } from "../components/Grid";
+import { buildRouteLink } from "../utils/shared";
export interface RepositoryHeroProps {
parentOrg: Organization;
@@ -34,11 +36,20 @@ const RepositoryHero: ReactIsland<RepositoryHeroProps> = ({
style={{ marginTop: 8, minWidth: 468 }}
>
<h1 style={{ margin: 0 }}>
- <a href={`/${parentOrg.slug}`}>
+ <a
+ href={buildRouteLink(AppRoute.ORGANIZATION_DETAILS, {
+ orgSlug: parentOrg.slug,
+ })}
+ >
{parentOrg.displayName || parentOrg.slug}
</a>
{" / "}
- <a href={`/${parentOrg.slug}/${repo.slug}`}>
+ <a
+ href={buildRouteLink(AppRoute.REPOSITORY_DETAILS, {
+ orgSlug: parentOrg.slug,
+ repoSlug: repo.slug,
+ })}
+ >
{repo.displayName || repo.slug}
</a>
{` ${separator} `}
@@ -55,13 +66,20 @@ const RepositoryHero: ReactIsland<RepositoryHeroProps> = ({
<h5 style={{ margin: 0, marginTop: 8 }}>
<span>Forked From</span>
{" ∙ "}
- <a href={`/${forkedFromRepo.organization.slug}`}>
+ <a
+ href={buildRouteLink(AppRoute.ORGANIZATION_DETAILS, {
+ orgSlug: forkedFromRepo.organization.slug,
+ })}
+ >
{forkedFromRepo.organization.displayName ||
forkedFromRepo.organization.slug}
</a>
{" / "}
<a
- href={`/${forkedFromRepo.organization.slug}/${forkedFromRepo.slug}`}
+ href={buildRouteLink(AppRoute.REPOSITORY_DETAILS, {
+ orgSlug: forkedFromRepo.organization.slug,
+ repoSlug: forkedFromRepo.slug,
+ })}
>
{forkedFromRepo.displayName || forkedFromRepo.slug}
</a>
@@ -70,7 +88,12 @@ const RepositoryHero: ReactIsland<RepositoryHeroProps> = ({
</div>
<div style={{ marginTop: 16 }}>
<div>
- <a href={`/${parentOrg.slug}/${repo.slug}/pulls`}>
+ <a
+ href={buildRouteLink(AppRoute.REPOSITORY_PULL_REQUESTS, {
+ orgSlug: parentOrg.slug,
+ repoSlug: repo.slug,
+ })}
+ >
Pull Requests
</a>
</div>
@@ -79,7 +102,10 @@ const RepositoryHero: ReactIsland<RepositoryHeroProps> = ({
<Grid.Row nowrap style={{ minWidth: 90, marginTop: 8 }}>
<span>{forksCount}</span>
<a
- href={`/${parentOrg.slug}/${repo.slug}/fork`}
+ href={buildRouteLink(AppRoute.REPOSITORY_FORK, {
+ orgSlug: parentOrg.slug,
+ repoSlug: repo.slug,
+ })}
style={{ marginLeft: 8 }}
>
Fork it!
@@ -10,9 +10,11 @@ import type {
RepositoryFileDiff,
RepositoryWithParentAndForkedFromRepos,
} from "../types";
+import { AppRoute } from "../routes.defs";
import { Card } from "../components/Card.styled";
import { Grid } from "../components/Grid";
import { IslandWrapper } from "../components/IslandWrapper.styled";
+import { buildRouteLink } from "../utils/shared";
// app islands
import RepositoryFilesDiffsList from "./RepositoryFilesDiffsList";
import PullRequestSourceSelect, {
@@ -183,7 +185,10 @@ const RepositoryPullRequestCreateForm: ReactIsland<RepositoryPullRequestCreateFo
<Grid.Col fluid nowrap>
<form
method={"POST"}
- action={`/${parentOrgSlug}/${repoSlug}/pulls/new`}
+ action={buildRouteLink(
+ AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION,
+ { orgSlug: parentOrgSlug, repoSlug }
+ )}
style={{ width: "100%" }}
>
<Card themeScheme={themeScheme}>
@@ -263,7 +268,14 @@ const RepositoryPullRequestCreateForm: ReactIsland<RepositoryPullRequestCreateFo
Try comparing two branches that have some differences before you
can create a pull request from the produced diff.
</p>
- <a href={`/${parentOrgSlug}/${repoSlug}/pulls/new`}>Try again</a>
+ <a
+ href={buildRouteLink(AppRoute.REPOSITORY_PULL_REQUEST_CREATE, {
+ orgSlug: parentOrgSlug,
+ repoSlug,
+ })}
+ >
+ Try again
+ </a>
</Grid.Col>
);
}
@@ -272,7 +284,10 @@ const RepositoryPullRequestCreateForm: ReactIsland<RepositoryPullRequestCreateFo
<Grid.Col fluid nowrap>
<form
method={"POST"}
- action={`/${parentOrgSlug}/${repoSlug}/pulls/new`}
+ action={buildRouteLink(
+ AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION,
+ { orgSlug: parentOrgSlug, repoSlug }
+ )}
style={{ width: "100%" }}
>
<input type={"hidden"} name={"state_from"} value={state} />
@@ -371,7 +386,10 @@ const RepositoryPullRequestCreateForm: ReactIsland<RepositoryPullRequestCreateFo
<Grid.Col fluid nowrap>
<form
method={"POST"}
- // action={`/${data.source.parentOrg.slug}/${data.source.repo.slug}/pulls/new`}
+ action={buildRouteLink(
+ AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION,
+ { orgSlug: parentOrgSlug, repoSlug }
+ )}
>
<input type={"hidden"} name={"state_from"} value={state} />
<button type={"submit"}>Submit the Pull Request</button>
@@ -9,8 +9,11 @@ import type {
RepositoryLog,
WithThemeSchemeProp,
} from "../types";
+import { AppRoute } from "../routes.defs";
import { Grid, TextEllipsis } from "../components";
import { NamedColors } from "../utils/style";
+import { buildRouteLink } from "../utils/shared";
+// app islands
// import RepositoryCommitSummaryLine from "./RepositoryCommitSummaryLine";
export interface RepositoryTreeViewProps {
@@ -40,14 +43,22 @@ const RepositoryTreeView: ReactIsland<
text: fileName,
href:
currentPath === "/"
- ? `/${orgSlug}/${repoSlug}/${encodeURIComponent(
- currentRef
- )}/tree/${fileName}`
- : `/${orgSlug}/${repoSlug}/${encodeURIComponent(currentRef)}/tree/${
- currentPath.endsWith("/") || currentPath === ""
- ? currentPath
- : `${currentPath}/`
- }${fileName}`,
+ ? buildRouteLink(AppRoute.REPOSITORY_BROWSER_WITH_PATH, {
+ orgSlug,
+ repoSlug,
+ currentRef: encodeURIComponent(currentRef),
+ "*": fileName,
+ })
+ : buildRouteLink(AppRoute.REPOSITORY_BROWSER_WITH_PATH, {
+ orgSlug,
+ repoSlug,
+ currentRef: encodeURIComponent(currentRef),
+ "*": `${
+ currentPath.endsWith("/") || currentPath === ""
+ ? currentPath
+ : `${currentPath}/`
+ }${fileName}`,
+ }),
};
},
[orgSlug, repoSlug, currentPath]
@@ -64,10 +75,13 @@ const RepositoryTreeView: ReactIsland<
const prevPathLink =
prevPath === "/"
- ? `/${orgSlug}/${repoSlug}`
- : `/${orgSlug}/${repoSlug}/${encodeURIComponent(currentRef)}/tree/${
- prevPath.endsWith("/") ? prevPath : `${prevPath}/`
- }`;
+ ? buildRouteLink(AppRoute.REPOSITORY_DETAILS, { orgSlug, repoSlug })
+ : buildRouteLink(AppRoute.REPOSITORY_BROWSER_WITH_PATH, {
+ orgSlug,
+ repoSlug,
+ currentRef: encodeURIComponent(currentRef),
+ "*": prevPath.endsWith("/") ? prevPath : `${prevPath}/`,
+ });
return (
<StyledRepositoryTreeViewContainer>
@@ -94,9 +108,15 @@ const RepositoryTreeView: ReactIsland<
title={`Go to "${currPathParts
.slice(0, idx + 1)
.join("/")}/" folder`}
- href={`/${orgSlug}/${repoSlug}/${encodeURIComponent(
- currentRef
- )}/tree/${currPathParts.slice(0, idx + 1).join("/")}/`}
+ href={buildRouteLink(
+ AppRoute.REPOSITORY_BROWSER_WITH_PATH,
+ {
+ orgSlug,
+ repoSlug,
+ currentRef: encodeURIComponent(currentRef),
+ "*": `${currPathParts.slice(0, idx + 1).join("/")}/`,
+ }
+ )}
>
<TextEllipsis>{pathPart}/</TextEllipsis>
</a>
@@ -106,9 +126,11 @@ const RepositoryTreeView: ReactIsland<
<Grid.Row nowrap alignItems={"center"}>
<a
style={{ minWidth: "max-content" }}
- href={`/${orgSlug}/${repoSlug}/${encodeURIComponent(
- currentRef
- )}/commits`}
+ href={buildRouteLink(AppRoute.REPOSITORY_COMMITS_LOG, {
+ orgSlug,
+ repoSlug,
+ currentRef: encodeURIComponent(currentRef),
+ })}
>
Commits History
</a>
@@ -156,7 +178,11 @@ const RepositoryTreeView: ReactIsland<
{file.lastCommit != null && (
<StyledTreeViewListItemAnchor
style={{ flex: 1, marginLeft: 16 }}
- href={`/${orgSlug}/${repoSlug}/show/${file.lastCommit.commit}`}
+ href={buildRouteLink(AppRoute.REPOSITORY_SHOW_OBJECT, {
+ orgSlug,
+ repoSlug,
+ objectId: file.lastCommit.commit,
+ })}
title={file.lastCommit.subject}
>
<span
@@ -0,0 +1,937 @@
+// 1st-party
+import type { IRouteParams } from "@ethicdevs/react-monolith";
+// 3rd-party
+import type { FastifySchema } from "fastify";
+// generated via script[generate:prisma]
+import { ResourceVisibility } from "@prisma/client";
+// app
+import type { AppThemeScheme } from "./types";
+// app islands DTO's
+import { PullRequestFormState } from "./islands/RepositoryPullRequestCreateForm";
+
+export enum AppRoute {
+ HOME = "home",
+ THEME_SET_SCHEME_ACTION = "theme.set_scheme.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",
+ ORGANIZATION_DETAILS = "organization.details",
+ REPOSITORY_BROWSER = "repository.browser",
+ REPOSITORY_BROWSER_WITH_PATH = "repository.browser.with_path",
+ 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_DETAILS_WITH_TRAILING_SLASH = "repository.details.with_trailing_slash",
+ REPOSITORY_EXPLORE = "repository.explore",
+ REPOSITORY_FORK = "repository.fork",
+ REPOSITORY_FORK_ACTION = "repository.fork.action",
+ REPOSITORY_PULL_REQUEST_CLOSE_ACTION = "repository.pull_request.close.action",
+ REPOSITORY_PULL_REQUEST_COMMENT_CREATE_ACTION = "repository.pull_request.comment.create.action",
+ REPOSITORY_PULL_REQUEST_COMMENT_DELETE_ACTION = "repository.pull_request.comment.delete.action",
+ REPOSITORY_PULL_REQUEST_COMMENT_UPDATE_ACTION = "repository.pull_request.comment.update.action",
+ REPOSITORY_PULL_REQUEST_CREATE = "repository.pull_request.create",
+ REPOSITORY_PULL_REQUEST_CREATE_ACTION = "repository.pull_request.create.action",
+ REPOSITORY_PULL_REQUEST_DELETE_ACTION = "repository.pull_request.delete.action",
+ REPOSITORY_PULL_REQUEST_DETAILS = "repository.pull_request.details",
+ REPOSITORY_PULL_REQUEST_MERGE_ACTION = "/:orgSlug/:repoSlug/pulls/:pullUid/merge",
+ REPOSITORY_PULL_REQUEST_UPDATE_ACTION = "repository.pull_request.update.action",
+ REPOSITORY_PULL_REQUESTS = "repository.pull_requests",
+ REPOSITORY_SHOW_OBJECT = "repository.show_object",
+ SYNTAX_HIGHLIGHT_HIGHLIGHT_CODE_ACTION = "syntax_highlight.highlight_code.action",
+ USER_DASHBOARD = "user.dashboard",
+ USER_DETAILS = "user.details",
+}
+
+export const AppRoutePaths: Record<AppRoute, string> = {
+ [AppRoute.HOME]: "/",
+ [AppRoute.THEME_SET_SCHEME_ACTION]: "/theme/:themeScheme",
+ [AppRoute.AUTH_REGISTER]: "/auth/register",
+ [AppRoute.AUTH_REGISTER_ACTION]: "/auth/register",
+ [AppRoute.AUTH_LOGIN]: "/auth/login",
+ [AppRoute.AUTH_LOGIN_ACTION]: "/auth/login",
+ [AppRoute.AUTH_LOGOUT_ACTION]: "/auth/logout",
+ [AppRoute.ORGANIZATION_DETAILS]: "/:orgSlug",
+ [AppRoute.REPOSITORY_BROWSER]: "/:orgSlug/:repoSlug/:currentRef/tree",
+ [AppRoute.REPOSITORY_BROWSER_WITH_PATH]:
+ "/:orgSlug/:repoSlug/:currentRef/tree/*",
+ [AppRoute.REPOSITORY_COMMITS_LOG]: "/:orgSlug/:repoSlug/:currentRef/commits",
+ [AppRoute.REPOSITORY_COMPARE]: "/:orgSlug/:repoSlug/compare/:refA..:refB",
+ [AppRoute.REPOSITORY_CREATE]: "/repo/new",
+ [AppRoute.REPOSITORY_CREATE_ACTION]: "/repo/new",
+ [AppRoute.REPOSITORY_DETAILS]: "/:orgSlug/:repoSlug",
+ [AppRoute.REPOSITORY_DETAILS_WITH_TRAILING_SLASH]: "/:orgSlug/:repoSlug/",
+ [AppRoute.REPOSITORY_EXPLORE]: "/repo/explore",
+ [AppRoute.REPOSITORY_FORK]: "/:orgSlug/:repoSlug/fork",
+ [AppRoute.REPOSITORY_FORK_ACTION]: "/:orgSlug/:repoSlug/fork",
+ [AppRoute.REPOSITORY_PULL_REQUEST_CLOSE_ACTION]:
+ "/:orgSlug/:repoSlug/pulls/:pullUid/close",
+ [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_CREATE_ACTION]:
+ "/:orgSlug/:repoSlug/pulls/:pullUid/comment",
+ [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_DELETE_ACTION]:
+ "/:orgSlug/:repoSlug/pulls/:pullUid/comment/delete",
+ [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_UPDATE_ACTION]:
+ "/:orgSlug/:repoSlug/pulls/:pullUid/comment/edit",
+ [AppRoute.REPOSITORY_PULL_REQUEST_CREATE]: "/:orgSlug/:repoSlug/pulls/new",
+ [AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION]:
+ "/:orgSlug/:repoSlug/pulls/new",
+ [AppRoute.REPOSITORY_PULL_REQUEST_DELETE_ACTION]:
+ "/:orgSlug/:repoSlug/pulls/:pullUid/delete",
+ [AppRoute.REPOSITORY_PULL_REQUEST_DETAILS]:
+ "/:orgSlug/:repoSlug/pulls/:pullUid",
+ [AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION]:
+ "/:orgSlug/:repoSlug/pulls/:pullUid/merge",
+ [AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION]:
+ "/:orgSlug/:repoSlug/pulls/:pullUid/edit",
+ [AppRoute.REPOSITORY_PULL_REQUESTS]: "/:orgSlug/:repoSlug/pulls",
+ [AppRoute.REPOSITORY_SHOW_OBJECT]: "/:orgSlug/:repoSlug/show/:objectId",
+ [AppRoute.SYNTAX_HIGHLIGHT_HIGHLIGHT_CODE_ACTION]:
+ "/api/syntax/highlight/:outputFormat",
+ [AppRoute.USER_DASHBOARD]: "/dashboard",
+ [AppRoute.USER_DETAILS]: "/@:username",
+};
+
+export interface AppRoutesParams extends IRouteParams {
+ [AppRoute.HOME]: undefined;
+ [AppRoute.THEME_SET_SCHEME_ACTION]: {
+ params: {
+ themeScheme: AppThemeScheme;
+ };
+ };
+ [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.ORGANIZATION_DETAILS]: {
+ params: {
+ orgSlug: string;
+ };
+ };
+ [AppRoute.REPOSITORY_BROWSER]: {
+ params: {
+ orgSlug: string;
+ repoSlug: string;
+ currentRef: string;
+ "*": string;
+ };
+ };
+ [AppRoute.REPOSITORY_BROWSER_WITH_PATH]: {
+ 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_DETAILS_WITH_TRAILING_SLASH]: {
+ 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_REQUEST_CLOSE_ACTION]: {
+ params: {
+ orgSlug: string;
+ repoSlug: string;
+ pullUid: number;
+ };
+ body: {
+ reason_message: string;
+ };
+ };
+ [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_CREATE_ACTION]: {
+ params: {
+ orgSlug: string;
+ repoSlug: string;
+ pullUid: number;
+ };
+ body: {}; // TODO: define this object shape
+ };
+ [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_DELETE_ACTION]: {
+ params: {
+ orgSlug: string;
+ repoSlug: string;
+ pullUid: number;
+ commentId: string;
+ };
+ };
+ [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_UPDATE_ACTION]: {
+ params: {
+ orgSlug: string;
+ repoSlug: string;
+ pullUid: number;
+ commentId: string;
+ };
+ body: {}; // TODO: define this object shape
+ };
+ [AppRoute.REPOSITORY_PULL_REQUEST_CREATE]: {
+ params: {
+ orgSlug: string;
+ repoSlug: string;
+ };
+ querystring: {
+ from_branch?: string;
+ };
+ };
+ [AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION]: {
+ params: {
+ orgSlug: string;
+ repoSlug: string;
+ };
+ body: {
+ state_from: PullRequestFormState;
+ state_dest: PullRequestFormState;
+ summary: string;
+ description: string;
+ source_parent_org_slug: string;
+ source_repository_slug: string;
+ source_repository_from_branch: string;
+ target_parent_org_slug: string;
+ target_repository_slug: string;
+ target_repository_dest_branch: string;
+ };
+ };
+ [AppRoute.REPOSITORY_PULL_REQUEST_DELETE_ACTION]: {
+ params: {
+ orgSlug: string;
+ repoSlug: string;
+ pullUid: number;
+ };
+ };
+ [AppRoute.REPOSITORY_PULL_REQUEST_DETAILS]: {
+ params: {
+ orgSlug: string;
+ repoSlug: string;
+ pullUid: number;
+ };
+ };
+ [AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION]: {
+ params: {
+ orgSlug: string;
+ repoSlug: string;
+ pullUid: number;
+ };
+ body: {
+ merge_summary: string;
+ merge_message: string;
+ };
+ };
+ [AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION]: {
+ params: {
+ orgSlug: string;
+ repoSlug: string;
+ pullUid: number;
+ };
+ body: {}; // TODO: define this object shape
+ };
+ [AppRoute.REPOSITORY_PULL_REQUESTS]: {
+ params: {
+ orgSlug: string;
+ repoSlug: string;
+ };
+ };
+ [AppRoute.REPOSITORY_SHOW_OBJECT]: {
+ params: {
+ orgSlug: string;
+ repoSlug: string;
+ objectId: string;
+ };
+ };
+ [AppRoute.SYNTAX_HIGHLIGHT_HIGHLIGHT_CODE_ACTION]: {
+ params: {
+ outputFormat?: "html" | "json";
+ };
+ body: {
+ code: string;
+ language: string;
+ theme_scheme: AppThemeScheme;
+ };
+ };
+ [AppRoute.USER_DASHBOARD]: undefined;
+ [AppRoute.USER_DETAILS]: {
+ params: {
+ username: string;
+ };
+ };
+}
+
+export const AppRoutesSchemas: Record<AppRoute, undefined | FastifySchema> = {
+ [AppRoute.HOME]: undefined,
+ [AppRoute.THEME_SET_SCHEME_ACTION]: {
+ 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.ORGANIZATION_DETAILS]: {
+ params: {
+ type: "object",
+ required: ["orgSlug"],
+ additionalProperties: false,
+ properties: {
+ orgSlug: {
+ type: "string",
+ },
+ },
+ },
+ },
+ [AppRoute.REPOSITORY_BROWSER]: {
+ params: {
+ type: "object",
+ required: ["orgSlug", "repoSlug", "currentRef", "*"],
+ additionalProperties: false,
+ properties: {
+ orgSlug: {
+ type: "string",
+ },
+ repoSlug: {
+ type: "string",
+ },
+ currentRef: {
+ type: "string",
+ },
+ "*": {
+ type: "string",
+ },
+ },
+ },
+ },
+ [AppRoute.REPOSITORY_BROWSER_WITH_PATH]: {
+ params: {
+ type: "object",
+ required: ["orgSlug", "repoSlug", "currentRef", "*"],
+ additionalProperties: false,
+ properties: {
+ orgSlug: {
+ type: "string",
+ },
+ repoSlug: {
+ type: "string",
+ },
+ currentRef: {
+ 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_DETAILS_WITH_TRAILING_SLASH]: {
+ 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_REQUEST_CLOSE_ACTION]: {
+ params: {
+ type: "object",
+ required: ["orgSlug", "repoSlug", "pullUid"],
+ additionalProperties: false,
+ properties: {
+ orgSlug: {
+ type: "string",
+ },
+ repoSlug: {
+ type: "string",
+ },
+ pullUid: {
+ type: "number",
+ },
+ },
+ },
+ },
+ [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_CREATE_ACTION]: {
+ params: {
+ type: "object",
+ required: ["orgSlug", "repoSlug", "pullUid"],
+ additionalProperties: false,
+ properties: {
+ orgSlug: {
+ type: "string",
+ },
+ repoSlug: {
+ type: "string",
+ },
+ pullUid: {
+ type: "number",
+ },
+ },
+ },
+ // body: {}, // TODO: define this object shape
+ },
+ [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_DELETE_ACTION]: {
+ params: {
+ type: "object",
+ required: ["orgSlug", "repoSlug", "pullUid"],
+ additionalProperties: false,
+ properties: {
+ orgSlug: {
+ type: "string",
+ },
+ repoSlug: {
+ type: "string",
+ },
+ pullUid: {
+ type: "number",
+ },
+ },
+ },
+ },
+ [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_UPDATE_ACTION]: {
+ params: {
+ type: "object",
+ required: ["orgSlug", "repoSlug", "pullUid"],
+ additionalProperties: false,
+ properties: {
+ orgSlug: {
+ type: "string",
+ },
+ repoSlug: {
+ type: "string",
+ },
+ pullUid: {
+ type: "number",
+ },
+ },
+ },
+ // body: {}, // TODO: define this object shape
+ },
+ [AppRoute.REPOSITORY_PULL_REQUEST_CREATE]: {
+ params: {
+ type: "object",
+ required: ["orgSlug", "repoSlug"],
+ additionalProperties: false,
+ properties: {
+ orgSlug: {
+ type: "string",
+ },
+ repoSlug: {
+ type: "string",
+ },
+ },
+ },
+ querystring: {
+ type: "object",
+ required: [],
+ additionalProperties: false,
+ properties: {
+ from_branch: {
+ type: "string",
+ },
+ },
+ },
+ },
+ [AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION]: {
+ params: {
+ type: "object",
+ required: ["orgSlug", "repoSlug"],
+ additionalProperties: false,
+ properties: {
+ orgSlug: {
+ type: "string",
+ },
+ repoSlug: {
+ type: "string",
+ },
+ },
+ },
+ body: {
+ type: "object",
+ required: [
+ "state_from",
+ "state_dest",
+ // --
+ "summary",
+ "source_parent_org_slug",
+ "source_repository_slug",
+ "source_repository_from_branch",
+ "target_parent_org_slug",
+ "target_repository_slug",
+ "target_repository_dest_branch",
+ ],
+ additionalProperties: false,
+ properties: {
+ state_from: {
+ type: "string",
+ },
+ state_dest: {
+ type: "string",
+ },
+ summary: {
+ type: "string",
+ },
+ description: {
+ type: "string",
+ },
+ source_parent_org_slug: {
+ type: "string",
+ },
+ source_repository_slug: {
+ type: "string",
+ },
+ source_repository_from_branch: {
+ type: "string",
+ },
+ target_parent_org_slug: {
+ type: "string",
+ },
+ target_repository_slug: {
+ type: "string",
+ },
+ target_repository_dest_branch: {
+ type: "string",
+ },
+ },
+ },
+ },
+ [AppRoute.REPOSITORY_PULL_REQUEST_DELETE_ACTION]: {
+ params: {
+ type: "object",
+ required: ["orgSlug", "repoSlug", "pullUid"],
+ additionalProperties: false,
+ properties: {
+ orgSlug: {
+ type: "string",
+ },
+ repoSlug: {
+ type: "string",
+ },
+ pullUid: {
+ type: "number",
+ },
+ },
+ },
+ },
+ [AppRoute.REPOSITORY_PULL_REQUEST_DETAILS]: {
+ params: {
+ type: "object",
+ required: ["orgSlug", "repoSlug", "pullUid"],
+ additionalProperties: false,
+ properties: {
+ orgSlug: {
+ type: "string",
+ },
+ repoSlug: {
+ type: "string",
+ },
+ pullUid: {
+ type: "number",
+ },
+ },
+ },
+ },
+ [AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION]: {
+ params: {
+ type: "object",
+ required: ["orgSlug", "repoSlug", "pullUid"],
+ additionalProperties: false,
+ properties: {
+ orgSlug: {
+ type: "string",
+ },
+ repoSlug: {
+ type: "string",
+ },
+ pullUid: {
+ type: "number",
+ },
+ },
+ },
+ body: {
+ type: "object",
+ required: ["merge_summary"],
+ additionalProperties: false,
+ properties: {
+ merge_summary: {
+ type: "string",
+ },
+ merge_message: {
+ type: "string",
+ },
+ },
+ },
+ },
+ [AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION]: {
+ params: {
+ type: "object",
+ required: ["orgSlug", "repoSlug", "pullUid"],
+ additionalProperties: false,
+ properties: {
+ orgSlug: {
+ type: "string",
+ },
+ repoSlug: {
+ type: "string",
+ },
+ pullUid: {
+ type: "number",
+ },
+ },
+ },
+ },
+ [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",
+ },
+ },
+ },
+ },
+ [AppRoute.SYNTAX_HIGHLIGHT_HIGHLIGHT_CODE_ACTION]: {
+ params: {
+ type: "object",
+ required: [],
+ additionalProperties: false,
+ properties: {
+ outputFormat: {
+ type: "string",
+ enum: ["html", "json"],
+ },
+ },
+ },
+ body: {
+ type: "object",
+ required: ["code", "language", "theme_scheme"],
+ additionalProperties: false,
+ properties: {
+ code: {
+ type: "string",
+ },
+ language: {
+ type: "string",
+ },
+ theme_scheme: {
+ type: "string",
+ enum: ["light", "dark"],
+ },
+ },
+ },
+ },
+ [AppRoute.USER_DASHBOARD]: undefined,
+ [AppRoute.USER_DETAILS]: {
+ params: {
+ type: "object",
+ required: ["username"],
+ additionalProperties: false,
+ properties: {
+ username: {
+ type: "string",
+ },
+ },
+ },
+ },
+};
@@ -1,16 +1,10 @@
// 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 type { AppThemeScheme } from "./types";
+import { AppRoute, AppRoutePaths, AppRoutesSchemas } from "./routes.defs";
import { authenticatedOrLogin, guestOrRedirect } from "./utils/server";
-// app islands
-import type { PullRequestFormState } from "./islands/RepositoryPullRequestCreateForm";
// app controllers
import {
AuthController,
@@ -23,836 +17,12 @@ import {
UserController,
} from "./controllers";
-export enum AppRoute {
- HOME = "home",
- THEME_SET_SCHEME_ACTION = "theme.set_scheme.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_REQUEST_CLOSE_ACTION = "repository.pull_request.close.action",
- REPOSITORY_PULL_REQUEST_COMMENT_CREATE_ACTION = "repository.pull_request.comment.create.action",
- REPOSITORY_PULL_REQUEST_COMMENT_DELETE_ACTION = "repository.pull_request.comment.delete.action",
- REPOSITORY_PULL_REQUEST_COMMENT_UPDATE_ACTION = "repository.pull_request.comment.update.action",
- REPOSITORY_PULL_REQUEST_CREATE = "repository.pull_request.create",
- REPOSITORY_PULL_REQUEST_CREATE_ACTION = "repository.pull_request.create.action",
- REPOSITORY_PULL_REQUEST_DELETE_ACTION = "repository.pull_request.delete.action",
- REPOSITORY_PULL_REQUEST_DETAILS = "repository.pull_request.details",
- REPOSITORY_PULL_REQUEST_MERGE_ACTION = "repository.pull_request.merge.action",
- REPOSITORY_PULL_REQUEST_UPDATE_ACTION = "repository.pull_request.update.action",
- REPOSITORY_PULL_REQUESTS = "repository.pull_requests",
- REPOSITORY_SHOW_OBJECT = "repository.show_object",
- SYNTAX_HIGHLIGHT_HIGHLIGHT_CODE_ACTION = "syntax_highlight.highlight_code.action",
-}
-
-export interface AppRoutesParams extends IRouteParams {
- [AppRoute.HOME]: undefined;
- [AppRoute.THEME_SET_SCHEME_ACTION]: {
- 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_REQUEST_CLOSE_ACTION]: {
- params: {
- orgSlug: string;
- repoSlug: string;
- pullUid: number;
- };
- body: {
- reason_message: string;
- };
- };
- [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_CREATE_ACTION]: {
- params: {
- orgSlug: string;
- repoSlug: string;
- pullUid: number;
- };
- body: {}; // TODO: define this object shape
- };
- [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_DELETE_ACTION]: {
- params: {
- orgSlug: string;
- repoSlug: string;
- pullUid: number;
- commentId: string;
- };
- };
- [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_UPDATE_ACTION]: {
- params: {
- orgSlug: string;
- repoSlug: string;
- pullUid: number;
- commentId: string;
- };
- body: {}; // TODO: define this object shape
- };
- [AppRoute.REPOSITORY_PULL_REQUEST_CREATE]: {
- params: {
- orgSlug: string;
- repoSlug: string;
- };
- querystring: {
- from_branch?: string;
- };
- };
- [AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION]: {
- params: {
- orgSlug: string;
- repoSlug: string;
- };
- body: {
- state_from: PullRequestFormState;
- state_dest: PullRequestFormState;
- summary: string;
- description: string;
- source_parent_org_slug: string;
- source_repository_slug: string;
- source_repository_from_branch: string;
- target_parent_org_slug: string;
- target_repository_slug: string;
- target_repository_dest_branch: string;
- };
- };
- [AppRoute.REPOSITORY_PULL_REQUEST_DELETE_ACTION]: {
- params: {
- orgSlug: string;
- repoSlug: string;
- pullUid: number;
- };
- };
- [AppRoute.REPOSITORY_PULL_REQUEST_DETAILS]: {
- params: {
- orgSlug: string;
- repoSlug: string;
- pullUid: number;
- };
- };
- [AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION]: {
- params: {
- orgSlug: string;
- repoSlug: string;
- pullUid: number;
- };
- body: {
- merge_summary: string;
- merge_message: string;
- };
- };
- [AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION]: {
- params: {
- orgSlug: string;
- repoSlug: string;
- pullUid: number;
- };
- body: {}; // TODO: define this object shape
- };
- [AppRoute.REPOSITORY_PULL_REQUESTS]: {
- params: {
- orgSlug: string;
- repoSlug: string;
- };
- };
- [AppRoute.REPOSITORY_SHOW_OBJECT]: {
- params: {
- orgSlug: string;
- repoSlug: string;
- objectId: string;
- };
- };
- [AppRoute.SYNTAX_HIGHLIGHT_HIGHLIGHT_CODE_ACTION]: {
- params: {
- outputFormat?: "html" | "json";
- };
- body: {
- code: string;
- language: string;
- theme_scheme: AppThemeScheme;
- };
- };
-}
-
-export const AppRoutesSchemas: Record<AppRoute, undefined | FastifySchema> = {
- [AppRoute.HOME]: undefined,
- [AppRoute.THEME_SET_SCHEME_ACTION]: {
- 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", "currentRef", "*"],
- additionalProperties: false,
- properties: {
- orgSlug: {
- type: "string",
- },
- repoSlug: {
- type: "string",
- },
- currentRef: {
- 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_REQUEST_CLOSE_ACTION]: {
- params: {
- type: "object",
- required: ["orgSlug", "repoSlug", "pullUid"],
- additionalProperties: false,
- properties: {
- orgSlug: {
- type: "string",
- },
- repoSlug: {
- type: "string",
- },
- pullUid: {
- type: "number",
- },
- },
- },
- },
- [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_CREATE_ACTION]: {
- params: {
- type: "object",
- required: ["orgSlug", "repoSlug", "pullUid"],
- additionalProperties: false,
- properties: {
- orgSlug: {
- type: "string",
- },
- repoSlug: {
- type: "string",
- },
- pullUid: {
- type: "number",
- },
- },
- },
- // body: {}, // TODO: define this object shape
- },
- [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_DELETE_ACTION]: {
- params: {
- type: "object",
- required: ["orgSlug", "repoSlug", "pullUid"],
- additionalProperties: false,
- properties: {
- orgSlug: {
- type: "string",
- },
- repoSlug: {
- type: "string",
- },
- pullUid: {
- type: "number",
- },
- },
- },
- },
- [AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_UPDATE_ACTION]: {
- params: {
- type: "object",
- required: ["orgSlug", "repoSlug", "pullUid"],
- additionalProperties: false,
- properties: {
- orgSlug: {
- type: "string",
- },
- repoSlug: {
- type: "string",
- },
- pullUid: {
- type: "number",
- },
- },
- },
- // body: {}, // TODO: define this object shape
- },
- [AppRoute.REPOSITORY_PULL_REQUEST_CREATE]: {
- params: {
- type: "object",
- required: ["orgSlug", "repoSlug"],
- additionalProperties: false,
- properties: {
- orgSlug: {
- type: "string",
- },
- repoSlug: {
- type: "string",
- },
- },
- },
- querystring: {
- type: "object",
- required: [],
- additionalProperties: false,
- properties: {
- from_branch: {
- type: "string",
- },
- },
- },
- },
- [AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION]: {
- params: {
- type: "object",
- required: ["orgSlug", "repoSlug"],
- additionalProperties: false,
- properties: {
- orgSlug: {
- type: "string",
- },
- repoSlug: {
- type: "string",
- },
- },
- },
- body: {
- type: "object",
- required: [
- "state_from",
- "state_dest",
- // --
- "summary",
- "source_parent_org_slug",
- "source_repository_slug",
- "source_repository_from_branch",
- "target_parent_org_slug",
- "target_repository_slug",
- "target_repository_dest_branch",
- ],
- additionalProperties: false,
- properties: {
- state_from: {
- type: "string",
- },
- state_dest: {
- type: "string",
- },
- summary: {
- type: "string",
- },
- description: {
- type: "string",
- },
- source_parent_org_slug: {
- type: "string",
- },
- source_repository_slug: {
- type: "string",
- },
- source_repository_from_branch: {
- type: "string",
- },
- target_parent_org_slug: {
- type: "string",
- },
- target_repository_slug: {
- type: "string",
- },
- target_repository_dest_branch: {
- type: "string",
- },
- },
- },
- },
- [AppRoute.REPOSITORY_PULL_REQUEST_DELETE_ACTION]: {
- params: {
- type: "object",
- required: ["orgSlug", "repoSlug", "pullUid"],
- additionalProperties: false,
- properties: {
- orgSlug: {
- type: "string",
- },
- repoSlug: {
- type: "string",
- },
- pullUid: {
- type: "number",
- },
- },
- },
- },
- [AppRoute.REPOSITORY_PULL_REQUEST_DETAILS]: {
- params: {
- type: "object",
- required: ["orgSlug", "repoSlug", "pullUid"],
- additionalProperties: false,
- properties: {
- orgSlug: {
- type: "string",
- },
- repoSlug: {
- type: "string",
- },
- pullUid: {
- type: "number",
- },
- },
- },
- },
- [AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION]: {
- params: {
- type: "object",
- required: ["orgSlug", "repoSlug", "pullUid"],
- additionalProperties: false,
- properties: {
- orgSlug: {
- type: "string",
- },
- repoSlug: {
- type: "string",
- },
- pullUid: {
- type: "number",
- },
- },
- },
- body: {
- type: "object",
- required: ["merge_summary"],
- additionalProperties: false,
- properties: {
- merge_summary: {
- type: "string",
- },
- merge_message: {
- type: "string",
- },
- },
- },
- },
- [AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION]: {
- params: {
- type: "object",
- required: ["orgSlug", "repoSlug", "pullUid"],
- additionalProperties: false,
- properties: {
- orgSlug: {
- type: "string",
- },
- repoSlug: {
- type: "string",
- },
- pullUid: {
- type: "number",
- },
- },
- },
- },
- [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",
- },
- },
- },
- },
- [AppRoute.SYNTAX_HIGHLIGHT_HIGHLIGHT_CODE_ACTION]: {
- params: {
- type: "object",
- required: [],
- additionalProperties: false,
- properties: {
- outputFormat: {
- type: "string",
- enum: ["html", "json"],
- },
- },
- },
- body: {
- type: "object",
- required: ["code", "language", "theme_scheme"],
- additionalProperties: false,
- properties: {
- code: {
- type: "string",
- },
- language: {
- type: "string",
- },
- theme_scheme: {
- type: "string",
- enum: ["light", "dark"],
- },
- },
- },
- },
-};
-
const RootAppRouter: AppRouter = () => {
- const guestOrDashboardRedirect = guestOrRedirect("/dashboard");
+ const guestOrDashboardRedirect = guestOrRedirect(
+ AppRoutePaths[AppRoute.USER_DASHBOARD]
+ );
const loggedOrLoginRedirect = authenticatedOrLogin();
+
return (
<Router.Root>
<></>
@@ -860,7 +30,7 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.THEME_SET_SCHEME_ACTION}
method={"GET"}
- path={"/theme/:themeScheme"}
+ path={AppRoutePaths[AppRoute.THEME_SET_SCHEME_ACTION]}
schema={AppRoutesSchemas[AppRoute.THEME_SET_SCHEME_ACTION]}
handler={ThemeController.setThemeSchemeAction}
/>
@@ -868,7 +38,7 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.HOME}
method={"GET"}
- path={"/"}
+ path={AppRoutePaths[AppRoute.HOME]}
preHandler={guestOrDashboardRedirect}
handler={HomeController.getHomeView}
/>
@@ -876,14 +46,14 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.AUTH_REGISTER}
method={"GET"}
- path={"/auth/register"}
+ path={AppRoutePaths[AppRoute.AUTH_REGISTER]}
preHandler={guestOrDashboardRedirect}
handler={AuthController.getRegisterView}
/>
<Router.Route
name={AppRoute.AUTH_REGISTER_ACTION}
method={"POST"}
- path={"/auth/register"}
+ path={AppRoutePaths[AppRoute.AUTH_REGISTER_ACTION]}
preHandler={guestOrDashboardRedirect}
schema={AppRoutesSchemas[AppRoute.AUTH_REGISTER_ACTION]}
handler={AuthController.postRegisterAction}
@@ -892,14 +62,14 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.AUTH_LOGIN}
method={"GET"}
- path={"/auth/login"}
+ path={AppRoutePaths[AppRoute.AUTH_LOGIN]}
preHandler={guestOrDashboardRedirect}
handler={AuthController.getLoginView}
/>
<Router.Route
name={AppRoute.AUTH_LOGIN_ACTION}
method={"POST"}
- path={"/auth/login"}
+ path={AppRoutePaths[AppRoute.AUTH_LOGIN_ACTION]}
preHandler={guestOrDashboardRedirect}
schema={AppRoutesSchemas[AppRoute.AUTH_LOGIN_ACTION]}
handler={AuthController.postLoginAction}
@@ -907,7 +77,7 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.AUTH_LOGOUT_ACTION}
method={"GET"}
- path={"/auth/logout"}
+ path={AppRoutePaths[AppRoute.AUTH_LOGOUT_ACTION]}
preHandler={loggedOrLoginRedirect}
schema={AppRoutesSchemas[AppRoute.AUTH_LOGOUT_ACTION]}
handler={AuthController.getLogoutAction}
@@ -916,21 +86,21 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.USER_DASHBOARD}
method={"GET"}
- path={"/dashboard"}
+ path={AppRoutePaths[AppRoute.USER_DASHBOARD]}
preHandler={loggedOrLoginRedirect}
handler={UserController.getUserDashboardView}
/>
<Router.Route
name={AppRoute.USER_DETAILS}
method={"GET"}
- path={"/@:username"}
+ path={AppRoutePaths[AppRoute.USER_DETAILS]}
handler={UserController.getUserDetailsView}
/>
{/* --- */}
<Router.Route
name={AppRoute.ORGANIZATION_DETAILS}
method={"GET"}
- path={"/:orgSlug"}
+ path={AppRoutePaths[AppRoute.ORGANIZATION_DETAILS]}
schema={AppRoutesSchemas[AppRoute.ORGANIZATION_DETAILS]}
handler={OrganizationController.getOrganizationDetailsView}
/>
@@ -938,42 +108,42 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.REPOSITORY_BROWSER}
method={"GET"}
- path={"/:orgSlug/:repoSlug/:currentRef/tree"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_BROWSER]}
schema={AppRoutesSchemas[AppRoute.REPOSITORY_BROWSER]}
handler={RepositoryController.getRepositoryBrowserView}
/>
<Router.Route
- name={AppRoute.REPOSITORY_BROWSER + ".with_path"}
+ name={AppRoute.REPOSITORY_BROWSER_WITH_PATH}
method={"GET"}
- path={"/:orgSlug/:repoSlug/:currentRef/tree/*"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_BROWSER_WITH_PATH]}
schema={AppRoutesSchemas[AppRoute.REPOSITORY_BROWSER]}
handler={RepositoryController.getRepositoryBrowserView}
/>
<Router.Route
name={AppRoute.REPOSITORY_COMMITS_LOG}
method={"GET"}
- path={"/:orgSlug/:repoSlug/:currentRef/commits"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_COMMITS_LOG]}
schema={AppRoutesSchemas[AppRoute.REPOSITORY_COMMITS_LOG]}
handler={RepositoryController.getRepositoryCommitsLogView}
/>
<Router.Route
name={AppRoute.REPOSITORY_COMPARE}
method={"GET"}
- path={"/:orgSlug/:repoSlug/compare/:refA..:refB"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_COMPARE]}
schema={AppRoutesSchemas[AppRoute.REPOSITORY_COMPARE]}
handler={RepositoryController.getRepositoryCompareView}
/>
<Router.Route
name={AppRoute.REPOSITORY_CREATE}
method={"GET"}
- path={"/repo/new"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_CREATE]}
preHandler={loggedOrLoginRedirect}
handler={RepositoryController.getRepositoryCreateView}
/>
<Router.Route
name={AppRoute.REPOSITORY_CREATE_ACTION}
method={"POST"}
- path={"/repo/new"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_CREATE_ACTION]}
preHandler={loggedOrLoginRedirect}
schema={AppRoutesSchemas[AppRoute.REPOSITORY_CREATE_ACTION]}
handler={RepositoryController.postRepositoryCreateAction}
@@ -981,41 +151,41 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.REPOSITORY_DETAILS}
method={"GET"}
- path={"/:orgSlug/:repoSlug"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_DETAILS]}
schema={AppRoutesSchemas[AppRoute.REPOSITORY_DETAILS]}
handler={RepositoryController.getRepositoryDetailsView}
/>
<Router.Route
- name={AppRoute.REPOSITORY_DETAILS}
+ name={AppRoute.REPOSITORY_DETAILS_WITH_TRAILING_SLASH}
method={"GET"}
- path={"/:orgSlug/:repoSlug/"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_DETAILS_WITH_TRAILING_SLASH]}
schema={AppRoutesSchemas[AppRoute.REPOSITORY_DETAILS]}
handler={RepositoryController.getRepositoryDetailsView}
/>
<Router.Route
name={AppRoute.REPOSITORY_EXPLORE}
method={"GET"}
- path={"/repo/explore"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_EXPLORE]}
handler={RepositoryController.getRepositoryExploreView}
/>
<Router.Route
name={AppRoute.REPOSITORY_FORK}
method={"GET"}
- path={"/:orgSlug/:repoSlug/fork"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_FORK]}
preHandler={loggedOrLoginRedirect}
handler={RepositoryController.getRepositoryForkView}
/>
<Router.Route
name={AppRoute.REPOSITORY_FORK_ACTION}
method={"POST"}
- path={"/:orgSlug/:repoSlug/fork"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_FORK_ACTION]}
preHandler={loggedOrLoginRedirect}
handler={RepositoryController.postRepositoryForkAction}
/>
<Router.Route
name={AppRoute.REPOSITORY_PULL_REQUEST_CLOSE_ACTION}
method={"POST"}
- path={"/:orgSlug/:repoSlug/pulls/:pullUid/close"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUEST_CLOSE_ACTION]}
schema={
AppRoutesSchemas[AppRoute.REPOSITORY_PULL_REQUEST_CLOSE_ACTION]
}
@@ -1025,11 +195,17 @@ const RootAppRouter: AppRouter = () => {
}
/>
<Router.Route
- name={AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION}
+ name={AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_CREATE_ACTION}
method={"POST"}
- path={"/:orgSlug/:repoSlug/pulls/:pullUid/comment"}
+ path={
+ AppRoutePaths[
+ AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_CREATE_ACTION
+ ]
+ }
schema={
- AppRoutesSchemas[AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION]
+ AppRoutesSchemas[
+ AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_CREATE_ACTION
+ ]
}
preHandler={loggedOrLoginRedirect}
handler={
@@ -1037,33 +213,45 @@ const RootAppRouter: AppRouter = () => {
}
/>
<Router.Route
- name={AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION}
+ name={AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_DELETE_ACTION}
method={"POST"}
- path={"/:orgSlug/:repoSlug/pulls/:pullUid/comment/edit"}
+ path={
+ AppRoutePaths[
+ AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_DELETE_ACTION
+ ]
+ }
schema={
- AppRoutesSchemas[AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION]
+ AppRoutesSchemas[
+ AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_DELETE_ACTION
+ ]
}
preHandler={loggedOrLoginRedirect}
handler={
- RepositoryPullRequestsController.getRepositoryPullRequestCommentUpdateAction
+ RepositoryPullRequestsController.getRepositoryPullRequestCommentDeleteAction
}
/>
<Router.Route
- name={AppRoute.REPOSITORY_PULL_REQUEST_DELETE_ACTION}
+ name={AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_UPDATE_ACTION}
method={"POST"}
- path={"/:orgSlug/:repoSlug/pulls/:pullUid/comment/delete"}
+ path={
+ AppRoutePaths[
+ AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_UPDATE_ACTION
+ ]
+ }
schema={
- AppRoutesSchemas[AppRoute.REPOSITORY_PULL_REQUEST_DELETE_ACTION]
+ AppRoutesSchemas[
+ AppRoute.REPOSITORY_PULL_REQUEST_COMMENT_UPDATE_ACTION
+ ]
}
preHandler={loggedOrLoginRedirect}
handler={
- RepositoryPullRequestsController.getRepositoryPullRequestCommentDeleteAction
+ RepositoryPullRequestsController.getRepositoryPullRequestCommentUpdateAction
}
/>
<Router.Route
name={AppRoute.REPOSITORY_PULL_REQUEST_CREATE}
method={"GET"}
- path={"/:orgSlug/:repoSlug/pulls/new"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUEST_CREATE]}
schema={AppRoutesSchemas[AppRoute.REPOSITORY_PULL_REQUEST_CREATE]}
preHandler={loggedOrLoginRedirect}
handler={
@@ -1073,7 +261,7 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION}
method={"POST"}
- path={"/:orgSlug/:repoSlug/pulls/new"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION]}
schema={
AppRoutesSchemas[AppRoute.REPOSITORY_PULL_REQUEST_CREATE_ACTION]
}
@@ -1085,7 +273,7 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.REPOSITORY_PULL_REQUEST_DELETE_ACTION}
method={"POST"}
- path={"/:orgSlug/:repoSlug/pulls/:pullUid/delete"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUEST_DELETE_ACTION]}
schema={
AppRoutesSchemas[AppRoute.REPOSITORY_PULL_REQUEST_DELETE_ACTION]
}
@@ -1097,7 +285,7 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.REPOSITORY_PULL_REQUEST_DETAILS}
method={"GET"}
- path={"/:orgSlug/:repoSlug/pulls/:pullUid"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUEST_DETAILS]}
schema={AppRoutesSchemas[AppRoute.REPOSITORY_PULL_REQUEST_DETAILS]}
preHandler={loggedOrLoginRedirect}
handler={
@@ -1107,7 +295,7 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION}
method={"POST"}
- path={"/:orgSlug/:repoSlug/pulls/:pullUid/merge"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION]}
schema={
AppRoutesSchemas[AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION]
}
@@ -1119,7 +307,7 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION}
method={"POST"}
- path={"/:orgSlug/:repoSlug/pulls/:pullUid/edit"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION]}
schema={
AppRoutesSchemas[AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION]
}
@@ -1131,7 +319,7 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.REPOSITORY_PULL_REQUESTS}
method={"GET"}
- path={"/:orgSlug/:repoSlug/pulls"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_PULL_REQUESTS]}
schema={AppRoutesSchemas[AppRoute.REPOSITORY_PULL_REQUESTS]}
handler={
RepositoryPullRequestsController.getRepositoryPullRequestsView
@@ -1140,7 +328,7 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.REPOSITORY_SHOW_OBJECT}
method={"GET"}
- path={"/:orgSlug/:repoSlug/show/:objectId"}
+ path={AppRoutePaths[AppRoute.REPOSITORY_SHOW_OBJECT]}
schema={AppRoutesSchemas[AppRoute.REPOSITORY_SHOW_OBJECT]}
handler={RepositoryController.getRepositoryShowObjectView}
/>
@@ -1148,7 +336,7 @@ const RootAppRouter: AppRouter = () => {
<Router.Route
name={AppRoute.SYNTAX_HIGHLIGHT_HIGHLIGHT_CODE_ACTION}
method={"POST"}
- path={"/api/syntax/highlight/:outputFormat"}
+ path={AppRoutePaths[AppRoute.SYNTAX_HIGHLIGHT_HIGHLIGHT_CODE_ACTION]}
schema={
AppRoutesSchemas[AppRoute.SYNTAX_HIGHLIGHT_HIGHLIGHT_CODE_ACTION]
}
@@ -1,6 +1,6 @@
import type { preHandlerHookHandler } from "fastify";
// app
-import { AppRoute } from "../../routes";
+import { AppRoute } from "../../routes.defs";
export const authenticatedOrLogin =
(): preHandlerHookHandler => async (request, reply) => {
@@ -0,0 +1,68 @@
+import { AppRoute, AppRoutePaths, AppRoutesParams } from "../../routes.defs";
+
+export default function buildRouteLink<P extends AppRoute>(
+ route: P,
+ routeParams: "params" extends keyof AppRoutesParams[P]
+ ? AppRoutesParams[P]["params"]
+ : {} | null
+): typeof AppRoutePaths[P] {
+ const path = AppRoutePaths[route];
+
+ if (
+ routeParams == null ||
+ (routeParams != null &&
+ typeof routeParams === "object" &&
+ Object.keys(routeParams as any).length <= 0)
+ ) {
+ return path;
+ }
+
+ const paramsEntries =
+ typeof routeParams === "object" ? Object.entries(routeParams as never) : [];
+
+ let pathParts = path.split("/");
+ let linkBuilder = [] as string[];
+
+ paramsEntries.forEach(([k, v]) => {
+ const keyRegExp = new RegExp(`:${k}`, "g");
+ pathParts = pathParts.map((part) => {
+ if (Array.isArray(part.match(keyRegExp))) {
+ return part.replace(keyRegExp, `${String(v)}`);
+ } else if (k === "*" && part === "*") {
+ return String(v);
+ }
+ return part;
+ });
+ });
+
+ pathParts.map((part) => linkBuilder.push(part));
+ return linkBuilder.join("/");
+}
+
+export function buildPathLink<P extends AppRoute>(
+ path: string,
+ routeParams: "params" extends keyof AppRoutesParams[P]
+ ? AppRoutesParams[P]["params"]
+ : undefined
+): string {
+ const paramsEntries =
+ typeof routeParams === "object" ? Object.entries(routeParams as never) : [];
+
+ let pathParts = path.split("/");
+ let linkBuilder = [] as string[];
+
+ paramsEntries.forEach(([k, v]) => {
+ const keyRegExp = new RegExp(`:${k}`, "g");
+ pathParts = pathParts.map((part) => {
+ if (Array.isArray(part.match(keyRegExp))) {
+ return part.replace(keyRegExp, `${String(v)}`);
+ } else if (k === "*" && part === "*") {
+ return String(v);
+ }
+ return part;
+ });
+ });
+
+ pathParts.map((part) => linkBuilder.push(part));
+ return linkBuilder.join("/");
+}
@@ -1,4 +1,5 @@
+export { escapeHtmlCode } from "./escapeHtmlCode";
+export { default as buildRouteLink } from "./buildRouteLink";
export { default as getFormEntries } from "./getFormEntries";
-export { default as slugify } from "./slugify";
export { default as getGitdiffLineStart } from "./getGitdiffLineStart";
-export { escapeHtmlCode } from "./escapeHtmlCode";
+export { default as slugify } from "./slugify";
@@ -5,7 +5,9 @@ import styled from "styled-components";
// app
import type { CommonProps } from "../types";
+import { AppRoute } from "../routes.defs";
import { ButtonAnchor, Layout, PageWrapper } from "../components";
+import { buildRouteLink } from "../utils/shared";
export interface HomeViewProps extends CommonProps {
foo?: boolean;
@@ -17,9 +19,13 @@ const HomeView: ReactView<HomeViewProps> = (props) => {
<Layout {...commonProps}>
<PageWrapper>
<StyledButtonsRow>
- <ButtonAnchor href={"/auth/register"}>Register</ButtonAnchor>
- <ButtonAnchor href={"/auth/login"}>Login</ButtonAnchor>
- <ButtonAnchor href={"/repo/explore"}>
+ <ButtonAnchor href={buildRouteLink(AppRoute.AUTH_REGISTER, {})}>
+ Register
+ </ButtonAnchor>
+ <ButtonAnchor href={buildRouteLink(AppRoute.AUTH_LOGIN, {})}>
+ Login
+ </ButtonAnchor>
+ <ButtonAnchor href={buildRouteLink(AppRoute.REPOSITORY_EXPLORE, {})}>
Explore Repositories
</ButtonAnchor>
</StyledButtonsRow>
@@ -5,7 +5,9 @@ import React from "react";
// app
import type { CommonProps } from "../types";
+import { AppRoute } from "../routes.defs";
import { Card, Layout, PageWrapper } from "../components";
+import { buildRouteLink } from "../utils/shared";
// app islands
import Code, { getThemedCodeCss } from "../islands/Code";
@@ -60,7 +62,7 @@ const InternalErrorView: ReactView<InternalErrorViewProps> = ({
<div style={{ marginTop: 8 }}>
{!isNotFoundError &&
(isRecoverableError ? (
- <a href="/" role={"button"}>
+ <a href={buildRouteLink(AppRoute.HOME, null)} role={"button"}>
Try again 🔄
</a>
) : (
@@ -2,7 +2,9 @@ import type { ReactView } from "@ethicdevs/react-monolith";
import React from "react";
// app
import type { CommonProps } from "../../types";
+import { AppRoute } from "../../routes.defs";
import { Button, Card, Layout, PageWrapper, TextInput } from "../../components";
+import { buildRouteLink } from "../../utils/shared";
export interface LoginViewProps extends CommonProps {
errorMessage?: null | string;
@@ -42,7 +44,10 @@ const LoginView: ReactView<LoginViewProps> = ({
themeScheme={commonProps.themeScheme}
style={{ marginTop: errorMessage != null ? 16 : 0, padding: 16 }}
>
- <form action={`/auth/login`} method={"POST"}>
+ <form
+ method={"POST"}
+ action={buildRouteLink(AppRoute.AUTH_LOGIN_ACTION, {})}
+ >
{/* Email Address */}
<div style={{ marginTop: 0 }}>
<label htmlFor={"username"} style={{ fontWeight: "bold" }}>
@@ -2,7 +2,9 @@ import type { ReactView } from "@ethicdevs/react-monolith";
import React from "react";
// app
import type { CommonProps } from "../../types";
+import { AppRoute } from "../../routes.defs";
import { Button, Card, Layout, PageWrapper, TextInput } from "../../components";
+import { buildRouteLink } from "../../utils/shared";
export interface RegisterViewProps extends CommonProps {
errorMessage?: null | string;
@@ -43,7 +45,10 @@ const RegisterView: ReactView<RegisterViewProps> = ({
themeScheme={commonProps.themeScheme}
style={{ marginTop: errorMessage != null ? 16 : 0, padding: 16 }}
>
- <form action={`/auth/register`} method={"POST"}>
+ <form
+ method={"POST"}
+ action={buildRouteLink(AppRoute.AUTH_REGISTER_ACTION, {})}
+ >
{/* Email Address */}
<div>
<label htmlFor={"username"} style={{ fontWeight: "bold" }}>
@@ -6,7 +6,9 @@ import React from "react";
import { Organization } from "@prisma/client";
// app
import type { CommonProps } from "../../types";
+import { AppRoute } from "../../routes.defs";
import { Layout, PageWrapper } from "../../components";
+import { buildRouteLink } from "../../utils/shared";
// app islands
import RepositoryCreateForm from "../../islands/RepositoryCreateForm";
@@ -39,7 +41,10 @@ const RepositoryCreateView: ReactView<RepositoryCreateViewProps> = ({
<p>{errorMessage}</p>
</div>
)}
- <form action={`/repo/new`} method={"POST"}>
+ <form
+ action={buildRouteLink(AppRoute.REPOSITORY_CREATE_ACTION, {})}
+ method={"POST"}
+ >
<div data-islandid={`${RepositoryCreateForm.name}$$0`}>
<RepositoryCreateForm
availableParentOrgs={availableParentOrgs}
@@ -13,6 +13,7 @@ import type {
RepositoryLog,
RepositoryWithForkedFromRepo,
} from "../../types";
+import { AppRoute } from "../../routes.defs";
import { NamedColors } from "../../utils/style";
import {
Card,
@@ -23,6 +24,7 @@ import {
MarkdownToJsx,
PageWrapper,
} from "../../components";
+import { buildRouteLink } from "../../utils/shared";
// app islands
import RepositoryCommitSummaryLine from "../../islands/RepositoryCommitSummaryLine";
import RepositoryHero from "../../islands/RepositoryHero";
@@ -235,13 +237,15 @@ const RepositoryDetailsView: ReactView<RepositoryDetailsViewProps> = ({
branch.trim() != "" && (
<React.Fragment key={branch}>
<a
- href={`/${parentOrg.slug}/${
- repo.slug
- }/${encodeURIComponent(branch)}/tree/${
- path != null && path.trim() !== "" && path !== "/"
- ? path
- : ""
- }`}
+ href={buildRouteLink(AppRoute.REPOSITORY_BROWSER, {
+ orgSlug: parentOrg.slug,
+ repoSlug: repo.slug,
+ currentRef: encodeURIComponent(branch),
+ "*":
+ path != null && path.trim() !== "" && path !== "/"
+ ? path
+ : "",
+ })}
>
{branch}
</a>
@@ -6,7 +6,9 @@ import React from "react";
import { Organization, ResourceVisibility } from "@prisma/client";
// app
import type { CommonProps, RepositoryWithForkedFromRepo } from "../../types";
+import { AppRoute } from "../../routes.defs";
import { IslandWrapper, Layout, PageWrapper } from "../../components";
+import { buildRouteLink } from "../../utils/shared";
// app islands
import RepositoryForkForm from "../../islands/RepositoryForkForm";
import RepositoryHero from "../../islands/RepositoryHero";
@@ -51,8 +53,11 @@ const RepositoryForkView: ReactView<RepositoryForkViewProps> = ({
</div>
)}
<form
- action={`/${sourceParentOrg.slug}/${sourceRepo.slug}/fork`}
method={"POST"}
+ action={buildRouteLink(AppRoute.REPOSITORY_FORK_ACTION, {
+ orgSlug: sourceParentOrg.slug,
+ repoSlug: sourceRepo.slug,
+ })}
>
<div data-islandid={`${RepositoryForkForm.name}$$0`}>
<RepositoryForkForm
@@ -11,6 +11,8 @@ import type {
RepositoryObject,
RepositoryWithForkedFromRepo,
} from "../../types";
+import { AppRoute } from "../../routes.defs";
+import { buildRouteLink } from "../../utils/shared";
import {
Card,
Grid,
@@ -32,6 +34,7 @@ export interface RepositoryPullRequestDetailsViewProps extends CommonProps {
sourceRepo: RepositoryWithForkedFromRepo;
targetParentOrg: Organization;
targetRepo: RepositoryWithForkedFromRepo;
+ isCurrentUserAllowedToMerge?: boolean;
}
const RepositoryPullRequestDetailsView: ReactView<RepositoryPullRequestDetailsViewProps> =
@@ -44,6 +47,7 @@ const RepositoryPullRequestDetailsView: ReactView<RepositoryPullRequestDetailsVi
sourceRepo,
targetParentOrg: parentOrg,
targetRepo: repo,
+ isCurrentUserAllowedToMerge = false,
}) => {
return (
<Layout {...commonProps}>
@@ -107,16 +111,50 @@ const RepositoryPullRequestDetailsView: ReactView<RepositoryPullRequestDetailsVi
</Grid.Row>
</Grid.Col>
<Grid.Col fluid style={{ marginTop: 32 }}>
- <a
- href={`/${parentOrg.slug}/${repo.slug}/pulls/${pr.uid}?action=edit`}
- >
- Edit PR
- </a>
- <a
- href={`/${parentOrg.slug}/${repo.slug}/pulls/${pr.uid}?action=delete`}
- >
- Delete PR
- </a>
+ <Grid.Row fluid>
+ <Grid.Col fluid>
+ <a
+ href={buildRouteLink(
+ AppRoute.REPOSITORY_PULL_REQUEST_UPDATE_ACTION,
+ {
+ orgSlug: parentOrg.slug,
+ repoSlug: repo.slug,
+ pullUid: pr.uid,
+ }
+ )}
+ >
+ Edit PR
+ </a>
+ <a
+ href={buildRouteLink(
+ AppRoute.REPOSITORY_PULL_REQUEST_DELETE_ACTION,
+ {
+ orgSlug: parentOrg.slug,
+ repoSlug: repo.slug,
+ pullUid: pr.uid,
+ }
+ )}
+ >
+ Delete PR
+ </a>
+ <a href={buildRouteLink(AppRoute.HOME, {})}>Home</a>
+ </Grid.Col>
+ {isCurrentUserAllowedToMerge && (
+ <Grid.Col>
+ <form
+ method={"POST"}
+ action={buildRouteLink(
+ AppRoute.REPOSITORY_PULL_REQUEST_MERGE_ACTION,
+ {
+ orgSlug: parentOrg.slug,
+ repoSlug: repo.slug,
+ pullUid: pr.uid,
+ }
+ )}
+ ></form>
+ </Grid.Col>
+ )}
+ </Grid.Row>
</Grid.Col>
<Grid.Col fluid style={{ marginTop: 24 }}>
<Card
@@ -6,7 +6,9 @@ import React from "react";
import type { Organization, PullRequest } from "@prisma/client";
// app
import type { CommonProps, RepositoryWithForkedFromRepo } from "../../types";
+import { AppRoute } from "../../routes.defs";
import { Grid, IslandWrapper, Layout, PageWrapper } from "../../components";
+import { buildRouteLink } from "../../utils/shared";
// app islands
import RepositoryHero from "../../islands/RepositoryHero";
@@ -40,7 +42,12 @@ const RepositoryPullRequestsView: ReactView<RepositoryPullRequestsViewProps> =
/>
</IslandWrapper>
<Grid.Col fluid style={{ marginTop: 32 }}>
- <a href={`/${parentOrg.slug}/${repo.slug}/pulls/new`}>
+ <a
+ href={buildRouteLink(AppRoute.REPOSITORY_PULL_REQUEST_CREATE, {
+ orgSlug: parentOrg.slug,
+ repoSlug: repo.slug,
+ })}
+ >
New Pull Request
</a>
</Grid.Col>
@@ -100,7 +107,16 @@ const RepositoryPullRequestsView: ReactView<RepositoryPullRequestsViewProps> =
fluid
style={{ marginTop: idx === 0 ? 0 : 16 }}
>
- <a href={`/${parentOrg.slug}/${repo.slug}/pulls/${pr.uid}`}>
+ <a
+ href={buildRouteLink(
+ AppRoute.REPOSITORY_PULL_REQUEST_DETAILS,
+ {
+ orgSlug: parentOrg.slug,
+ repoSlug: repo.slug,
+ pullUid: pr.uid,
+ }
+ )}
+ >
#{pr.uid} - {pr.summary} [{pr.state}]
</a>
<span style={{ opacity: 0.67 }}>
@@ -142,7 +158,15 @@ const RepositoryPullRequestsView: ReactView<RepositoryPullRequestsViewProps> =
<h1>No Pull Request Yet</h1>
<p>
<span>Be the change you want to see, </span>
- <a href={`/${parentOrg.slug}/${repo.slug}/pulls/new`}>
+ <a
+ href={buildRouteLink(
+ AppRoute.REPOSITORY_PULL_REQUEST_CREATE,
+ {
+ orgSlug: parentOrg.slug,
+ repoSlug: repo.slug,
+ }
+ )}
+ >
open the first Pull Request
</a>
<span> to this repository 🚀.</span>