Skip to content

Commit bc255ca

Browse files
committed
fix(db): address PR #208 review issues
- Add Prisma middleware to auto-generate NanoID for missing IDs on create - Add foreign key relation from Consumption.courseId to Course - Update mock builders to use generateId() instead of faker UUID - Update testing principles docs to use NanoID examples
1 parent 2202b00 commit bc255ca

6 files changed

Lines changed: 58 additions & 13 deletions

File tree

app/components/__tests__/transaction-item.test.tsx

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
1-
import { build, fake, oneOf } from '@jackfranklin/test-data-bot'
1+
import { build, fake, oneOf, perBuild } from '@jackfranklin/test-data-bot'
22
import { screen } from '@testing-library/react'
33
import { TransactionItem, TransactionItemProps } from '../transaction-item'
44
import { render } from '#test/test-utils'
55
import { printLocaleDateTimeString } from '~/utils/format'
66
import { TRANSACTION_STATUS } from '~/models/enum'
7+
import { generateId } from '~/utils/nanoid'
78

89
const transactionItemBuilder = build<TransactionItemProps>('TransactionItem', {
910
fields: {
10-
to: fake(
11-
(f) =>
12-
`${f.datatype.uuid()}?status=${oneOf(
13-
TRANSACTION_STATUS
14-
)}&page=${f.datatype.number()}`
11+
to: perBuild(
12+
() =>
13+
`${generateId()}?status=${oneOf(TRANSACTION_STATUS)}&page=${Math.floor(
14+
Math.random() * 100
15+
)}`
1516
),
1617
bankAccountName: fake((f) => f.finance.accountName()),
1718
bankAccountNumber: fake((f) => f.finance.account()),

app/models/__mocks__/audit-log.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
import { build, fake, perBuild } from '@jackfranklin/test-data-bot'
1+
import { build, perBuild } from '@jackfranklin/test-data-bot'
22
import { AuditLog } from '@prisma/client'
33
import { AUDIT_ACTION, AUDIT_ENTITY_TYPE } from '../enum'
4+
import { generateId } from '~/utils/nanoid'
45

56
export const auditLogBuilder = build<Omit<AuditLog, 'id' | 'createdAt'>>({
67
fields: {
78
userId: null,
89
action: perBuild(() => AUDIT_ACTION.CREATE),
910
entityType: perBuild(() => AUDIT_ENTITY_TYPE.USER),
10-
entityId: fake((f) => f.datatype.uuid()),
11+
entityId: perBuild(() => generateId()),
1112
oldValue: null,
1213
newValue: null,
1314
metadata: null,
@@ -38,7 +39,7 @@ export const auditLogBuilder = build<Omit<AuditLog, 'id' | 'createdAt'>>({
3839
},
3940
withUser: {
4041
overrides: {
41-
userId: fake((f) => f.datatype.uuid()),
42+
userId: perBuild(() => generateId()),
4243
},
4344
},
4445
withMetadata: {

app/utils/db.server.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { PrismaClient } from '@prisma/client'
2+
import { generateId } from './nanoid'
23

34
let db: PrismaClient
45

@@ -7,15 +8,32 @@ declare global {
78
var __db: PrismaClient | undefined
89
}
910

11+
function createPrismaClient(): PrismaClient {
12+
const client = new PrismaClient()
13+
14+
// Middleware to auto-generate NanoID for models missing an id on create.
15+
// This serves as a safety net in case `id: generateId()` is forgotten.
16+
client.$use(async (params, next) => {
17+
if (params.action === 'create' && params.args?.data) {
18+
if (!params.args.data.id) {
19+
params.args.data.id = generateId()
20+
}
21+
}
22+
return next(params)
23+
})
24+
25+
return client
26+
}
27+
1028
// this is needed because in development we don't want to restart
1129
// the server with every change, but we want to make sure we don't
1230
// create a new connection to the DB with every change either.
1331
if (process.env.NODE_ENV === 'production') {
14-
db = new PrismaClient()
32+
db = createPrismaClient()
1533
db.$connect()
1634
} else {
1735
if (!global.__db) {
18-
global.__db = new PrismaClient()
36+
global.__db = createPrismaClient()
1937
global.__db.$connect()
2038
}
2139
db = global.__db

docs/testing-principles.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,11 +231,12 @@ test.use({
231231
For generating consistent test data, use `@jackfranklin/test-data-bot`:
232232

233233
```typescript
234-
import { build, fake } from '@jackfranklin/test-data-bot'
234+
import { build, fake, perBuild } from '@jackfranklin/test-data-bot'
235+
import { generateId } from '~/utils/nanoid'
235236

236237
const userBuilder = build('User', {
237238
fields: {
238-
id: fake((f) => f.datatype.uuid()),
239+
id: perBuild(() => generateId()),
239240
email: fake((f) => f.internet.email()),
240241
name: fake((f) => f.name.fullName()),
241242
},
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
-- RedefineTables
2+
PRAGMA defer_foreign_keys=ON;
3+
PRAGMA foreign_keys=OFF;
4+
CREATE TABLE "new_Consumption" (
5+
"id" TEXT NOT NULL PRIMARY KEY,
6+
"createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
7+
"updatedAt" DATETIME NOT NULL,
8+
"userId" TEXT NOT NULL,
9+
"contentId" TEXT NOT NULL,
10+
"courseId" TEXT NOT NULL,
11+
"progress" INTEGER NOT NULL DEFAULT 0,
12+
"status" TEXT NOT NULL DEFAULT 'PRISTINE',
13+
CONSTRAINT "Consumption_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
14+
CONSTRAINT "Consumption_contentId_fkey" FOREIGN KEY ("contentId") REFERENCES "Content" ("id") ON DELETE CASCADE ON UPDATE CASCADE,
15+
CONSTRAINT "Consumption_courseId_fkey" FOREIGN KEY ("courseId") REFERENCES "Course" ("id") ON DELETE CASCADE ON UPDATE CASCADE
16+
);
17+
INSERT INTO "new_Consumption" ("contentId", "courseId", "createdAt", "id", "progress", "status", "updatedAt", "userId") SELECT "contentId", "courseId", "createdAt", "id", "progress", "status", "updatedAt", "userId" FROM "Consumption";
18+
DROP TABLE "Consumption";
19+
ALTER TABLE "new_Consumption" RENAME TO "Consumption";
20+
CREATE UNIQUE INDEX "Consumption_userId_contentId_key" ON "Consumption"("userId", "contentId");
21+
PRAGMA foreign_keys=ON;
22+
PRAGMA defer_foreign_keys=OFF;

prisma/schema.prisma

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ model Course {
5454
transactions Transaction[]
5555
chapters Chapter[]
5656
contents Content[]
57+
consumptions Consumption[]
5758
}
5859

5960
model Transaction {
@@ -139,6 +140,7 @@ model Consumption {
139140
status String @default("PRISTINE")
140141
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
141142
content Content @relation(fields: [contentId], references: [id], onDelete: Cascade)
143+
course Course @relation(fields: [courseId], references: [id], onDelete: Cascade)
142144
143145
@@unique([userId, contentId])
144146
}

0 commit comments

Comments
 (0)