GitFOSS
feat(pull_requests): implement create/get pull request service methods
+ 151
- 4
new file
.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+    "typescript.tsdk": "node_modules/typescript/lib"
+}

new file
app/services/pullRequest/createPullRequest.ts
@@ -0,0 +1,42 @@
+// 1st-party
+import type { ServiceMethodFactory } from "@ethicdevs/react-monolith";
+// generated via script[generate:prisma]
+import type { PullRequest } from "@prisma/client";
+// service
+import type { CreatePullRequestDTO, PullRequestServiceDeps } from "./types";
+
+const createPullRequest: ServiceMethodFactory<
+  PullRequestServiceDeps,
+  [CreatePullRequestDTO],
+  Promise<PullRequest>
+> = ({ request }) => {
+  return async ({ author, source, summary, target, textMd }) => {
+    const pullRequest = await request.prisma.pullRequest.create({
+      data: {
+        summary,
+        textMd,
+        sourceBranch: source.fromBranch,
+        targetBranch: target.destBranch,
+        author: {
+          connect: {
+            id: author.id,
+          },
+        },
+        sourceRepository: {
+          connect: {
+            id: source.repository.id,
+          },
+        },
+        targetRepository: {
+          connect: {
+            id: target.repository.id,
+          },
+        },
+      },
+    });
+
+    return pullRequest;
+  };
+};
+
+export default createPullRequest;

new file
app/services/pullRequest/getPullRequest.ts
@@ -0,0 +1,28 @@
+// 1st-party
+import type { ServiceMethodFactory } from "@ethicdevs/react-monolith";
+// generated via script[generate:prisma]
+import type { PullRequest } from "@prisma/client";
+// service
+import type {
+  PullRequestSelectOrIncludes,
+  PullRequestServiceDeps,
+} from "./types";
+
+const getPullRequest: ServiceMethodFactory<
+  PullRequestServiceDeps,
+  [string, PullRequestSelectOrIncludes],
+  Promise<PullRequest | null>
+> = ({ request }) => {
+  return async (pullRequestId, selectOrIncludes) => {
+    const pullRequest = await request.prisma.pullRequest.findUnique({
+      ...selectOrIncludes,
+      where: {
+        id: pullRequestId,
+      },
+    });
+
+    return pullRequest;
+  };
+};
+
+export default getPullRequest;

new file
app/services/pullRequest/index.ts
@@ -0,0 +1,15 @@
+// 1st-party
+import { makeService } from "@ethicdevs/react-monolith";
+// service types
+import type { PullRequestServiceDeps, PullRequestServiceAPI } from "./types";
+// service methods
+import { default as makeCreatePullRequest } from "./createPullRequest";
+import { default as makeGetPullRequest } from "./getPullRequest";
+
+export const makePullRequestService = makeService<
+  PullRequestServiceAPI,
+  PullRequestServiceDeps
+>({
+  createPullRequest: makeCreatePullRequest,
+  getPullRequest: makeGetPullRequest,
+});

new file
app/services/pullRequest/types.ts
@@ -0,0 +1,33 @@
+// 1st-party
+import { ServiceApiContract } from "@ethicdevs/react-monolith";
+// 3rd-party
+import { FastifyRequest } from "fastify";
+// generated via script[prisma:generate]
+import { Prisma, PullRequest, Repository, User } from "@prisma/client";
+
+export interface CreatePullRequestDTO {
+  author: User;
+  summary: string;
+  textMd: string;
+  source: {
+    repository: Repository;
+    fromBranch: string;
+  };
+  target: {
+    repository: Repository;
+    destBranch: string;
+  };
+}
+
+export type PullRequestSelectOrIncludes =
+  | { select?: Prisma.PullRequestSelect }
+  | { includes?: Prisma.PullRequestInclude };
+
+export interface PullRequestServiceAPI extends ServiceApiContract {
+  getPullRequest(pullRequestId: string): Promise<PullRequest | null>;
+  createPullRequest(dto: CreatePullRequestDTO): Promise<PullRequest>;
+}
+
+export interface PullRequestServiceDeps {
+  request: FastifyRequest;
+}

new file
db/migrations/20220929155220_make_pull_request_closed_at_optional/migration.sql
@@ -0,0 +1,2 @@
+-- AlterTable
+ALTER TABLE "PullRequest" ALTER COLUMN "closedAt" DROP NOT NULL;

new file
db/migrations/20220929155607_rework_uniqueness_in_relations/migration.sql
@@ -0,0 +1,19 @@
+/*
+  Warnings:
+
+  - A unique constraint covering the columns `[uid,targetRepositoryId]` on the table `PullRequest` will be added. If there are existing duplicate values, this will fail.
+  - A unique constraint covering the columns `[sourceRepositoryId,sourceBranch,targetRepositoryId,targetBranch]` on the table `PullRequest` will be added. If there are existing duplicate values, this will fail.
+  - A unique constraint covering the columns `[slug,organizationId]` on the table `Repository` will be added. If there are existing duplicate values, this will fail.
+
+*/
+-- DropIndex
+DROP INDEX "Repository_slug_key";
+
+-- CreateIndex
+CREATE UNIQUE INDEX "PullRequest_uid_targetRepositoryId_key" ON "PullRequest"("uid", "targetRepositoryId");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "PullRequest_sourceRepositoryId_sourceBranch_targetRepositor_key" ON "PullRequest"("sourceRepositoryId", "sourceBranch", "targetRepositoryId", "targetBranch");
+
+-- CreateIndex
+CREATE UNIQUE INDEX "Repository_slug_organizationId_key" ON "Repository"("slug", "organizationId");

@@ -51,9 +51,9 @@ model PullRequest {
   sourceRepositoryId String
   targetRepositoryId String
 
-  createdAt DateTime @default(now())
-  updatedAt DateTime @updatedAt
-  closedAt  DateTime
+  createdAt DateTime  @default(now())
+  updatedAt DateTime  @updatedAt
+  closedAt  DateTime?
 
   state        PullRequestState @default(OPEN)
   sourceBranch String

...
@@ -66,6 +66,9 @@ model PullRequest {
   comments         PullRequestComment[] @relation("OnePullRequestCommentToOnePullRequest")
   sourceRepository Repository           @relation("OneSourceRepositoryToManyPullRequests", fields: [sourceRepositoryId], references: [id])
   targetRepository Repository           @relation("OneTargetRepositoryToManyPullRequests", fields: [targetRepositoryId], references: [id])
+
+  @@unique([uid, targetRepositoryId])
+  @@unique([sourceRepositoryId, sourceBranch, targetRepositoryId, targetBranch])
 }
 
 model PullRequestComment {

...
@@ -86,7 +89,7 @@ model Repository {
   id               String  @id @default(cuid())
   forkedFromRepoId String?
   organizationId   String
-  slug             String  @unique
+  slug             String
 
   createdAt    DateTime  @default(now())
   updatedAt    DateTime  @updatedAt

...
@@ -103,6 +106,8 @@ model Repository {
   organization            Organization  @relation("ManyRepositoriesToOneOrganization", fields: [organizationId], references: [id])
   pullRequestsWhereSource PullRequest[] @relation("OneSourceRepositoryToManyPullRequests")
   pullRequestsWhereTarget PullRequest[] @relation("OneTargetRepositoryToManyPullRequests")
+
+  @@unique([slug, organizationId])
 }
 
 model Session {