diff --git a/prisma/migrations/20230914194400_init/migration.sql b/prisma/migrations/20230914194400_init/migration.sql index 5ee0147e9..6349954e9 100644 --- a/prisma/migrations/20230914194400_init/migration.sql +++ b/prisma/migrations/20230914194400_init/migration.sql @@ -173,53 +173,6 @@ CREATE INDEX "_RoleToUser_B_index" ON "_RoleToUser"("B"); -- Hey there, Kent here! This is how you can reliably seed your database with -- some data. You edit the migration.sql file and that will handle it for you. --- The user Roles and Permissions are seeded here. --- If you'd like to customise roles and permissions, you can edit and add the code below to your `prisma/seed.ts` file. --- Seed your development database with `npx prisma db seed` --- Create a sql dump of your database with `sqlite3 prisma/data.db .dump > seed.sql` --- Replace the SQL below with your new Roles & Permissions related SQL from `seed.sql` - --- console.time('๐Ÿ”‘ Created permissions...') --- const entities = ['user', 'note'] --- const actions = ['create', 'read', 'update', 'delete'] --- const accesses = ['own', 'any'] as const - --- let permissionsToCreate = [] --- for (const entity of entities) { --- for (const action of actions) { --- for (const access of accesses) { --- permissionsToCreate.push({ entity, action, access }) --- } --- } --- } --- await prisma.permission.createMany({ data: permissionsToCreate }) --- console.timeEnd('๐Ÿ”‘ Created permissions...') - --- console.time('๐Ÿ‘‘ Created roles...') --- await prisma.role.create({ --- data: { --- name: 'admin', --- permissions: { --- connect: await prisma.permission.findMany({ --- select: { id: true }, --- where: { access: 'any' }, --- }), --- }, --- }, --- }) --- await prisma.role.create({ --- data: { --- name: 'user', --- permissions: { --- connect: await prisma.permission.findMany({ --- select: { id: true }, --- where: { access: 'own' }, --- }), --- }, --- }, --- }) --- console.timeEnd('๐Ÿ‘‘ Created roles...') - INSERT INTO Permission VALUES('clnf2zvli0000pcou3zzzzome','create','user','own','',1696625465526,1696625465526); INSERT INTO Permission VALUES('clnf2zvll0001pcouly1310ku','create','user','any','',1696625465529,1696625465529); INSERT INTO Permission VALUES('clnf2zvll0002pcouka7348re','read','user','own','',1696625465530,1696625465530); @@ -255,4 +208,4 @@ INSERT INTO _PermissionToRole VALUES('clnf2zvlo0006pcouyoptc5jp','clnf2zvlx000hp INSERT INTO _PermissionToRole VALUES('clnf2zvlp0008pcou9r0fhbm8','clnf2zvlx000hpcou5dfrbegs'); INSERT INTO _PermissionToRole VALUES('clnf2zvlq000apcouxnspejs9','clnf2zvlx000hpcou5dfrbegs'); INSERT INTO _PermissionToRole VALUES('clnf2zvlr000cpcouy1vp6oeg','clnf2zvlx000hpcou5dfrbegs'); -INSERT INTO _PermissionToRole VALUES('clnf2zvls000epcou4ts5ui8f','clnf2zvlx000hpcou5dfrbegs'); +INSERT INTO _PermissionToRole VALUES('clnf2zvls000epcou4ts5ui8f','clnf2zvlx000hpcou5dfrbegs'); \ No newline at end of file diff --git a/prisma/seed.ts b/prisma/seed.ts index 5c59bd634..9f29df1f1 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -3,12 +3,12 @@ import { promiseHash } from 'remix-utils/promise' import { prisma } from '#app/utils/db.server.ts' import { MOCK_CODE_GITHUB } from '#app/utils/providers/constants' import { + cleanupDb, createPassword, createUser, getNoteImages, getUserImages, img, - resetDb, } from '#tests/db-utils.ts' import { insertGitHubUser } from '#tests/mocks/github.ts' @@ -17,9 +17,50 @@ async function seed() { console.time(`๐ŸŒฑ Database has been seeded`) console.time('๐Ÿงน Cleaned up the database...') - await resetDb() + await cleanupDb(prisma) console.timeEnd('๐Ÿงน Cleaned up the database...') + console.time('๐Ÿ”‘ Created permissions...') + const entities = ['user', 'note'] + const actions = ['create', 'read', 'update', 'delete'] + const accesses = ['own', 'any'] as const + + let permissionsToCreate = [] + for (const entity of entities) { + for (const action of actions) { + for (const access of accesses) { + permissionsToCreate.push({ entity, action, access }) + } + } + } + await prisma.permission.createMany({ data: permissionsToCreate }) + console.timeEnd('๐Ÿ”‘ Created permissions...') + + console.time('๐Ÿ‘‘ Created roles...') + await prisma.role.create({ + data: { + name: 'admin', + permissions: { + connect: await prisma.permission.findMany({ + select: { id: true }, + where: { access: 'any' }, + }), + }, + }, + }) + await prisma.role.create({ + data: { + name: 'user', + permissions: { + connect: await prisma.permission.findMany({ + select: { id: true }, + where: { access: 'own' }, + }), + }, + }, + }) + console.timeEnd('๐Ÿ‘‘ Created roles...') + const totalUsers = 5 console.time(`๐Ÿ‘ค Created ${totalUsers} users...`) const noteImages = await getNoteImages() diff --git a/tests/db-utils.ts b/tests/db-utils.ts index 0841c9cbf..b9bed2476 100644 --- a/tests/db-utils.ts +++ b/tests/db-utils.ts @@ -3,7 +3,6 @@ import { faker } from '@faker-js/faker' import { type PrismaClient } from '@prisma/client' import bcrypt from 'bcryptjs' import { UniqueEnforcer } from 'enforce-unique' -import { execaCommand } from 'execa' const uniqueUsernameEnforcer = new UniqueEnforcer() @@ -116,17 +115,23 @@ export async function img({ } } -export async function resetDb(dbPath?: string) { - const databaseUrl = dbPath ? { DATABASE_URL: `file:${dbPath}` } : {} +export async function cleanupDb(prisma: PrismaClient) { + const tables = await prisma.$queryRaw< + { name: string }[] + >`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '_prisma_migrations';` - await execaCommand( - 'npx prisma migrate reset --force --skip-seed --skip-generate', - { - stdio: 'inherit', - env: { - ...process.env, - ...databaseUrl, - }, - }, - ) + try { + // Disable FK constraints to avoid relation conflicts during deletion + await prisma.$executeRawUnsafe(`PRAGMA foreign_keys = OFF`) + await prisma.$transaction([ + // Delete all rows from each table, preserving table structures + ...tables.map(({ name }) => + prisma.$executeRawUnsafe(`DELETE from "${name}"`), + ), + ]) + } catch (error) { + console.error('Error cleaning up database:', error) + } finally { + await prisma.$executeRawUnsafe(`PRAGMA foreign_keys = ON`) + } } diff --git a/tests/setup/db-setup.ts b/tests/setup/db-setup.ts index 9e71d20c7..ea66e14bb 100644 --- a/tests/setup/db-setup.ts +++ b/tests/setup/db-setup.ts @@ -1,7 +1,8 @@ import path from 'node:path' import fsExtra from 'fs-extra' import { afterAll, afterEach, beforeAll } from 'vitest' -import { BASE_DATABASE_PATH, setup } from './global-setup.ts' +import { cleanupDb } from '#tests/db-utils.ts' +import { BASE_DATABASE_PATH } from './global-setup.ts' const databaseFile = `./tests/prisma/data.${process.env.VITEST_POOL_ID || 0}.db` const databasePath = path.join(process.cwd(), databaseFile) @@ -11,8 +12,11 @@ beforeAll(async () => { await fsExtra.copyFile(BASE_DATABASE_PATH, databasePath) }) +// we *must* use dynamic imports here so the process.env.DATABASE_URL is set +// before prisma is imported and initialized afterEach(async () => { - await setup() + const { prisma } = await import('#app/utils/db.server.ts') + await cleanupDb(prisma) }) afterAll(async () => { diff --git a/tests/setup/global-setup.ts b/tests/setup/global-setup.ts index 6ec2745e9..af7fe31e7 100644 --- a/tests/setup/global-setup.ts +++ b/tests/setup/global-setup.ts @@ -1,6 +1,6 @@ import path from 'node:path' +import { execaCommand } from 'execa' import fsExtra from 'fs-extra' -import { resetDb } from '#tests/db-utils.js' export const BASE_DATABASE_PATH = path.join( process.cwd(), @@ -22,5 +22,14 @@ export async function setup() { } } - await resetDb(BASE_DATABASE_PATH) + await execaCommand( + 'npx prisma migrate reset --force --skip-seed --skip-generate', + { + stdio: 'inherit', + env: { + ...process.env, + DATABASE_URL: `file:${BASE_DATABASE_PATH}`, + }, + }, + ) }