Atproto AMA app
1import { relations } from "drizzle-orm";
2import {
3 boolean,
4 pgTable,
5 text,
6 timestamp,
7 uuid,
8 index,
9} from "drizzle-orm/pg-core";
10
11export const users = pgTable("users", {
12 did: text("did").primaryKey(),
13 handle: text("handle").notNull().unique(),
14 displayName: text("display_name"),
15 avatarUrl: text("avatar_url"),
16 questionsOpen: boolean("questions_open").notNull().default(false),
17 createdAt: timestamp("created_at", { withTimezone: true })
18 .notNull()
19 .defaultNow(),
20 updatedAt: timestamp("updated_at", { withTimezone: true })
21 .notNull()
22 .defaultNow()
23 .$onUpdate(() => new Date()),
24});
25
26export const questions = pgTable("questions", {
27 id: uuid("id").primaryKey().defaultRandom(),
28 authorDid: text("author_did")
29 .notNull()
30 .references(() => users.did),
31 targetDid: text("target_did")
32 .notNull()
33 .references(() => users.did),
34 content: text("content").notNull(),
35 sourceType: text("source_type").notNull().default("askimut"),
36 anonymous: boolean("anonymous").notNull().default(false),
37 atUri: text("at_uri"),
38 sourceUri: text("source_uri"), // Original URI from source platform
39 sourceData: text("source_data"), // JSON string of platform-specific data
40 reindexed: boolean("reindexed").notNull().default(false),
41 createdAt: timestamp("created_at", { withTimezone: true })
42 .notNull()
43 .defaultNow(),
44}, (table) => ({
45 sourceTypeIdx: index("questions_source_type_idx").on(table.sourceType),
46 sourceUriIdx: index("questions_source_uri_idx").on(table.sourceUri),
47}));
48
49export const answers = pgTable("answers", {
50 id: uuid("id").primaryKey().defaultRandom(),
51 questionId: uuid("question_id")
52 .notNull()
53 .references(() => questions.id),
54 authorDid: text("author_did")
55 .notNull()
56 .references(() => users.did),
57 content: text("content").notNull(),
58 sourceType: text("source_type").notNull().default("askimut"),
59 atUri: text("at_uri"),
60 sourceUri: text("source_uri"), // Original URI from source platform
61 sourceData: text("source_data"), // JSON string of platform-specific data
62 reindexed: boolean("reindexed").notNull().default(false),
63 createdAt: timestamp("created_at", { withTimezone: true })
64 .notNull()
65 .defaultNow(),
66}, (table) => ({
67 sourceTypeIdx: index("answers_source_type_idx").on(table.sourceType),
68 sourceUriIdx: index("answers_source_uri_idx").on(table.sourceUri),
69}));
70
71export const sessions = pgTable("sessions", {
72 id: text("id").primaryKey(),
73 did: text("did")
74 .notNull()
75 .references(() => users.did),
76 expiresAt: timestamp("expires_at", { withTimezone: true }).notNull(),
77 createdAt: timestamp("created_at", { withTimezone: true })
78 .notNull()
79 .defaultNow(),
80});
81
82export const oauthStates = pgTable("oauth_states", {
83 key: text("key").primaryKey(),
84 state: text("state").notNull(),
85 createdAt: timestamp("created_at", { withTimezone: true })
86 .notNull()
87 .defaultNow(),
88});
89
90export const oauthSessions = pgTable("oauth_sessions", {
91 key: text("key").primaryKey(),
92 session: text("session").notNull(),
93 createdAt: timestamp("created_at", { withTimezone: true })
94 .notNull()
95 .defaultNow(),
96});
97
98export const usersRelations = relations(users, ({ many }) => ({
99 questionsAuthored: many(questions, {
100 relationName: "questionAuthor",
101 }),
102 questionsReceived: many(questions, {
103 relationName: "questionTarget",
104 }),
105 answers: many(answers),
106 sessions: many(sessions),
107}));
108
109export const questionsRelations = relations(questions, ({ one, many }) => ({
110 author: one(users, {
111 fields: [questions.authorDid],
112 references: [users.did],
113 relationName: "questionAuthor",
114 }),
115 target: one(users, {
116 fields: [questions.targetDid],
117 references: [users.did],
118 relationName: "questionTarget",
119 }),
120 answers: many(answers),
121}));
122
123export const answersRelations = relations(answers, ({ one }) => ({
124 question: one(questions, {
125 fields: [answers.questionId],
126 references: [questions.id],
127 }),
128 author: one(users, {
129 fields: [answers.authorDid],
130 references: [users.did],
131 }),
132}));
133
134export const sessionsRelations = relations(sessions, ({ one }) => ({
135 user: one(users, {
136 fields: [sessions.did],
137 references: [users.did],
138 }),
139}));
140
141export const oauthStatesRelations = relations(oauthStates, () => ({}));
142
143export const oauthSessionsRelations = relations(oauthSessions, () => ({}));