diff --git a/prisma/migrations/20230914194400_init/migration.sql b/prisma/migrations/20230914194400_init/migration.sql index 6349954e..5ee0147e 100644 --- a/prisma/migrations/20230914194400_init/migration.sql +++ b/prisma/migrations/20230914194400_init/migration.sql @@ -173,6 +173,53 @@ 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); @@ -208,4 +255,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'); \ No newline at end of file +INSERT INTO _PermissionToRole VALUES('clnf2zvls000epcou4ts5ui8f','clnf2zvlx000hpcou5dfrbegs'); diff --git a/prisma/seed.ts b/prisma/seed.ts index 9f29df1f..f38edef3 100644 --- a/prisma/seed.ts +++ b/prisma/seed.ts @@ -17,50 +17,9 @@ async function seed() { console.time(`๐ŸŒฑ Database has been seeded`) console.time('๐Ÿงน Cleaned up the database...') - await cleanupDb(prisma) + await cleanupDb() 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 b9bed247..5264125e 100644 --- a/tests/db-utils.ts +++ b/tests/db-utils.ts @@ -1,7 +1,7 @@ import fs from 'node:fs' import { faker } from '@faker-js/faker' -import { type PrismaClient } from '@prisma/client' import bcrypt from 'bcryptjs' +import Database from 'better-sqlite3' import { UniqueEnforcer } from 'enforce-unique' const uniqueUsernameEnforcer = new UniqueEnforcer() @@ -115,23 +115,63 @@ export async function img({ } } -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';` +let _migrationSqls: Array> | undefined +async function getMigrationSqls() { + if (_migrationSqls) return _migrationSqls + + const migrationSqls: Array> = [] + const migrationPaths = (await fs.promises.readdir('prisma/migrations')) + .filter((dir) => dir !== 'migration_lock.toml') + .map((dir) => `prisma/migrations/${dir}/migration.sql`) + + for (const path of migrationPaths) { + const sql = await fs.promises.readFile(path, 'utf8') + const statements = sql + .split(';') + .map((statement) => statement.trim()) + .filter(Boolean) + migrationSqls.push(statements) + } + + _migrationSqls = migrationSqls + + return migrationSqls +} + +export async function cleanupDb() { + const db = new Database(process.env.DATABASE_URL!.replace('file:', '')) 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) + db.exec('PRAGMA foreign_keys = OFF') + + // Get all table names + const tables = db + .prepare( + ` + SELECT name FROM sqlite_master + WHERE type='table' AND name NOT LIKE 'sqlite_%' AND name NOT LIKE '_prisma_migrations' + `, + ) + .all() as { name: string }[] + + // Delete tables except the ones that are excluded above + for (const { name } of tables) { + db.exec(`DROP TABLE IF EXISTS "${name}"`) + } + + // Get migration SQLs and run each migration + const migrationSqls = await getMigrationSqls() + for (const statements of migrationSqls) { + // Run each sql statement in the migration + db.transaction(() => { + for (const statement of statements) { + db.exec(statement) + } + })() + } } finally { - await prisma.$executeRawUnsafe(`PRAGMA foreign_keys = ON`) + db.exec('PRAGMA foreign_keys = ON') + db.close() } } diff --git a/tests/setup/db-setup.ts b/tests/setup/db-setup.ts index ea66e14b..4ddaa591 100644 --- a/tests/setup/db-setup.ts +++ b/tests/setup/db-setup.ts @@ -15,8 +15,7 @@ beforeAll(async () => { // we *must* use dynamic imports here so the process.env.DATABASE_URL is set // before prisma is imported and initialized afterEach(async () => { - const { prisma } = await import('#app/utils/db.server.ts') - await cleanupDb(prisma) + await cleanupDb() }) afterAll(async () => {