prisma-query
convert query params to prisma args
Rest Api Format
REST API should based on JSON Server Project.
query params provided via rest api need to be compatible with the REST rules and methods of the JSON Server.
For more info visit json-server npm package https://www.npmjs.com/package/json-server
Usage
processFindAllQuery
import { processFindAllQuery } from 'prisma-query';
const req = {
query: {
_sort: 'likes',
_expand: 'comments',
_page: '9',
_limit: '10',
},
};
const args = processFindAllQuery(req.query);
console.log(args);
const posts = await prismaClient.posts.findMany(args);
processFindOneQuery
import { processFindOneQuery } from 'prisma-query';
const req = {
query: { _expand: 'comments', 'comments.user.name': 'justin' },
};
const args = processFindOneQuery(req.query);
console.log(JSON.stringify(args, null, 2));
const post = await prismaClient.post.findUnique(args);
QueryModifier
when passing numeric values in query, distinction can't be made between numeric or string values, we have two ways to solve for this
First ->
in case of number, we can wrap the value in num() function like ?id=num(12)
in case of boolean, we can wrap the value in bool() function like ?vip=bool(true)
Second ->
we can define queryModifier for the model and pass it as second argument of processFindAllQuery or processFindOneQuery
NOTE: this will work only for first level, for filters in nested models wrapping with num() and bool() is necessary
import { processFindAllQuery, QueryModifier } from 'prisma-query';
export type Guest = {
id: number;
fans: number;
name: string;
vip: boolean;
eventId: number;
eventSignupId: number | null;
createdAt: Date;
updatedAt: Date;
};
const guestQueryModifier: QueryModifier<Guest> = {
numericValues: ['id', 'fans', 'eventId', 'eventSignupId'],
booleanValues: ['vip'],
};
const req = {
query: {
eventId: '1',
fans_gt: '1000',
vip: 'true',
'eventSignup.verified': 'bool(true)',
_expand: 'events',
'events.attendees_gt': 'num(1000)',
},
};
const args = processFindAllQuery(req.query, guestQueryModifier);
console.log(JSON.stringify(args, null, 2));
Examples
const routeToFindManyArgs = {
'/events?id=6&id=7': { where: { id: { in: [6, 7] } } },
'/events?_expand=guests&guests.name_like=John': {
include: {
guests: {
where: { name: { contains: 'John', mode: 'insensitive' } },
},
},
},
'/events?_expand=guests&guests.vip=bool(false)': {
include: { guests: { where: { vip: false } } },
},
'/events?hosts.every.name_like=Hitesh&_expand=hosts': {
where: {
hosts: { every: { name: { contains: 'Hitesh', mode: 'insensitive' } } },
},
include: {
hosts: true,
},
},
'/events?_expand=hosts&hosts.name_like=Hitesh': {
include: {
hosts: { where: { name: { contains: 'Hitesh', mode: 'insensitive' } } },
},
},
'/events?_expand=guests&guests.name_like=Rahul&guests.vip=bool(true)': {
include: {
guests: {
where: {
vip: true,
name: { contains: 'Rahul', mode: 'insensitive' },
},
},
},
},
'/guests?eventSignupId_ne=null': {
where: { eventSignupId: { not: null } },
},
'/eventCategories?_expand=events.hosts&_expand=events.eventMetadata': {
include: {
events: { include: { eventMetadata: true, hosts: true } },
},
},
'/events?_sort=startTime&_sort=id&_order=asc': {
orderBy: [{ startTime: 'asc' }, { id: 'asc' }],
},
'/events?_sort=duration,id&_order=desc': {
orderBy: [{ duration: 'desc' }, { id: 'asc' }],
},
'/guests?_page=2&_limit=5': { skip: 5, take: 5 },
'/guests?_start=0&_end=10': {
skip: 0,
take: 10,
},
'/events?_expand=guests&guests.fans_gt=num(21000)': {
include: { guests: { where: { fans: { gt: 21000 } } } },
},
'/guests?eventId=1&fans_gt=21000': {
where: { eventId: 1, fans: { gt: 21000 } },
},
};