feat: premium workspace usernames
This commit is contained in:
@@ -10,6 +10,17 @@ if (!postgresUrl) {
|
||||
}
|
||||
|
||||
const migrationClient = postgres(postgresUrl, { max: 1 });
|
||||
console.log("Starting database migration...");
|
||||
|
||||
migrate(drizzle(migrationClient), {
|
||||
migrationsFolder: "./src/server/db/migrations",
|
||||
}).catch((e) => console.log(e));
|
||||
migrationsFolder: "./migrations",
|
||||
})
|
||||
.then(() => {
|
||||
console.log("✅ Database migration completed successfully");
|
||||
process.exit(0);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("❌ Migration failed:");
|
||||
console.error(error);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
@@ -5,7 +5,7 @@ import type { Database } from "@kan/db/types/database.types";
|
||||
export const getById = async (db: SupabaseClient<Database>, userId: string) => {
|
||||
const { data } = await db
|
||||
.from("user")
|
||||
.select(`id, name, email`)
|
||||
.select(`id, name, email, stripeCustomerId`)
|
||||
.eq("id", userId)
|
||||
.limit(1)
|
||||
.single();
|
||||
@@ -29,11 +29,15 @@ export const getByEmail = async (
|
||||
|
||||
export const create = async (
|
||||
db: SupabaseClient<Database>,
|
||||
user: { id: string; email: string },
|
||||
user: { id: string; email: string; stripeCustomerId: string },
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("user")
|
||||
.insert({ id: user.id, email: user.email })
|
||||
.insert({
|
||||
id: user.id,
|
||||
email: user.email,
|
||||
stripeCustomerId: user.stripeCustomerId,
|
||||
})
|
||||
.select()
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
@@ -159,3 +159,18 @@ export const hardDelete = async (
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export const isWorkspaceSlugAvailable = async (
|
||||
db: SupabaseClient<Database>,
|
||||
workspaceSlug: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("workspace")
|
||||
.select("id")
|
||||
.eq("slug", workspaceSlug)
|
||||
.is("deletedAt", null)
|
||||
.limit(1)
|
||||
.single();
|
||||
|
||||
return data === null;
|
||||
};
|
||||
|
||||
16
packages/db/src/repository/workspaceSlug.repo.ts
Normal file
16
packages/db/src/repository/workspaceSlug.repo.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import type { SupabaseClient } from "@supabase/supabase-js";
|
||||
|
||||
import type { Database } from "@kan/db/types/database.types";
|
||||
|
||||
export const getWorkspaceSlug = async (
|
||||
db: SupabaseClient<Database>,
|
||||
slug: string,
|
||||
) => {
|
||||
const { data } = await db
|
||||
.from("workspace_slugs")
|
||||
.select(`slug, type`)
|
||||
.eq("slug", slug)
|
||||
.single();
|
||||
|
||||
return data;
|
||||
};
|
||||
@@ -1,15 +1,15 @@
|
||||
import { relations } from "drizzle-orm";
|
||||
import {
|
||||
integer,
|
||||
bigint,
|
||||
bigserial,
|
||||
uuid,
|
||||
integer,
|
||||
pgEnum,
|
||||
pgTable,
|
||||
primaryKey,
|
||||
text,
|
||||
timestamp,
|
||||
uuid,
|
||||
varchar,
|
||||
bigint,
|
||||
} from "drizzle-orm/pg-core";
|
||||
|
||||
export const importSourceEnum = pgEnum("source", ["trello"]);
|
||||
@@ -39,6 +39,7 @@ export const activityTypeEnum = pgEnum("card_activity_type", [
|
||||
"card.updated.comment.deleted",
|
||||
"card.archived",
|
||||
]);
|
||||
export const slugTypeEnum = pgEnum("slug_type", ["reserved", "premium"]);
|
||||
|
||||
export const boards = pgTable("board", {
|
||||
id: bigserial("id", { mode: "number" }).primaryKey(),
|
||||
@@ -272,6 +273,7 @@ export const users = pgTable("user", {
|
||||
email: varchar("email", { length: 255 }).notNull().unique(),
|
||||
emailVerified: timestamp("emailVerified", { mode: "date" }),
|
||||
image: varchar("image", { length: 255 }),
|
||||
stripeCustomerId: varchar("stripeCustomerId", { length: 255 }),
|
||||
});
|
||||
|
||||
export const usersRelations = relations(users, ({ many }) => ({
|
||||
@@ -430,3 +432,8 @@ export const commentsRelations = relations(comments, ({ one }) => ({
|
||||
references: [users.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const slugs = pgTable("workspace_slugs", {
|
||||
slug: varchar("slug", { length: 255 }).notNull().unique(),
|
||||
type: slugTypeEnum("type").notNull(),
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ export type Json =
|
||||
| { [key: string]: Json | undefined }
|
||||
| Json[];
|
||||
|
||||
export type Database = {
|
||||
export interface Database {
|
||||
public: {
|
||||
Tables: {
|
||||
_card_labels: {
|
||||
@@ -558,6 +558,7 @@ export type Database = {
|
||||
id: string;
|
||||
image: string | null;
|
||||
name: string | null;
|
||||
stripeCustomerId: string | null;
|
||||
};
|
||||
Insert: {
|
||||
email: string;
|
||||
@@ -565,6 +566,7 @@ export type Database = {
|
||||
id: string;
|
||||
image?: string | null;
|
||||
name?: string | null;
|
||||
stripeCustomerId?: string | null;
|
||||
};
|
||||
Update: {
|
||||
email?: string;
|
||||
@@ -572,6 +574,7 @@ export type Database = {
|
||||
id?: string;
|
||||
image?: string | null;
|
||||
name?: string | null;
|
||||
stripeCustomerId?: string | null;
|
||||
};
|
||||
Relationships: [];
|
||||
};
|
||||
@@ -690,10 +693,23 @@ export type Database = {
|
||||
},
|
||||
];
|
||||
};
|
||||
workspace_slugs: {
|
||||
Row: {
|
||||
slug: string;
|
||||
type: Database["public"]["Enums"]["slug_type"];
|
||||
};
|
||||
Insert: {
|
||||
slug: string;
|
||||
type: Database["public"]["Enums"]["slug_type"];
|
||||
};
|
||||
Update: {
|
||||
slug?: string;
|
||||
type?: Database["public"]["Enums"]["slug_type"];
|
||||
};
|
||||
Relationships: [];
|
||||
};
|
||||
};
|
||||
Views: {
|
||||
[_ in never]: never;
|
||||
};
|
||||
Views: Record<never, never>;
|
||||
Functions: {
|
||||
is_workspace_admin: {
|
||||
Args: {
|
||||
@@ -717,7 +733,7 @@ export type Database = {
|
||||
current_index: number;
|
||||
new_index: number;
|
||||
};
|
||||
Returns: undefined;
|
||||
Returns: boolean;
|
||||
};
|
||||
reorder_lists: {
|
||||
Args: {
|
||||
@@ -726,7 +742,7 @@ export type Database = {
|
||||
current_index: number;
|
||||
new_index: number;
|
||||
};
|
||||
Returns: undefined;
|
||||
Returns: boolean;
|
||||
};
|
||||
shift_card_index: {
|
||||
Args: {
|
||||
@@ -760,15 +776,14 @@ export type Database = {
|
||||
| "card.updated.comment.deleted";
|
||||
member_status: "invited" | "active" | "removed";
|
||||
role: "admin" | "member" | "guest";
|
||||
slug_type: "reserved" | "premium";
|
||||
source: "trello";
|
||||
status: "started" | "success" | "failed";
|
||||
workspace_invite_status: "pending" | "accepted" | "cancelled";
|
||||
};
|
||||
CompositeTypes: {
|
||||
[_ in never]: never;
|
||||
};
|
||||
CompositeTypes: Record<never, never>;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
type PublicSchema = Database[Extract<keyof Database, "public">];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user