Added Project slug, WIP on Jobs/Runs presenters
This commit is contained in:
@@ -64,37 +64,35 @@ export async function createOrganization(
|
||||
{
|
||||
title,
|
||||
userId,
|
||||
desiredSlug,
|
||||
projectName,
|
||||
}: Pick<Organization, "title"> & {
|
||||
userId: User["id"];
|
||||
desiredSlug?: string;
|
||||
projectName: string;
|
||||
},
|
||||
attemptCount = 0
|
||||
): Promise<Organization & { projects: Project[] }> {
|
||||
if (desiredSlug === undefined) {
|
||||
desiredSlug = slug(title);
|
||||
}
|
||||
const uniqueOrgSlug = `${slug(title)}-${nanoid(4)}`;
|
||||
const uniqueProjectSlug = `${slug(projectName)}-${nanoid(4)}`;
|
||||
|
||||
const uniqueSlug = `${desiredSlug}-${nanoid(4)}`;
|
||||
const orgWithSameSlug = await prisma.organization.findFirst({
|
||||
where: { slug: uniqueOrgSlug },
|
||||
});
|
||||
|
||||
const withSameSlug = await prisma.organization.findFirst({
|
||||
where: { slug: uniqueSlug },
|
||||
const projectWithSameSlug = await prisma.project.findFirst({
|
||||
where: { slug: uniqueProjectSlug },
|
||||
});
|
||||
|
||||
if (attemptCount > 100) {
|
||||
throw new Error(
|
||||
`Unable to create organization with slug ${uniqueSlug} after 100 attempts`
|
||||
`Unable to create organization with slug ${uniqueOrgSlug} after 100 attempts`
|
||||
);
|
||||
}
|
||||
|
||||
if (withSameSlug) {
|
||||
if (orgWithSameSlug || projectWithSameSlug) {
|
||||
return createOrganization(
|
||||
{
|
||||
title,
|
||||
userId,
|
||||
desiredSlug,
|
||||
projectName,
|
||||
},
|
||||
attemptCount + 1
|
||||
@@ -104,7 +102,7 @@ export async function createOrganization(
|
||||
const organization = await prisma.organization.create({
|
||||
data: {
|
||||
title,
|
||||
slug: uniqueSlug,
|
||||
slug: uniqueOrgSlug,
|
||||
members: {
|
||||
create: {
|
||||
userId: userId,
|
||||
@@ -114,6 +112,7 @@ export async function createOrganization(
|
||||
projects: {
|
||||
create: {
|
||||
name: projectName,
|
||||
slug: uniqueProjectSlug,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import { prisma } from "~/db.server";
|
||||
|
||||
type JobListOptions = {
|
||||
userId: string;
|
||||
projectSlug: string;
|
||||
environmentId: string;
|
||||
};
|
||||
|
||||
export async function jobList({ userId, projectSlug }: JobListOptions) {
|
||||
const jobs = await prisma.job.findMany({
|
||||
select: {
|
||||
id: true,
|
||||
slug: true,
|
||||
title: true,
|
||||
projectId: true,
|
||||
aliases: {
|
||||
select: {
|
||||
version: {
|
||||
select: {
|
||||
version: true,
|
||||
eventSpecification: true,
|
||||
runs: {
|
||||
select: {
|
||||
createdAt: true,
|
||||
status: true,
|
||||
},
|
||||
take: 1,
|
||||
orderBy: [{ createdAt: "desc" }],
|
||||
},
|
||||
integrations: {
|
||||
select: {
|
||||
metadata: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
environment: {
|
||||
select: {
|
||||
orgMember: {
|
||||
select: {
|
||||
userId: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
where: {
|
||||
name: "latest",
|
||||
},
|
||||
},
|
||||
},
|
||||
where: {
|
||||
organization: { members: { some: { userId } } },
|
||||
project: { slug: projectSlug },
|
||||
internal: false,
|
||||
},
|
||||
orderBy: [{ title: "asc" }],
|
||||
});
|
||||
|
||||
return jobs;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
import { prisma } from "~/db.server";
|
||||
|
||||
type RunListOptions = {
|
||||
userId: string;
|
||||
jobId: string;
|
||||
cursor?: string;
|
||||
};
|
||||
|
||||
const PAGE_SIZE = 20;
|
||||
|
||||
export async function runList({ userId, jobId, cursor }: RunListOptions) {
|
||||
const runs = await prisma.jobRun.findMany({
|
||||
//todo change to a select
|
||||
include: {
|
||||
environment: {
|
||||
select: {
|
||||
type: true,
|
||||
},
|
||||
},
|
||||
version: {
|
||||
select: {
|
||||
version: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
where: {
|
||||
jobId,
|
||||
organization: { members: { some: { userId } } },
|
||||
environment: {
|
||||
OR: [
|
||||
{
|
||||
orgMember: null,
|
||||
},
|
||||
{
|
||||
orgMember: {
|
||||
userId,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
orderBy: [{ id: "desc" }],
|
||||
//take an extra page to tell if there are more
|
||||
take: PAGE_SIZE + 1,
|
||||
//skip the cursor if there is one
|
||||
skip: cursor ? 1 : 0,
|
||||
cursor: cursor
|
||||
? {
|
||||
id: cursor,
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
|
||||
const hasMore = runs.length > PAGE_SIZE;
|
||||
return {
|
||||
runs: runs.slice(0, PAGE_SIZE),
|
||||
hasMore,
|
||||
//todo look at Stripe for how to structure the object, needs previous cursor too
|
||||
cursor: hasMore ? runs[PAGE_SIZE - 1].id : undefined,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
Warnings:
|
||||
|
||||
- A unique constraint covering the columns `[slug]` on the table `Project` will be added. If there are existing duplicate values, this will fail.
|
||||
- Added the required column `slug` to the `Project` table without a default value. This is not possible if the table is not empty.
|
||||
|
||||
*/
|
||||
-- AlterTable
|
||||
ALTER TABLE "Project" ADD COLUMN "slug" TEXT NOT NULL;
|
||||
|
||||
-- CreateIndex
|
||||
CREATE UNIQUE INDEX "Project_slug_key" ON "Project"("slug");
|
||||
@@ -220,6 +220,7 @@ enum RuntimeEnvironmentType {
|
||||
|
||||
model Project {
|
||||
id String @id @default(cuid())
|
||||
slug String @unique
|
||||
name String
|
||||
|
||||
organization Organization @relation(fields: [organizationId], references: [id], onDelete: Cascade, onUpdate: Cascade)
|
||||
@@ -595,7 +596,7 @@ enum SecretStoreProvider {
|
||||
AWS_PARAM_STORE
|
||||
}
|
||||
|
||||
/// Used when the provider = "database". Not recommended outside of local development. */
|
||||
/// Used when the provider = "database". Not recommended outside of local development.
|
||||
model SecretStore {
|
||||
key String @unique
|
||||
value Json
|
||||
|
||||
Reference in New Issue
Block a user