Updating schema to have more foreign key constraints in line with prisma migration and primary key on join tables.

This commit is contained in:
Bradley Shellnut 2024-02-19 00:22:05 -08:00
parent bbb6df0fec
commit b7d7113262
11 changed files with 2966 additions and 130 deletions

View file

@ -7,9 +7,13 @@ export default defineConfig({
driver: 'pg',
dbCredentials: {
host: process.env.DATABASE_HOST || 'localhost',
port: process.env.DATABASE_PORT || 5432,
port: Number(process.env.DATABASE_PORT) || 5432,
user: process.env.DATABASE_USER,
password: process.env.DATABASE_PASSWORD,
database: process.env.DATABASE || 'boredgame'
}
},
// Print all statements
verbose: true,
// Always as for confirmation
strict: true
});

View file

@ -0,0 +1,97 @@
ALTER TABLE "categories_to_external_ids" DROP CONSTRAINT "categories_to_external_ids_category_id_categories_id_fk";
--> statement-breakpoint
ALTER TABLE "expansions" DROP CONSTRAINT "expansions_base_game_id_games_id_fk";
--> statement-breakpoint
ALTER TABLE "expansions_to_external_ids" DROP CONSTRAINT "expansions_to_external_ids_expansion_id_expansions_id_fk";
--> statement-breakpoint
ALTER TABLE "games_to_external_ids" DROP CONSTRAINT "games_to_external_ids_game_id_games_id_fk";
--> statement-breakpoint
ALTER TABLE "mechanics_to_external_ids" DROP CONSTRAINT "mechanics_to_external_ids_mechanic_id_mechanics_id_fk";
--> statement-breakpoint
ALTER TABLE "publishers_to_external_ids" DROP CONSTRAINT "publishers_to_external_ids_publisher_id_publishers_id_fk";
--> statement-breakpoint
ALTER TABLE "categories_to_games" ALTER COLUMN "category_id" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "categories_to_games" ALTER COLUMN "game_id" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "mechanics_to_games" ALTER COLUMN "mechanic_id" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "mechanics_to_games" ALTER COLUMN "game_id" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "publishers_to_games" ALTER COLUMN "publisher_id" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "publishers_to_games" ALTER COLUMN "game_id" SET NOT NULL;--> statement-breakpoint
ALTER TABLE "categories_to_external_ids" ADD CONSTRAINT "categories_to_external_ids_category_id_external_id_pk" PRIMARY KEY("category_id","external_id");--> statement-breakpoint
ALTER TABLE "categories_to_games" ADD CONSTRAINT "categories_to_games_category_id_game_id_pk" PRIMARY KEY("category_id","game_id");--> statement-breakpoint
ALTER TABLE "expansions_to_external_ids" ADD CONSTRAINT "expansions_to_external_ids_expansion_id_external_id_pk" PRIMARY KEY("expansion_id","external_id");--> statement-breakpoint
ALTER TABLE "games_to_external_ids" ADD CONSTRAINT "games_to_external_ids_game_id_external_id_pk" PRIMARY KEY("game_id","external_id");--> statement-breakpoint
ALTER TABLE "mechanics_to_external_ids" ADD CONSTRAINT "mechanics_to_external_ids_mechanic_id_external_id_pk" PRIMARY KEY("mechanic_id","external_id");--> statement-breakpoint
ALTER TABLE "mechanics_to_games" ADD CONSTRAINT "mechanics_to_games_mechanic_id_game_id_pk" PRIMARY KEY("mechanic_id","game_id");--> statement-breakpoint
ALTER TABLE "publishers_to_external_ids" ADD CONSTRAINT "publishers_to_external_ids_publisher_id_external_id_pk" PRIMARY KEY("publisher_id","external_id");--> statement-breakpoint
ALTER TABLE "publishers_to_games" ADD CONSTRAINT "publishers_to_games_publisher_id_game_id_pk" PRIMARY KEY("publisher_id","game_id");--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "categories_to_external_ids" ADD CONSTRAINT "categories_to_external_ids_category_id_categories_id_fk" FOREIGN KEY ("category_id") REFERENCES "categories"("id") ON DELETE restrict ON UPDATE cascade;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "categories_to_games" ADD CONSTRAINT "categories_to_games_category_id_categories_id_fk" FOREIGN KEY ("category_id") REFERENCES "categories"("id") ON DELETE restrict ON UPDATE cascade;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "categories_to_games" ADD CONSTRAINT "categories_to_games_game_id_games_id_fk" FOREIGN KEY ("game_id") REFERENCES "games"("id") ON DELETE restrict ON UPDATE cascade;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "expansions" ADD CONSTRAINT "expansions_base_game_id_games_id_fk" FOREIGN KEY ("base_game_id") REFERENCES "games"("id") ON DELETE restrict ON UPDATE cascade;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "expansions_to_external_ids" ADD CONSTRAINT "expansions_to_external_ids_expansion_id_expansions_id_fk" FOREIGN KEY ("expansion_id") REFERENCES "expansions"("id") ON DELETE restrict ON UPDATE cascade;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "games_to_external_ids" ADD CONSTRAINT "games_to_external_ids_game_id_games_id_fk" FOREIGN KEY ("game_id") REFERENCES "games"("id") ON DELETE restrict ON UPDATE cascade;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "mechanics_to_external_ids" ADD CONSTRAINT "mechanics_to_external_ids_mechanic_id_mechanics_id_fk" FOREIGN KEY ("mechanic_id") REFERENCES "mechanics"("id") ON DELETE restrict ON UPDATE cascade;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "mechanics_to_games" ADD CONSTRAINT "mechanics_to_games_mechanic_id_mechanics_id_fk" FOREIGN KEY ("mechanic_id") REFERENCES "mechanics"("id") ON DELETE restrict ON UPDATE cascade;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "mechanics_to_games" ADD CONSTRAINT "mechanics_to_games_game_id_games_id_fk" FOREIGN KEY ("game_id") REFERENCES "games"("id") ON DELETE restrict ON UPDATE cascade;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "publishers_to_external_ids" ADD CONSTRAINT "publishers_to_external_ids_publisher_id_publishers_id_fk" FOREIGN KEY ("publisher_id") REFERENCES "publishers"("id") ON DELETE restrict ON UPDATE cascade;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "publishers_to_games" ADD CONSTRAINT "publishers_to_games_publisher_id_publishers_id_fk" FOREIGN KEY ("publisher_id") REFERENCES "publishers"("id") ON DELETE restrict ON UPDATE cascade;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "publishers_to_games" ADD CONSTRAINT "publishers_to_games_game_id_games_id_fk" FOREIGN KEY ("game_id") REFERENCES "games"("id") ON DELETE restrict ON UPDATE cascade;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View file

@ -0,0 +1,2 @@
ALTER TABLE "users" ALTER COLUMN "created_at" SET DATA TYPE timestamp (6) with time zone;--> statement-breakpoint
ALTER TABLE "users" ALTER COLUMN "updated_at" SET DATA TYPE timestamp (6) with time zone;

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -78,6 +78,20 @@
"when": 1708243232524,
"tag": "0010_flat_mister_sinister",
"breakpoints": true
},
{
"idx": 11,
"version": "5",
"when": 1708330668971,
"tag": "0011_gigantic_mister_sinister",
"breakpoints": true
},
{
"idx": 12,
"version": "5",
"when": 1708330799655,
"tag": "0012_dizzy_lethal_legion",
"breakpoints": true
}
]
}

View file

@ -1,103 +1,39 @@
import type { Game } from '@prisma/client';
import kebabCase from 'just-kebab-case';
import type { BggLinkDto } from 'boardgamegeekclient/dist/esm/dto/concrete/subdto';
import prisma from '$lib/prisma';
import { mapAPIGameToBoredGame } from './gameMapper';
import db from '$lib/drizzle';
import { games } from '../../schema';
import { externalIds, games, publishersToExternalIds, type Publishers, publishers } from '../../schema';
import { eq, sql } from 'drizzle-orm';
import { error } from '@sveltejs/kit';
export async function createArtist(locals: App.Locals, externalArtist: BggLinkDto) {
try {
let dbArtist = await prisma.artist.findFirst({
where: {
external_id: externalArtist.id
},
select: {
id: true,
name: true,
slug: true,
external_id: true
}
});
if (dbArtist) {
console.log('Artist already exists', dbArtist.name);
return dbArtist;
}
console.log('Creating artist', JSON.stringify(externalArtist, null, 2));
let artist = await prisma.artist.create({
data: {
name: externalArtist.value,
external_id: externalArtist.id,
slug: kebabCase(externalArtist.value)
},
select: {
id: true,
name: true,
slug: true,
external_id: true
}
});
console.log('Created artist', JSON.stringify(artist, null, 2));
return artist;
} catch (e) {
console.error(e);
throw new Error('Something went wrong creating Artist');
export async function createPublisher(locals: App.Locals, publisher: Publishers, externalId: string) {
if (!publisher || !externalId || externalId === '') {
error(400, 'Invalid Request');
}
}
export async function createDesigner(locals: App.Locals, externalDesigner: BggLinkDto) {
try {
let dbDesigner = await prisma.designer.findFirst({
where: {
external_id: externalDesigner.id
},
select: {
id: true,
name: true,
slug: true,
external_id: true
}
let dbExternalId = await db.query.externalIds.findFirst({
where: eq(externalIds.id, externalId),
});
if (dbDesigner) {
console.log('Designer already exists', dbDesigner.name);
return dbDesigner;
if (dbExternalId) {
const dbPublisher = await db.select().from(publishers).leftJoin(publishersToExternalIds, eq(publishersToExternalIds.externalId, externalId));
}
console.log('Creating designer', JSON.stringify(externalDesigner, null, 2));
let designer = await prisma.designer.create({
data: {
name: externalDesigner.value,
external_id: externalDesigner.id,
slug: kebabCase(externalDesigner.value)
},
select: {
let dbPublisher = await db.query.publishers.findFirst({
where: eq(publishers.external_id, externalPublisher.id),
columns: {
id: true,
name: true,
slug: true,
external_id: true
}
});
console.log('Created designer', JSON.stringify(designer, null, 2));
return designer;
} catch (e) {
console.error(e);
throw new Error('Something went wrong creating Designer');
}
}
export async function createPublisher(locals: App.Locals, externalPublisher: BggLinkDto) {
try {
let dbPublisher = await prisma.publisher.findFirst({
where: {
external_id: externalPublisher.id
},
select: {
id: true,
name: true,
slug: true,
external_id: true
with: {
publishersToExternalIds: {
columns: {
externalId: true
}
}
}
});
if (dbPublisher) {

View file

@ -98,7 +98,6 @@ export const load: PageServerLoad = async ({ fetch, url, locals }) => {
export const actions: Actions = {
// Add game to a wishlist
add: async (event) => {
const { params, locals, request } = event;
const form = await superValidate(event, modifyListGameSchema);
if (!event.locals.user) {
@ -145,14 +144,14 @@ export const actions: Actions = {
}
},
// Create new wishlist
create: async ({ params, locals, request }) => {
create: async ({ locals }) => {
if (!locals.user) {
throw fail(401);
}
return error(405, 'Method not allowed');
},
// Delete a wishlist
delete: async ({ params, locals, request }) => {
delete: async ({ locals }) => {
if (!locals.user) {
throw fail(401);
}
@ -160,14 +159,14 @@ export const actions: Actions = {
},
// Remove game from a wishlist
remove: async (event) => {
const { params, locals, request } = event;
const { locals } = event;
const form = await superValidate(event, modifyListGameSchema);
if (!locals.user) {
throw fail(401);
}
let game = await db.query.games.findFirst({
const game = await db.query.games.findFirst({
where: eq(games.id, form.data.id)
});

View file

@ -63,6 +63,19 @@ export const actions: Actions = {
return setError(form, '', 'Your username or password is incorrect.');
}
await db
.insert(collections)
.values({
user_id: user.id
})
.onConflictDoNothing();
await db
.insert(wishlists)
.values({
user_id: user.id
})
.onConflictDoNothing();
console.log('ip', locals.ip);
console.log('country', locals.country);
session = await lucia.createSession(user.id, {

View file

@ -82,8 +82,8 @@ export const actions: Actions = {
try {
session = await lucia.createSession(user[0].id, {
ip_country: event.locals.session?.ipCountry,
ip_address: event.locals.session?.ipAddress
ip_country: event.locals.ip,
ip_address: event.locals.country
});
sessionCookie = lucia.createSessionCookie(session.id);
} catch (e: any) {

View file

@ -7,7 +7,8 @@ import {
integer,
text,
index,
pgEnum
pgEnum,
primaryKey
} from 'drizzle-orm/pg-core';
import { nanoid } from 'nanoid';
import { tsvector } from './tsVector';
@ -40,8 +41,16 @@ export const users = pgTable('users', {
theme: varchar('theme', {
length: 255
}).default('system'),
created_at: timestamp('created_at').default(sql`now()`),
updated_at: timestamp('updated_at').default(sql`now()`)
created_at: timestamp('created_at', {
withTimezone: true,
mode: 'date',
precision: 6
}).default(sql`now()`),
updated_at: timestamp('updated_at', {
withTimezone: true,
mode: 'date',
precision: 6
}).default(sql`now()`)
});
export const user_relations = relations(users, ({ many }) => ({
@ -348,18 +357,28 @@ export const games = pgTable(
export type Games = InferSelectModel<typeof games>;
export const gamesToExternalIds = pgTable('games_to_external_ids', {
gameId: varchar('game_id', {
length: 255
})
.notNull()
.references(() => games.id, { onDelete: 'cascade' }),
externalId: varchar('external_id', {
length: 255
})
.notNull()
.references(() => externalIds.id, { onDelete: 'cascade' })
});
export const gamesToExternalIds = pgTable(
'games_to_external_ids',
{
gameId: varchar('game_id', {
length: 255
})
.notNull()
.references(() => games.id, { onDelete: 'restrict', onUpdate: 'cascade' }),
externalId: varchar('external_id', {
length: 255
})
.notNull()
.references(() => externalIds.id, { onDelete: 'restrict', onUpdate: 'cascade' })
},
(table) => {
return {
gamesToExternalIdsPkey: primaryKey({
columns: [table.gameId, table.externalId]
})
};
}
);
export const gameRelations = relations(games, ({ many }) => ({
categories_to_games: many(categories_to_games),
@ -378,12 +397,12 @@ export const expansions = pgTable('expansions', {
length: 255
})
.notNull()
.references(() => games.id, { onDelete: 'cascade' }),
.references(() => games.id, { onDelete: 'restrict', onUpdate: 'cascade' }),
game_id: varchar('game_id', {
length: 255
})
.notNull()
.references(() => games.id, { onDelete: 'cascade' }),
.references(() => games.id, { onDelete: 'restrict', onUpdate: 'cascade' }),
created_at: timestamp('created_at', {
withTimezone: true,
mode: 'date',
@ -396,18 +415,28 @@ export const expansions = pgTable('expansions', {
}).default(sql`now()`)
});
export const expansionsToExternalIds = pgTable('expansions_to_external_ids', {
expansionId: varchar('expansion_id', {
length: 255
})
.notNull()
.references(() => expansions.id, { onDelete: 'cascade' }),
externalId: varchar('external_id', {
length: 255
})
.notNull()
.references(() => externalIds.id, { onDelete: 'cascade' })
});
export const expansionsToExternalIds = pgTable(
'expansions_to_external_ids',
{
expansionId: varchar('expansion_id', {
length: 255
})
.notNull()
.references(() => expansions.id, { onDelete: 'restrict', onUpdate: 'cascade' }),
externalId: varchar('external_id', {
length: 255
})
.notNull()
.references(() => externalIds.id, { onDelete: 'restrict', onUpdate: 'cascade' })
},
(table) => {
return {
expansionsToExternalIdsPkey: primaryKey({
columns: [table.expansionId, table.externalId]
})
};
}
);
export const expansion_relations = relations(expansions, ({ one, many }) => ({
baseGame: one(games, {
@ -446,17 +475,25 @@ export const publishers = pgTable('publishers', {
}).default(sql`now()`)
});
export type Publishers = InferSelectModel<typeof publishers>;
export const publishersToExternalIds = pgTable('publishers_to_external_ids', {
publisherId: varchar('publisher_id', {
length: 255
})
.notNull()
.references(() => publishers.id, { onDelete: 'cascade' }),
.references(() => publishers.id, { onDelete: 'restrict', onUpdate: 'cascade' }),
externalId: varchar('external_id', {
length: 255
})
.notNull()
.references(() => externalIds.id, { onDelete: 'cascade' })
.references(() => externalIds.id, { onDelete: 'restrict', onUpdate: 'cascade' })
}, (table) => {
return {
publishersToExternalIdsPkey: primaryKey({
columns: [table.publisherId, table.externalId]
})
}
});
export const publishers_relations = relations(publishers, ({ many }) => ({
@ -494,21 +531,37 @@ export const categoriesToExternalIds = pgTable('categories_to_external_ids', {
length: 255
})
.notNull()
.references(() => categories.id, { onDelete: 'cascade' }),
.references(() => categories.id, { onDelete: 'restrict', onUpdate: 'cascade' }),
externalId: varchar('external_id', {
length: 255
})
.notNull()
.references(() => externalIds.id, { onDelete: 'cascade' })
.references(() => externalIds.id, { onDelete: 'restrict', onUpdate: 'cascade' })
}, (table) => {
return {
categoriesToExternalIdsPkey: primaryKey({
columns: [table.categoryId, table.externalId]
})
}
});
export const categories_to_games = pgTable('categories_to_games', {
category_id: varchar('category_id', {
length: 255
}),
})
.notNull()
.references(() => categories.id, { onDelete: 'restrict', onUpdate: 'cascade' }),
game_id: varchar('game_id', {
length: 255
})
.notNull()
.references(() => games.id, { onDelete: 'restrict', onUpdate: 'cascade' })
}, (table) => {
return {
categoriesToGamesPkey: primaryKey({
columns: [table.category_id, table.game_id]
})
}
});
export const categories_to_games_relations = relations(categories_to_games, ({ one }) => ({
@ -557,12 +610,18 @@ export const mechanicsToExternalIds = pgTable('mechanics_to_external_ids', {
length: 255
})
.notNull()
.references(() => mechanics.id, { onDelete: 'cascade' }),
.references(() => mechanics.id, { onDelete: 'restrict', onUpdate: 'cascade' }),
externalId: varchar('external_id', {
length: 255
})
.notNull()
.references(() => externalIds.id, { onDelete: 'cascade' })
.references(() => externalIds.id, { onDelete: 'restrict', onUpdate: 'cascade' })
}, (table) => {
return {
mechanicsToExternalIdsPkey: primaryKey({
columns: [table.mechanicId, table.externalId]
})
}
});
export const mechanic_relations = relations(mechanics, ({ many }) => ({
@ -573,10 +632,20 @@ export const mechanic_relations = relations(mechanics, ({ many }) => ({
export const mechanics_to_games = pgTable('mechanics_to_games', {
mechanic_id: varchar('mechanic_id', {
length: 255
}),
})
.notNull()
.references(() => mechanics.id, { onDelete: 'restrict', onUpdate: 'cascade' }),
game_id: varchar('game_id', {
length: 255
})
.notNull()
.references(() => games.id, { onDelete: 'restrict', onUpdate: 'cascade' })
}, (table) => {
return {
mechanicsToGamesPkey: primaryKey({
columns: [table.mechanic_id, table.game_id]
})
}
});
export const mechanics_to_games_relations = relations(mechanics_to_games, ({ one }) => ({
@ -593,10 +662,20 @@ export const mechanics_to_games_relations = relations(mechanics_to_games, ({ one
export const publishers_to_games = pgTable('publishers_to_games', {
publisher_id: varchar('publisher_id', {
length: 255
}),
})
.notNull()
.references(() => publishers.id, { onDelete: 'restrict', onUpdate: 'cascade' }),
game_id: varchar('game_id', {
length: 255
})
.notNull()
.references(() => games.id, { onDelete: 'restrict', onUpdate: 'cascade' })
}, (table) => {
return {
publishersToGamesPkey: primaryKey({
columns: [table.publisher_id, table.game_id]
})
}
});
export const publishers_to_games_relations = relations(publishers_to_games, ({ one }) => ({