168 lines
5.4 KiB
TypeScript
168 lines
5.4 KiB
TypeScript
import { pgTable, text, timestamp, numeric, boolean, primaryKey } from 'drizzle-orm/pg-core';
|
|
import { relations } from 'drizzle-orm';
|
|
import { createId } from '@paralleldrive/cuid2';
|
|
import type { AdapterAccountType } from '@auth/core/adapters';
|
|
|
|
export const users = pgTable('user', {
|
|
id: text('id')
|
|
.primaryKey()
|
|
.$defaultFn(() => createId()),
|
|
name: text('name'),
|
|
email: text('email').unique(),
|
|
emailVerified: timestamp('emailVerified', { mode: 'date' }),
|
|
image: text('image'),
|
|
password: text('password'),
|
|
username: text('username').unique()
|
|
});
|
|
|
|
export const accounts = pgTable(
|
|
'account',
|
|
{
|
|
userId: text('userId')
|
|
.notNull()
|
|
.references(() => users.id, { onDelete: 'cascade' }),
|
|
type: text('type').$type<AdapterAccountType>().notNull(),
|
|
provider: text('provider').notNull(),
|
|
providerAccountId: text('providerAccountId').notNull(),
|
|
refresh_token: text('refresh_token'),
|
|
access_token: text('access_token'),
|
|
expires_at: numeric('expires_at'),
|
|
token_type: text('token_type'),
|
|
scope: text('scope'),
|
|
id_token: text('id_token'),
|
|
session_state: text('session_state')
|
|
},
|
|
(account) => ({
|
|
compoundKey: primaryKey({
|
|
columns: [account.provider, account.providerAccountId]
|
|
})
|
|
})
|
|
);
|
|
|
|
export const sessions = pgTable('session', {
|
|
sessionToken: text('sessionToken').primaryKey(),
|
|
userId: text('userId')
|
|
.notNull()
|
|
.references(() => users.id, { onDelete: 'cascade' }),
|
|
expires: timestamp('expires', { mode: 'date' }).notNull()
|
|
});
|
|
|
|
export const verificationTokens = pgTable(
|
|
'verificationToken',
|
|
{
|
|
identifier: text('identifier').notNull(),
|
|
token: text('token').notNull(),
|
|
expires: timestamp('expires', { mode: 'date' }).notNull()
|
|
},
|
|
(verificationToken) => ({
|
|
compositePk: primaryKey({
|
|
columns: [verificationToken.identifier, verificationToken.token]
|
|
})
|
|
})
|
|
);
|
|
|
|
export const wishlists = pgTable('wishlists', {
|
|
id: text('id').primaryKey().$defaultFn(() => createId()),
|
|
userId: text('user_id').references(() => users.id, { onDelete: 'set null' }),
|
|
title: text('title').notNull(),
|
|
description: text('description'),
|
|
ownerToken: text('owner_token').notNull().unique(),
|
|
publicToken: text('public_token').notNull().unique(),
|
|
isFavorite: boolean('is_favorite').default(false).notNull(),
|
|
color: text('color'),
|
|
endDate: timestamp('end_date', { mode: 'date' }),
|
|
createdAt: timestamp('created_at').defaultNow().notNull(),
|
|
updatedAt: timestamp('updated_at').defaultNow().notNull()
|
|
});
|
|
|
|
export const wishlistsRelations = relations(wishlists, ({ one, many }) => ({
|
|
user: one(users, {
|
|
fields: [wishlists.userId],
|
|
references: [users.id]
|
|
}),
|
|
items: many(items),
|
|
savedBy: many(savedWishlists)
|
|
}));
|
|
|
|
export const items = pgTable('items', {
|
|
id: text('id').primaryKey().$defaultFn(() => createId()),
|
|
wishlistId: text('wishlist_id')
|
|
.notNull()
|
|
.references(() => wishlists.id, { onDelete: 'cascade' }),
|
|
title: text('title').notNull(),
|
|
description: text('description'),
|
|
link: text('link'),
|
|
imageUrl: text('image_url'),
|
|
price: numeric('price', { precision: 10, scale: 2 }),
|
|
currency: text('currency').default('DKK'),
|
|
color: text('color'),
|
|
order: numeric('order').notNull().default('0'),
|
|
isReserved: boolean('is_reserved').default(false).notNull(),
|
|
createdAt: timestamp('created_at').defaultNow().notNull(),
|
|
updatedAt: timestamp('updated_at').defaultNow().notNull()
|
|
});
|
|
|
|
export const itemsRelations = relations(items, ({ one, many }) => ({
|
|
wishlist: one(wishlists, {
|
|
fields: [items.wishlistId],
|
|
references: [wishlists.id]
|
|
}),
|
|
reservations: many(reservations)
|
|
}));
|
|
|
|
export const reservations = pgTable('reservations', {
|
|
id: text('id').primaryKey().$defaultFn(() => createId()),
|
|
itemId: text('item_id')
|
|
.notNull()
|
|
.references(() => items.id, { onDelete: 'cascade' }),
|
|
reserverName: text('reserver_name'),
|
|
createdAt: timestamp('created_at').defaultNow().notNull()
|
|
});
|
|
|
|
export const reservationsRelations = relations(reservations, ({ one }) => ({
|
|
item: one(items, {
|
|
fields: [reservations.itemId],
|
|
references: [items.id]
|
|
})
|
|
}));
|
|
|
|
export const savedWishlists = pgTable('saved_wishlists', {
|
|
id: text('id').primaryKey().$defaultFn(() => createId()),
|
|
userId: text('user_id')
|
|
.notNull()
|
|
.references(() => users.id, { onDelete: 'cascade' }),
|
|
wishlistId: text('wishlist_id')
|
|
.notNull()
|
|
.references(() => wishlists.id, { onDelete: 'cascade' }),
|
|
ownerToken: text('owner_token'), // Stores the owner token if user has edit access (claimed via edit link)
|
|
isFavorite: boolean('is_favorite').default(false).notNull(),
|
|
createdAt: timestamp('created_at').defaultNow().notNull()
|
|
});
|
|
|
|
export const savedWishlistsRelations = relations(savedWishlists, ({ one }) => ({
|
|
user: one(users, {
|
|
fields: [savedWishlists.userId],
|
|
references: [users.id]
|
|
}),
|
|
wishlist: one(wishlists, {
|
|
fields: [savedWishlists.wishlistId],
|
|
references: [wishlists.id]
|
|
})
|
|
}));
|
|
|
|
export const usersRelations = relations(users, ({ many }) => ({
|
|
wishlists: many(wishlists),
|
|
savedWishlists: many(savedWishlists)
|
|
}));
|
|
|
|
export type User = typeof users.$inferSelect;
|
|
export type NewUser = typeof users.$inferInsert;
|
|
export type Wishlist = typeof wishlists.$inferSelect;
|
|
export type NewWishlist = typeof wishlists.$inferInsert;
|
|
export type Item = typeof items.$inferSelect;
|
|
export type NewItem = typeof items.$inferInsert;
|
|
export type Reservation = typeof reservations.$inferSelect;
|
|
export type NewReservation = typeof reservations.$inferInsert;
|
|
export type SavedWishlist = typeof savedWishlists.$inferSelect;
|
|
export type NewSavedWishlist = typeof savedWishlists.$inferInsert;
|