diff --git a/lib/prisma.ts b/lib/prisma.ts index b20a1b48..5d75ada2 100644 --- a/lib/prisma.ts +++ b/lib/prisma.ts @@ -12,16 +12,25 @@ if (process.env.NODE_ENV === "production") { prisma = globalAny.prisma; } +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( - (select: { [string]: boolean }, attr: string) => ({ - ...select, - [attr]: true, - }), - {} - ), + select: pluckedAttributes.reduce(pluck, {}), }); export { whereAndSelect }; diff --git a/test/lib/prisma.test.ts b/test/lib/prisma.test.ts new file mode 100644 index 00000000..45c34398 --- /dev/null +++ b/test/lib/prisma.test.ts @@ -0,0 +1,101 @@ + +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", + ]) +});