Restructure codebase to use src directory

This commit is contained in:
Aaron William Po
2023-04-11 23:32:06 -04:00
parent 90f2cc2c0c
commit 08422fe24e
141 changed files with 6 additions and 4 deletions

18
src/prisma/DBClient.ts Normal file
View File

@@ -0,0 +1,18 @@
import { PrismaClient } from '@prisma/client';
import { NODE_ENV } from '@/config/env';
const globalForPrisma = global as unknown as { prisma: PrismaClient };
const DBClient = {
instance:
globalForPrisma.prisma ||
new PrismaClient({
log: ['info', 'warn'],
}),
};
if (NODE_ENV !== 'production') {
globalForPrisma.prisma = DBClient.instance;
}
export default DBClient;

1
src/prisma/ERD.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 104 KiB

View File

@@ -0,0 +1,171 @@
-- CreateTable
CREATE TABLE "User" (
"id" STRING NOT NULL,
"username" STRING NOT NULL,
"firstName" STRING NOT NULL,
"lastName" STRING NOT NULL,
"hash" STRING NOT NULL,
"email" STRING NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
"isAccountVerified" BOOL NOT NULL DEFAULT false,
"dateOfBirth" TIMESTAMP(3) NOT NULL,
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "BeerPost" (
"id" STRING NOT NULL,
"name" STRING NOT NULL,
"ibu" FLOAT8 NOT NULL,
"abv" FLOAT8 NOT NULL,
"description" STRING NOT NULL,
"postedById" STRING NOT NULL,
"breweryId" STRING NOT NULL,
"typeId" STRING NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
CONSTRAINT "BeerPost_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "BeerPostLike" (
"id" STRING NOT NULL,
"beerPostId" STRING NOT NULL,
"likedById" STRING NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
CONSTRAINT "BeerPostLike_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "BeerComment" (
"id" STRING NOT NULL,
"rating" INT4 NOT NULL,
"beerPostId" STRING NOT NULL,
"postedById" STRING NOT NULL,
"content" STRING NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
CONSTRAINT "BeerComment_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "BeerType" (
"id" STRING NOT NULL,
"name" STRING NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
"postedById" STRING NOT NULL,
CONSTRAINT "BeerType_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "BreweryPost" (
"id" STRING NOT NULL,
"name" STRING NOT NULL,
"location" STRING NOT NULL,
"description" STRING NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
"postedById" STRING NOT NULL,
CONSTRAINT "BreweryPost_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "BreweryComment" (
"id" STRING NOT NULL,
"rating" INT4 NOT NULL,
"breweryPostId" STRING NOT NULL,
"postedById" STRING NOT NULL,
"content" STRING NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
CONSTRAINT "BreweryComment_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "BeerImage" (
"id" STRING NOT NULL,
"beerPostId" STRING NOT NULL,
"path" STRING NOT NULL,
"alt" STRING NOT NULL,
"caption" STRING NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
"postedById" STRING NOT NULL,
CONSTRAINT "BeerImage_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "BreweryImage" (
"id" STRING NOT NULL,
"breweryPostId" STRING NOT NULL,
"path" STRING NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3),
"caption" STRING NOT NULL,
"alt" STRING NOT NULL,
"postedById" STRING NOT NULL,
CONSTRAINT "BreweryImage_pkey" PRIMARY KEY ("id")
);
-- CreateIndex
CREATE UNIQUE INDEX "User_username_key" ON "User"("username");
-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
-- AddForeignKey
ALTER TABLE "BeerPost" ADD CONSTRAINT "BeerPost_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BeerPost" ADD CONSTRAINT "BeerPost_breweryId_fkey" FOREIGN KEY ("breweryId") REFERENCES "BreweryPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BeerPost" ADD CONSTRAINT "BeerPost_typeId_fkey" FOREIGN KEY ("typeId") REFERENCES "BeerType"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BeerPostLike" ADD CONSTRAINT "BeerPostLike_beerPostId_fkey" FOREIGN KEY ("beerPostId") REFERENCES "BeerPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BeerPostLike" ADD CONSTRAINT "BeerPostLike_likedById_fkey" FOREIGN KEY ("likedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BeerComment" ADD CONSTRAINT "BeerComment_beerPostId_fkey" FOREIGN KEY ("beerPostId") REFERENCES "BeerPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BeerComment" ADD CONSTRAINT "BeerComment_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BeerType" ADD CONSTRAINT "BeerType_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BreweryPost" ADD CONSTRAINT "BreweryPost_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BreweryComment" ADD CONSTRAINT "BreweryComment_breweryPostId_fkey" FOREIGN KEY ("breweryPostId") REFERENCES "BreweryPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BreweryComment" ADD CONSTRAINT "BreweryComment_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BeerImage" ADD CONSTRAINT "BeerImage_beerPostId_fkey" FOREIGN KEY ("beerPostId") REFERENCES "BeerPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BeerImage" ADD CONSTRAINT "BeerImage_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BreweryImage" ADD CONSTRAINT "BreweryImage_breweryPostId_fkey" FOREIGN KEY ("breweryPostId") REFERENCES "BreweryPost"("id") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "BreweryImage" ADD CONSTRAINT "BreweryImage_postedById_fkey" FOREIGN KEY ("postedById") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "cockroachdb"

135
src/prisma/schema.prisma Normal file
View File

@@ -0,0 +1,135 @@
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "cockroachdb"
url = env("DATABASE_URL")
}
model User {
id String @id @default(uuid())
username String @unique
firstName String
lastName String
hash String
email String @unique
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime? @updatedAt @db.Timestamptz(3)
isAccountVerified Boolean @default(false)
dateOfBirth DateTime
beerPosts BeerPost[]
beerTypes BeerType[]
breweryPosts BreweryPost[]
beerComments BeerComment[]
breweryComments BreweryComment[]
BeerPostLikes BeerPostLike[]
BeerImage BeerImage[]
BreweryImage BreweryImage[]
}
model BeerPost {
id String @id @default(uuid())
name String
ibu Float
abv Float
description String
postedBy User @relation(fields: [postedById], references: [id], onDelete: Cascade)
postedById String
brewery BreweryPost @relation(fields: [breweryId], references: [id], onDelete: Cascade)
breweryId String
type BeerType @relation(fields: [typeId], references: [id], onDelete: Cascade)
typeId String
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime? @updatedAt @db.Timestamptz(3)
beerComments BeerComment[]
beerImages BeerImage[]
BeerPostLikes BeerPostLike[]
}
model BeerPostLike {
id String @id @default(uuid())
beerPost BeerPost @relation(fields: [beerPostId], references: [id], onDelete: Cascade)
beerPostId String
likedBy User @relation(fields: [likedById], references: [id], onDelete: Cascade)
likedById String
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime? @updatedAt @db.Timestamptz(3)
}
model BeerComment {
id String @id @default(uuid())
rating Int
beerPost BeerPost @relation(fields: [beerPostId], references: [id], onDelete: Cascade)
beerPostId String
postedBy User @relation(fields: [postedById], references: [id], onDelete: Cascade)
postedById String
content String
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime? @updatedAt @db.Timestamptz(3)
}
model BeerType {
id String @id @default(uuid())
name String
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime? @updatedAt @db.Timestamptz(3)
postedBy User @relation(fields: [postedById], references: [id], onDelete: Cascade)
postedById String
beerPosts BeerPost[]
}
model BreweryPost {
id String @id @default(uuid())
name String
location String
beers BeerPost[]
description String
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime? @updatedAt @db.Timestamptz(3)
postedBy User @relation(fields: [postedById], references: [id], onDelete: Cascade)
postedById String
breweryComments BreweryComment[]
breweryImages BreweryImage[]
}
model BreweryComment {
id String @id @default(uuid())
rating Int
breweryPost BreweryPost @relation(fields: [breweryPostId], references: [id], onDelete: Cascade)
breweryPostId String
postedBy User @relation(fields: [postedById], references: [id], onDelete: Cascade)
postedById String
content String
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime? @updatedAt @db.Timestamptz(3)
}
model BeerImage {
id String @id @default(uuid())
beerPost BeerPost @relation(fields: [beerPostId], references: [id], onDelete: Cascade)
beerPostId String
path String
alt String
caption String
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime? @updatedAt @db.Timestamptz(3)
postedBy User @relation(fields: [postedById], references: [id], onDelete: Cascade)
postedById String
}
model BreweryImage {
id String @id @default(uuid())
breweryPost BreweryPost @relation(fields: [breweryPostId], references: [id], onDelete: Cascade)
breweryPostId String
path String
createdAt DateTime @default(now()) @db.Timestamptz(3)
updatedAt DateTime? @updatedAt @db.Timestamptz(3)
caption String
alt String
postedBy User @relation(fields: [postedById], references: [id], onDelete: Cascade)
postedById String
}

View File

@@ -0,0 +1,18 @@
import DBClient from '../../DBClient';
const cleanDatabase = async () => {
const prisma = DBClient.instance;
await prisma.$executeRaw`TRUNCATE TABLE "User" CASCADE`;
await prisma.$executeRaw`TRUNCATE TABLE "BeerPost" CASCADE`;
await prisma.$executeRaw`TRUNCATE TABLE "BeerType" CASCADE`;
await prisma.$executeRaw`TRUNCATE TABLE "BreweryPost" CASCADE`;
await prisma.$executeRaw`TRUNCATE TABLE "BeerComment" CASCADE`;
await prisma.$executeRaw`TRUNCATE TABLE "BreweryComment" CASCADE`;
await prisma.$executeRaw`TRUNCATE TABLE "BeerPostLike" CASCADE`;
await prisma.$executeRaw`TRUNCATE TABLE "BeerImage" CASCADE`;
await prisma.$executeRaw`TRUNCATE TABLE "BreweryImage" CASCADE`;
await prisma.$disconnect();
};
export default cleanDatabase;

View File

@@ -0,0 +1,43 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { faker } from '@faker-js/faker';
import { BeerPost, BeerImage, User } from '@prisma/client';
import DBClient from '../../DBClient';
interface CreateNewBeerImagesArgs {
numberOfImages: number;
joinData: { beerPosts: BeerPost[]; users: User[] };
}
const createNewBeerImages = async ({
numberOfImages,
joinData: { beerPosts, users },
}: CreateNewBeerImagesArgs) => {
const prisma = DBClient.instance;
const createdAt = faker.date.past(1);
const beerImagesPromises: Promise<BeerImage>[] = [];
// eslint-disable-next-line no-plusplus
for (let i = 0; i < numberOfImages; i++) {
const beerPost = beerPosts[Math.floor(Math.random() * beerPosts.length)];
const user = users[Math.floor(Math.random() * users.length)];
const caption = faker.lorem.sentence();
const alt = faker.lorem.sentence();
beerImagesPromises.push(
prisma.beerImage.create({
data: {
path: 'https://picsum.photos/5000/5000',
alt,
caption,
beerPost: { connect: { id: beerPost.id } },
postedBy: { connect: { id: user.id } },
createdAt,
},
}),
);
}
return Promise.all(beerImagesPromises);
};
export default createNewBeerImages;

View File

@@ -0,0 +1,42 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { faker } from '@faker-js/faker';
import { BeerComment, BeerPost, User } from '@prisma/client';
import DBClient from '../../DBClient';
interface CreateNewBeerCommentsArgs {
numberOfComments: number;
joinData: {
beerPosts: BeerPost[];
users: User[];
};
}
const createNewBeerComments = async ({
numberOfComments,
joinData,
}: CreateNewBeerCommentsArgs) => {
const { beerPosts, users } = joinData;
const prisma = DBClient.instance;
const beerCommentPromises: Promise<BeerComment>[] = [];
// eslint-disable-next-line no-plusplus
for (let i = 0; i < numberOfComments; i++) {
const content = faker.lorem.lines(5);
const user = users[Math.floor(Math.random() * users.length)];
const beerPost = beerPosts[Math.floor(Math.random() * beerPosts.length)];
const createdAt = faker.date.past(1);
beerCommentPromises.push(
prisma.beerComment.create({
data: {
content,
postedBy: { connect: { id: user.id } },
beerPost: { connect: { id: beerPost.id } },
rating: Math.floor(Math.random() * 5) + 1,
createdAt,
},
}),
);
}
return Promise.all(beerCommentPromises);
};
export default createNewBeerComments;

View File

@@ -0,0 +1,34 @@
import type { BeerPost, BeerPostLike, User } from '@prisma/client';
import DBClient from '../../DBClient';
const createNewBeerPostLikes = async ({
joinData: { beerPosts, users },
numberOfLikes,
}: {
joinData: {
beerPosts: BeerPost[];
users: User[];
};
numberOfLikes: number;
}) => {
const beerPostLikePromises: Promise<BeerPostLike>[] = [];
// eslint-disable-next-line no-plusplus
for (let i = 0; i < numberOfLikes; i++) {
const beerPost = beerPosts[Math.floor(Math.random() * beerPosts.length)];
const user = users[Math.floor(Math.random() * users.length)];
beerPostLikePromises.push(
DBClient.instance.beerPostLike.create({
data: {
beerPost: { connect: { id: beerPost.id } },
likedBy: { connect: { id: user.id } },
},
}),
);
}
return Promise.all(beerPostLikePromises);
};
export default createNewBeerPostLikes;

View File

@@ -0,0 +1,47 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { faker } from '@faker-js/faker';
import { User, BeerType, BreweryPost } from '@prisma/client';
import DBClient from '../../DBClient';
interface CreateNewBeerPostsArgs {
numberOfPosts: number;
joinData: {
users: User[];
breweryPosts: BreweryPost[];
beerTypes: BeerType[];
};
}
const createNewBeerPosts = async ({
numberOfPosts,
joinData,
}: CreateNewBeerPostsArgs) => {
const { users, breweryPosts, beerTypes } = joinData;
const prisma = DBClient.instance;
const beerPostPromises = [];
// eslint-disable-next-line no-plusplus
for (let i = 0; i < numberOfPosts; i++) {
const user = users[Math.floor(Math.random() * users.length)];
const beerType = beerTypes[Math.floor(Math.random() * beerTypes.length)];
const breweryPost = breweryPosts[Math.floor(Math.random() * breweryPosts.length)];
const createdAt = faker.date.past(1);
beerPostPromises.push(
prisma.beerPost.create({
data: {
abv: Math.floor(Math.random() * (12 - 4) + 4),
ibu: Math.floor(Math.random() * (60 - 10) + 10),
name: faker.commerce.productName(),
description: faker.lorem.lines(12).replace(/(\r\n|\n|\r)/gm, ' '),
brewery: { connect: { id: breweryPost.id } },
postedBy: { connect: { id: user.id } },
type: { connect: { id: beerType.id } },
createdAt,
},
}),
);
}
return Promise.all(beerPostPromises);
};
export default createNewBeerPosts;

View File

@@ -0,0 +1,52 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { faker } from '@faker-js/faker';
import { User, BeerType } from '@prisma/client';
import DBClient from '../../DBClient';
interface CreateNewBeerTypesArgs {
joinData: {
users: User[];
};
}
const createNewBeerTypes = async ({ joinData }: CreateNewBeerTypesArgs) => {
const { users } = joinData;
const prisma = DBClient.instance;
const beerTypePromises: Promise<BeerType>[] = [];
const types = [
'IPA',
'Pilsner',
'Stout',
'Lager',
'Wheat Beer',
'Belgian Ale',
'Pale Ale',
'Brown Ale',
'Sour Beer',
'Porter',
'Bock',
'Rauchbier',
'Sasion',
'Kolsch',
'Helles',
'Weizenbock',
'Doppelbock',
'Eisbock',
'Barley Wine',
];
types.forEach((type) => {
const user = users[Math.floor(Math.random() * users.length)];
const createdAt = faker.date.past(1);
beerTypePromises.push(
prisma.beerType.create({
data: { name: type, postedBy: { connect: { id: user.id } }, createdAt },
}),
);
});
return Promise.all(beerTypePromises);
};
export default createNewBeerTypes;

View File

@@ -0,0 +1,44 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { faker } from '@faker-js/faker';
import { BreweryPost, BreweryImage, User } from '@prisma/client';
import DBClient from '../../DBClient';
interface CreateBreweryImagesArgs {
numberOfImages: number;
joinData: {
breweryPosts: BreweryPost[];
users: User[];
};
}
const createNewBreweryImages = async ({
numberOfImages,
joinData: { breweryPosts, users },
}: CreateBreweryImagesArgs) => {
const prisma = DBClient.instance;
const createdAt = faker.date.past(1);
const breweryImagesPromises: Promise<BreweryImage>[] = [];
// eslint-disable-next-line no-plusplus
for (let i = 0; i < numberOfImages; i++) {
const breweryPost = breweryPosts[Math.floor(Math.random() * breweryPosts.length)];
const user = users[Math.floor(Math.random() * users.length)];
breweryImagesPromises.push(
prisma.breweryImage.create({
data: {
path: 'https://picsum.photos/5000/5000',
alt: 'Placeholder brewery image.',
caption: 'Placeholder brewery image caption.',
breweryPost: { connect: { id: breweryPost.id } },
postedBy: { connect: { id: user.id } },
createdAt,
},
}),
);
}
return Promise.all(breweryImagesPromises);
};
export default createNewBreweryImages;

View File

@@ -0,0 +1,42 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { faker } from '@faker-js/faker';
import { BreweryComment, BreweryPost, User } from '@prisma/client';
import DBClient from '../../DBClient';
interface CreateNewBreweryPostCommentsArgs {
numberOfComments: number;
joinData: {
breweryPosts: BreweryPost[];
users: User[];
};
}
const createNewBreweryPostComments = async ({
numberOfComments,
joinData,
}: CreateNewBreweryPostCommentsArgs) => {
const { breweryPosts, users } = joinData;
const prisma = DBClient.instance;
const breweryCommentPromises: Promise<BreweryComment>[] = [];
const createdAt = faker.date.past(1);
// eslint-disable-next-line no-plusplus
for (let i = 0; i < numberOfComments; i++) {
const content = faker.lorem.lines(5);
const user = users[Math.floor(Math.random() * users.length)];
const breweryPost = breweryPosts[Math.floor(Math.random() * breweryPosts.length)];
breweryCommentPromises.push(
prisma.breweryComment.create({
data: {
content,
postedBy: { connect: { id: user.id } },
breweryPost: { connect: { id: breweryPost.id } },
rating: Math.floor(Math.random() * 5) + 1,
createdAt,
},
}),
);
}
return Promise.all(breweryCommentPromises);
};
export default createNewBreweryPostComments;

View File

@@ -0,0 +1,42 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import { faker } from '@faker-js/faker';
import { User } from '@prisma/client';
import DBClient from '../../DBClient';
interface CreateNewBreweryPostsArgs {
numberOfPosts: number;
joinData: {
users: User[];
};
}
const createNewBreweryPosts = async ({
numberOfPosts,
joinData,
}: CreateNewBreweryPostsArgs) => {
const { users } = joinData;
const prisma = DBClient.instance;
const breweryPromises = [];
// eslint-disable-next-line no-plusplus
for (let i = 0; i < numberOfPosts; i++) {
const name = `${faker.commerce.productName()} Brewing Company`;
const location = faker.address.cityName();
const description = faker.lorem.lines(5);
const user = users[Math.floor(Math.random() * users.length)];
const createdAt = faker.date.past(1);
breweryPromises.push(
prisma.breweryPost.create({
data: {
name,
location,
description,
postedBy: { connect: { id: user.id } },
createdAt,
},
}),
);
}
return Promise.all(breweryPromises);
};
export default createNewBreweryPosts;

View File

@@ -0,0 +1,47 @@
import argon2 from 'argon2';
// eslint-disable-next-line import/no-extraneous-dependencies
import { faker } from '@faker-js/faker';
import crypto from 'crypto';
import DBClient from '../../DBClient';
interface CreateNewUsersArgs {
numberOfUsers: number;
}
const createNewUsers = async ({ numberOfUsers }: CreateNewUsersArgs) => {
const prisma = DBClient.instance;
const userPromises = [];
const hashedPasswords = await Promise.all(
Array.from({ length: numberOfUsers }, () => argon2.hash(faker.internet.password())),
);
// eslint-disable-next-line no-plusplus
for (let i = 0; i < numberOfUsers; i++) {
const randomValue = crypto.randomBytes(10).toString('hex');
const firstName = faker.name.firstName();
const lastName = faker.name.lastName();
const username = `${firstName[0]}.${lastName}.${randomValue}`;
const email = faker.internet.email(firstName, randomValue, 'example.com');
const hash = hashedPasswords[i];
const dateOfBirth = faker.date.birthdate({ mode: 'age', min: 19 });
const createdAt = faker.date.past(1);
userPromises.push(
prisma.user.create({
data: {
firstName,
lastName,
email,
username,
dateOfBirth,
createdAt,
hash,
},
}),
);
}
return Promise.all(userPromises);
};
export default createNewUsers;

90
src/prisma/seed/index.ts Normal file
View File

@@ -0,0 +1,90 @@
import { performance } from 'perf_hooks';
import logger from '../../config/pino/logger';
import cleanDatabase from './clean/cleanDatabase';
import createNewBeerImages from './create/createNewBeerImages';
import createNewBeerPostComments from './create/createNewBeerPostComments';
import createNewBeerPostLikes from './create/createNewBeerPostLikes';
import createNewBeerPosts from './create/createNewBeerPosts';
import createNewBeerTypes from './create/createNewBeerTypes';
import createNewBreweryImages from './create/createNewBreweryImages';
import createNewBreweryPostComments from './create/createNewBreweryPostComments';
import createNewBreweryPosts from './create/createNewBreweryPosts';
import createNewUsers from './create/createNewUsers';
(async () => {
try {
const start = performance.now();
logger.info('Clearing database.');
await cleanDatabase();
logger.info('Database cleared successfully, preparing to seed.');
const users = await createNewUsers({ numberOfUsers: 1000 });
const [breweryPosts, beerTypes] = await Promise.all([
createNewBreweryPosts({ numberOfPosts: 100, joinData: { users } }),
createNewBeerTypes({ joinData: { users } }),
]);
const beerPosts = await createNewBeerPosts({
numberOfPosts: 200,
joinData: { breweryPosts, beerTypes, users },
});
const [
beerPostComments,
breweryPostComments,
beerPostLikes,
beerImages,
breweryImages,
] = await Promise.all([
createNewBeerPostComments({
numberOfComments: 45000,
joinData: { beerPosts, users },
}),
createNewBreweryPostComments({
numberOfComments: 45000,
joinData: { breweryPosts, users },
}),
createNewBeerPostLikes({
numberOfLikes: 10000,
joinData: { beerPosts, users },
}),
createNewBeerImages({
numberOfImages: 1000,
joinData: { beerPosts, users },
}),
createNewBreweryImages({
numberOfImages: 1000,
joinData: { breweryPosts, users },
}),
]);
const end = performance.now();
const timeElapsed = (end - start) / 1000;
logger.info('Database seeded successfully.');
logger.info({
numberOfUsers: users.length,
numberOfBreweryPosts: breweryPosts.length,
numberOfBeerPosts: beerPosts.length,
numberOfBeerTypes: beerTypes.length,
numberOfBeerPostLikes: beerPostLikes.length,
numberOfBeerPostComments: beerPostComments.length,
numberOfBreweryPostComments: breweryPostComments.length,
numberOfBeerImages: beerImages.length,
numberOfBreweryImages: breweryImages.length,
});
logger.info(`Database seeded in ${timeElapsed.toFixed(2)} seconds.`);
process.exit(0);
} catch (error) {
logger.error('Error seeding database.');
logger.error(error);
process.exit(1);
}
})();