|
1 |
| -/** |
2 |
| - * This is the schema for the database. |
3 |
| - * 💡Tip: you can use the `$` global variable to access goodies |
4 |
| - * Do not forget to `export` your tables 😅 |
5 |
| - */ |
| 1 | +import { sql, eq, getTableColumns } from "drizzle-orm"; |
| 2 | +import { |
| 3 | + bigint, |
| 4 | + foreignKey, |
| 5 | + pgTable, |
| 6 | + text, |
| 7 | + timestamp, |
| 8 | + unique, |
| 9 | + uuid, |
| 10 | + pgPolicy, |
| 11 | + pgView, |
| 12 | + pgSchema, |
| 13 | + pgRole, |
| 14 | +} from "drizzle-orm/pg-core"; |
6 | 15 |
|
7 |
| -import { relations } from "drizzle-orm"; |
8 |
| -import { integer, text, pgTable, timestamp } from "drizzle-orm/pg-core"; |
| 16 | +/* ------------------------------ Supabase emulation ------------------------------ */ |
9 | 17 |
|
10 |
| -export const users = pgTable("users", { |
11 |
| - id: integer("id").primaryKey().generatedByDefaultAsIdentity(), |
12 |
| - name: text("name").notNull(), |
13 |
| - createdAt: timestamp("created_at", { precision: 3 }).notNull().defaultNow(), |
| 18 | +export const anonRole = pgRole("anon"); |
| 19 | +export const authenticatedRole = pgRole("authenticated"); |
| 20 | +export const serviceRole = pgRole("service_role"); |
| 21 | +export const supabaseAuthAdminRole = pgRole("supabase_auth_admin"); |
| 22 | +export const auth = pgSchema("auth"); |
| 23 | +export const authUsers = auth.table("users", { |
| 24 | + id: uuid().primaryKey().notNull(), |
14 | 25 | });
|
| 26 | +const authUid = sql`(select auth.uid())`; |
15 | 27 |
|
16 |
| -export const usersRelations = relations(users, ({ many }) => ({ |
17 |
| - posts: many(posts), |
18 |
| -})); |
| 28 | +/* ------------------------------ public schema; ------------------------------ */ |
19 | 29 |
|
20 |
| -export const posts = pgTable("posts", { |
21 |
| - id: integer("id").primaryKey().generatedByDefaultAsIdentity(), |
22 |
| - content: text("content").notNull(), |
23 |
| - authorId: integer("author_id") |
24 |
| - .notNull() |
25 |
| - .references(() => users.id), |
26 |
| - createdAt: timestamp("created_at", { precision: 3 }).notNull().defaultNow(), |
27 |
| -}); |
| 30 | +export const rooms = pgTable( |
| 31 | + "rooms", |
| 32 | + { |
| 33 | + id: bigint({ mode: "number" }).primaryKey().generatedByDefaultAsIdentity(), |
| 34 | + topic: text().notNull(), |
| 35 | + }, |
| 36 | + (table) => [ |
| 37 | + unique("rooms_topic_key").on(table.topic), |
| 38 | + pgPolicy("authenticated can read rooms", { |
| 39 | + for: "select", |
| 40 | + to: authenticatedRole, |
| 41 | + using: sql`true`, |
| 42 | + }), |
| 43 | + pgPolicy("authenticated can add rooms", { |
| 44 | + for: "insert", |
| 45 | + to: authenticatedRole, |
| 46 | + withCheck: sql`true`, |
| 47 | + }), |
| 48 | + ], |
| 49 | +); |
| 50 | + |
| 51 | +export const profiles = pgTable( |
| 52 | + "profiles", |
| 53 | + { |
| 54 | + id: uuid() |
| 55 | + .primaryKey() |
| 56 | + .notNull() |
| 57 | + .references(() => authUsers.id, { onDelete: "cascade" }), |
| 58 | + email: text().notNull(), |
| 59 | + }, |
| 60 | + (table) => [ |
| 61 | + pgPolicy("authenticated can view all profiles", { |
| 62 | + for: "select", |
| 63 | + to: authenticatedRole, |
| 64 | + using: sql`true`, |
| 65 | + }), |
| 66 | + pgPolicy("owner can update profile", { |
| 67 | + for: "update", |
| 68 | + to: authenticatedRole, |
| 69 | + using: eq(table.id, authUid), |
| 70 | + withCheck: eq(table.id, authUid), |
| 71 | + }), |
| 72 | + ], |
| 73 | +); |
| 74 | + |
| 75 | +export const roomsUsers = pgTable( |
| 76 | + "rooms_users", |
| 77 | + { |
| 78 | + userId: uuid().notNull(), |
| 79 | + roomTopic: text().notNull(), |
| 80 | + joinedAt: timestamp({ |
| 81 | + mode: "string", |
| 82 | + precision: 3, |
| 83 | + }) |
| 84 | + .notNull() |
| 85 | + .defaultNow(), |
| 86 | + }, |
| 87 | + (table) => [ |
| 88 | + foreignKey({ |
| 89 | + columns: [table.userId], |
| 90 | + foreignColumns: [authUsers.id], |
| 91 | + name: "rooms_users_user_id_fk", |
| 92 | + }), |
| 93 | + foreignKey({ |
| 94 | + columns: [table.roomTopic], |
| 95 | + foreignColumns: [rooms.topic], |
| 96 | + name: "rooms_users_room_topic_fk", |
| 97 | + }), |
| 98 | + pgPolicy("authenticated can read rooms_users", { |
| 99 | + for: "select", |
| 100 | + to: authenticatedRole, |
| 101 | + using: sql`true`, |
| 102 | + }), |
| 103 | + pgPolicy("authenticated can add rooms_users", { |
| 104 | + for: "insert", |
| 105 | + to: authenticatedRole, |
| 106 | + withCheck: sql`true`, |
| 107 | + }), |
| 108 | + ], |
| 109 | +); |
28 | 110 |
|
29 |
| -export const postsRelations = relations(posts, ({ one }) => ({ |
30 |
| - author: one(users, { fields: [posts.authorId], references: [users.id] }), |
31 |
| -})); |
| 111 | +export const roomsUsersProfiles = pgView("rooms_users_profiles") |
| 112 | + .with({ |
| 113 | + securityInvoker: true, |
| 114 | + }) |
| 115 | + .as((qb) => |
| 116 | + qb |
| 117 | + .select({ |
| 118 | + ...getTableColumns(roomsUsers), |
| 119 | + email: profiles.email, |
| 120 | + }) |
| 121 | + .from(roomsUsers) |
| 122 | + .innerJoin(profiles, eq(roomsUsers.userId, profiles.id)), |
| 123 | + ); |
0 commit comments