diff --git a/lib/prisma.ts b/lib/prisma.ts index 4d3f8470..5d75ada2 100644 --- a/lib/prisma.ts +++ b/lib/prisma.ts @@ -1,9 +1,9 @@ -import { PrismaClient } from '@prisma/client'; +import { PrismaClient } from "@prisma/client"; let prisma: PrismaClient; -const globalAny:any = global; +const globalAny: any = global; -if (process.env.NODE_ENV === 'production') { +if (process.env.NODE_ENV === "production") { prisma = new PrismaClient(); } else { if (!globalAny.prisma) { @@ -12,4 +12,27 @@ if (process.env.NODE_ENV === 'production') { prisma = globalAny.prisma; } -export default prisma; \ No newline at end of file +const pluck = (select: Record, attr: string) => { + const parts = attr.split("."); + const alwaysAttr = parts[0]; + const pluckedValue = + parts.length > 1 + ? { + select: pluck(select[alwaysAttr] ? select[alwaysAttr].select : {}, parts.slice(1).join(".")), + } + : true; + return { + ...select, + [alwaysAttr]: pluckedValue, + }; +}; + +const whereAndSelect = (modelQuery, criteria: Record, pluckedAttributes: string[]) => + modelQuery({ + where: criteria, + select: pluckedAttributes.reduce(pluck, {}), + }); + +export { whereAndSelect }; + +export default prisma; diff --git a/package.json b/package.json index b0ac1af3..4b8836be 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "dev": "next dev", - "test": "node --experimental-vm-modules node_modules/.bin/jest", + "test": "node node_modules/.bin/jest", "build": "next build", "start": "next start", "postinstall": "prisma generate", diff --git a/test/lib/prisma.test.ts b/test/lib/prisma.test.ts new file mode 100644 index 00000000..b2164ffd --- /dev/null +++ b/test/lib/prisma.test.ts @@ -0,0 +1,109 @@ + +import { it, expect } from '@jest/globals'; +import { whereAndSelect } from "@lib/prisma"; + +it("can decorate using whereAndSelect", async () => { + whereAndSelect( + (queryObj) => { + expect(queryObj).toStrictEqual({ where: { id: 1 }, select: { example: true } }); + }, + { id: 1 }, + [ + "example", + ] + ); +}); + +it("can do nested selects using . seperator", async () => { + + whereAndSelect( + (queryObj) => { + expect(queryObj).toStrictEqual({ + where: { + uid: 1, + }, + select: { + description: true, + attendees: { + select: { + email: true, + name: true, + }, + }, + }, + }); + }, + { uid: 1 }, + [ + "description", + "attendees.email", + "attendees.name", + ] + ); +}); + +it("can handle nesting deeply", async () => { + whereAndSelect( + (queryObj) => { + expect(queryObj).toStrictEqual({ + where: { + uid: 1, + }, + select: { + description: true, + attendees: { + select: { + email: { + select: { + nested: true, + } + }, + name: true, + }, + }, + }, + }); + }, + { uid: 1 }, + [ + "description", + "attendees.email.nested", + "attendees.name", + ] + ); +}); + +it("can handle nesting multiple", async () => { + whereAndSelect( + (queryObj) => { + expect(queryObj).toStrictEqual({ + where: { + uid: 1, + }, + select: { + description: true, + attendees: { + select: { + email: true, + name: true, + }, + }, + bookings: { + select: { + id: true, + name: true, + } + } + } + }); + }, + { uid: 1 }, + [ + "description", + "attendees.email", + "attendees.name", + "bookings.id", + "bookings.name", + ] + ); +});