feat: monorepo
This commit is contained in:
11
packages/db/drizzle.config.ts
Normal file
11
packages/db/drizzle.config.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { type Config } from "drizzle-kit";
|
||||
|
||||
export default {
|
||||
schema: "./src/server/db/schema.ts",
|
||||
out: "./src/server/db/migrations",
|
||||
driver: "pg",
|
||||
dbCredentials: {
|
||||
connectionString: process.env.POSTGRES_URL,
|
||||
},
|
||||
// tablesFilter: ["kan_*"],
|
||||
} satisfies Config;
|
||||
9
packages/db/eslint.config.js
Normal file
9
packages/db/eslint.config.js
Normal file
@@ -0,0 +1,9 @@
|
||||
import baseConfig from "@kan/eslint-config/base";
|
||||
|
||||
/** @type {import('typescript-eslint').Config} */
|
||||
export default [
|
||||
{
|
||||
ignores: ["dist/**"],
|
||||
},
|
||||
...baseConfig,
|
||||
];
|
||||
317
packages/db/migrations/0000_legal_quicksilver.sql
Normal file
317
packages/db/migrations/0000_legal_quicksilver.sql
Normal file
@@ -0,0 +1,317 @@
|
||||
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 TABLE IF NOT EXISTS "board" (
|
||||
"id" bigserial PRIMARY KEY NOT NULL,
|
||||
"publicId" varchar(12) NOT NULL,
|
||||
"name" varchar(255) NOT NULL,
|
||||
"createdBy" uuid NOT NULL,
|
||||
"createdAt" timestamp DEFAULT now() NOT NULL,
|
||||
"updatedAt" timestamp,
|
||||
"deletedAt" timestamp DEFAULT now(),
|
||||
"deletedBy" uuid,
|
||||
"importId" bigint,
|
||||
"workspaceId" bigint NOT NULL,
|
||||
CONSTRAINT "board_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")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE IF NOT EXISTS "card" (
|
||||
"id" bigserial PRIMARY KEY NOT NULL,
|
||||
"publicId" varchar(12) NOT NULL,
|
||||
"title" varchar(255) NOT NULL,
|
||||
"description" text,
|
||||
"index" integer NOT NULL,
|
||||
"createdBy" uuid NOT NULL,
|
||||
"createdAt" timestamp DEFAULT now() NOT NULL,
|
||||
"updatedAt" timestamp,
|
||||
"deletedAt" timestamp,
|
||||
"deletedBy" uuid,
|
||||
"listId" bigint NOT NULL,
|
||||
"importId" bigint,
|
||||
CONSTRAINT "card_publicId_unique" UNIQUE("publicId")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE IF NOT EXISTS "_card_labels" (
|
||||
"cardId" bigint NOT NULL,
|
||||
"labelId" bigint NOT NULL,
|
||||
CONSTRAINT _card_labels_cardId_labelId PRIMARY KEY("cardId","labelId")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE IF NOT EXISTS "import" (
|
||||
"id" bigserial PRIMARY KEY NOT NULL,
|
||||
"publicId" varchar(12) NOT NULL,
|
||||
"source" "source" NOT NULL,
|
||||
"status" "status" NOT NULL,
|
||||
"createdBy" uuid NOT NULL,
|
||||
"createdAt" timestamp DEFAULT now() NOT NULL,
|
||||
CONSTRAINT "import_publicId_unique" UNIQUE("publicId")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE IF NOT EXISTS "label" (
|
||||
"id" bigserial PRIMARY KEY NOT NULL,
|
||||
"publicId" varchar(12) NOT NULL,
|
||||
"name" varchar(255) NOT NULL,
|
||||
"colourCode" varchar(12),
|
||||
"createdBy" uuid NOT NULL,
|
||||
"createdAt" timestamp DEFAULT now() NOT NULL,
|
||||
"updatedAt" timestamp,
|
||||
"boardId" bigint NOT NULL,
|
||||
"importId" bigint,
|
||||
CONSTRAINT "label_publicId_unique" UNIQUE("publicId")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE IF NOT EXISTS "list" (
|
||||
"id" bigserial PRIMARY KEY NOT NULL,
|
||||
"publicId" varchar(12) NOT NULL,
|
||||
"name" varchar(255) NOT NULL,
|
||||
"index" integer NOT NULL,
|
||||
"createdBy" uuid NOT NULL,
|
||||
"createdAt" timestamp DEFAULT now() NOT NULL,
|
||||
"updatedAt" timestamp,
|
||||
"deletedAt" timestamp,
|
||||
"deletedBy" uuid,
|
||||
"boardId" bigint NOT NULL,
|
||||
"importId" bigint,
|
||||
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
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE IF NOT EXISTS "user" (
|
||||
"id" uuid PRIMARY KEY NOT NULL,
|
||||
"name" varchar(255),
|
||||
"email" varchar(255) NOT NULL,
|
||||
"emailVerified" timestamp,
|
||||
"image" varchar(255),
|
||||
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,
|
||||
"userId" uuid NOT NULL,
|
||||
"workspaceId" bigint NOT NULL,
|
||||
"createdBy" uuid NOT NULL,
|
||||
"createdAt" timestamp DEFAULT now() NOT NULL,
|
||||
"updatedAt" timestamp,
|
||||
"deletedAt" timestamp,
|
||||
"role" "role" NOT NULL,
|
||||
CONSTRAINT "workspace_members_publicId_unique" UNIQUE("publicId")
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE IF NOT EXISTS "workspace" (
|
||||
"id" bigserial PRIMARY KEY NOT NULL,
|
||||
"publicId" varchar(12) NOT NULL,
|
||||
"name" varchar(255) NOT NULL,
|
||||
"slug" varchar(255) NOT NULL,
|
||||
"createdBy" uuid NOT NULL,
|
||||
"createdAt" timestamp DEFAULT now() NOT NULL,
|
||||
"updatedAt" timestamp,
|
||||
"deletedAt" timestamp,
|
||||
"deletedBy" uuid,
|
||||
CONSTRAINT "workspace_publicId_unique" UNIQUE("publicId"),
|
||||
CONSTRAINT "workspace_slug_unique" UNIQUE("slug")
|
||||
);
|
||||
--> 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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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 $$;
|
||||
--> 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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
EXCEPTION
|
||||
WHEN duplicate_object THEN null;
|
||||
END $$;
|
||||
1
packages/db/migrations/0001_stale_mattie_franklin.sql
Normal file
1
packages/db/migrations/0001_stale_mattie_franklin.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE "board" ALTER COLUMN "deletedAt" DROP DEFAULT;
|
||||
66
packages/db/migrations/0002_clever_robin_chapel.sql
Normal file
66
packages/db/migrations/0002_clever_robin_chapel.sql
Normal file
@@ -0,0 +1,66 @@
|
||||
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 $$;
|
||||
22
packages/db/migrations/0003_naive_secret_warriors.sql
Normal file
22
packages/db/migrations/0003_naive_secret_warriors.sql
Normal file
@@ -0,0 +1,22 @@
|
||||
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 $$;
|
||||
6
packages/db/migrations/0004_rainy_archangel.sql
Normal file
6
packages/db/migrations/0004_rainy_archangel.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
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 $$;
|
||||
55
packages/db/migrations/0005_blue_marvex.sql
Normal file
55
packages/db/migrations/0005_blue_marvex.sql
Normal file
@@ -0,0 +1,55 @@
|
||||
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 $$;
|
||||
5
packages/db/migrations/0006_neat_korg.sql
Normal file
5
packages/db/migrations/0006_neat_korg.sql
Normal file
@@ -0,0 +1,5 @@
|
||||
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 $$;
|
||||
30
packages/db/migrations/0007_adorable_crystal.sql
Normal file
30
packages/db/migrations/0007_adorable_crystal.sql
Normal file
@@ -0,0 +1,30 @@
|
||||
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 $$;
|
||||
11
packages/db/migrations/0008_nasty_bloodstorm.sql
Normal file
11
packages/db/migrations/0008_nasty_bloodstorm.sql
Normal file
@@ -0,0 +1,11 @@
|
||||
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 $$;
|
||||
1180
packages/db/migrations/meta/0000_snapshot.json
Normal file
1180
packages/db/migrations/meta/0000_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1179
packages/db/migrations/meta/0001_snapshot.json
Normal file
1179
packages/db/migrations/meta/0001_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1003
packages/db/migrations/meta/0002_snapshot.json
Normal file
1003
packages/db/migrations/meta/0002_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1018
packages/db/migrations/meta/0003_snapshot.json
Normal file
1018
packages/db/migrations/meta/0003_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1037
packages/db/migrations/meta/0004_snapshot.json
Normal file
1037
packages/db/migrations/meta/0004_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1233
packages/db/migrations/meta/0005_snapshot.json
Normal file
1233
packages/db/migrations/meta/0005_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1246
packages/db/migrations/meta/0006_snapshot.json
Normal file
1246
packages/db/migrations/meta/0006_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1359
packages/db/migrations/meta/0007_snapshot.json
Normal file
1359
packages/db/migrations/meta/0007_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
1393
packages/db/migrations/meta/0008_snapshot.json
Normal file
1393
packages/db/migrations/meta/0008_snapshot.json
Normal file
File diff suppressed because it is too large
Load Diff
69
packages/db/migrations/meta/_journal.json
Normal file
69
packages/db/migrations/meta/_journal.json
Normal file
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"version": "12",
|
||||
"dialect": "pg",
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "5",
|
||||
"when": 1711571659259,
|
||||
"tag": "0000_legal_quicksilver",
|
||||
"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",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
58
packages/db/package.json
Normal file
58
packages/db/package.json
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
"name": "@kan/db",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/index.d.ts",
|
||||
"default": "./src/index.ts"
|
||||
},
|
||||
"./client": {
|
||||
"types": "./dist/client.d.ts",
|
||||
"default": "./src/client.ts"
|
||||
},
|
||||
"./schema": {
|
||||
"types": "./dist/schema.d.ts",
|
||||
"default": "./src/schema.ts"
|
||||
},
|
||||
"./types/*": {
|
||||
"types": "./dist/types/*.d.ts",
|
||||
"default": "./src/types/*"
|
||||
},
|
||||
"./repository/*": {
|
||||
"types": "./dist/repository/*.d.ts",
|
||||
"default": "./src/repository/*.ts"
|
||||
}
|
||||
},
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"clean": "git clean -xdf .cache .turbo dist node_modules",
|
||||
"dev": "tsc",
|
||||
"format": "prettier --check . --ignore-path ../../.gitignore",
|
||||
"lint": "eslint",
|
||||
"push": "pnpm with-env drizzle-kit push",
|
||||
"studio": "pnpm with-env drizzle-kit studio",
|
||||
"typecheck": "tsc --noEmit --emitDeclarationOnly false",
|
||||
"with-env": "dotenv -e ../../.env --"
|
||||
},
|
||||
"dependencies": {
|
||||
"@kan/utils": "workspace:^",
|
||||
"@vercel/postgres": "^0.10.0",
|
||||
"drizzle-orm": "^0.36.4",
|
||||
"drizzle-zod": "^0.5.1",
|
||||
"zod": "catalog:"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kan/eslint-config": "workspace:*",
|
||||
"@kan/prettier-config": "workspace:*",
|
||||
"@kan/tsconfig": "workspace:*",
|
||||
"dotenv-cli": "^7.4.4",
|
||||
"drizzle-kit": "^0.28.1",
|
||||
"eslint": "catalog:",
|
||||
"prettier": "catalog:",
|
||||
"typescript": "catalog:"
|
||||
},
|
||||
"prettier": "@kan/prettier-config"
|
||||
}
|
||||
346
packages/db/seed.sql
Normal file
346
packages/db/seed.sql
Normal file
@@ -0,0 +1,346 @@
|
||||
CREATE OR REPLACE FUNCTION reorder_lists(board_id BIGINT, list_id BIGINT, current_index INT, new_index INT)
|
||||
RETURNS BOOLEAN
|
||||
LANGUAGE PLPGSQL
|
||||
AS $$
|
||||
BEGIN
|
||||
UPDATE list
|
||||
SET index =
|
||||
CASE
|
||||
WHEN index = current_index AND id = list_id THEN new_index
|
||||
WHEN current_index < new_index AND index > current_index AND index <= new_index THEN index - 1
|
||||
WHEN current_index > new_index AND index >= new_index AND index < current_index THEN index + 1
|
||||
ELSE index
|
||||
END
|
||||
WHERE "boardId" = board_id;
|
||||
|
||||
-- Check for duplicate indices after the update
|
||||
IF EXISTS (
|
||||
SELECT index, COUNT(*)
|
||||
FROM list
|
||||
WHERE "boardId" = board_id
|
||||
AND "deletedAt" IS NULL
|
||||
GROUP BY index
|
||||
HAVING COUNT(*) > 1
|
||||
) THEN
|
||||
RAISE EXCEPTION 'Duplicate indices found after reordering in board %', board_id;
|
||||
END IF;
|
||||
|
||||
RETURN TRUE;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE OR REPLACE FUNCTION reorder_cards(card_id BIGINT, current_list_id BIGINT, new_list_id BIGINT, current_index INT, new_index INT)
|
||||
RETURNS BOOLEAN
|
||||
LANGUAGE PLPGSQL
|
||||
AS $$
|
||||
DECLARE
|
||||
card_index INT;
|
||||
BEGIN
|
||||
SELECT index INTO card_index FROM card WHERE "listId" = current_list_id AND id = card_id AND "deletedAt" IS NULL;
|
||||
|
||||
IF current_list_id = new_list_id THEN
|
||||
UPDATE card
|
||||
SET index =
|
||||
CASE
|
||||
WHEN index = current_index THEN new_index
|
||||
WHEN current_index < new_index AND index > current_index AND index <= new_index THEN index - 1
|
||||
WHEN current_index > new_index AND index >= new_index AND index < current_index THEN index + 1
|
||||
ELSE index
|
||||
END
|
||||
WHERE "listId" = current_list_id AND "deletedAt" IS NULL;
|
||||
ELSE
|
||||
UPDATE card
|
||||
SET index = index + 1
|
||||
WHERE "listId" = new_list_id AND index >= new_index AND "deletedAt" IS NULL;
|
||||
|
||||
UPDATE card
|
||||
SET index = index - 1
|
||||
WHERE "listId" = current_list_id AND index >= current_index AND "deletedAt" IS NULL;
|
||||
|
||||
UPDATE card
|
||||
SET "listId" = new_list_id, index = new_index
|
||||
WHERE id = card_id AND "deletedAt" IS NULL;
|
||||
END IF;
|
||||
|
||||
-- Check for duplicate indices in both affected lists
|
||||
IF EXISTS (
|
||||
SELECT index, COUNT(*)
|
||||
FROM card
|
||||
WHERE "listId" IN (current_list_id, new_list_id)
|
||||
AND "deletedAt" IS NULL
|
||||
GROUP BY "listId", index
|
||||
HAVING COUNT(*) > 1
|
||||
) THEN
|
||||
RAISE EXCEPTION 'Duplicate indices found after reordering in list % or %', current_list_id, new_list_id;
|
||||
END IF;
|
||||
|
||||
RETURN TRUE;
|
||||
END;
|
||||
$$;
|
||||
|
||||
CREATE OR REPLACE FUNCTION shift_list_index(board_id BIGINT, list_index INT)
|
||||
RETURNS VOID
|
||||
LANGUAGE SQL
|
||||
AS $$
|
||||
UPDATE list
|
||||
SET index = index - 1
|
||||
WHERE "boardId" = board_id AND index > list_index AND "deletedAt" IS NULL;
|
||||
$$;
|
||||
|
||||
CREATE OR REPLACE FUNCTION shift_card_index(list_id BIGINT, card_index INT)
|
||||
RETURNS VOID
|
||||
LANGUAGE SQL
|
||||
AS $$
|
||||
UPDATE card
|
||||
SET index = index - 1
|
||||
WHERE "listId" = list_id AND index > card_index AND "deletedAt" IS NULL;
|
||||
$$;
|
||||
|
||||
CREATE OR REPLACE FUNCTION push_card_index(list_id BIGINT, card_index INT)
|
||||
RETURNS VOID
|
||||
LANGUAGE SQL
|
||||
AS $$
|
||||
UPDATE card
|
||||
SET index = index + 1
|
||||
WHERE "listId" = list_id AND index >= card_index AND "deletedAt" IS NULL;
|
||||
$$;
|
||||
|
||||
CREATE OR REPLACE FUNCTION is_workspace_admin(user_id UUID, workspace_id BIGINT)
|
||||
RETURNS BOOLEAN
|
||||
LANGUAGE SQL
|
||||
AS $$
|
||||
SELECT EXISTS (
|
||||
SELECT 1
|
||||
FROM workspace_members
|
||||
WHERE "workspaceId" = workspace_id
|
||||
AND "userId" = user_id
|
||||
AND "role" = 'admin'
|
||||
);
|
||||
$$;
|
||||
|
||||
alter table "_card_labels" enable row level security;
|
||||
alter table "_card_workspace_members" enable row level security;
|
||||
alter table "board" enable row level security;
|
||||
alter table "card" enable row level security;
|
||||
alter table "import" enable row level security;
|
||||
alter table "label" enable row level security;
|
||||
alter table "user" enable row level security;
|
||||
alter table "list" enable row level security;
|
||||
alter table "workspace" enable row level security;
|
||||
alter table "workspace_members" enable row level security;
|
||||
|
||||
CREATE POLICY "Allow access to boards in user's workspace"
|
||||
ON public.board
|
||||
AS PERMISSIVE
|
||||
FOR ALL
|
||||
TO authenticated
|
||||
USING (
|
||||
"workspaceId" IN (
|
||||
SELECT "workspaceId"
|
||||
FROM workspace_members
|
||||
WHERE "userId" = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "Allow access to lists in user's workspace"
|
||||
ON public.list
|
||||
AS PERMISSIVE
|
||||
FOR ALL
|
||||
TO authenticated
|
||||
USING (
|
||||
"boardId" IN (
|
||||
SELECT b.id
|
||||
FROM board b
|
||||
JOIN workspace_members wm ON b."workspaceId" = wm."workspaceId"
|
||||
WHERE wm."userId" = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "Allow access to cards in user's workspace"
|
||||
ON public.card
|
||||
AS PERMISSIVE
|
||||
FOR ALL
|
||||
TO authenticated
|
||||
USING (
|
||||
"listId" IN (
|
||||
SELECT l.id
|
||||
FROM list l
|
||||
JOIN board b ON l."boardId" = b."id"
|
||||
JOIN workspace_members wm ON b."workspaceId" = wm."workspaceId"
|
||||
WHERE wm."userId" = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "Allow access to labels in user's workspace"
|
||||
ON public.label
|
||||
AS PERMISSIVE
|
||||
FOR ALL
|
||||
TO authenticated
|
||||
USING (
|
||||
"boardId" IN (
|
||||
SELECT b.id
|
||||
FROM board b
|
||||
JOIN workspace_members wm ON b."workspaceId" = wm."workspaceId"
|
||||
WHERE wm."userId" = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "Allow access to card labels in user's workspace"
|
||||
ON public._card_labels
|
||||
AS PERMISSIVE
|
||||
FOR ALL
|
||||
TO authenticated
|
||||
USING (
|
||||
"cardId" IN (
|
||||
SELECT c.id
|
||||
FROM card c
|
||||
JOIN list l ON c."listId" = l.id
|
||||
JOIN board b ON l."boardId" = b.id
|
||||
JOIN workspace_members wm ON b."workspaceId" = wm."workspaceId"
|
||||
WHERE wm."userId" = auth.uid()
|
||||
)
|
||||
AND
|
||||
"labelId" IN (
|
||||
SELECT l.id
|
||||
FROM label l
|
||||
JOIN board b ON l."boardId" = b.id
|
||||
JOIN workspace_members wm ON b."workspaceId" = wm."workspaceId"
|
||||
WHERE wm."userId" = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "Allow access to card workspace members in user's workspace"
|
||||
ON public._card_workspace_members
|
||||
AS PERMISSIVE
|
||||
FOR ALL
|
||||
TO authenticated
|
||||
USING (
|
||||
"cardId" IN (
|
||||
SELECT c.id
|
||||
FROM card c
|
||||
JOIN list l ON c."listId" = l.id
|
||||
JOIN board b ON l."boardId" = b.id
|
||||
JOIN workspace_members wm ON b."workspaceId" = wm."workspaceId"
|
||||
WHERE wm."userId" = auth.uid()
|
||||
)
|
||||
AND
|
||||
"workspaceMemberId" IN (
|
||||
SELECT wm.id
|
||||
FROM workspace_members wm
|
||||
JOIN workspace w ON wm."workspaceId" = w.id
|
||||
JOIN board b ON w.id = b."workspaceId"
|
||||
WHERE wm."userId" = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "Allow viewing members in user's workspace"
|
||||
ON public.user
|
||||
AS PERMISSIVE
|
||||
FOR SELECT
|
||||
TO authenticated
|
||||
USING (
|
||||
id IN (
|
||||
SELECT wm."userId"
|
||||
FROM workspace_members wm
|
||||
WHERE wm."workspaceId" IN (
|
||||
SELECT "workspaceId"
|
||||
FROM workspace_members
|
||||
WHERE "userId" = auth.uid()
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "Allow viewing user's workspaces"
|
||||
ON public.workspace
|
||||
AS PERMISSIVE
|
||||
FOR SELECT
|
||||
TO authenticated
|
||||
USING (
|
||||
id IN (
|
||||
SELECT "workspaceId"
|
||||
FROM workspace_members
|
||||
WHERE "userId" = auth.uid()
|
||||
)
|
||||
OR
|
||||
"createdBy" = auth.uid()
|
||||
);
|
||||
|
||||
CREATE POLICY "Allow updating user's workspaces"
|
||||
ON public.workspace
|
||||
AS PERMISSIVE
|
||||
FOR UPDATE
|
||||
TO authenticated
|
||||
USING (
|
||||
id IN (
|
||||
SELECT "workspaceId"
|
||||
FROM workspace_members
|
||||
WHERE "userId" = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "Allow deleting user's workspaces"
|
||||
ON public.workspace
|
||||
AS PERMISSIVE
|
||||
FOR DELETE
|
||||
TO authenticated
|
||||
USING (
|
||||
id IN (
|
||||
SELECT "workspaceId"
|
||||
FROM workspace_members
|
||||
WHERE "userId" = auth.uid()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY "Allow authenticated users to create workspaces"
|
||||
ON public.workspace
|
||||
AS PERMISSIVE
|
||||
FOR INSERT
|
||||
TO authenticated
|
||||
USING (true);
|
||||
|
||||
CREATE POLICY "Allow members to view workspace membership"
|
||||
ON public.workspace_members
|
||||
AS PERMISSIVE
|
||||
FOR SELECT
|
||||
TO authenticated
|
||||
USING (
|
||||
"userId" = auth.uid() OR
|
||||
is_workspace_admin(auth.uid(), "workspaceId")
|
||||
);
|
||||
|
||||
CREATE POLICY "Allow admins to add workspace members"
|
||||
ON public.workspace_members
|
||||
AS PERMISSIVE
|
||||
FOR INSERT
|
||||
TO authenticated
|
||||
WITH CHECK (
|
||||
is_workspace_admin(auth.uid(), "workspaceId")
|
||||
);
|
||||
|
||||
CREATE POLICY "Allow admins to update workspace members"
|
||||
ON public.workspace_members
|
||||
AS PERMISSIVE
|
||||
FOR UPDATE
|
||||
TO authenticated
|
||||
USING (
|
||||
is_workspace_admin(auth.uid(), "workspaceId")
|
||||
);
|
||||
|
||||
CREATE POLICY "Allow admins to remove workspace members"
|
||||
ON public.workspace_members
|
||||
AS PERMISSIVE
|
||||
FOR DELETE
|
||||
TO authenticated
|
||||
USING (
|
||||
is_workspace_admin(auth.uid(), "workspaceId")
|
||||
);
|
||||
CREATE POLICY "Allow access to user's own imports"
|
||||
ON public.import
|
||||
AS PERMISSIVE
|
||||
FOR ALL
|
||||
TO authenticated
|
||||
USING (
|
||||
"createdBy" = auth.uid()
|
||||
);
|
||||
|
||||
|
||||
9
packages/db/src/client.ts
Normal file
9
packages/db/src/client.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { sql } from "@vercel/postgres";
|
||||
import { drizzle } from "drizzle-orm/vercel-postgres";
|
||||
|
||||
import * as schema from "./schema";
|
||||
|
||||
export const db = drizzle({
|
||||
client: sql,
|
||||
schema,
|
||||
});
|
||||
15
packages/db/src/migrate.ts
Normal file
15
packages/db/src/migrate.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import "dotenv/config";
|
||||
|
||||
import { drizzle } from "drizzle-orm/postgres-js";
|
||||
import { migrate } from "drizzle-orm/postgres-js/migrator";
|
||||
import postgres from "postgres";
|
||||
|
||||
const postgresUrl = process.env.POSTGRES_URL;
|
||||
if (!postgresUrl) {
|
||||
throw new Error("POSTGRES_URL environment variable is not set");
|
||||
}
|
||||
|
||||
const migrationClient = postgres(postgresUrl, { max: 1 });
|
||||
migrate(drizzle(migrationClient), {
|
||||
migrationsFolder: "./src/server/db/migrations",
|
||||
}).catch((e) => console.log(e));
|
||||
191
packages/db/src/repository/board.repo.ts
Normal file
191
packages/db/src/repository/board.repo.ts
Normal file
@@ -0,0 +1,191 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
|
||||
import type { Database } from "@kan/db/types/database.types";
|
||||
import { generateUID } from "@kan/utils";
|
||||
|
||||
export const getAllByWorkspaceId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
workspaceId: number,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("board")
|
||||
.select(`publicId, name`)
|
||||
.is("deletedAt", null)
|
||||
.eq("workspaceId", workspaceId);
|
||||
|
||||
return data ?? [];
|
||||
};
|
||||
|
||||
export const getByPublicId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
boardPublicId: string,
|
||||
filters: {
|
||||
members: string[];
|
||||
labels: string[];
|
||||
},
|
||||
) => {
|
||||
let query = db
|
||||
.from("board")
|
||||
.select(
|
||||
`
|
||||
publicId,
|
||||
name,
|
||||
workspace (
|
||||
publicId,
|
||||
members:workspace_members (
|
||||
publicId,
|
||||
user!workspace_members_userId_user_id_fk (
|
||||
name
|
||||
)
|
||||
)
|
||||
),
|
||||
labels:label (
|
||||
publicId,
|
||||
name,
|
||||
colourCode
|
||||
),
|
||||
lists:list (
|
||||
publicId,
|
||||
name,
|
||||
boardId,
|
||||
index,
|
||||
cards:card (
|
||||
publicId,
|
||||
title,
|
||||
description,
|
||||
listId,
|
||||
index,
|
||||
labels:label${filters.labels.length > 0 ? "!inner" : ""} (
|
||||
publicId,
|
||||
name,
|
||||
colourCode
|
||||
),
|
||||
members:workspace_members${filters.members.length > 0 ? "!inner" : ""} (
|
||||
publicId,
|
||||
user!workspace_members_userId_user_id_fk (
|
||||
name
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
`,
|
||||
)
|
||||
.eq("publicId", boardPublicId)
|
||||
.is("deletedAt", null)
|
||||
.is("lists.deletedAt", null)
|
||||
.is("lists.cards.deletedAt", null)
|
||||
.is("workspace.members.deletedAt", null)
|
||||
.is("lists.cards.members.deletedAt", null);
|
||||
|
||||
if (filters.labels.length > 0) {
|
||||
query = query.in("lists.cards.labels.publicId", filters.labels);
|
||||
}
|
||||
|
||||
if (filters.members.length > 0) {
|
||||
query = query.in("lists.cards.members.publicId", filters.members);
|
||||
}
|
||||
|
||||
const { data } = await query
|
||||
.order("index", { foreignTable: "list", ascending: true })
|
||||
.order("index", { foreignTable: "list.card", ascending: true })
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getWithListIdsByPublicId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
boardPublicId: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("board")
|
||||
.select(`id, lists:list (id)`)
|
||||
.eq("publicId", boardPublicId)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getWithLatestListIndexByPublicId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
boardPublicId: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("board")
|
||||
.select(`id, lists:list (index)`)
|
||||
.eq("publicId", boardPublicId)
|
||||
.order("index", { foreignTable: "list", ascending: false })
|
||||
.is("list.deletedAt", null)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const create = async (
|
||||
db: SupabaseClient<Database>,
|
||||
boardInput: {
|
||||
name: string;
|
||||
createdBy: string;
|
||||
workspaceId: number;
|
||||
importId?: number;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("board")
|
||||
.insert({
|
||||
publicId: generateUID(),
|
||||
name: boardInput.name,
|
||||
createdBy: boardInput.createdBy,
|
||||
workspaceId: boardInput.workspaceId,
|
||||
importId: boardInput.importId,
|
||||
})
|
||||
.select(`id, publicId, name`)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const update = async (
|
||||
db: SupabaseClient<Database>,
|
||||
boardInput: { name: string; boardPublicId: string },
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("board")
|
||||
.update({ name: boardInput.name })
|
||||
.eq("publicId", boardInput.boardPublicId)
|
||||
.select(`publicId, name`)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const softDelete = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: {
|
||||
boardId: number;
|
||||
deletedAt: string;
|
||||
deletedBy: string;
|
||||
},
|
||||
) => {
|
||||
const result = db
|
||||
.from("board")
|
||||
.update({ deletedAt: args.deletedAt, deletedBy: args.deletedBy })
|
||||
.eq("id", args.boardId)
|
||||
.is("deletedAt", null);
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export const hardDelete = async (
|
||||
db: SupabaseClient<Database>,
|
||||
workspaceId: number,
|
||||
) => {
|
||||
const result = db.from("board").delete().eq("workspaceId", workspaceId);
|
||||
|
||||
return result;
|
||||
};
|
||||
426
packages/db/src/repository/card.repo.ts
Normal file
426
packages/db/src/repository/card.repo.ts
Normal file
@@ -0,0 +1,426 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
|
||||
import type { Database } from "@kan/db/types/database.types";
|
||||
import { generateUID } from "@kan/utils";
|
||||
|
||||
export const create = async (
|
||||
db: SupabaseClient<Database>,
|
||||
cardInput: {
|
||||
title: string;
|
||||
description: string;
|
||||
createdBy: string;
|
||||
listId: number;
|
||||
index: number;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("card")
|
||||
.insert({
|
||||
publicId: generateUID(),
|
||||
title: cardInput.title,
|
||||
description: cardInput.description,
|
||||
createdBy: cardInput.createdBy,
|
||||
listId: cardInput.listId,
|
||||
index: cardInput.index,
|
||||
})
|
||||
.select(`id`)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const bulkCreateCardLabelRelationships = async (
|
||||
db: SupabaseClient<Database>,
|
||||
cardLabelRelationshipInput: {
|
||||
cardId: number;
|
||||
labelId: number;
|
||||
}[],
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("_card_labels")
|
||||
.insert(cardLabelRelationshipInput)
|
||||
.select();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const bulkCreateCardWorkspaceMemberRelationships = async (
|
||||
db: SupabaseClient<Database>,
|
||||
cardWorkspaceMemberRelationshipInput: {
|
||||
cardId: number;
|
||||
workspaceMemberId: number;
|
||||
}[],
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("_card_workspace_members")
|
||||
.insert(cardWorkspaceMemberRelationshipInput)
|
||||
.select();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const update = async (
|
||||
db: SupabaseClient<Database>,
|
||||
cardInput: {
|
||||
title: string;
|
||||
description: string;
|
||||
},
|
||||
args: {
|
||||
cardPublicId: string;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("card")
|
||||
.update({ title: cardInput.title, description: cardInput.description })
|
||||
.eq("publicId", args.cardPublicId)
|
||||
.is("deletedAt", null)
|
||||
.select(`id, publicId, title, description`)
|
||||
.order("id", { ascending: true })
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getCardWithListByPublicId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
cardPublicId: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("card")
|
||||
.select(`id, index, list (id, boardId)`)
|
||||
.eq("publicId", cardPublicId)
|
||||
.is("deletedAt", null)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getByPublicId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
cardPublicId: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("card")
|
||||
.select(`id, publicId, title, description`)
|
||||
.eq("publicId", cardPublicId)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getCardLabelRelationship = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: { cardId: number; labelId: number },
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("_card_labels")
|
||||
.select()
|
||||
.eq("cardId", args.cardId)
|
||||
.eq("labelId", args.labelId)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const bulkCreate = async (
|
||||
db: SupabaseClient<Database>,
|
||||
cardInput: {
|
||||
publicId: string;
|
||||
title: string;
|
||||
description: string;
|
||||
createdBy: string;
|
||||
listId: number;
|
||||
index: number;
|
||||
importId?: number;
|
||||
}[],
|
||||
) => {
|
||||
const { data } = await db.from("card").insert(cardInput).select(`id`);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const createCardLabelRelationship = async (
|
||||
db: SupabaseClient<Database>,
|
||||
cardLabelRelationshipInput: { cardId: number; labelId: number },
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("_card_labels")
|
||||
.insert({
|
||||
cardId: cardLabelRelationshipInput.cardId,
|
||||
labelId: cardLabelRelationshipInput.labelId,
|
||||
})
|
||||
.select()
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getCardMemberRelationship = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: { cardId: number; memberId: number },
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("_card_workspace_members")
|
||||
.select()
|
||||
.eq("cardId", args.cardId)
|
||||
.eq("workspaceMemberId", args.memberId)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const createCardMemberRelationship = async (
|
||||
db: SupabaseClient<Database>,
|
||||
cardMemberRelationshipInput: { cardId: number; memberId: number },
|
||||
) => {
|
||||
const { error } = await db.from("_card_workspace_members").insert({
|
||||
cardId: cardMemberRelationshipInput.cardId,
|
||||
workspaceMemberId: cardMemberRelationshipInput.memberId,
|
||||
});
|
||||
|
||||
return { success: !error };
|
||||
};
|
||||
|
||||
export const getWithListAndMembersByPublicId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
cardPublicId: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("card")
|
||||
.select(
|
||||
`
|
||||
publicId,
|
||||
title,
|
||||
description,
|
||||
labels:label (
|
||||
publicId,
|
||||
name,
|
||||
colourCode
|
||||
),
|
||||
list (
|
||||
publicId,
|
||||
name,
|
||||
board (
|
||||
publicId,
|
||||
name,
|
||||
labels:label (
|
||||
publicId,
|
||||
colourCode,
|
||||
name
|
||||
),
|
||||
lists:list (
|
||||
publicId,
|
||||
name
|
||||
),
|
||||
workspace (
|
||||
publicId,
|
||||
members:workspace_members (
|
||||
publicId,
|
||||
user!workspace_members_userId_user_id_fk (
|
||||
id,
|
||||
name
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
members:workspace_members (
|
||||
publicId,
|
||||
user!workspace_members_userId_user_id_fk (
|
||||
id,
|
||||
name
|
||||
)
|
||||
),
|
||||
activities:card_activity (
|
||||
publicId,
|
||||
type,
|
||||
createdAt,
|
||||
fromIndex,
|
||||
toIndex,
|
||||
fromTitle,
|
||||
toTitle,
|
||||
fromDescription,
|
||||
toDescription,
|
||||
fromList:list!card_activity_fromListId_list_id_fk (
|
||||
publicId,
|
||||
name,
|
||||
index
|
||||
),
|
||||
toList:list!card_activity_toListId_list_id_fk (
|
||||
publicId,
|
||||
name,
|
||||
index
|
||||
),
|
||||
label!card_activity_labelId_label_id_fk (
|
||||
publicId,
|
||||
name
|
||||
),
|
||||
member:workspace_members!card_activity_workspaceMemberId_workspace_members_id_fk (
|
||||
publicId,
|
||||
user!workspace_members_userId_user_id_fk (
|
||||
id,
|
||||
name,
|
||||
email
|
||||
)
|
||||
),
|
||||
user!card_activity_createdBy_user_id_fk (
|
||||
id,
|
||||
name,
|
||||
email
|
||||
),
|
||||
comment:card_comments!card_activity_commentId_card_comments_id_fk (
|
||||
publicId,
|
||||
comment,
|
||||
createdBy,
|
||||
updatedAt
|
||||
)
|
||||
)
|
||||
`,
|
||||
)
|
||||
.eq("publicId", cardPublicId)
|
||||
.is("deletedAt", null)
|
||||
.is("list.board.lists.deletedAt", null)
|
||||
.is("list.board.workspace.members.deletedAt", null)
|
||||
.is("members.deletedAt", null)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const reorder = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: {
|
||||
currentListId: number;
|
||||
newListId: number;
|
||||
currentIndex: number;
|
||||
newIndex: number;
|
||||
cardId: number;
|
||||
},
|
||||
) => {
|
||||
const { error } = await db.rpc("reorder_cards", {
|
||||
current_list_id: args.currentListId,
|
||||
new_list_id: args.newListId,
|
||||
current_index: args.currentIndex,
|
||||
new_index: args.newIndex,
|
||||
card_id: args.cardId,
|
||||
});
|
||||
|
||||
return { success: !error };
|
||||
};
|
||||
|
||||
export const shiftIndex = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: {
|
||||
listId: number;
|
||||
cardIndex: number;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db.rpc("shift_card_index", {
|
||||
list_id: args.listId,
|
||||
card_index: args.cardIndex,
|
||||
});
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const pushIndex = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: {
|
||||
listId: number;
|
||||
cardIndex: number;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db.rpc("push_card_index", {
|
||||
list_id: args.listId,
|
||||
card_index: args.cardIndex,
|
||||
});
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const softDelete = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: {
|
||||
cardId: number;
|
||||
deletedAt: string;
|
||||
deletedBy: string;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("card")
|
||||
.update({ deletedAt: args.deletedAt, deletedBy: args.deletedBy })
|
||||
.eq("id", args.cardId)
|
||||
.select(`id`)
|
||||
.order("id", { ascending: true })
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const softDeleteAllByListIds = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: {
|
||||
listIds: number[];
|
||||
deletedAt: string;
|
||||
deletedBy: string;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("card")
|
||||
.update({ deletedAt: args.deletedAt, deletedBy: args.deletedBy })
|
||||
.in("listId", args.listIds)
|
||||
.is("deletedAt", null)
|
||||
.select(`id`);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const hardDeleteCardMemberRelationship = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: { cardId: number; memberId: number },
|
||||
) => {
|
||||
const { error } = await db
|
||||
.from("_card_workspace_members")
|
||||
.delete()
|
||||
.eq("cardId", args.cardId)
|
||||
.eq("workspaceMemberId", args.memberId)
|
||||
.select()
|
||||
.order("cardId", { ascending: true })
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return { success: !error };
|
||||
};
|
||||
|
||||
export const hardDeleteCardLabelRelationship = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: { cardId: number; labelId: number },
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("_card_labels")
|
||||
.delete()
|
||||
.eq("cardId", args.cardId)
|
||||
.eq("labelId", args.labelId)
|
||||
.select()
|
||||
.single();
|
||||
|
||||
return { data };
|
||||
};
|
||||
|
||||
export const hardDeleteAllCardLabelRelationships = async (
|
||||
db: SupabaseClient<Database>,
|
||||
labelId: number,
|
||||
) => {
|
||||
const result = await db.from("_card_labels").delete().eq("labelId", labelId);
|
||||
|
||||
return result;
|
||||
};
|
||||
84
packages/db/src/repository/cardActivity.repo.ts
Normal file
84
packages/db/src/repository/cardActivity.repo.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
|
||||
import type { Database } from "@kan/db/types/database.types";
|
||||
import { generateUID } from "@kan/utils";
|
||||
|
||||
export const create = async (
|
||||
db: SupabaseClient<Database>,
|
||||
activityInput: {
|
||||
type: Database["public"]["Enums"]["card_activity_type"];
|
||||
cardId: number;
|
||||
fromIndex?: number;
|
||||
toIndex?: number;
|
||||
fromListId?: number;
|
||||
toListId?: number;
|
||||
labelId?: number;
|
||||
workspaceMemberId?: number;
|
||||
fromTitle?: string;
|
||||
toTitle?: string;
|
||||
fromDescription?: string;
|
||||
toDescription?: string;
|
||||
createdBy: string;
|
||||
commentId?: number;
|
||||
fromComment?: string;
|
||||
toComment?: string;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("card_activity")
|
||||
.insert({
|
||||
publicId: generateUID(),
|
||||
type: activityInput.type,
|
||||
cardId: activityInput.cardId,
|
||||
fromListId: activityInput.fromListId,
|
||||
toListId: activityInput.toListId,
|
||||
fromIndex: activityInput.fromIndex,
|
||||
toIndex: activityInput.toIndex,
|
||||
labelId: activityInput.labelId,
|
||||
workspaceMemberId: activityInput.workspaceMemberId,
|
||||
fromTitle: activityInput.fromTitle,
|
||||
toTitle: activityInput.toTitle,
|
||||
fromDescription: activityInput.fromDescription,
|
||||
toDescription: activityInput.toDescription,
|
||||
createdBy: activityInput.createdBy,
|
||||
commentId: activityInput.commentId,
|
||||
fromComment: activityInput.fromComment,
|
||||
toComment: activityInput.toComment,
|
||||
})
|
||||
.select(`id`)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const bulkCreate = async (
|
||||
db: SupabaseClient<Database>,
|
||||
activityInputs: {
|
||||
type: Database["public"]["Enums"]["card_activity_type"];
|
||||
cardId: number;
|
||||
fromIndex?: number;
|
||||
toIndex?: number;
|
||||
fromListId?: number;
|
||||
toListId?: number;
|
||||
labelId?: number;
|
||||
workspaceMemberId?: number;
|
||||
fromTitle?: string;
|
||||
toTitle?: string;
|
||||
fromDescription?: string;
|
||||
toDescription?: string;
|
||||
createdBy: string;
|
||||
}[],
|
||||
) => {
|
||||
const activitiesWithPublicIds = activityInputs.map((activity) => ({
|
||||
...activity,
|
||||
publicId: generateUID(),
|
||||
}));
|
||||
|
||||
const { data } = await db
|
||||
.from("card_activity")
|
||||
.insert(activitiesWithPublicIds)
|
||||
.select("id");
|
||||
|
||||
return data;
|
||||
};
|
||||
63
packages/db/src/repository/cardComment.repo.ts
Normal file
63
packages/db/src/repository/cardComment.repo.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
|
||||
import type { Database } from "@kan/db/types/database.types";
|
||||
import { generateUID } from "@kan/utils";
|
||||
|
||||
export const create = async (
|
||||
db: SupabaseClient<Database>,
|
||||
commentInput: {
|
||||
cardId: number;
|
||||
comment: string;
|
||||
createdBy: string;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("card_comments")
|
||||
.insert({
|
||||
publicId: generateUID(),
|
||||
comment: commentInput.comment,
|
||||
createdBy: commentInput.createdBy,
|
||||
cardId: commentInput.cardId,
|
||||
})
|
||||
.select(`id, publicId, comment`)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getByPublicId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
publicId: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("card_comments")
|
||||
.select(`id, publicId, comment, createdBy`)
|
||||
.eq("publicId", publicId)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const update = async (
|
||||
db: SupabaseClient<Database>,
|
||||
commentInput: {
|
||||
id: number;
|
||||
comment: string;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("card_comments")
|
||||
.update({
|
||||
comment: commentInput.comment,
|
||||
updatedAt: new Date().toISOString(),
|
||||
})
|
||||
.eq("id", commentInput.id)
|
||||
.select(`id, publicId, comment`)
|
||||
.limit(1)
|
||||
.order("id", { ascending: false })
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
38
packages/db/src/repository/import.repo.ts
Normal file
38
packages/db/src/repository/import.repo.ts
Normal file
@@ -0,0 +1,38 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
|
||||
import type { Database } from "@kan/db/types/database.types";
|
||||
import { generateUID } from "@kan/utils";
|
||||
|
||||
export const create = async (
|
||||
db: SupabaseClient<Database>,
|
||||
importInput: { source: string; createdBy: string },
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("import")
|
||||
.insert({
|
||||
publicId: generateUID(),
|
||||
source: "trello",
|
||||
createdBy: importInput.createdBy,
|
||||
status: "started",
|
||||
})
|
||||
.select(`id`)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const update = async (
|
||||
db: SupabaseClient<Database>,
|
||||
importInput: { status: "started" | "success" | "failed" },
|
||||
args: { importId: number },
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("import")
|
||||
.update({ status: importInput.status })
|
||||
.eq("importId", args.importId)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
90
packages/db/src/repository/label.repo.ts
Normal file
90
packages/db/src/repository/label.repo.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
|
||||
import type { Database } from "@kan/db/types/database.types";
|
||||
import { generateUID } from "@kan/utils";
|
||||
|
||||
export const create = async (
|
||||
db: SupabaseClient<Database>,
|
||||
labelInput: {
|
||||
name: string;
|
||||
colourCode: string;
|
||||
createdBy: string;
|
||||
boardId: number;
|
||||
cardId?: number;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("label")
|
||||
.insert({
|
||||
publicId: generateUID(),
|
||||
name: labelInput.name,
|
||||
colourCode: labelInput.colourCode,
|
||||
createdBy: labelInput.createdBy,
|
||||
boardId: labelInput.boardId,
|
||||
})
|
||||
.select(`id`)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
if (labelInput.cardId && data)
|
||||
await db.from("_card_labels").insert({
|
||||
cardId: labelInput.cardId,
|
||||
labelId: data.id,
|
||||
});
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getAllByPublicIds = async (
|
||||
db: SupabaseClient<Database>,
|
||||
labelPublicIds: string[],
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("label")
|
||||
.select(`id`)
|
||||
.in("publicId", labelPublicIds);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getByPublicId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
labelPublicId: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("label")
|
||||
.select(`id, publicId, name, colourCode`)
|
||||
.eq("publicId", labelPublicId)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const update = async (
|
||||
db: SupabaseClient<Database>,
|
||||
labelInput: {
|
||||
labelPublicId: string;
|
||||
name: string;
|
||||
colourCode: string;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("label")
|
||||
.update({
|
||||
name: labelInput.name,
|
||||
colourCode: labelInput.colourCode,
|
||||
})
|
||||
.eq("publicId", labelInput.labelPublicId);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const hardDelete = async (
|
||||
db: SupabaseClient<Database>,
|
||||
labelId: number,
|
||||
) => {
|
||||
const { data } = await db.from("label").delete().eq("id", labelId);
|
||||
|
||||
return data;
|
||||
};
|
||||
161
packages/db/src/repository/list.repo.ts
Normal file
161
packages/db/src/repository/list.repo.ts
Normal file
@@ -0,0 +1,161 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
|
||||
import type { Database } from "@kan/db/types/database.types";
|
||||
import { generateUID } from "@kan/utils";
|
||||
|
||||
export const create = async (
|
||||
db: SupabaseClient<Database>,
|
||||
listInput: {
|
||||
name: string;
|
||||
createdBy: string;
|
||||
boardId: number;
|
||||
index: number;
|
||||
importId?: number;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("list")
|
||||
.insert({
|
||||
publicId: generateUID(),
|
||||
name: listInput.name,
|
||||
createdBy: listInput.createdBy,
|
||||
boardId: listInput.boardId,
|
||||
index: listInput.index,
|
||||
importId: listInput.importId,
|
||||
})
|
||||
.select(
|
||||
`
|
||||
id,
|
||||
publicId,
|
||||
name
|
||||
`,
|
||||
)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getByPublicId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
listPublicId: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("list")
|
||||
.select(`id, boardId, index`)
|
||||
.eq("publicId", listPublicId)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getWithCardsByPublicId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
listPublicId: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("list")
|
||||
.select(`id, cards:card (index)`)
|
||||
.eq("publicId", listPublicId)
|
||||
.is("deletedAt", null)
|
||||
.is("card.deletedAt", null)
|
||||
.order("index", { foreignTable: "card", ascending: false })
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const update = async (
|
||||
db: SupabaseClient<Database>,
|
||||
listInput: {
|
||||
name: string;
|
||||
},
|
||||
args: {
|
||||
listPublicId: string;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("list")
|
||||
.update({ name: listInput.name })
|
||||
.eq("publicId", args.listPublicId)
|
||||
.is("deletedAt", null)
|
||||
.select(`publicId, name`);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const reorder = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: {
|
||||
boardPublicId: number;
|
||||
listPublicId: number;
|
||||
currentIndex: number;
|
||||
newIndex: number;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db.rpc("reorder_lists", {
|
||||
board_id: args.boardPublicId,
|
||||
list_id: args.listPublicId,
|
||||
current_index: args.currentIndex,
|
||||
new_index: args.newIndex,
|
||||
});
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const shiftIndex = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: {
|
||||
boardId: number;
|
||||
listIndex: number;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db.rpc("shift_list_index", {
|
||||
board_id: args.boardId,
|
||||
list_index: args.listIndex,
|
||||
});
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const softDeleteAllByBoardId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: {
|
||||
boardId: number;
|
||||
deletedAt: string;
|
||||
deletedBy: string;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("list")
|
||||
.update({ deletedAt: args.deletedAt, deletedBy: args.deletedBy })
|
||||
.eq("boardId", args.boardId)
|
||||
.is("deletedAt", null)
|
||||
.select(`id`)
|
||||
.order("id", { ascending: true });
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const softDeleteById = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: {
|
||||
listId: number;
|
||||
deletedAt: string;
|
||||
deletedBy: string;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("list")
|
||||
.update({ deletedAt: args.deletedAt, deletedBy: args.deletedBy })
|
||||
.eq("id", args.listId)
|
||||
.is("deletedAt", null)
|
||||
.select(`id`)
|
||||
.order("id", { ascending: true })
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
74
packages/db/src/repository/member.repo.ts
Normal file
74
packages/db/src/repository/member.repo.ts
Normal file
@@ -0,0 +1,74 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
|
||||
import type { Database } from "@kan/db/types/database.types";
|
||||
import { generateUID } from "@kan/utils";
|
||||
|
||||
export const create = async (
|
||||
db: SupabaseClient<Database>,
|
||||
memberInput: {
|
||||
userId: string;
|
||||
workspaceId: number;
|
||||
createdBy: string;
|
||||
role: "admin" | "member" | "guest";
|
||||
status: "invited" | "active" | "removed";
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("workspace_members")
|
||||
.insert({
|
||||
publicId: generateUID(),
|
||||
userId: memberInput.userId,
|
||||
workspaceId: memberInput.workspaceId,
|
||||
createdBy: memberInput.createdBy,
|
||||
role: memberInput.role,
|
||||
status: memberInput.status,
|
||||
})
|
||||
.select(`id, publicId`)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getByPublicId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
publicId: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("workspace_members")
|
||||
.select()
|
||||
.eq("publicId", publicId)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const acceptInvite = async (
|
||||
db: SupabaseClient<Database>,
|
||||
id: number,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("workspace_members")
|
||||
.update({ status: "active" })
|
||||
.eq("id", id);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const softDelete = async (
|
||||
db: SupabaseClient<Database>,
|
||||
args: {
|
||||
memberId: number;
|
||||
deletedAt: string;
|
||||
deletedBy: string;
|
||||
},
|
||||
) => {
|
||||
const result = await db
|
||||
.from("workspace_members")
|
||||
.update({ deletedAt: args.deletedAt, deletedBy: args.deletedBy })
|
||||
.eq("id", args.memberId)
|
||||
.is("deletedAt", null);
|
||||
|
||||
return result;
|
||||
};
|
||||
42
packages/db/src/repository/user.repo.ts
Normal file
42
packages/db/src/repository/user.repo.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
|
||||
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`)
|
||||
.eq("id", userId)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getByEmail = async (
|
||||
db: SupabaseClient<Database>,
|
||||
email: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("user")
|
||||
.select(`id, name, email`)
|
||||
.eq("email", email)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const create = async (
|
||||
db: SupabaseClient<Database>,
|
||||
user: { id: string; email: string },
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("user")
|
||||
.insert({ id: user.id, email: user.email })
|
||||
.select()
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
159
packages/db/src/repository/workspace.repo.ts
Normal file
159
packages/db/src/repository/workspace.repo.ts
Normal file
@@ -0,0 +1,159 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
|
||||
import type { Database } from "@kan/db/types/database.types";
|
||||
import { generateUID } from "@kan/utils";
|
||||
|
||||
export const create = async (
|
||||
db: SupabaseClient<Database>,
|
||||
workspaceInput: {
|
||||
name: string;
|
||||
slug: string;
|
||||
createdBy: string;
|
||||
},
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("workspace")
|
||||
.insert({
|
||||
publicId: generateUID(),
|
||||
name: workspaceInput.name,
|
||||
slug: workspaceInput.name.toLowerCase(),
|
||||
createdBy: workspaceInput.createdBy,
|
||||
})
|
||||
.select(`id, publicId, name`)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
if (data)
|
||||
await db.from("workspace_members").insert({
|
||||
publicId: generateUID(),
|
||||
userId: workspaceInput.createdBy,
|
||||
workspaceId: data.id,
|
||||
createdBy: workspaceInput.createdBy,
|
||||
role: "admin",
|
||||
});
|
||||
|
||||
const newWorkspace = { ...data };
|
||||
|
||||
delete newWorkspace.id;
|
||||
|
||||
return newWorkspace;
|
||||
};
|
||||
|
||||
export const update = async (
|
||||
db: SupabaseClient<Database>,
|
||||
workspacePublicId: string,
|
||||
name: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("workspace")
|
||||
.update({ name })
|
||||
.eq("publicId", workspacePublicId)
|
||||
.is("deletedAt", null);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getByPublicId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
workspacePublicId: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("workspace")
|
||||
.select(`id, publicId, name`)
|
||||
.is("deletedAt", null)
|
||||
.eq("publicId", workspacePublicId)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getByPublicIdWithMembers = async (
|
||||
db: SupabaseClient<Database>,
|
||||
workspacePublicId: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("workspace")
|
||||
.select(
|
||||
`
|
||||
id,
|
||||
publicId,
|
||||
members: workspace_members (
|
||||
publicId,
|
||||
role,
|
||||
status,
|
||||
user!workspace_members_userId_user_id_fk (
|
||||
id,
|
||||
name,
|
||||
email
|
||||
)
|
||||
)
|
||||
`,
|
||||
)
|
||||
.eq("publicId", workspacePublicId)
|
||||
.is("deletedAt", null)
|
||||
.is("members.deletedAt", null)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getAllByUserId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
userId: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("workspace_members")
|
||||
.select(
|
||||
`
|
||||
role,
|
||||
workspace (
|
||||
publicId,
|
||||
name
|
||||
)
|
||||
`,
|
||||
)
|
||||
.eq("userId", userId)
|
||||
.is("deletedAt", null);
|
||||
|
||||
return data ?? [];
|
||||
};
|
||||
|
||||
export const getMemberByPublicId = async (
|
||||
db: SupabaseClient<Database>,
|
||||
memberPublicId: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("workspace_members")
|
||||
.select(`id`)
|
||||
.eq("publicId", memberPublicId)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const getAllMembersByPublicIds = async (
|
||||
db: SupabaseClient<Database>,
|
||||
memberPublicIds: string[],
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("workspace_members")
|
||||
.select(`id`)
|
||||
.eq("publicId", memberPublicIds);
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
export const hardDelete = async (
|
||||
db: SupabaseClient<Database>,
|
||||
workspacePublicId: string,
|
||||
) => {
|
||||
const result = db
|
||||
.from("workspace")
|
||||
.delete()
|
||||
.eq("publicId", workspacePublicId);
|
||||
|
||||
return result;
|
||||
};
|
||||
432
packages/db/src/schema.ts
Normal file
432
packages/db/src/schema.ts
Normal file
@@ -0,0 +1,432 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import {
|
||||
integer,
|
||||
bigserial,
|
||||
uuid,
|
||||
pgEnum,
|
||||
pgTable,
|
||||
primaryKey,
|
||||
text,
|
||||
timestamp,
|
||||
varchar,
|
||||
bigint,
|
||||
} from "drizzle-orm/pg-core";
|
||||
|
||||
export const importSourceEnum = pgEnum("source", ["trello"]);
|
||||
export const importStatusEnum = pgEnum("status", [
|
||||
"started",
|
||||
"success",
|
||||
"failed",
|
||||
]);
|
||||
export const memberRoleEnum = pgEnum("role", ["admin", "member", "guest"]);
|
||||
export const memberStatusEnum = pgEnum("member_status", [
|
||||
"invited",
|
||||
"active",
|
||||
"removed",
|
||||
]);
|
||||
export const activityTypeEnum = pgEnum("card_activity_type", [
|
||||
"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",
|
||||
]);
|
||||
|
||||
export const boards = pgTable("board", {
|
||||
id: bigserial("id", { mode: "number" }).primaryKey(),
|
||||
publicId: varchar("publicId", { length: 12 }).notNull().unique(),
|
||||
name: varchar("name", { length: 255 }).notNull(),
|
||||
createdBy: uuid("createdBy")
|
||||
.notNull()
|
||||
.references(() => users.id),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt"),
|
||||
deletedAt: timestamp("deletedAt"),
|
||||
deletedBy: uuid("deletedBy").references(() => users.id),
|
||||
importId: bigint("importId", { mode: "number" }).references(() => imports.id),
|
||||
workspaceId: bigint("workspaceId", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => workspaces.id, { onDelete: "cascade" }),
|
||||
});
|
||||
|
||||
export const boardsRelations = relations(boards, ({ one, many }) => ({
|
||||
createdBy: one(users, {
|
||||
fields: [boards.createdBy],
|
||||
references: [users.id],
|
||||
}),
|
||||
lists: many(lists),
|
||||
labels: many(labels),
|
||||
deletedBy: one(users, {
|
||||
fields: [boards.deletedBy],
|
||||
references: [users.id],
|
||||
}),
|
||||
import: one(imports, {
|
||||
fields: [boards.importId],
|
||||
references: [imports.id],
|
||||
}),
|
||||
workspace: one(workspaces, {
|
||||
fields: [boards.workspaceId],
|
||||
references: [workspaces.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const imports = pgTable("import", {
|
||||
id: bigserial("id", { mode: "number" }).primaryKey(),
|
||||
publicId: varchar("publicId", { length: 12 }).notNull().unique(),
|
||||
source: importSourceEnum("source").notNull(),
|
||||
status: importStatusEnum("status").notNull(),
|
||||
createdBy: uuid("createdBy")
|
||||
.notNull()
|
||||
.references(() => users.id),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
});
|
||||
|
||||
export const importsRelations = relations(imports, ({ one, many }) => ({
|
||||
createdBy: one(users, {
|
||||
fields: [imports.createdBy],
|
||||
references: [users.id],
|
||||
}),
|
||||
boards: many(boards),
|
||||
cards: many(cards),
|
||||
lists: many(lists),
|
||||
labels: many(labels),
|
||||
}));
|
||||
|
||||
export const labels = pgTable("label", {
|
||||
id: bigserial("id", { mode: "number" }).primaryKey(),
|
||||
publicId: varchar("publicId", { length: 12 }).notNull().unique(),
|
||||
name: varchar("name", { length: 255 }).notNull(),
|
||||
colourCode: varchar("colourCode", { length: 12 }),
|
||||
createdBy: uuid("createdBy")
|
||||
.notNull()
|
||||
.references(() => users.id),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt"),
|
||||
boardId: bigint("boardId", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => boards.id, { onDelete: "cascade" }),
|
||||
importId: bigint("importId", { mode: "number" }).references(() => imports.id),
|
||||
});
|
||||
|
||||
export const labelsRelations = relations(labels, ({ one, many }) => ({
|
||||
createdBy: one(users, {
|
||||
fields: [labels.createdBy],
|
||||
references: [users.id],
|
||||
}),
|
||||
board: one(boards, {
|
||||
fields: [labels.boardId],
|
||||
references: [boards.id],
|
||||
}),
|
||||
cards: many(cardsToLabels),
|
||||
import: one(imports, {
|
||||
fields: [labels.importId],
|
||||
references: [imports.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const cardsToLabels = pgTable(
|
||||
"_card_labels",
|
||||
{
|
||||
cardId: bigint("cardId", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => cards.id),
|
||||
labelId: bigint("labelId", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => labels.id, { onDelete: "cascade" }),
|
||||
},
|
||||
(t) => ({
|
||||
pk: primaryKey(t.cardId, t.labelId),
|
||||
}),
|
||||
);
|
||||
|
||||
export const cardToLabelsRelations = relations(cardsToLabels, ({ one }) => ({
|
||||
card: one(cards, {
|
||||
fields: [cardsToLabels.cardId],
|
||||
references: [cards.id],
|
||||
}),
|
||||
label: one(labels, {
|
||||
fields: [cardsToLabels.labelId],
|
||||
references: [labels.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const cardToWorkspaceMembers = pgTable(
|
||||
"_card_workspace_members",
|
||||
{
|
||||
cardId: bigint("cardId", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => cards.id),
|
||||
workspaceMemberId: bigint("workspaceMemberId", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => workspaceMembers.id, { onDelete: "cascade" }),
|
||||
},
|
||||
(t) => ({
|
||||
pk: primaryKey(t.cardId, t.workspaceMemberId),
|
||||
}),
|
||||
);
|
||||
|
||||
export const cardToWorkspaceMembersRelations = relations(
|
||||
cardToWorkspaceMembers,
|
||||
({ one }) => ({
|
||||
card: one(cards, {
|
||||
fields: [cardToWorkspaceMembers.cardId],
|
||||
references: [cards.id],
|
||||
}),
|
||||
member: one(workspaceMembers, {
|
||||
fields: [cardToWorkspaceMembers.workspaceMemberId],
|
||||
references: [workspaceMembers.id],
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
export const lists = pgTable("list", {
|
||||
id: bigserial("id", { mode: "number" }).primaryKey(),
|
||||
publicId: varchar("publicId", { length: 12 }).notNull().unique(),
|
||||
name: varchar("name", { length: 255 }).notNull(),
|
||||
index: integer("index").notNull(),
|
||||
createdBy: uuid("createdBy")
|
||||
.notNull()
|
||||
.references(() => users.id),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt"),
|
||||
deletedAt: timestamp("deletedAt"),
|
||||
deletedBy: uuid("deletedBy").references(() => users.id),
|
||||
boardId: bigint("boardId", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => boards.id, { onDelete: "cascade" }),
|
||||
importId: bigint("importId", { mode: "number" }).references(() => imports.id),
|
||||
});
|
||||
|
||||
export const listsRelations = relations(lists, ({ one, many }) => ({
|
||||
createdBy: one(users, {
|
||||
fields: [lists.createdBy],
|
||||
references: [users.id],
|
||||
}),
|
||||
board: one(boards, {
|
||||
fields: [lists.boardId],
|
||||
references: [boards.id],
|
||||
}),
|
||||
cards: many(cards),
|
||||
deletedBy: one(users, {
|
||||
fields: [lists.deletedBy],
|
||||
references: [users.id],
|
||||
}),
|
||||
import: one(imports, {
|
||||
fields: [lists.importId],
|
||||
references: [imports.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const cards = pgTable("card", {
|
||||
id: bigserial("id", { mode: "number" }).primaryKey(),
|
||||
publicId: varchar("publicId", { length: 12 }).notNull().unique(),
|
||||
title: varchar("title", { length: 255 }).notNull(),
|
||||
description: text("description"),
|
||||
index: integer("index").notNull(),
|
||||
createdBy: uuid("createdBy")
|
||||
.notNull()
|
||||
.references(() => users.id),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt"),
|
||||
deletedAt: timestamp("deletedAt"),
|
||||
deletedBy: uuid("deletedBy").references(() => users.id),
|
||||
listId: bigint("listId", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => lists.id, { onDelete: "cascade" }),
|
||||
importId: bigint("importId", { mode: "number" }).references(() => imports.id),
|
||||
});
|
||||
|
||||
export const cardsRelations = relations(cards, ({ one, many }) => ({
|
||||
createdBy: one(users, {
|
||||
fields: [cards.createdBy],
|
||||
references: [users.id],
|
||||
}),
|
||||
list: one(lists, {
|
||||
fields: [cards.listId],
|
||||
references: [lists.id],
|
||||
}),
|
||||
deletedBy: one(users, {
|
||||
fields: [cards.deletedBy],
|
||||
references: [users.id],
|
||||
}),
|
||||
labels: many(cardsToLabels),
|
||||
members: many(cardToWorkspaceMembers),
|
||||
import: one(imports, {
|
||||
fields: [cards.importId],
|
||||
references: [imports.id],
|
||||
}),
|
||||
comments: many(comments),
|
||||
}));
|
||||
|
||||
export const users = pgTable("user", {
|
||||
id: uuid("id").notNull().primaryKey(),
|
||||
name: varchar("name", { length: 255 }),
|
||||
email: varchar("email", { length: 255 }).notNull().unique(),
|
||||
emailVerified: timestamp("emailVerified", { mode: "date" }),
|
||||
image: varchar("image", { length: 255 }),
|
||||
});
|
||||
|
||||
export const usersRelations = relations(users, ({ many }) => ({
|
||||
boards: many(boards),
|
||||
cards: many(cards),
|
||||
imports: many(imports),
|
||||
lists: many(lists),
|
||||
workspaces: many(workspaces),
|
||||
}));
|
||||
|
||||
export const workspaces = pgTable("workspace", {
|
||||
id: bigserial("id", { mode: "number" }).primaryKey(),
|
||||
publicId: varchar("publicId", { length: 12 }).notNull().unique(),
|
||||
name: varchar("name", { length: 255 }).notNull(),
|
||||
slug: varchar("slug", { length: 255 }).notNull().unique(),
|
||||
createdBy: uuid("createdBy")
|
||||
.notNull()
|
||||
.references(() => users.id),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt"),
|
||||
deletedAt: timestamp("deletedAt"),
|
||||
deletedBy: uuid("deletedBy").references(() => users.id),
|
||||
});
|
||||
|
||||
export const workspaceRelations = relations(workspaces, ({ one, many }) => ({
|
||||
user: one(users, { fields: [workspaces.createdBy], references: [users.id] }),
|
||||
members: many(workspaceMembers),
|
||||
}));
|
||||
|
||||
export const workspaceMembers = pgTable("workspace_members", {
|
||||
id: bigserial("id", { mode: "number" }).primaryKey(),
|
||||
publicId: varchar("publicId", { length: 12 }).notNull().unique(),
|
||||
userId: uuid("userId")
|
||||
.notNull()
|
||||
.references(() => users.id),
|
||||
workspaceId: bigint("workspaceId", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => workspaces.id, { onDelete: "cascade" }),
|
||||
createdBy: uuid("createdBy").notNull(),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt"),
|
||||
deletedAt: timestamp("deletedAt"),
|
||||
deletedBy: uuid("deletedBy").references(() => users.id),
|
||||
role: memberRoleEnum("role").notNull(),
|
||||
status: memberStatusEnum("status").default("invited").notNull(),
|
||||
});
|
||||
|
||||
export const usersToWorkspacesRelations = relations(
|
||||
workspaceMembers,
|
||||
({ one }) => ({
|
||||
addedBy: one(users, {
|
||||
fields: [workspaceMembers.createdBy],
|
||||
references: [users.id],
|
||||
}),
|
||||
deletedBy: one(users, {
|
||||
fields: [workspaceMembers.deletedBy],
|
||||
references: [users.id],
|
||||
}),
|
||||
user: one(users, {
|
||||
fields: [workspaceMembers.userId],
|
||||
references: [users.id],
|
||||
}),
|
||||
workspace: one(workspaces, {
|
||||
fields: [workspaceMembers.workspaceId],
|
||||
references: [workspaces.id],
|
||||
}),
|
||||
}),
|
||||
);
|
||||
|
||||
export const cardActivities = pgTable("card_activity", {
|
||||
id: bigserial("id", { mode: "number" }).primaryKey(),
|
||||
publicId: varchar("publicId", { length: 12 }).notNull().unique(),
|
||||
type: activityTypeEnum("type").notNull(),
|
||||
cardId: bigint("cardId", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => cards.id, { onDelete: "cascade" }),
|
||||
fromIndex: integer("fromIndex"),
|
||||
toIndex: integer("toIndex"),
|
||||
fromListId: bigint("fromListId", { mode: "number" }).references(
|
||||
() => lists.id,
|
||||
),
|
||||
toListId: bigint("toListId", { mode: "number" }).references(() => lists.id),
|
||||
labelId: bigint("labelId", { mode: "number" }).references(() => labels.id),
|
||||
workspaceMemberId: bigint("workspaceMemberId", { mode: "number" }).references(
|
||||
() => workspaceMembers.id,
|
||||
),
|
||||
fromTitle: varchar("fromTitle", { length: 255 }),
|
||||
toTitle: varchar("toTitle", { length: 255 }),
|
||||
fromDescription: text("fromDescription"),
|
||||
toDescription: text("toDescription"),
|
||||
createdBy: uuid("createdBy")
|
||||
.notNull()
|
||||
.references(() => users.id),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
commentId: bigint("commentId", { mode: "number" }).references(
|
||||
() => comments.id,
|
||||
),
|
||||
fromComment: text("fromComment"),
|
||||
toComment: text("toComment"),
|
||||
});
|
||||
|
||||
export const cardActivitiesRelations = relations(cardActivities, ({ one }) => ({
|
||||
card: one(cards, {
|
||||
fields: [cardActivities.cardId],
|
||||
references: [cards.id],
|
||||
}),
|
||||
fromList: one(lists, {
|
||||
fields: [cardActivities.fromListId],
|
||||
references: [lists.id],
|
||||
}),
|
||||
toList: one(lists, {
|
||||
fields: [cardActivities.toListId],
|
||||
references: [lists.id],
|
||||
}),
|
||||
label: one(labels, {
|
||||
fields: [cardActivities.labelId],
|
||||
references: [labels.id],
|
||||
}),
|
||||
workspaceMember: one(workspaceMembers, {
|
||||
fields: [cardActivities.workspaceMemberId],
|
||||
references: [workspaceMembers.id],
|
||||
}),
|
||||
createdBy: one(users, {
|
||||
fields: [cardActivities.createdBy],
|
||||
references: [users.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const comments = pgTable("card_comments", {
|
||||
id: bigserial("id", { mode: "number" }).primaryKey(),
|
||||
publicId: varchar("publicId", { length: 12 }).notNull().unique(),
|
||||
comment: text("comment").notNull(),
|
||||
cardId: bigint("cardId", { mode: "number" })
|
||||
.notNull()
|
||||
.references(() => cards.id, { onDelete: "cascade" }),
|
||||
createdBy: uuid("createdBy")
|
||||
.notNull()
|
||||
.references(() => users.id),
|
||||
createdAt: timestamp("createdAt").defaultNow().notNull(),
|
||||
updatedAt: timestamp("updatedAt"),
|
||||
deletedAt: timestamp("deletedAt"),
|
||||
deletedBy: uuid("deletedBy").references(() => users.id),
|
||||
});
|
||||
|
||||
export const commentsRelations = relations(comments, ({ one }) => ({
|
||||
card: one(cards, {
|
||||
fields: [comments.cardId],
|
||||
references: [cards.id],
|
||||
}),
|
||||
createdBy: one(users, {
|
||||
fields: [comments.createdBy],
|
||||
references: [users.id],
|
||||
}),
|
||||
deletedBy: one(users, {
|
||||
fields: [comments.deletedBy],
|
||||
references: [users.id],
|
||||
}),
|
||||
}));
|
||||
868
packages/db/src/types/database.types.ts
Normal file
868
packages/db/src/types/database.types.ts
Normal file
@@ -0,0 +1,868 @@
|
||||
/* eslint-disable @typescript-eslint/no-redundant-type-constituents */
|
||||
|
||||
export type Json =
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null
|
||||
| { [key: string]: Json | undefined }
|
||||
| Json[];
|
||||
|
||||
export type Database = {
|
||||
public: {
|
||||
Tables: {
|
||||
_card_labels: {
|
||||
Row: {
|
||||
cardId: number;
|
||||
labelId: number;
|
||||
};
|
||||
Insert: {
|
||||
cardId: number;
|
||||
labelId: number;
|
||||
};
|
||||
Update: {
|
||||
cardId?: number;
|
||||
labelId?: number;
|
||||
};
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "_card_labels_cardId_card_id_fk";
|
||||
columns: ["cardId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "card";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "_card_labels_labelId_label_id_fk";
|
||||
columns: ["labelId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "label";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
];
|
||||
};
|
||||
_card_workspace_members: {
|
||||
Row: {
|
||||
cardId: number;
|
||||
workspaceMemberId: number;
|
||||
};
|
||||
Insert: {
|
||||
cardId: number;
|
||||
workspaceMemberId: number;
|
||||
};
|
||||
Update: {
|
||||
cardId?: number;
|
||||
workspaceMemberId?: number;
|
||||
};
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "_card_workspace_members_cardId_card_id_fk";
|
||||
columns: ["cardId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "card";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "_card_workspace_members_workspaceMemberId_workspace_members_id_";
|
||||
columns: ["workspaceMemberId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "workspace_members";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
];
|
||||
};
|
||||
board: {
|
||||
Row: {
|
||||
createdAt: string;
|
||||
createdBy: string;
|
||||
deletedAt: string | null;
|
||||
deletedBy: string | null;
|
||||
id: number;
|
||||
importId: number | null;
|
||||
name: string;
|
||||
publicId: string;
|
||||
updatedAt: string | null;
|
||||
workspaceId: number;
|
||||
};
|
||||
Insert: {
|
||||
createdAt?: string;
|
||||
createdBy: string;
|
||||
deletedAt?: string | null;
|
||||
deletedBy?: string | null;
|
||||
id?: number;
|
||||
importId?: number | null;
|
||||
name: string;
|
||||
publicId: string;
|
||||
updatedAt?: string | null;
|
||||
workspaceId: number;
|
||||
};
|
||||
Update: {
|
||||
createdAt?: string;
|
||||
createdBy?: string;
|
||||
deletedAt?: string | null;
|
||||
deletedBy?: string | null;
|
||||
id?: number;
|
||||
importId?: number | null;
|
||||
name?: string;
|
||||
publicId?: string;
|
||||
updatedAt?: string | null;
|
||||
workspaceId?: number;
|
||||
};
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "board_createdBy_user_id_fk";
|
||||
columns: ["createdBy"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "board_deletedBy_user_id_fk";
|
||||
columns: ["deletedBy"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "board_importId_import_id_fk";
|
||||
columns: ["importId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "import";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "board_workspaceId_workspace_id_fk";
|
||||
columns: ["workspaceId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "workspace";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
];
|
||||
};
|
||||
card: {
|
||||
Row: {
|
||||
createdAt: string;
|
||||
createdBy: string;
|
||||
deletedAt: string | null;
|
||||
deletedBy: string | null;
|
||||
description: string | null;
|
||||
id: number;
|
||||
importId: number | null;
|
||||
index: number;
|
||||
listId: number;
|
||||
publicId: string;
|
||||
title: string;
|
||||
updatedAt: string | null;
|
||||
};
|
||||
Insert: {
|
||||
createdAt?: string;
|
||||
createdBy: string;
|
||||
deletedAt?: string | null;
|
||||
deletedBy?: string | null;
|
||||
description?: string | null;
|
||||
id?: number;
|
||||
importId?: number | null;
|
||||
index: number;
|
||||
listId: number;
|
||||
publicId: string;
|
||||
title: string;
|
||||
updatedAt?: string | null;
|
||||
};
|
||||
Update: {
|
||||
createdAt?: string;
|
||||
createdBy?: string;
|
||||
deletedAt?: string | null;
|
||||
deletedBy?: string | null;
|
||||
description?: string | null;
|
||||
id?: number;
|
||||
importId?: number | null;
|
||||
index?: number;
|
||||
listId?: number;
|
||||
publicId?: string;
|
||||
title?: string;
|
||||
updatedAt?: string | null;
|
||||
};
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "card_createdBy_user_id_fk";
|
||||
columns: ["createdBy"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "card_deletedBy_user_id_fk";
|
||||
columns: ["deletedBy"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "card_importId_import_id_fk";
|
||||
columns: ["importId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "import";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "card_listId_list_id_fk";
|
||||
columns: ["listId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "list";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
];
|
||||
};
|
||||
card_activity: {
|
||||
Row: {
|
||||
cardId: number;
|
||||
commentId: number | null;
|
||||
createdAt: string;
|
||||
createdBy: string;
|
||||
fromComment: string | null;
|
||||
fromDescription: string | null;
|
||||
fromIndex: number | null;
|
||||
fromListId: number | null;
|
||||
fromTitle: string | null;
|
||||
id: number;
|
||||
labelId: number | null;
|
||||
publicId: string;
|
||||
toComment: string | null;
|
||||
toDescription: string | null;
|
||||
toIndex: number | null;
|
||||
toListId: number | null;
|
||||
toTitle: string | null;
|
||||
type: Database["public"]["Enums"]["card_activity_type"];
|
||||
workspaceMemberId: number | null;
|
||||
};
|
||||
Insert: {
|
||||
cardId: number;
|
||||
commentId?: number | null;
|
||||
createdAt?: string;
|
||||
createdBy: string;
|
||||
fromComment?: string | null;
|
||||
fromDescription?: string | null;
|
||||
fromIndex?: number | null;
|
||||
fromListId?: number | null;
|
||||
fromTitle?: string | null;
|
||||
id?: number;
|
||||
labelId?: number | null;
|
||||
publicId: string;
|
||||
toComment?: string | null;
|
||||
toDescription?: string | null;
|
||||
toIndex?: number | null;
|
||||
toListId?: number | null;
|
||||
toTitle?: string | null;
|
||||
type: Database["public"]["Enums"]["card_activity_type"];
|
||||
workspaceMemberId?: number | null;
|
||||
};
|
||||
Update: {
|
||||
cardId?: number;
|
||||
commentId?: number | null;
|
||||
createdAt?: string;
|
||||
createdBy?: string;
|
||||
fromComment?: string | null;
|
||||
fromDescription?: string | null;
|
||||
fromIndex?: number | null;
|
||||
fromListId?: number | null;
|
||||
fromTitle?: string | null;
|
||||
id?: number;
|
||||
labelId?: number | null;
|
||||
publicId?: string;
|
||||
toComment?: string | null;
|
||||
toDescription?: string | null;
|
||||
toIndex?: number | null;
|
||||
toListId?: number | null;
|
||||
toTitle?: string | null;
|
||||
type?: Database["public"]["Enums"]["card_activity_type"];
|
||||
workspaceMemberId?: number | null;
|
||||
};
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "card_activity_cardId_card_id_fk";
|
||||
columns: ["cardId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "card";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "card_activity_commentId_card_comments_id_fk";
|
||||
columns: ["commentId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "card_comments";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "card_activity_createdBy_user_id_fk";
|
||||
columns: ["createdBy"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "card_activity_fromListId_list_id_fk";
|
||||
columns: ["fromListId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "list";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "card_activity_labelId_label_id_fk";
|
||||
columns: ["labelId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "label";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "card_activity_toListId_list_id_fk";
|
||||
columns: ["toListId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "list";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "card_activity_workspaceMemberId_workspace_members_id_fk";
|
||||
columns: ["workspaceMemberId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "workspace_members";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
];
|
||||
};
|
||||
card_comments: {
|
||||
Row: {
|
||||
cardId: number;
|
||||
comment: string;
|
||||
createdAt: string;
|
||||
createdBy: string;
|
||||
deletedAt: string | null;
|
||||
deletedBy: string | null;
|
||||
id: number;
|
||||
publicId: string;
|
||||
updatedAt: string | null;
|
||||
};
|
||||
Insert: {
|
||||
cardId: number;
|
||||
comment: string;
|
||||
createdAt?: string;
|
||||
createdBy: string;
|
||||
deletedAt?: string | null;
|
||||
deletedBy?: string | null;
|
||||
id?: number;
|
||||
publicId: string;
|
||||
updatedAt?: string | null;
|
||||
};
|
||||
Update: {
|
||||
cardId?: number;
|
||||
comment?: string;
|
||||
createdAt?: string;
|
||||
createdBy?: string;
|
||||
deletedAt?: string | null;
|
||||
deletedBy?: string | null;
|
||||
id?: number;
|
||||
publicId?: string;
|
||||
updatedAt?: string | null;
|
||||
};
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "card_comments_cardId_card_id_fk";
|
||||
columns: ["cardId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "card";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "card_comments_createdBy_user_id_fk";
|
||||
columns: ["createdBy"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "card_comments_deletedBy_user_id_fk";
|
||||
columns: ["deletedBy"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
];
|
||||
};
|
||||
import: {
|
||||
Row: {
|
||||
createdAt: string;
|
||||
createdBy: string;
|
||||
id: number;
|
||||
publicId: string;
|
||||
source: Database["public"]["Enums"]["source"];
|
||||
status: Database["public"]["Enums"]["status"];
|
||||
};
|
||||
Insert: {
|
||||
createdAt?: string;
|
||||
createdBy: string;
|
||||
id?: number;
|
||||
publicId: string;
|
||||
source: Database["public"]["Enums"]["source"];
|
||||
status: Database["public"]["Enums"]["status"];
|
||||
};
|
||||
Update: {
|
||||
createdAt?: string;
|
||||
createdBy?: string;
|
||||
id?: number;
|
||||
publicId?: string;
|
||||
source?: Database["public"]["Enums"]["source"];
|
||||
status?: Database["public"]["Enums"]["status"];
|
||||
};
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "import_createdBy_user_id_fk";
|
||||
columns: ["createdBy"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
];
|
||||
};
|
||||
label: {
|
||||
Row: {
|
||||
boardId: number;
|
||||
colourCode: string | null;
|
||||
createdAt: string;
|
||||
createdBy: string;
|
||||
id: number;
|
||||
importId: number | null;
|
||||
name: string;
|
||||
publicId: string;
|
||||
updatedAt: string | null;
|
||||
};
|
||||
Insert: {
|
||||
boardId: number;
|
||||
colourCode?: string | null;
|
||||
createdAt?: string;
|
||||
createdBy: string;
|
||||
id?: number;
|
||||
importId?: number | null;
|
||||
name: string;
|
||||
publicId: string;
|
||||
updatedAt?: string | null;
|
||||
};
|
||||
Update: {
|
||||
boardId?: number;
|
||||
colourCode?: string | null;
|
||||
createdAt?: string;
|
||||
createdBy?: string;
|
||||
id?: number;
|
||||
importId?: number | null;
|
||||
name?: string;
|
||||
publicId?: string;
|
||||
updatedAt?: string | null;
|
||||
};
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "label_boardId_board_id_fk";
|
||||
columns: ["boardId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "board";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "label_createdBy_user_id_fk";
|
||||
columns: ["createdBy"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "label_importId_import_id_fk";
|
||||
columns: ["importId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "import";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
];
|
||||
};
|
||||
list: {
|
||||
Row: {
|
||||
boardId: number;
|
||||
createdAt: string;
|
||||
createdBy: string;
|
||||
deletedAt: string | null;
|
||||
deletedBy: string | null;
|
||||
id: number;
|
||||
importId: number | null;
|
||||
index: number;
|
||||
name: string;
|
||||
publicId: string;
|
||||
updatedAt: string | null;
|
||||
};
|
||||
Insert: {
|
||||
boardId: number;
|
||||
createdAt?: string;
|
||||
createdBy: string;
|
||||
deletedAt?: string | null;
|
||||
deletedBy?: string | null;
|
||||
id?: number;
|
||||
importId?: number | null;
|
||||
index: number;
|
||||
name: string;
|
||||
publicId: string;
|
||||
updatedAt?: string | null;
|
||||
};
|
||||
Update: {
|
||||
boardId?: number;
|
||||
createdAt?: string;
|
||||
createdBy?: string;
|
||||
deletedAt?: string | null;
|
||||
deletedBy?: string | null;
|
||||
id?: number;
|
||||
importId?: number | null;
|
||||
index?: number;
|
||||
name?: string;
|
||||
publicId?: string;
|
||||
updatedAt?: string | null;
|
||||
};
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "list_boardId_board_id_fk";
|
||||
columns: ["boardId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "board";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "list_createdBy_user_id_fk";
|
||||
columns: ["createdBy"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "list_deletedBy_user_id_fk";
|
||||
columns: ["deletedBy"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "list_importId_import_id_fk";
|
||||
columns: ["importId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "import";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
];
|
||||
};
|
||||
user: {
|
||||
Row: {
|
||||
email: string;
|
||||
emailVerified: string | null;
|
||||
id: string;
|
||||
image: string | null;
|
||||
name: string | null;
|
||||
};
|
||||
Insert: {
|
||||
email: string;
|
||||
emailVerified?: string | null;
|
||||
id: string;
|
||||
image?: string | null;
|
||||
name?: string | null;
|
||||
};
|
||||
Update: {
|
||||
email?: string;
|
||||
emailVerified?: string | null;
|
||||
id?: string;
|
||||
image?: string | null;
|
||||
name?: string | null;
|
||||
};
|
||||
Relationships: [];
|
||||
};
|
||||
workspace: {
|
||||
Row: {
|
||||
createdAt: string;
|
||||
createdBy: string;
|
||||
deletedAt: string | null;
|
||||
deletedBy: string | null;
|
||||
id: number;
|
||||
name: string;
|
||||
publicId: string;
|
||||
slug: string;
|
||||
updatedAt: string | null;
|
||||
};
|
||||
Insert: {
|
||||
createdAt?: string;
|
||||
createdBy: string;
|
||||
deletedAt?: string | null;
|
||||
deletedBy?: string | null;
|
||||
id?: number;
|
||||
name: string;
|
||||
publicId: string;
|
||||
slug: string;
|
||||
updatedAt?: string | null;
|
||||
};
|
||||
Update: {
|
||||
createdAt?: string;
|
||||
createdBy?: string;
|
||||
deletedAt?: string | null;
|
||||
deletedBy?: string | null;
|
||||
id?: number;
|
||||
name?: string;
|
||||
publicId?: string;
|
||||
slug?: string;
|
||||
updatedAt?: string | null;
|
||||
};
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "workspace_createdBy_user_id_fk";
|
||||
columns: ["createdBy"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "workspace_deletedBy_user_id_fk";
|
||||
columns: ["deletedBy"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
];
|
||||
};
|
||||
workspace_members: {
|
||||
Row: {
|
||||
createdAt: string;
|
||||
createdBy: string;
|
||||
deletedAt: string | null;
|
||||
deletedBy: string | null;
|
||||
id: number;
|
||||
publicId: string;
|
||||
role: Database["public"]["Enums"]["role"];
|
||||
status: Database["public"]["Enums"]["member_status"];
|
||||
updatedAt: string | null;
|
||||
userId: string;
|
||||
workspaceId: number;
|
||||
};
|
||||
Insert: {
|
||||
createdAt?: string;
|
||||
createdBy: string;
|
||||
deletedAt?: string | null;
|
||||
deletedBy?: string | null;
|
||||
id?: number;
|
||||
publicId: string;
|
||||
role: Database["public"]["Enums"]["role"];
|
||||
status?: Database["public"]["Enums"]["member_status"];
|
||||
updatedAt?: string | null;
|
||||
userId: string;
|
||||
workspaceId: number;
|
||||
};
|
||||
Update: {
|
||||
createdAt?: string;
|
||||
createdBy?: string;
|
||||
deletedAt?: string | null;
|
||||
deletedBy?: string | null;
|
||||
id?: number;
|
||||
publicId?: string;
|
||||
role?: Database["public"]["Enums"]["role"];
|
||||
status?: Database["public"]["Enums"]["member_status"];
|
||||
updatedAt?: string | null;
|
||||
userId?: string;
|
||||
workspaceId?: number;
|
||||
};
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "workspace_members_deletedBy_user_id_fk";
|
||||
columns: ["deletedBy"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "workspace_members_userId_user_id_fk";
|
||||
columns: ["userId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "user";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
{
|
||||
foreignKeyName: "workspace_members_workspaceId_workspace_id_fk";
|
||||
columns: ["workspaceId"];
|
||||
isOneToOne: false;
|
||||
referencedRelation: "workspace";
|
||||
referencedColumns: ["id"];
|
||||
},
|
||||
];
|
||||
};
|
||||
};
|
||||
Views: {
|
||||
[_ in never]: never;
|
||||
};
|
||||
Functions: {
|
||||
is_workspace_admin: {
|
||||
Args: {
|
||||
user_id: string;
|
||||
workspace_id: number;
|
||||
};
|
||||
Returns: boolean;
|
||||
};
|
||||
push_card_index: {
|
||||
Args: {
|
||||
list_id: number;
|
||||
card_index: number;
|
||||
};
|
||||
Returns: undefined;
|
||||
};
|
||||
reorder_cards: {
|
||||
Args: {
|
||||
card_id: number;
|
||||
current_list_id: number;
|
||||
new_list_id: number;
|
||||
current_index: number;
|
||||
new_index: number;
|
||||
};
|
||||
Returns: undefined;
|
||||
};
|
||||
reorder_lists: {
|
||||
Args: {
|
||||
board_id: number;
|
||||
list_id: number;
|
||||
current_index: number;
|
||||
new_index: number;
|
||||
};
|
||||
Returns: undefined;
|
||||
};
|
||||
shift_card_index: {
|
||||
Args: {
|
||||
list_id: number;
|
||||
card_index: number;
|
||||
};
|
||||
Returns: undefined;
|
||||
};
|
||||
shift_list_index: {
|
||||
Args: {
|
||||
board_id: number;
|
||||
list_index: number;
|
||||
};
|
||||
Returns: undefined;
|
||||
};
|
||||
};
|
||||
Enums: {
|
||||
card_activity_type:
|
||||
| "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"
|
||||
| "card.updated.comment.added"
|
||||
| "card.updated.comment.updated"
|
||||
| "card.updated.comment.deleted";
|
||||
member_status: "invited" | "active" | "removed";
|
||||
role: "admin" | "member" | "guest";
|
||||
source: "trello";
|
||||
status: "started" | "success" | "failed";
|
||||
workspace_invite_status: "pending" | "accepted" | "cancelled";
|
||||
};
|
||||
CompositeTypes: {
|
||||
[_ in never]: never;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
type PublicSchema = Database[Extract<keyof Database, "public">];
|
||||
|
||||
export type Tables<
|
||||
PublicTableNameOrOptions extends
|
||||
| keyof (PublicSchema["Tables"] & PublicSchema["Views"])
|
||||
| { schema: keyof Database },
|
||||
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
|
||||
? keyof (Database[PublicTableNameOrOptions["schema"]]["Tables"] &
|
||||
Database[PublicTableNameOrOptions["schema"]]["Views"])
|
||||
: never = never,
|
||||
> = PublicTableNameOrOptions extends { schema: keyof Database }
|
||||
? (Database[PublicTableNameOrOptions["schema"]]["Tables"] &
|
||||
Database[PublicTableNameOrOptions["schema"]]["Views"])[TableName] extends {
|
||||
Row: infer R;
|
||||
}
|
||||
? R
|
||||
: never
|
||||
: PublicTableNameOrOptions extends keyof (PublicSchema["Tables"] &
|
||||
PublicSchema["Views"])
|
||||
? (PublicSchema["Tables"] &
|
||||
PublicSchema["Views"])[PublicTableNameOrOptions] extends {
|
||||
Row: infer R;
|
||||
}
|
||||
? R
|
||||
: never
|
||||
: never;
|
||||
|
||||
export type TablesInsert<
|
||||
PublicTableNameOrOptions extends
|
||||
| keyof PublicSchema["Tables"]
|
||||
| { schema: keyof Database },
|
||||
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
|
||||
? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"]
|
||||
: never = never,
|
||||
> = PublicTableNameOrOptions extends { schema: keyof Database }
|
||||
? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends {
|
||||
Insert: infer I;
|
||||
}
|
||||
? I
|
||||
: never
|
||||
: PublicTableNameOrOptions extends keyof PublicSchema["Tables"]
|
||||
? PublicSchema["Tables"][PublicTableNameOrOptions] extends {
|
||||
Insert: infer I;
|
||||
}
|
||||
? I
|
||||
: never
|
||||
: never;
|
||||
|
||||
export type TablesUpdate<
|
||||
PublicTableNameOrOptions extends
|
||||
| keyof PublicSchema["Tables"]
|
||||
| { schema: keyof Database },
|
||||
TableName extends PublicTableNameOrOptions extends { schema: keyof Database }
|
||||
? keyof Database[PublicTableNameOrOptions["schema"]]["Tables"]
|
||||
: never = never,
|
||||
> = PublicTableNameOrOptions extends { schema: keyof Database }
|
||||
? Database[PublicTableNameOrOptions["schema"]]["Tables"][TableName] extends {
|
||||
Update: infer U;
|
||||
}
|
||||
? U
|
||||
: never
|
||||
: PublicTableNameOrOptions extends keyof PublicSchema["Tables"]
|
||||
? PublicSchema["Tables"][PublicTableNameOrOptions] extends {
|
||||
Update: infer U;
|
||||
}
|
||||
? U
|
||||
: never
|
||||
: never;
|
||||
|
||||
export type Enums<
|
||||
PublicEnumNameOrOptions extends
|
||||
| keyof PublicSchema["Enums"]
|
||||
| { schema: keyof Database },
|
||||
EnumName extends PublicEnumNameOrOptions extends { schema: keyof Database }
|
||||
? keyof Database[PublicEnumNameOrOptions["schema"]]["Enums"]
|
||||
: never = never,
|
||||
> = PublicEnumNameOrOptions extends { schema: keyof Database }
|
||||
? Database[PublicEnumNameOrOptions["schema"]]["Enums"][EnumName]
|
||||
: PublicEnumNameOrOptions extends keyof PublicSchema["Enums"]
|
||||
? PublicSchema["Enums"][PublicEnumNameOrOptions]
|
||||
: never;
|
||||
|
||||
export type CompositeTypes<
|
||||
PublicCompositeTypeNameOrOptions extends
|
||||
| keyof PublicSchema["CompositeTypes"]
|
||||
| { schema: keyof Database },
|
||||
CompositeTypeName extends PublicCompositeTypeNameOrOptions extends {
|
||||
schema: keyof Database;
|
||||
}
|
||||
? keyof Database[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"]
|
||||
: never = never,
|
||||
> = PublicCompositeTypeNameOrOptions extends { schema: keyof Database }
|
||||
? Database[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"][CompositeTypeName]
|
||||
: PublicCompositeTypeNameOrOptions extends keyof PublicSchema["CompositeTypes"]
|
||||
? PublicSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions]
|
||||
: never;
|
||||
8
packages/db/tsconfig.json
Normal file
8
packages/db/tsconfig.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "@kan/tsconfig/internal-package.json",
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules"],
|
||||
"compilerOptions": {
|
||||
"rootDir": "./src"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user