feat: premium workspace usernames

This commit is contained in:
Henry
2025-01-02 20:40:29 +00:00
parent b5dc9433db
commit 67e714b8b0
41 changed files with 1767 additions and 9088 deletions

View File

@@ -38,6 +38,7 @@
"react-hook-form": "^7.51.1",
"react-icons": "^4.12.0",
"react-lottie-player": "^1.5.5",
"stripe": "^17.5.0",
"superjson": "2.2.1",
"tailwind-merge": "^2.5.2",
"zod": "catalog:"

View File

@@ -5,8 +5,10 @@ import { twMerge } from "tailwind-merge";
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
contentEditable?: boolean;
prefix?: string;
iconRight?: React.ReactNode;
value?: string;
errorMessage?: string;
className?: string;
onChange?: (
e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,
) => void;
@@ -14,7 +16,16 @@ interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
const Input = forwardRef<HTMLInputElement, InputProps>(
(
{ contentEditable, errorMessage, prefix, value, onChange, ...props },
{
contentEditable,
errorMessage,
prefix,
value,
onChange,
iconRight,
className,
...props
},
ref,
) => {
if (contentEditable) {
@@ -30,7 +41,7 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
return (
<div className="flex w-full flex-col gap-1">
<div className="flex">
<div className="relative flex">
{prefix && (
<div className="flex shrink-0 items-center rounded-l-md border border-r-0 border-light-600 px-3 text-base dark:border-dark-700 sm:text-sm/6">
{prefix}
@@ -42,9 +53,15 @@ const Input = forwardRef<HTMLInputElement, InputProps>(
className={twMerge(
"block w-full rounded-md border-0 bg-dark-300 bg-white/5 py-1.5 shadow-sm ring-1 ring-inset ring-light-600 placeholder:text-dark-800 focus:ring-2 focus:ring-inset focus:ring-light-700 dark:text-dark-1000 dark:ring-dark-700 dark:focus:ring-dark-700 sm:text-sm sm:leading-6",
prefix && "rounded-l-none",
className && className,
)}
{...props}
/>
{iconRight && (
<div className="absolute right-3 top-1/2 -translate-y-1/2">
{iconRight}
</div>
)}
</div>
{errorMessage && (
<div className="text-xs text-red-500">{errorMessage}</div>

View File

@@ -15,6 +15,7 @@ export const env = createEnv({
*/
server: {
POSTGRES_URL: z.string().url(),
STRIPE_SECRET_KEY: z.string().optional(),
},
/**

View File

@@ -0,0 +1,23 @@
import { useEffect, useState } from "react";
/**
* A hook that delays updating a value until a specified delay has passed
* @param value The value to debounce
* @param delay The delay in milliseconds
* @returns The debounced value
*/
export function useDebounce<T>(value: T, delay: number): [T] {
const [debouncedValue, setDebouncedValue] = useState<T>(value);
useEffect(() => {
const timeoutId = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(timeoutId);
};
}, [value, delay]);
return [debouncedValue];
}

View File

@@ -1,11 +1,22 @@
import type { EmailOtpType } from "@supabase/supabase-js";
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { Stripe } from "stripe";
import * as memberRepo from "@kan/db/repository/member.repo";
import * as userRepo from "@kan/db/repository/user.repo";
import { createNextClient } from "@kan/supabase/clients";
const stripeSecretKey = process.env.STRIPE_SECRET_KEY;
if (!stripeSecretKey) {
throw new Error("STRIPE_SECRET_KEY is not defined");
}
const stripe = new Stripe(stripeSecretKey, {
apiVersion: "2024-12-18.acacia",
});
export default async function handler(req: NextRequest) {
if (req.method !== "GET") {
return new NextResponse(null, {
@@ -54,9 +65,17 @@ export default async function handler(req: NextRequest) {
const existingUser = await userRepo.getById(db, user.id);
if (!existingUser) {
const stripeCustomer = await stripe.customers.create({
email: user.email,
metadata: {
userId: user.id,
},
});
await userRepo.create(db, {
id: user.id,
email: user.email,
stripeCustomerId: stripeCustomer.id,
});
}
}

View File

@@ -0,0 +1,135 @@
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { Stripe } from "stripe";
import { z } from "zod";
import * as userRepo from "@kan/db/repository/user.repo";
import * as workspaceRepo from "@kan/db/repository/workspace.repo";
import { createNextClient } from "@kan/supabase/clients";
const stripeSecretKey = process.env.STRIPE_SECRET_KEY;
if (!stripeSecretKey) {
throw new Error("STRIPE_SECRET_KEY is not defined");
}
const stripe = new Stripe(stripeSecretKey, {
apiVersion: "2024-12-18.acacia",
});
const usernameSchema = z
.string()
.min(3)
.max(24)
.regex(/^(?![-]+$)[a-zA-Z0-9-]+$/);
interface CheckoutSessionRequest {
successUrl: string;
cancelUrl: string;
username: string;
workspacePublicId: string;
stripeCustomerId: string;
}
export default async function handler(req: NextRequest) {
if (req.method !== "POST") {
return new Response(JSON.stringify({ error: "Method not allowed" }), {
status: 405,
headers: { "Content-Type": "application/json" },
});
}
try {
const response = NextResponse.next();
const db = createNextClient(req, response);
const { data } = await db.auth.getUser();
if (!data.user) {
return new Response(JSON.stringify({ error: "Unauthorized" }), {
status: 403,
headers: { "Content-Type": "application/json" },
});
}
const user = await userRepo.getById(db, data.user.id);
if (!user) {
return new Response(JSON.stringify({ error: "User not found" }), {
status: 404,
headers: { "Content-Type": "application/json" },
});
}
const body = (await req.json()) as CheckoutSessionRequest;
const { successUrl, cancelUrl, username, workspacePublicId } = body;
if (!successUrl || !cancelUrl || !username || !workspacePublicId) {
return new Response(
JSON.stringify({ error: "Missing required fields" }),
{
status: 400,
headers: { "Content-Type": "application/json" },
},
);
}
const usernameResult = usernameSchema.safeParse(username);
if (!usernameResult.success) {
return new Response(JSON.stringify({ error: "Invalid username" }), {
status: 400,
headers: { "Content-Type": "application/json" },
});
}
const workspace = await workspaceRepo.getAllByUserId(db, user.id);
const isMemberOfWorkspace = workspace.some(
({ workspace }) => workspace?.publicId === body.workspacePublicId,
);
if (!isMemberOfWorkspace) {
return new Response(JSON.stringify({ error: "Unauthorized" }), {
status: 403,
headers: { "Content-Type": "application/json" },
});
}
const session = await stripe.checkout.sessions.create({
mode: "subscription",
line_items: [
{
price: "price_1QcpmyDlDJBL8JHbeqhe1Ruq",
quantity: 1,
},
],
success_url: `${process.env.WEBSITE_URL}${successUrl}`,
cancel_url: `${process.env.WEBSITE_URL}${cancelUrl}`,
customer: user.stripeCustomerId ?? undefined,
metadata: {
username,
workspacePublicId,
},
});
return new Response(JSON.stringify({ url: session.url }), {
status: 200,
headers: { "Content-Type": "application/json" },
});
} catch (error) {
console.error("Error:", error);
return new Response(
JSON.stringify({ error: "Error creating checkout session" }),
{
status: 500,
headers: { "Content-Type": "application/json" },
},
);
}
}
export const runtime = "edge";
export const preferredRegion = "lhr1";
export const dynamic = "force-dynamic";

View File

@@ -0,0 +1,82 @@
import type { NextRequest } from "next/server";
import { NextResponse } from "next/server";
import { Stripe } from "stripe";
import * as workspaceRepo from "@kan/db/repository/workspace.repo";
import { createNextClient } from "@kan/supabase/clients";
const stripeSecretKey = process.env.STRIPE_SECRET_KEY;
if (!stripeSecretKey) {
throw new Error("STRIPE_SECRET_KEY is not defined");
}
export const webCrypto = Stripe.createSubtleCryptoProvider();
const stripe: Stripe = new Stripe(stripeSecretKey, {
apiVersion: "2024-12-18.acacia",
httpClient: Stripe.createFetchHttpClient(),
});
export default async function handler(req: NextRequest) {
if (req.method !== "POST") {
return new Response(JSON.stringify({ message: "Method not allowed" }), {
status: 405,
});
}
const sig = req.headers.get("stripe-signature");
if (!sig) {
return new Response(JSON.stringify({ message: "No signature found" }), {
status: 400,
});
}
try {
const body = await req.text();
const event = await stripe.webhooks.constructEventAsync(
body,
sig,
process.env.STRIPE_WEBHOOK_SECRET!,
undefined,
webCrypto,
);
const response = NextResponse.next();
const db = createNextClient(req, response);
switch (event.type) {
case "checkout.session.completed": {
const checkoutSession = event.data.object;
const metaData = checkoutSession.metadata;
if (metaData?.workspacePublicId && metaData.username) {
await workspaceRepo.update(
db,
metaData.workspacePublicId,
undefined,
metaData.username,
);
}
break;
}
default:
console.log(`Unhandled event type: ${event.type}`);
}
return new Response(JSON.stringify({ received: true }), { status: 200 });
} catch (err) {
console.error("Webhook error:", err);
return new Response(JSON.stringify({ message: "Webhook handler failed" }), {
status: 400,
});
}
}
export const runtime = "edge";
export const preferredRegion = "lhr1";
export const dynamic = "force-dynamic";

View File

@@ -1,19 +1,16 @@
import { HiOutlinePlusSmall, HiEllipsisHorizontal } from "react-icons/hi2";
import { HiEllipsisHorizontal, HiOutlinePlusSmall } from "react-icons/hi2";
import { twMerge } from "tailwind-merge";
import Dropdown from "~/components/Dropdown";
import Modal from "~/components/modal";
import { NewWorkspaceForm } from "~/components/NewWorkspaceForm";
import { PageHead } from "~/components/PageHead";
import { useModal } from "~/providers/modal";
import { useWorkspace } from "~/providers/workspace";
import { PageHead } from "~/components/PageHead";
import Modal from "~/components/modal";
import { NewWorkspaceForm } from "~/components/NewWorkspaceForm";
import { InviteMemberForm } from "./components/InviteMemberForm";
import { DeleteMemberConfirmation } from "./components/DeleteMemberConfirmation";
import Dropdown from "~/components/Dropdown";
import { api } from "~/utils/api";
import { getInitialsFromName, inferInitialsFromEmail } from "~/utils/helpers";
import { DeleteMemberConfirmation } from "./components/DeleteMemberConfirmation";
import { InviteMemberForm } from "./components/InviteMemberForm";
export default function MembersPage() {
const { modalContentType, openModal } = useModal();
@@ -24,6 +21,25 @@ export default function MembersPage() {
// { enabled: workspace?.publicId ? true : false },
);
const handleUpgrade = async () => {
try {
const response = await fetch("/api/stripe/create_checkout_session", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
});
const { url } = (await response.json()) as { url: string };
if (url) {
window.location.href = url;
}
} catch (error) {
console.error("Error creating checkout session:", error);
}
};
const TableRow = ({
memberPublicId,
memberName,
@@ -139,7 +155,7 @@ export default function MembersPage() {
return (
<>
<PageHead title={`Members | ${workspace?.name ?? "Workspace"}`} />
<PageHead title={`Members | ${workspace.name ?? "Workspace"}`} />
<div className="px-28 py-12">
<div className="mb-8 flex w-full justify-between">
<h1 className="font-medium tracking-tight text-neutral-900 dark:text-dark-1000 sm:text-[1.2rem]">
@@ -149,7 +165,7 @@ export default function MembersPage() {
<button
type="button"
className="flex items-center gap-x-1.5 rounded-md bg-light-1000 px-3 py-2 text-sm font-semibold text-light-50 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 dark:bg-dark-1000 dark:text-dark-50"
onClick={() => openModal("INVITE_MEMBER")}
onClick={() => handleUpgrade()}
>
<div className="h-5 w-5 items-center">
<HiOutlinePlusSmall
@@ -189,8 +205,8 @@ export default function MembersPage() {
<TableRow
key={member.publicId}
memberPublicId={member.publicId}
memberName={member?.user?.name}
memberEmail={member?.user?.email}
memberName={member.user?.name}
memberEmail={member.user?.email}
memberRole={member.role}
memberStatus={member.status}
isLastRow={index === data.members.length - 1}

View File

@@ -0,0 +1,56 @@
import Button from "~/components/Button";
import { useModal } from "~/providers/modal";
export function PremiumUsernameConfirmation({
workspacePublicId,
}: {
workspacePublicId: string;
}) {
const { closeModal, entityId } = useModal();
const handleUpgrade = async () => {
try {
const response = await fetch("/api/stripe/create_checkout_session", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username: entityId,
workspacePublicId: workspacePublicId,
cancelUrl: "/settings",
successUrl: "/settings",
}),
});
const { url } = (await response.json()) as { url: string };
if (url) {
window.location.href = url;
}
} catch (error) {
console.error("Error creating checkout session:", error);
}
};
return (
<div className="p-5">
<div className="flex w-full flex-col justify-between pb-4">
<h2 className="text-md pb-4 font-medium text-neutral-900 dark:text-dark-1000">
{`Confirm username change`}
</h2>
<p className="text-sm font-medium text-light-900 dark:text-dark-900">
{
"As you are changing from a standard to a premium username, you will be taken to the checkout to upgrade."
}
</p>
</div>
<div className="mt-5 flex justify-end space-x-2 sm:mt-6">
<Button onClick={() => closeModal()} variant="secondary">
Cancel
</Button>
<Button onClick={handleUpgrade}>Upgrade</Button>
</div>
</div>
);
}

View File

@@ -1,17 +1,25 @@
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
import { HiCheck, HiMiniStar } from "react-icons/hi2";
import { z } from "zod";
import Button from "~/components/Button";
import Input from "~/components/Input";
import { useDebounce } from "~/hooks/useDebounce";
import { useModal } from "~/providers/modal";
import { usePopup } from "~/providers/popup";
import { api } from "~/utils/api";
const schema = z.object({
slug: z
.string()
.min(3, { message: "Workspace URL must be at least 3 characters long" })
.max(24, { message: "Workspace URL cannot exceed 24 characters" }),
.min(3, {
message: "Username must be at least 3 characters long",
})
.max(24, { message: "Username cannot exceed 24 characters" })
.regex(/^(?![-]+$)[a-zA-Z0-9-]+$/, {
message: "Username can only contain letters, numbers, and hyphens",
}),
});
type FormValues = z.infer<typeof schema>;
@@ -25,17 +33,22 @@ const UpdateWorkspaceUrlForm = ({
}) => {
const utils = api.useUtils();
const { showPopup } = usePopup();
const { openModal } = useModal();
const {
register,
handleSubmit,
formState: { isDirty, errors },
watch,
} = useForm<FormValues>({
resolver: zodResolver(schema),
values: {
slug: workspaceUrl,
},
mode: "onChange",
});
const slug = watch("slug");
const updateWorkspaceSlug = api.workspace.update.useMutation({
onSuccess: async () => {
try {
@@ -47,13 +60,33 @@ const UpdateWorkspaceUrlForm = ({
},
onError: () => {
showPopup({
header: "Error updating workspace URL",
header: "Error updating workspace username",
message: "Please try again later, or contact customer support.",
});
},
});
const [debouncedSlug] = useDebounce(slug, 500);
const isTyping = slug !== debouncedSlug;
const checkWorkspaceSlugAvailability =
api.workspace.checkSlugAvailability.useQuery(
{
workspaceSlug: debouncedSlug,
},
{
enabled:
!!debouncedSlug && debouncedSlug !== workspaceUrl && !errors.slug,
},
);
const isWorkspaceSlugAvailable = checkWorkspaceSlugAvailability.data;
const onSubmit = (data: FormValues) => {
if (isWorkspaceSlugAvailable?.isPremium)
return openModal("PREMIUM_USERNAME", data.slug);
updateWorkspaceSlug.mutate({
workspacePublicId,
slug: data.slug,
@@ -65,14 +98,35 @@ const UpdateWorkspaceUrlForm = ({
<div className="mb-4 flex max-w-[350px] items-center gap-2">
<Input
{...register("slug")}
errorMessage={errors.slug?.message}
prefix="kanbn.com/"
className={`${
isWorkspaceSlugAvailable?.isPremium ? "focus:ring-yellow-500" : ""
}`}
errorMessage={
errors.slug?.message ||
(isWorkspaceSlugAvailable?.isAvailable === false
? "This workspace username has already been taken"
: undefined)
}
prefix="kan.bn/"
iconRight={
isWorkspaceSlugAvailable?.isPremium ? (
<HiMiniStar className="h-4 w-4 text-yellow-500" />
) : isWorkspaceSlugAvailable?.isAvailable ? (
<HiCheck className="h-4 w-4" />
) : null
}
/>
</div>
<Button
onClick={handleSubmit(onSubmit)}
variant="primary"
disabled={!isDirty || updateWorkspaceSlug.isPending}
disabled={
!isDirty ||
updateWorkspaceSlug.isPending ||
checkWorkspaceSlugAvailability.isPending ||
isWorkspaceSlugAvailable?.isAvailable === false ||
isTyping
}
isLoading={updateWorkspaceSlug.isPending}
>
Update

View File

@@ -4,6 +4,7 @@ import { PageHead } from "~/components/PageHead";
import { useModal } from "~/providers/modal";
import { useWorkspace } from "~/providers/workspace";
import { DeleteWorkspaceConfirmation } from "./components/DeleteWorkspaceConfirmation";
import { PremiumUsernameConfirmation } from "./components/PremiumUsernameConfirmation";
import UpdateWorkspaceNameForm from "./components/UpdateWorkspaceNameForm";
import UpdateWorkspaceUrlForm from "./components/UpdateWorkspaceUrlForm";
@@ -31,7 +32,7 @@ export default function SettingsPage() {
/>
<h2 className="mb-4 mt-8 text-[14px] text-neutral-900 dark:text-dark-1000">
Workspace URL
Workspace username
</h2>
<UpdateWorkspaceUrlForm
workspacePublicId={workspace.publicId}
@@ -59,6 +60,11 @@ export default function SettingsPage() {
{modalContentType === "DELETE_WORKSPACE" && (
<DeleteWorkspaceConfirmation />
)}
{modalContentType === "PREMIUM_USERNAME" && (
<PremiumUsernameConfirmation
workspacePublicId={workspace.publicId}
/>
)}
</Modal>
</div>
</>

View File

@@ -24,6 +24,7 @@ export const authRouter = createTRPCRouter({
id: z.string(),
email: z.string(),
name: z.string().nullable(),
stripeCustomerId: z.string().nullable(),
}),
)
.query(async ({ ctx }) => {

View File

@@ -2,8 +2,9 @@ import { TRPCError } from "@trpc/server";
import { z } from "zod";
import * as workspaceRepo from "@kan/db/repository/workspace.repo";
import * as workspaceSlugRepo from "@kan/db/repository/workspaceSlug.repo";
import { createTRPCRouter, protectedProcedure } from "../trpc";
import { createTRPCRouter, protectedProcedure, publicProcedure } from "../trpc";
export const workspaceRouter = createTRPCRouter({
all: protectedProcedure
@@ -161,4 +162,42 @@ export const workspaceRouter = createTRPCRouter({
return result;
}),
checkSlugAvailability: publicProcedure
.meta({
openapi: {
summary: "Check if a workspace slug is available",
method: "GET",
path: "/workspaces/check-slug-availability",
description: "Checks if a workspace slug is available",
tags: ["Workspaces"],
protect: true,
},
})
.input(z.object({ workspaceSlug: z.string().min(3).max(24) }))
.output(
z.object({
isAvailable: z.boolean(),
isReserved: z.boolean(),
isPremium: z.boolean(),
}),
)
.query(async ({ ctx, input }) => {
const slug = input.workspaceSlug.toLowerCase();
// check list of reserved or premium slugs
const workspaceSlug = await workspaceSlugRepo.getWorkspaceSlug(
ctx.db,
slug,
);
// check slug is not taken already
const isWorkspaceSlugAvailable =
await workspaceRepo.isWorkspaceSlugAvailable(ctx.db, slug);
return {
isAvailable:
isWorkspaceSlugAvailable && workspaceSlug?.type !== "reserved",
isReserved: workspaceSlug?.type === "reserved",
isPremium: workspaceSlug?.type === "premium",
};
}),
});

View File

@@ -1,11 +1,18 @@
import { type Config } from "drizzle-kit";
export default {
schema: "./src/server/db/schema.ts",
out: "./src/server/db/migrations",
driver: "pg",
schema: "./src/schema.ts",
out: "./migrations",
dialect: "postgresql",
dbCredentials: {
connectionString: process.env.POSTGRES_URL,
host: process.env.POSTGRES_HOST ?? "localhost",
port: process.env.POSTGRES_PORT
? parseInt(process.env.POSTGRES_PORT)
: 5432,
user: process.env.POSTGRES_USER,
password: process.env.POSTGRES_PASSWORD,
database: process.env.POSTGRES_DATABASE ?? "postgres",
ssl: true,
},
// tablesFilter: ["kan_*"],
} satisfies Config;

View File

@@ -1,36 +1,9 @@
DO $$ BEGIN
CREATE TYPE "source" AS ENUM('trello');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
CREATE TYPE "status" AS ENUM('started', 'success', 'failed');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
CREATE TYPE "role" AS ENUM('admin', 'member', 'guest');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "account" (
"userId" uuid NOT NULL,
"type" varchar(255) NOT NULL,
"provider" varchar(255) NOT NULL,
"providerAccountId" varchar(255) NOT NULL,
"refresh_token" text,
"access_token" text,
"expires_at" integer,
"token_type" varchar(255),
"scope" varchar(255),
"id_token" text,
"session_state" varchar(255),
CONSTRAINT account_provider_providerAccountId PRIMARY KEY("provider","providerAccountId")
);
--> statement-breakpoint
CREATE TYPE "public"."card_activity_type" AS ENUM('card.created', 'card.updated.title', 'card.updated.description', 'card.updated.index', 'card.updated.list', 'card.updated.label.added', 'card.updated.label.removed', 'card.updated.member.added', 'card.updated.member.removed', 'card.updated.comment.added', 'card.updated.comment.updated', 'card.updated.comment.deleted', 'card.archived');--> statement-breakpoint
CREATE TYPE "public"."source" AS ENUM('trello');--> statement-breakpoint
CREATE TYPE "public"."status" AS ENUM('started', 'success', 'failed');--> statement-breakpoint
CREATE TYPE "public"."role" AS ENUM('admin', 'member', 'guest');--> statement-breakpoint
CREATE TYPE "public"."member_status" AS ENUM('invited', 'active', 'removed');--> statement-breakpoint
CREATE TYPE "public"."slug_type" AS ENUM('reserved', 'premium');--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "board" (
"id" bigserial PRIMARY KEY NOT NULL,
"publicId" varchar(12) NOT NULL,
@@ -38,17 +11,40 @@ CREATE TABLE IF NOT EXISTS "board" (
"createdBy" uuid NOT NULL,
"createdAt" timestamp DEFAULT now() NOT NULL,
"updatedAt" timestamp,
"deletedAt" timestamp DEFAULT now(),
"deletedAt" timestamp,
"deletedBy" uuid,
"importId" bigint,
"workspaceId" bigint NOT NULL,
CONSTRAINT "board_publicId_unique" UNIQUE("publicId")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "card_activity" (
"id" bigserial PRIMARY KEY NOT NULL,
"publicId" varchar(12) NOT NULL,
"type" "card_activity_type" NOT NULL,
"cardId" bigint NOT NULL,
"fromIndex" integer,
"toIndex" integer,
"fromListId" bigint,
"toListId" bigint,
"labelId" bigint,
"workspaceMemberId" bigint,
"fromTitle" varchar(255),
"toTitle" varchar(255),
"fromDescription" text,
"toDescription" text,
"createdBy" uuid NOT NULL,
"createdAt" timestamp DEFAULT now() NOT NULL,
"commentId" bigint,
"fromComment" text,
"toComment" text,
CONSTRAINT "card_activity_publicId_unique" UNIQUE("publicId")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "_card_workspace_members" (
"cardId" bigint NOT NULL,
"workspaceMemberId" bigint NOT NULL,
CONSTRAINT _card_workspace_members_cardId_workspaceMemberId PRIMARY KEY("cardId","workspaceMemberId")
CONSTRAINT "_card_workspace_members_cardId_workspaceMemberId_pk" PRIMARY KEY("cardId","workspaceMemberId")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "card" (
@@ -70,7 +66,20 @@ CREATE TABLE IF NOT EXISTS "card" (
CREATE TABLE IF NOT EXISTS "_card_labels" (
"cardId" bigint NOT NULL,
"labelId" bigint NOT NULL,
CONSTRAINT _card_labels_cardId_labelId PRIMARY KEY("cardId","labelId")
CONSTRAINT "_card_labels_cardId_labelId_pk" PRIMARY KEY("cardId","labelId")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "card_comments" (
"id" bigserial PRIMARY KEY NOT NULL,
"publicId" varchar(12) NOT NULL,
"comment" text NOT NULL,
"cardId" bigint NOT NULL,
"createdBy" uuid NOT NULL,
"createdAt" timestamp DEFAULT now() NOT NULL,
"updatedAt" timestamp,
"deletedAt" timestamp,
"deletedBy" uuid,
CONSTRAINT "card_comments_publicId_unique" UNIQUE("publicId")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "import" (
@@ -111,10 +120,10 @@ CREATE TABLE IF NOT EXISTS "list" (
CONSTRAINT "list_publicId_unique" UNIQUE("publicId")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "session" (
"sessionToken" varchar(255) PRIMARY KEY NOT NULL,
"userId" uuid NOT NULL,
"expires" timestamp NOT NULL
CREATE TABLE IF NOT EXISTS "workspace_slugs" (
"slug" varchar(255) NOT NULL,
"type" "slug_type" NOT NULL,
CONSTRAINT "workspace_slugs_slug_unique" UNIQUE("slug")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "user" (
@@ -126,13 +135,6 @@ CREATE TABLE IF NOT EXISTS "user" (
CONSTRAINT "user_email_unique" UNIQUE("email")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "verificationToken" (
"identifier" varchar(255) NOT NULL,
"token" varchar(255) NOT NULL,
"expires" timestamp NOT NULL,
CONSTRAINT verificationToken_identifier_token PRIMARY KEY("identifier","token")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "workspace_members" (
"id" bigserial PRIMARY KEY NOT NULL,
"publicId" varchar(12) NOT NULL,
@@ -142,7 +144,9 @@ CREATE TABLE IF NOT EXISTS "workspace_members" (
"createdAt" timestamp DEFAULT now() NOT NULL,
"updatedAt" timestamp,
"deletedAt" timestamp,
"deletedBy" uuid,
"role" "role" NOT NULL,
"status" "member_status" DEFAULT 'invited' NOT NULL,
CONSTRAINT "workspace_members_publicId_unique" UNIQUE("publicId")
);
--> statement-breakpoint
@@ -161,157 +165,211 @@ CREATE TABLE IF NOT EXISTS "workspace" (
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "account" ADD CONSTRAINT "account_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "board" ADD CONSTRAINT "board_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "board" ADD CONSTRAINT "board_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "board" ADD CONSTRAINT "board_deletedBy_user_id_fk" FOREIGN KEY ("deletedBy") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "board" ADD CONSTRAINT "board_deletedBy_user_id_fk" FOREIGN KEY ("deletedBy") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "board" ADD CONSTRAINT "board_importId_import_id_fk" FOREIGN KEY ("importId") REFERENCES "public"."import"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "board" ADD CONSTRAINT "board_importId_import_id_fk" FOREIGN KEY ("importId") REFERENCES "import"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "board" ADD CONSTRAINT "board_workspaceId_workspace_id_fk" FOREIGN KEY ("workspaceId") REFERENCES "public"."workspace"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "board" ADD CONSTRAINT "board_workspaceId_workspace_id_fk" FOREIGN KEY ("workspaceId") REFERENCES "workspace"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "card_activity" ADD CONSTRAINT "card_activity_cardId_card_id_fk" FOREIGN KEY ("cardId") REFERENCES "public"."card"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "_card_workspace_members" ADD CONSTRAINT "_card_workspace_members_cardId_card_id_fk" FOREIGN KEY ("cardId") REFERENCES "card"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "card_activity" ADD CONSTRAINT "card_activity_fromListId_list_id_fk" FOREIGN KEY ("fromListId") REFERENCES "public"."list"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "_card_workspace_members" ADD CONSTRAINT "_card_workspace_members_workspaceMemberId_workspace_members_id_fk" FOREIGN KEY ("workspaceMemberId") REFERENCES "workspace_members"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "card_activity" ADD CONSTRAINT "card_activity_toListId_list_id_fk" FOREIGN KEY ("toListId") REFERENCES "public"."list"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card" ADD CONSTRAINT "card_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "card_activity" ADD CONSTRAINT "card_activity_labelId_label_id_fk" FOREIGN KEY ("labelId") REFERENCES "public"."label"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card" ADD CONSTRAINT "card_deletedBy_user_id_fk" FOREIGN KEY ("deletedBy") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "card_activity" ADD CONSTRAINT "card_activity_workspaceMemberId_workspace_members_id_fk" FOREIGN KEY ("workspaceMemberId") REFERENCES "public"."workspace_members"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card" ADD CONSTRAINT "card_listId_list_id_fk" FOREIGN KEY ("listId") REFERENCES "list"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "card_activity" ADD CONSTRAINT "card_activity_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card" ADD CONSTRAINT "card_importId_import_id_fk" FOREIGN KEY ("importId") REFERENCES "import"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "card_activity" ADD CONSTRAINT "card_activity_commentId_card_comments_id_fk" FOREIGN KEY ("commentId") REFERENCES "public"."card_comments"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "_card_labels" ADD CONSTRAINT "_card_labels_cardId_card_id_fk" FOREIGN KEY ("cardId") REFERENCES "card"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "_card_workspace_members" ADD CONSTRAINT "_card_workspace_members_cardId_card_id_fk" FOREIGN KEY ("cardId") REFERENCES "public"."card"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "_card_labels" ADD CONSTRAINT "_card_labels_labelId_label_id_fk" FOREIGN KEY ("labelId") REFERENCES "label"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "_card_workspace_members" ADD CONSTRAINT "_card_workspace_members_workspaceMemberId_workspace_members_id_fk" FOREIGN KEY ("workspaceMemberId") REFERENCES "public"."workspace_members"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "import" ADD CONSTRAINT "import_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "card" ADD CONSTRAINT "card_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "label" ADD CONSTRAINT "label_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "card" ADD CONSTRAINT "card_deletedBy_user_id_fk" FOREIGN KEY ("deletedBy") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "label" ADD CONSTRAINT "label_boardId_board_id_fk" FOREIGN KEY ("boardId") REFERENCES "board"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "card" ADD CONSTRAINT "card_listId_list_id_fk" FOREIGN KEY ("listId") REFERENCES "public"."list"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "label" ADD CONSTRAINT "label_importId_import_id_fk" FOREIGN KEY ("importId") REFERENCES "import"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "card" ADD CONSTRAINT "card_importId_import_id_fk" FOREIGN KEY ("importId") REFERENCES "public"."import"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "list" ADD CONSTRAINT "list_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "_card_labels" ADD CONSTRAINT "_card_labels_cardId_card_id_fk" FOREIGN KEY ("cardId") REFERENCES "public"."card"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "list" ADD CONSTRAINT "list_deletedBy_user_id_fk" FOREIGN KEY ("deletedBy") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "_card_labels" ADD CONSTRAINT "_card_labels_labelId_label_id_fk" FOREIGN KEY ("labelId") REFERENCES "public"."label"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "list" ADD CONSTRAINT "list_boardId_board_id_fk" FOREIGN KEY ("boardId") REFERENCES "board"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "card_comments" ADD CONSTRAINT "card_comments_cardId_card_id_fk" FOREIGN KEY ("cardId") REFERENCES "public"."card"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "list" ADD CONSTRAINT "list_importId_import_id_fk" FOREIGN KEY ("importId") REFERENCES "import"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "card_comments" ADD CONSTRAINT "card_comments_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "session" ADD CONSTRAINT "session_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "card_comments" ADD CONSTRAINT "card_comments_deletedBy_user_id_fk" FOREIGN KEY ("deletedBy") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "workspace_members" ADD CONSTRAINT "workspace_members_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "import" ADD CONSTRAINT "import_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "workspace_members" ADD CONSTRAINT "workspace_members_workspaceId_workspace_id_fk" FOREIGN KEY ("workspaceId") REFERENCES "workspace"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "label" ADD CONSTRAINT "label_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "workspace" ADD CONSTRAINT "workspace_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "label" ADD CONSTRAINT "label_boardId_board_id_fk" FOREIGN KEY ("boardId") REFERENCES "public"."board"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "workspace" ADD CONSTRAINT "workspace_deletedBy_user_id_fk" FOREIGN KEY ("deletedBy") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
ALTER TABLE "label" ADD CONSTRAINT "label_importId_import_id_fk" FOREIGN KEY ("importId") REFERENCES "public"."import"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "list" ADD CONSTRAINT "list_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "list" ADD CONSTRAINT "list_deletedBy_user_id_fk" FOREIGN KEY ("deletedBy") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "list" ADD CONSTRAINT "list_boardId_board_id_fk" FOREIGN KEY ("boardId") REFERENCES "public"."board"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "list" ADD CONSTRAINT "list_importId_import_id_fk" FOREIGN KEY ("importId") REFERENCES "public"."import"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "workspace_members" ADD CONSTRAINT "workspace_members_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "workspace_members" ADD CONSTRAINT "workspace_members_workspaceId_workspace_id_fk" FOREIGN KEY ("workspaceId") REFERENCES "public"."workspace"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "workspace_members" ADD CONSTRAINT "workspace_members_deletedBy_user_id_fk" FOREIGN KEY ("deletedBy") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "workspace" ADD CONSTRAINT "workspace_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "workspace" ADD CONSTRAINT "workspace_deletedBy_user_id_fk" FOREIGN KEY ("deletedBy") REFERENCES "public"."user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View File

@@ -0,0 +1 @@
ALTER TABLE "user" ADD COLUMN "stripeCustomerId" varchar(255);

View File

@@ -1 +0,0 @@
ALTER TABLE "board" ALTER COLUMN "deletedAt" DROP DEFAULT;

View File

@@ -1,66 +0,0 @@
DROP TABLE IF EXISTS "account";--> statement-breakpoint
DROP TABLE IF EXISTS "session";--> statement-breakpoint
DROP TABLE IF EXISTS "verificationToken";--> statement-breakpoint
ALTER TABLE "board" DROP CONSTRAINT "board_workspaceId_workspace_id_fk";
--> statement-breakpoint
ALTER TABLE "_card_workspace_members" DROP CONSTRAINT "_card_workspace_members_cardId_card_id_fk";
--> statement-breakpoint
ALTER TABLE "card" DROP CONSTRAINT "card_listId_list_id_fk";
--> statement-breakpoint
ALTER TABLE "_card_labels" DROP CONSTRAINT IF EXISTS "_card_labels_cardId_card_id_fk";
--> statement-breakpoint
ALTER TABLE "_card_labels" DROP CONSTRAINT IF EXISTS "_card_labels_labelId_label_id_fk";
--> statement-breakpoint
ALTER TABLE "label" DROP CONSTRAINT "label_boardId_board_id_fk";
--> statement-breakpoint
ALTER TABLE "list" DROP CONSTRAINT "list_boardId_board_id_fk";
--> statement-breakpoint
ALTER TABLE "workspace_members" DROP CONSTRAINT "workspace_members_workspaceId_workspace_id_fk";
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "board" ADD CONSTRAINT "board_workspaceId_workspace_id_fk" FOREIGN KEY ("workspaceId") REFERENCES "workspace"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "_card_workspace_members" ADD CONSTRAINT "_card_workspace_members_workspaceMemberId_workspace_members_id_fk" FOREIGN KEY ("workspaceMemberId") REFERENCES "workspace_members"("id") ON DELETE CASCADE ON UPDATE NO ACTION;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card" ADD CONSTRAINT "card_listId_list_id_fk" FOREIGN KEY ("listId") REFERENCES "list"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "_card_labels" ADD CONSTRAINT "_card_labels_cardId_card_id_fk" FOREIGN KEY ("cardId") REFERENCES "card"("id") ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "_card_labels" ADD CONSTRAINT "_card_labels_labelId_label_id_fk" FOREIGN KEY ("labelId") REFERENCES "label"("id") ON DELETE CASCADE;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "label" ADD CONSTRAINT "label_boardId_board_id_fk" FOREIGN KEY ("boardId") REFERENCES "board"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "list" ADD CONSTRAINT "list_boardId_board_id_fk" FOREIGN KEY ("boardId") REFERENCES "board"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "workspace_members" ADD CONSTRAINT "workspace_members_workspaceId_workspace_id_fk" FOREIGN KEY ("workspaceId") REFERENCES "workspace"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View File

@@ -1,22 +0,0 @@
DO $$ BEGIN
CREATE TYPE "member_status" AS ENUM('invited', 'active', 'removed');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
ALTER TABLE "_card_workspace_members" DROP CONSTRAINT "_card_workspace_members_cardId_card_id_fk";
--> statement-breakpoint
ALTER TABLE "_card_labels" DROP CONSTRAINT "_card_labels_cardId_card_id_fk";
--> statement-breakpoint
ALTER TABLE "workspace_members" ADD COLUMN "status" "member_status" DEFAULT 'invited' NOT NULL;--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "_card_workspace_members" ADD CONSTRAINT "_card_workspace_members_cardId_card_id_fk" FOREIGN KEY ("cardId") REFERENCES "card"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "_card_labels" ADD CONSTRAINT "_card_labels_cardId_card_id_fk" FOREIGN KEY ("cardId") REFERENCES "card"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View File

@@ -1,6 +0,0 @@
ALTER TABLE "workspace_members" ADD COLUMN "deletedBy" uuid;--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "workspace_members" ADD CONSTRAINT "workspace_members_deletedBy_user_id_fk" FOREIGN KEY ("deletedBy") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View File

@@ -1,55 +0,0 @@
DO $$ BEGIN
CREATE TYPE "card_activity_type" AS ENUM('card.created', 'card.updated.title', 'card.updated.description', 'card.updated.index', 'card.updated.list', 'card.updated.label.added', 'card.updated.label.removed', 'card.updated.member.added', 'card.updated.member.removed', 'card.archived');
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "card_activity" (
"id" bigserial PRIMARY KEY NOT NULL,
"publicId" varchar(12) NOT NULL,
"type" "card_activity_type" NOT NULL,
"cardId" bigint NOT NULL,
"fromIndex" integer,
"toIndex" integer,
"fromListId" bigint,
"toListId" bigint,
"labelId" bigint,
"workspaceMemberId" bigint,
"fromTitle" varchar(255),
"toTitle" varchar(255),
"fromDescription" text,
"toDescription" text,
"createdBy" uuid NOT NULL,
"createdAt" timestamp DEFAULT now() NOT NULL,
CONSTRAINT "card_activity_publicId_unique" UNIQUE("publicId")
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_activity" ADD CONSTRAINT "card_activity_cardId_card_id_fk" FOREIGN KEY ("cardId") REFERENCES "card"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_activity" ADD CONSTRAINT "card_activity_toListId_list_id_fk" FOREIGN KEY ("toListId") REFERENCES "list"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_activity" ADD CONSTRAINT "card_activity_labelId_label_id_fk" FOREIGN KEY ("labelId") REFERENCES "label"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_activity" ADD CONSTRAINT "card_activity_workspaceMemberId_workspace_members_id_fk" FOREIGN KEY ("workspaceMemberId") REFERENCES "workspace_members"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_activity" ADD CONSTRAINT "card_activity_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View File

@@ -1,5 +0,0 @@
DO $$ BEGIN
ALTER TABLE "card_activity" ADD CONSTRAINT "card_activity_fromListId_list_id_fk" FOREIGN KEY ("fromListId") REFERENCES "list"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View File

@@ -1,30 +0,0 @@
CREATE TABLE IF NOT EXISTS "card_comments" (
"id" bigserial PRIMARY KEY NOT NULL,
"publicId" varchar(12) NOT NULL,
"comment" text NOT NULL,
"cardId" bigint NOT NULL,
"createdBy" uuid NOT NULL,
"createdAt" timestamp DEFAULT now() NOT NULL,
"updatedAt" timestamp,
"deletedAt" timestamp,
"deletedBy" uuid,
CONSTRAINT "card_comments_publicId_unique" UNIQUE("publicId")
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_comments" ADD CONSTRAINT "card_comments_cardId_card_id_fk" FOREIGN KEY ("cardId") REFERENCES "card"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_comments" ADD CONSTRAINT "card_comments_createdBy_user_id_fk" FOREIGN KEY ("createdBy") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_comments" ADD CONSTRAINT "card_comments_deletedBy_user_id_fk" FOREIGN KEY ("deletedBy") REFERENCES "user"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View File

@@ -1,11 +0,0 @@
ALTER TYPE "card_activity_type" ADD VALUE 'card.updated.comment.added';--> statement-breakpoint
ALTER TYPE "card_activity_type" ADD VALUE 'card.updated.comment.updated';--> statement-breakpoint
ALTER TYPE "card_activity_type" ADD VALUE 'card.updated.comment.deleted';--> statement-breakpoint
ALTER TABLE "card_activity" ADD COLUMN "commentId" bigint;--> statement-breakpoint
ALTER TABLE "card_activity" ADD COLUMN "fromComment" text;--> statement-breakpoint
ALTER TABLE "card_activity" ADD COLUMN "toComment" text;--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "card_activity" ADD CONSTRAINT "card_activity_commentId_card_comments_id_fk" FOREIGN KEY ("commentId") REFERENCES "card_comments"("id") ON DELETE no action ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View File

@@ -1,108 +1,10 @@
{
"version": "5",
"dialect": "pg",
"id": "32295e0d-123f-4eae-b323-1fe55e3c4dca",
"id": "3bf82a86-d7ff-4ab7-81ed-024350dfb32a",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
"tables": {
"account": {
"name": "account",
"schema": "",
"columns": {
"userId": {
"name": "userId",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"provider": {
"name": "provider",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"providerAccountId": {
"name": "providerAccountId",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"token_type": {
"name": "token_type",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"scope": {
"name": "scope",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"id_token": {
"name": "id_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"session_state": {
"name": "session_state",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"account_userId_user_id_fk": {
"name": "account_userId_user_id_fk",
"tableFrom": "account",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"account_provider_providerAccountId": {
"name": "account_provider_providerAccountId",
"columns": [
"provider",
"providerAccountId"
]
}
},
"uniqueConstraints": {}
},
"board": {
"public.board": {
"name": "board",
"schema": "",
"columns": {
@@ -147,8 +49,7 @@
"name": "deletedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": false,
"default": "now()"
"notNull": false
},
"deletedBy": {
"name": "deletedBy",
@@ -220,7 +121,7 @@
"columnsTo": [
"id"
],
"onDelete": "no action",
"onDelete": "cascade",
"onUpdate": "no action"
}
},
@@ -233,9 +134,241 @@
"publicId"
]
}
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"_card_workspace_members": {
"public.card_activity": {
"name": "card_activity",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "bigserial",
"primaryKey": true,
"notNull": true
},
"publicId": {
"name": "publicId",
"type": "varchar(12)",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "card_activity_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"cardId": {
"name": "cardId",
"type": "bigint",
"primaryKey": false,
"notNull": true
},
"fromIndex": {
"name": "fromIndex",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"toIndex": {
"name": "toIndex",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"fromListId": {
"name": "fromListId",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"toListId": {
"name": "toListId",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"labelId": {
"name": "labelId",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"workspaceMemberId": {
"name": "workspaceMemberId",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"fromTitle": {
"name": "fromTitle",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"toTitle": {
"name": "toTitle",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"fromDescription": {
"name": "fromDescription",
"type": "text",
"primaryKey": false,
"notNull": false
},
"toDescription": {
"name": "toDescription",
"type": "text",
"primaryKey": false,
"notNull": false
},
"createdBy": {
"name": "createdBy",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"commentId": {
"name": "commentId",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"fromComment": {
"name": "fromComment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"toComment": {
"name": "toComment",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"card_activity_cardId_card_id_fk": {
"name": "card_activity_cardId_card_id_fk",
"tableFrom": "card_activity",
"tableTo": "card",
"columnsFrom": [
"cardId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"card_activity_fromListId_list_id_fk": {
"name": "card_activity_fromListId_list_id_fk",
"tableFrom": "card_activity",
"tableTo": "list",
"columnsFrom": [
"fromListId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"card_activity_toListId_list_id_fk": {
"name": "card_activity_toListId_list_id_fk",
"tableFrom": "card_activity",
"tableTo": "list",
"columnsFrom": [
"toListId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"card_activity_labelId_label_id_fk": {
"name": "card_activity_labelId_label_id_fk",
"tableFrom": "card_activity",
"tableTo": "label",
"columnsFrom": [
"labelId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"card_activity_workspaceMemberId_workspace_members_id_fk": {
"name": "card_activity_workspaceMemberId_workspace_members_id_fk",
"tableFrom": "card_activity",
"tableTo": "workspace_members",
"columnsFrom": [
"workspaceMemberId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"card_activity_createdBy_user_id_fk": {
"name": "card_activity_createdBy_user_id_fk",
"tableFrom": "card_activity",
"tableTo": "user",
"columnsFrom": [
"createdBy"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"card_activity_commentId_card_comments_id_fk": {
"name": "card_activity_commentId_card_comments_id_fk",
"tableFrom": "card_activity",
"tableTo": "card_comments",
"columnsFrom": [
"commentId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"card_activity_publicId_unique": {
"name": "card_activity_publicId_unique",
"nullsNotDistinct": false,
"columns": [
"publicId"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public._card_workspace_members": {
"name": "_card_workspace_members",
"schema": "",
"columns": {
@@ -277,22 +410,25 @@
"columnsTo": [
"id"
],
"onDelete": "no action",
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"_card_workspace_members_cardId_workspaceMemberId": {
"name": "_card_workspace_members_cardId_workspaceMemberId",
"_card_workspace_members_cardId_workspaceMemberId_pk": {
"name": "_card_workspace_members_cardId_workspaceMemberId_pk",
"columns": [
"cardId",
"workspaceMemberId"
]
}
},
"uniqueConstraints": {}
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"card": {
"public.card": {
"name": "card",
"schema": "",
"columns": {
@@ -408,7 +544,7 @@
"columnsTo": [
"id"
],
"onDelete": "no action",
"onDelete": "cascade",
"onUpdate": "no action"
},
"card_importId_import_id_fk": {
@@ -434,9 +570,12 @@
"publicId"
]
}
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"_card_labels": {
"public._card_labels": {
"name": "_card_labels",
"schema": "",
"columns": {
@@ -478,22 +617,141 @@
"columnsTo": [
"id"
],
"onDelete": "no action",
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"_card_labels_cardId_labelId": {
"name": "_card_labels_cardId_labelId",
"_card_labels_cardId_labelId_pk": {
"name": "_card_labels_cardId_labelId_pk",
"columns": [
"cardId",
"labelId"
]
}
},
"uniqueConstraints": {}
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"import": {
"public.card_comments": {
"name": "card_comments",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "bigserial",
"primaryKey": true,
"notNull": true
},
"publicId": {
"name": "publicId",
"type": "varchar(12)",
"primaryKey": false,
"notNull": true
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": true
},
"cardId": {
"name": "cardId",
"type": "bigint",
"primaryKey": false,
"notNull": true
},
"createdBy": {
"name": "createdBy",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"deletedAt": {
"name": "deletedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"deletedBy": {
"name": "deletedBy",
"type": "uuid",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"card_comments_cardId_card_id_fk": {
"name": "card_comments_cardId_card_id_fk",
"tableFrom": "card_comments",
"tableTo": "card",
"columnsFrom": [
"cardId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"card_comments_createdBy_user_id_fk": {
"name": "card_comments_createdBy_user_id_fk",
"tableFrom": "card_comments",
"tableTo": "user",
"columnsFrom": [
"createdBy"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"card_comments_deletedBy_user_id_fk": {
"name": "card_comments_deletedBy_user_id_fk",
"tableFrom": "card_comments",
"tableTo": "user",
"columnsFrom": [
"deletedBy"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"card_comments_publicId_unique": {
"name": "card_comments_publicId_unique",
"nullsNotDistinct": false,
"columns": [
"publicId"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.import": {
"name": "import",
"schema": "",
"columns": {
@@ -512,12 +770,14 @@
"source": {
"name": "source",
"type": "source",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
@@ -560,9 +820,12 @@
"publicId"
]
}
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"label": {
"public.label": {
"name": "label",
"schema": "",
"columns": {
@@ -647,7 +910,7 @@
"columnsTo": [
"id"
],
"onDelete": "no action",
"onDelete": "cascade",
"onUpdate": "no action"
},
"label_importId_import_id_fk": {
@@ -673,9 +936,12 @@
"publicId"
]
}
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"list": {
"public.list": {
"name": "list",
"schema": "",
"columns": {
@@ -785,7 +1051,7 @@
"columnsTo": [
"id"
],
"onDelete": "no action",
"onDelete": "cascade",
"onUpdate": "no action"
},
"list_importId_import_id_fk": {
@@ -811,51 +1077,46 @@
"publicId"
]
}
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"session": {
"name": "session",
"public.workspace_slugs": {
"name": "workspace_slugs",
"schema": "",
"columns": {
"sessionToken": {
"name": "sessionToken",
"slug": {
"name": "slug",
"type": "varchar(255)",
"primaryKey": true,
"notNull": true
},
"userId": {
"name": "userId",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"expires": {
"name": "expires",
"type": "timestamp",
"type": {
"name": "type",
"type": "slug_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"session_userId_user_id_fk": {
"name": "session_userId_user_id_fk",
"tableFrom": "session",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"workspace_slugs_slug_unique": {
"name": "workspace_slugs_slug_unique",
"nullsNotDistinct": false,
"columns": [
"slug"
]
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"user": {
"public.user": {
"name": "user",
"schema": "",
"columns": {
@@ -901,45 +1162,12 @@
"email"
]
}
}
},
"verificationToken": {
"name": "verificationToken",
"schema": "",
"columns": {
"identifier": {
"name": "identifier",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"token": {
"name": "token",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"expires": {
"name": "expires",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"verificationToken_identifier_token": {
"name": "verificationToken_identifier_token",
"columns": [
"identifier",
"token"
]
}
},
"uniqueConstraints": {}
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"workspace_members": {
"public.workspace_members": {
"name": "workspace_members",
"schema": "",
"columns": {
@@ -992,11 +1220,26 @@
"primaryKey": false,
"notNull": false
},
"deletedBy": {
"name": "deletedBy",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"role": {
"name": "role",
"type": "role",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "member_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'invited'"
}
},
"indexes": {},
@@ -1024,6 +1267,19 @@
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"workspace_members_deletedBy_user_id_fk": {
"name": "workspace_members_deletedBy_user_id_fk",
"tableFrom": "workspace_members",
"tableTo": "user",
"columnsFrom": [
"deletedBy"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
@@ -1037,9 +1293,12 @@
"publicId"
]
}
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"workspace": {
"public.workspace": {
"name": "workspace",
"schema": "",
"columns": {
@@ -1144,37 +1403,83 @@
"slug"
]
}
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {
"source": {
"public.card_activity_type": {
"name": "card_activity_type",
"schema": "public",
"values": [
"card.created",
"card.updated.title",
"card.updated.description",
"card.updated.index",
"card.updated.list",
"card.updated.label.added",
"card.updated.label.removed",
"card.updated.member.added",
"card.updated.member.removed",
"card.updated.comment.added",
"card.updated.comment.updated",
"card.updated.comment.deleted",
"card.archived"
]
},
"public.source": {
"name": "source",
"values": {
"trello": "trello"
}
"schema": "public",
"values": [
"trello"
]
},
"status": {
"public.status": {
"name": "status",
"values": {
"started": "started",
"success": "success",
"failed": "failed"
}
"schema": "public",
"values": [
"started",
"success",
"failed"
]
},
"role": {
"public.role": {
"name": "role",
"values": {
"admin": "admin",
"member": "member",
"guest": "guest"
}
"schema": "public",
"values": [
"admin",
"member",
"guest"
]
},
"public.member_status": {
"name": "member_status",
"schema": "public",
"values": [
"invited",
"active",
"removed"
]
},
"public.slug_type": {
"name": "slug_type",
"schema": "public",
"values": [
"reserved",
"premium"
]
}
},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {},
"columns": {}
"tables": {}
}
}

View File

@@ -1,108 +1,10 @@
{
"version": "5",
"dialect": "pg",
"id": "9ebe8f2d-46c1-43e9-b5ca-4b05e3e37090",
"prevId": "32295e0d-123f-4eae-b323-1fe55e3c4dca",
"id": "dbb6beb4-cd15-47c0-959a-64d161045634",
"prevId": "3bf82a86-d7ff-4ab7-81ed-024350dfb32a",
"version": "7",
"dialect": "postgresql",
"tables": {
"account": {
"name": "account",
"schema": "",
"columns": {
"userId": {
"name": "userId",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"provider": {
"name": "provider",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"providerAccountId": {
"name": "providerAccountId",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"token_type": {
"name": "token_type",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"scope": {
"name": "scope",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"id_token": {
"name": "id_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"session_state": {
"name": "session_state",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"account_userId_user_id_fk": {
"name": "account_userId_user_id_fk",
"tableFrom": "account",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"account_provider_providerAccountId": {
"name": "account_provider_providerAccountId",
"columns": [
"provider",
"providerAccountId"
]
}
},
"uniqueConstraints": {}
},
"board": {
"public.board": {
"name": "board",
"schema": "",
"columns": {
@@ -219,7 +121,7 @@
"columnsTo": [
"id"
],
"onDelete": "no action",
"onDelete": "cascade",
"onUpdate": "no action"
}
},
@@ -232,9 +134,241 @@
"publicId"
]
}
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"_card_workspace_members": {
"public.card_activity": {
"name": "card_activity",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "bigserial",
"primaryKey": true,
"notNull": true
},
"publicId": {
"name": "publicId",
"type": "varchar(12)",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "card_activity_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"cardId": {
"name": "cardId",
"type": "bigint",
"primaryKey": false,
"notNull": true
},
"fromIndex": {
"name": "fromIndex",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"toIndex": {
"name": "toIndex",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"fromListId": {
"name": "fromListId",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"toListId": {
"name": "toListId",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"labelId": {
"name": "labelId",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"workspaceMemberId": {
"name": "workspaceMemberId",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"fromTitle": {
"name": "fromTitle",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"toTitle": {
"name": "toTitle",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"fromDescription": {
"name": "fromDescription",
"type": "text",
"primaryKey": false,
"notNull": false
},
"toDescription": {
"name": "toDescription",
"type": "text",
"primaryKey": false,
"notNull": false
},
"createdBy": {
"name": "createdBy",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"commentId": {
"name": "commentId",
"type": "bigint",
"primaryKey": false,
"notNull": false
},
"fromComment": {
"name": "fromComment",
"type": "text",
"primaryKey": false,
"notNull": false
},
"toComment": {
"name": "toComment",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"card_activity_cardId_card_id_fk": {
"name": "card_activity_cardId_card_id_fk",
"tableFrom": "card_activity",
"tableTo": "card",
"columnsFrom": [
"cardId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"card_activity_fromListId_list_id_fk": {
"name": "card_activity_fromListId_list_id_fk",
"tableFrom": "card_activity",
"tableTo": "list",
"columnsFrom": [
"fromListId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"card_activity_toListId_list_id_fk": {
"name": "card_activity_toListId_list_id_fk",
"tableFrom": "card_activity",
"tableTo": "list",
"columnsFrom": [
"toListId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"card_activity_labelId_label_id_fk": {
"name": "card_activity_labelId_label_id_fk",
"tableFrom": "card_activity",
"tableTo": "label",
"columnsFrom": [
"labelId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"card_activity_workspaceMemberId_workspace_members_id_fk": {
"name": "card_activity_workspaceMemberId_workspace_members_id_fk",
"tableFrom": "card_activity",
"tableTo": "workspace_members",
"columnsFrom": [
"workspaceMemberId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"card_activity_createdBy_user_id_fk": {
"name": "card_activity_createdBy_user_id_fk",
"tableFrom": "card_activity",
"tableTo": "user",
"columnsFrom": [
"createdBy"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"card_activity_commentId_card_comments_id_fk": {
"name": "card_activity_commentId_card_comments_id_fk",
"tableFrom": "card_activity",
"tableTo": "card_comments",
"columnsFrom": [
"commentId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"card_activity_publicId_unique": {
"name": "card_activity_publicId_unique",
"nullsNotDistinct": false,
"columns": [
"publicId"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public._card_workspace_members": {
"name": "_card_workspace_members",
"schema": "",
"columns": {
@@ -276,22 +410,25 @@
"columnsTo": [
"id"
],
"onDelete": "no action",
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"_card_workspace_members_cardId_workspaceMemberId": {
"name": "_card_workspace_members_cardId_workspaceMemberId",
"_card_workspace_members_cardId_workspaceMemberId_pk": {
"name": "_card_workspace_members_cardId_workspaceMemberId_pk",
"columns": [
"cardId",
"workspaceMemberId"
]
}
},
"uniqueConstraints": {}
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"card": {
"public.card": {
"name": "card",
"schema": "",
"columns": {
@@ -407,7 +544,7 @@
"columnsTo": [
"id"
],
"onDelete": "no action",
"onDelete": "cascade",
"onUpdate": "no action"
},
"card_importId_import_id_fk": {
@@ -433,9 +570,12 @@
"publicId"
]
}
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"_card_labels": {
"public._card_labels": {
"name": "_card_labels",
"schema": "",
"columns": {
@@ -477,22 +617,141 @@
"columnsTo": [
"id"
],
"onDelete": "no action",
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"_card_labels_cardId_labelId": {
"name": "_card_labels_cardId_labelId",
"_card_labels_cardId_labelId_pk": {
"name": "_card_labels_cardId_labelId_pk",
"columns": [
"cardId",
"labelId"
]
}
},
"uniqueConstraints": {}
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"import": {
"public.card_comments": {
"name": "card_comments",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "bigserial",
"primaryKey": true,
"notNull": true
},
"publicId": {
"name": "publicId",
"type": "varchar(12)",
"primaryKey": false,
"notNull": true
},
"comment": {
"name": "comment",
"type": "text",
"primaryKey": false,
"notNull": true
},
"cardId": {
"name": "cardId",
"type": "bigint",
"primaryKey": false,
"notNull": true
},
"createdBy": {
"name": "createdBy",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"createdAt": {
"name": "createdAt",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
},
"updatedAt": {
"name": "updatedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"deletedAt": {
"name": "deletedAt",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"deletedBy": {
"name": "deletedBy",
"type": "uuid",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"card_comments_cardId_card_id_fk": {
"name": "card_comments_cardId_card_id_fk",
"tableFrom": "card_comments",
"tableTo": "card",
"columnsFrom": [
"cardId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"card_comments_createdBy_user_id_fk": {
"name": "card_comments_createdBy_user_id_fk",
"tableFrom": "card_comments",
"tableTo": "user",
"columnsFrom": [
"createdBy"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
},
"card_comments_deletedBy_user_id_fk": {
"name": "card_comments_deletedBy_user_id_fk",
"tableFrom": "card_comments",
"tableTo": "user",
"columnsFrom": [
"deletedBy"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"card_comments_publicId_unique": {
"name": "card_comments_publicId_unique",
"nullsNotDistinct": false,
"columns": [
"publicId"
]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.import": {
"name": "import",
"schema": "",
"columns": {
@@ -511,12 +770,14 @@
"source": {
"name": "source",
"type": "source",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
@@ -559,9 +820,12 @@
"publicId"
]
}
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"label": {
"public.label": {
"name": "label",
"schema": "",
"columns": {
@@ -646,7 +910,7 @@
"columnsTo": [
"id"
],
"onDelete": "no action",
"onDelete": "cascade",
"onUpdate": "no action"
},
"label_importId_import_id_fk": {
@@ -672,9 +936,12 @@
"publicId"
]
}
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"list": {
"public.list": {
"name": "list",
"schema": "",
"columns": {
@@ -784,7 +1051,7 @@
"columnsTo": [
"id"
],
"onDelete": "no action",
"onDelete": "cascade",
"onUpdate": "no action"
},
"list_importId_import_id_fk": {
@@ -810,51 +1077,46 @@
"publicId"
]
}
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"session": {
"name": "session",
"public.workspace_slugs": {
"name": "workspace_slugs",
"schema": "",
"columns": {
"sessionToken": {
"name": "sessionToken",
"slug": {
"name": "slug",
"type": "varchar(255)",
"primaryKey": true,
"notNull": true
},
"userId": {
"name": "userId",
"type": "uuid",
"primaryKey": false,
"notNull": true
},
"expires": {
"name": "expires",
"type": "timestamp",
"type": {
"name": "type",
"type": "slug_type",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"session_userId_user_id_fk": {
"name": "session_userId_user_id_fk",
"tableFrom": "session",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"workspace_slugs_slug_unique": {
"name": "workspace_slugs_slug_unique",
"nullsNotDistinct": false,
"columns": [
"slug"
]
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"user": {
"public.user": {
"name": "user",
"schema": "",
"columns": {
@@ -887,6 +1149,12 @@
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
},
"stripeCustomerId": {
"name": "stripeCustomerId",
"type": "varchar(255)",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
@@ -900,45 +1168,12 @@
"email"
]
}
}
},
"verificationToken": {
"name": "verificationToken",
"schema": "",
"columns": {
"identifier": {
"name": "identifier",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"token": {
"name": "token",
"type": "varchar(255)",
"primaryKey": false,
"notNull": true
},
"expires": {
"name": "expires",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"verificationToken_identifier_token": {
"name": "verificationToken_identifier_token",
"columns": [
"identifier",
"token"
]
}
},
"uniqueConstraints": {}
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"workspace_members": {
"public.workspace_members": {
"name": "workspace_members",
"schema": "",
"columns": {
@@ -991,11 +1226,26 @@
"primaryKey": false,
"notNull": false
},
"deletedBy": {
"name": "deletedBy",
"type": "uuid",
"primaryKey": false,
"notNull": false
},
"role": {
"name": "role",
"type": "role",
"typeSchema": "public",
"primaryKey": false,
"notNull": true
},
"status": {
"name": "status",
"type": "member_status",
"typeSchema": "public",
"primaryKey": false,
"notNull": true,
"default": "'invited'"
}
},
"indexes": {},
@@ -1023,6 +1273,19 @@
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
},
"workspace_members_deletedBy_user_id_fk": {
"name": "workspace_members_deletedBy_user_id_fk",
"tableFrom": "workspace_members",
"tableTo": "user",
"columnsFrom": [
"deletedBy"
],
"columnsTo": [
"id"
],
"onDelete": "no action",
"onUpdate": "no action"
}
@@ -1036,9 +1299,12 @@
"publicId"
]
}
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"workspace": {
"public.workspace": {
"name": "workspace",
"schema": "",
"columns": {
@@ -1143,37 +1409,83 @@
"slug"
]
}
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {
"source": {
"public.card_activity_type": {
"name": "card_activity_type",
"schema": "public",
"values": [
"card.created",
"card.updated.title",
"card.updated.description",
"card.updated.index",
"card.updated.list",
"card.updated.label.added",
"card.updated.label.removed",
"card.updated.member.added",
"card.updated.member.removed",
"card.updated.comment.added",
"card.updated.comment.updated",
"card.updated.comment.deleted",
"card.archived"
]
},
"public.source": {
"name": "source",
"values": {
"trello": "trello"
}
"schema": "public",
"values": [
"trello"
]
},
"status": {
"public.status": {
"name": "status",
"values": {
"started": "started",
"success": "success",
"failed": "failed"
}
"schema": "public",
"values": [
"started",
"success",
"failed"
]
},
"role": {
"public.role": {
"name": "role",
"values": {
"admin": "admin",
"member": "member",
"guest": "guest"
}
"schema": "public",
"values": [
"admin",
"member",
"guest"
]
},
"public.member_status": {
"name": "member_status",
"schema": "public",
"values": [
"invited",
"active",
"removed"
]
},
"public.slug_type": {
"name": "slug_type",
"schema": "public",
"values": [
"reserved",
"premium"
]
}
},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {},
"columns": {}
"tables": {}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,68 +1,19 @@
{
"version": "12",
"dialect": "pg",
"version": "7",
"dialect": "postgresql",
"entries": [
{
"idx": 0,
"version": "5",
"when": 1711571659259,
"tag": "0000_legal_quicksilver",
"version": "7",
"when": 1735766172233,
"tag": "0000_eager_krista_starr",
"breakpoints": true
},
{
"idx": 1,
"version": "5",
"when": 1713021051974,
"tag": "0001_stale_mattie_franklin",
"breakpoints": true
},
{
"idx": 2,
"version": "5",
"when": 1724967733894,
"tag": "0002_clever_robin_chapel",
"breakpoints": true
},
{
"idx": 3,
"version": "5",
"when": 1728246215706,
"tag": "0003_naive_secret_warriors",
"breakpoints": true
},
{
"idx": 4,
"version": "5",
"when": 1730205607613,
"tag": "0004_rainy_archangel",
"breakpoints": true
},
{
"idx": 5,
"version": "5",
"when": 1730813108528,
"tag": "0005_blue_marvex",
"breakpoints": true
},
{
"idx": 6,
"version": "5",
"when": 1730967400524,
"tag": "0006_neat_korg",
"breakpoints": true
},
{
"idx": 7,
"version": "5",
"when": 1731934769875,
"tag": "0007_adorable_crystal",
"breakpoints": true
},
{
"idx": 8,
"version": "5",
"when": 1731958265600,
"tag": "0008_nasty_bloodstorm",
"version": "7",
"when": 1735821726274,
"tag": "0001_little_red_hulk",
"breakpoints": true
}
]

View File

@@ -10,6 +10,17 @@ if (!postgresUrl) {
}
const migrationClient = postgres(postgresUrl, { max: 1 });
console.log("Starting database migration...");
migrate(drizzle(migrationClient), {
migrationsFolder: "./src/server/db/migrations",
}).catch((e) => console.log(e));
migrationsFolder: "./migrations",
})
.then(() => {
console.log("✅ Database migration completed successfully");
process.exit(0);
})
.catch((error) => {
console.error("❌ Migration failed:");
console.error(error);
process.exit(1);
});

View File

@@ -5,7 +5,7 @@ import type { Database } from "@kan/db/types/database.types";
export const getById = async (db: SupabaseClient<Database>, userId: string) => {
const { data } = await db
.from("user")
.select(`id, name, email`)
.select(`id, name, email, stripeCustomerId`)
.eq("id", userId)
.limit(1)
.single();
@@ -29,11 +29,15 @@ export const getByEmail = async (
export const create = async (
db: SupabaseClient<Database>,
user: { id: string; email: string },
user: { id: string; email: string; stripeCustomerId: string },
) => {
const { data } = await db
.from("user")
.insert({ id: user.id, email: user.email })
.insert({
id: user.id,
email: user.email,
stripeCustomerId: user.stripeCustomerId,
})
.select()
.limit(1)
.single();

View File

@@ -159,3 +159,18 @@ export const hardDelete = async (
return result;
};
export const isWorkspaceSlugAvailable = async (
db: SupabaseClient<Database>,
workspaceSlug: string,
) => {
const { data } = await db
.from("workspace")
.select("id")
.eq("slug", workspaceSlug)
.is("deletedAt", null)
.limit(1)
.single();
return data === null;
};

View File

@@ -0,0 +1,16 @@
import type { SupabaseClient } from "@supabase/supabase-js";
import type { Database } from "@kan/db/types/database.types";
export const getWorkspaceSlug = async (
db: SupabaseClient<Database>,
slug: string,
) => {
const { data } = await db
.from("workspace_slugs")
.select(`slug, type`)
.eq("slug", slug)
.single();
return data;
};

View File

@@ -1,15 +1,15 @@
import { relations } from "drizzle-orm";
import {
integer,
bigint,
bigserial,
uuid,
integer,
pgEnum,
pgTable,
primaryKey,
text,
timestamp,
uuid,
varchar,
bigint,
} from "drizzle-orm/pg-core";
export const importSourceEnum = pgEnum("source", ["trello"]);
@@ -39,6 +39,7 @@ export const activityTypeEnum = pgEnum("card_activity_type", [
"card.updated.comment.deleted",
"card.archived",
]);
export const slugTypeEnum = pgEnum("slug_type", ["reserved", "premium"]);
export const boards = pgTable("board", {
id: bigserial("id", { mode: "number" }).primaryKey(),
@@ -272,6 +273,7 @@ export const users = pgTable("user", {
email: varchar("email", { length: 255 }).notNull().unique(),
emailVerified: timestamp("emailVerified", { mode: "date" }),
image: varchar("image", { length: 255 }),
stripeCustomerId: varchar("stripeCustomerId", { length: 255 }),
});
export const usersRelations = relations(users, ({ many }) => ({
@@ -430,3 +432,8 @@ export const commentsRelations = relations(comments, ({ one }) => ({
references: [users.id],
}),
}));
export const slugs = pgTable("workspace_slugs", {
slug: varchar("slug", { length: 255 }).notNull().unique(),
type: slugTypeEnum("type").notNull(),
});

View File

@@ -8,7 +8,7 @@ export type Json =
| { [key: string]: Json | undefined }
| Json[];
export type Database = {
export interface Database {
public: {
Tables: {
_card_labels: {
@@ -558,6 +558,7 @@ export type Database = {
id: string;
image: string | null;
name: string | null;
stripeCustomerId: string | null;
};
Insert: {
email: string;
@@ -565,6 +566,7 @@ export type Database = {
id: string;
image?: string | null;
name?: string | null;
stripeCustomerId?: string | null;
};
Update: {
email?: string;
@@ -572,6 +574,7 @@ export type Database = {
id?: string;
image?: string | null;
name?: string | null;
stripeCustomerId?: string | null;
};
Relationships: [];
};
@@ -690,10 +693,23 @@ export type Database = {
},
];
};
workspace_slugs: {
Row: {
slug: string;
type: Database["public"]["Enums"]["slug_type"];
};
Insert: {
slug: string;
type: Database["public"]["Enums"]["slug_type"];
};
Update: {
slug?: string;
type?: Database["public"]["Enums"]["slug_type"];
};
Relationships: [];
};
};
Views: {
[_ in never]: never;
};
Views: Record<never, never>;
Functions: {
is_workspace_admin: {
Args: {
@@ -717,7 +733,7 @@ export type Database = {
current_index: number;
new_index: number;
};
Returns: undefined;
Returns: boolean;
};
reorder_lists: {
Args: {
@@ -726,7 +742,7 @@ export type Database = {
current_index: number;
new_index: number;
};
Returns: undefined;
Returns: boolean;
};
shift_card_index: {
Args: {
@@ -760,15 +776,14 @@ export type Database = {
| "card.updated.comment.deleted";
member_status: "invited" | "active" | "removed";
role: "admin" | "member" | "guest";
slug_type: "reserved" | "premium";
source: "trello";
status: "started" | "success" | "failed";
workspace_invite_status: "pending" | "accepted" | "cancelled";
};
CompositeTypes: {
[_ in never]: never;
};
CompositeTypes: Record<never, never>;
};
};
}
type PublicSchema = Database[Extract<keyof Database, "public">];

12
pnpm-lock.yaml generated
View File

@@ -147,6 +147,9 @@ importers:
react-lottie-player:
specifier: ^1.5.5
version: 1.5.6(react@18.3.1)
stripe:
specifier: ^17.5.0
version: 17.5.0
superjson:
specifier: 2.2.1
version: 2.2.1
@@ -4753,6 +4756,10 @@ packages:
resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==}
engines: {node: '>=8'}
stripe@17.5.0:
resolution: {integrity: sha512-kcyeAkDFjGsVl17FqnG7q/+xIjt0ZjOo9Dm+q8deAvs2Xe4iAHrhxyoP4etUVFc+/LZJANjIPVR+ZOnt9hr/Ug==}
engines: {node: '>=12.*'}
styled-jsx@5.1.1:
resolution: {integrity: sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==}
engines: {node: '>= 12.0.0'}
@@ -9923,6 +9930,11 @@ snapshots:
strip-json-comments@3.1.1: {}
stripe@17.5.0:
dependencies:
'@types/node': 20.17.9
qs: 6.13.1
styled-jsx@5.1.1(react@18.3.1):
dependencies:
client-only: 0.0.1