import { PrismaClient } from '.prisma/client';
const prisma = new PrismaClient();
prisma.$use(async (params, next) => {
if (hasUndefinedValue(params.args?.where))
throw new Error(
`Invalid where: ${JSON.stringify(params.args.where)}`
return await next(params);
});
export default prisma;
function hasUndefinedValue<T>(obj: T): boolean {
if (typeof obj !== 'object' || obj === null) return false;
for (const key in obj) {
if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
const value = obj[key];
if (value === undefined) return true;
if (typeof value === 'object' && !Array.isArray(value))
if (hasUndefinedValue(value)) return true;
return false;
Then you could export and use the prismaClient
instance as usual. It will also be better to have the test case to verify the middleware is working fine:
describe('with undefined', () => {
it('should throw Error', async () => {
const error = new Error('Invalid where: {}');
await expect(
prisma.user.findUnique({ where: { email: undefined } })
).rejects.toThrow(error);
});
});
Hope this help somebody!
This is sorta weird Prisma behavior, if the main attribute of the where
clause is `undefined` in a `findFirst` query, it will exclude that
condition and then it is just going to grab the first row from the table
and return that. prisma/prisma#5149
This is sorta weird Prisma behavior, if the main attribute of the where
clause is `undefined` in a `findFirst` query, it will exclude that
condition and then it is just going to grab the first row from the table
and return that. prisma/prisma#5149
This is sorta weird Prisma behavior, if the main attribute of the where
clause is `undefined` in a `findFirst` query, it will exclude that
condition and then it is just going to grab the first row from the table
and return that. prisma/prisma#5149
* feat(commerce): move pppApplied into helper
* feat(commerce): move hasPPP check to helper
* feat(commerce): return result instead of throwing
* feat(commerce): move more PPP logic into helper
* feat(commerce): consolidate PPP logic
* cleanup(commerce): remove user purchases lookup
* feat(commerce): combine PPP formatting scenarios
* feat(commerce): move bulk coupon logic into helper
* feat(commerce): try renaming incoming coupon
The incoming `merchantCouponId` is a reference to a candidate coupon,
e.g. maybe a site-wide coupon. We may override this with a better
coupon, so we should treat it is as a candidate while we figure out what
coupon will actually be applied.
* feat(commerce): make coupon comparison more explicit
* feat(commerce): find available coupons in helper
* feat(commerce): lookup bulk coupon in helper
* cleanup(commerce): remove unused PPP percent const
* feat(commerce): apply bulk, combine conditions
* feat(commerce): tighten fixed discount logic
* feat(commerce): pull upgradeDetails logic up
* feat(commerce): collapse bulk logic into rest
* feat(commerce): collapse available PPP logic
* feat(commerce): collapse extraneous 'special' logic
The block toward the top of the price formatting that was catching a
first pass of 'special' coupon logic is now redundant with the following
logic that applies any coupons, including 'special', as needed.
* feat(commerce): remove commented error-throwing
* cleanup(commerce): clean up some comments
* cleanup(commerce): more coupon comment cleanup
* feat(commerce): reduce PPP details logic
* feat(commerce): remove unused hasPurchaseWithPPP
* feat(commerce): note future refactoring
* feat(commerce): get bulk coupon, instead of details
* feat(commerce): no need to return pppDetails
The `pppDetails` served their purpose for the refactoring, but all that
info is self-contained to the helper module and doesn't need to be
passed to the price formatter anymore.
* feat(commerce): remove coupon `code` logic branch
The `code` to `Coupon.id` look up and translation happens in the
`propsForCommerce` endpoint which then only passes along a coupon ID
after that point. There is no consumer or app of the
`formatPricesForProduct` code path that passes in a `code`.
* feat(commerce): remove last redundant price block
* fix(commerce): don't lookup coupon w/ undefined
This is sorta weird Prisma behavior, if the main attribute of the where
clause is `undefined` in a `findFirst` query, it will exclude that
condition and then it is just going to grab the first row from the table
and return that. prisma/prisma#5149
* fix(commerce): ensure PPP does not leak through
In the scenario where you had 'checked' the PPP discount box and then
changed to Team/Bulk purchase (via toggle), the applied PPP merchant
coupon would be carried over and applied as a fall-through value.
This updates the logic to ensure PPP only gets assigned via the PPP code
path and that special coupons are the ones that fall through.
* fix(commerce): remove unused var, function call
* feat(commerce): handle PPP + Bundle Upgrade
This deals with linear issue TT-331
It's a nightmare.
You need to add a huge red banner with an explanation to the documentation!
I can only imagine how many bugs appear because of this "smart" design
Hi everyone, I don't think that Prisma team (I don't work at Prisma anymore) monitors closed issues (someone from the team, please correct me if I am wrong?).
I do see that this issue is getting a lot of attention. To make progress, please create a new ticket, link it back to this one and show that a lot of community members want this changed 🙏🏼
Thank you.
No. Someone made this design decision a long time ago, we can only change it with a breaking change, and we are not eager to do that right now. We are aware it is a problem and are taking comments like these into account. But I am also aware that engaging here will not really make any of you happy, as you want to get the behavior reverted or a big red banner at the top of our docs - both which will not happen.
There also a lot of other issues about this, for example #11021 or #20169. You can leave you upvotes on these.
Appreciate the response. I figured that was the case and while not the ideal people in this thread want, I understand, because yeah.... this would be a massive breaking change. Appreciate ya chiming in here so that way in the future people at least know the current state on this from Prisma's perspective!
I still believe this is such a dangerous design: once again just imagine writing auth function that looks up user by email and hash and by accident it comes up empty. The first user is usually the admin…
It would be worth it to change it with breaking change and add configuration option to opt in to the old behavior.
It’s just dangerous and not only bad design. For now the big red alert anywhere near filters documentation should be posted.
Respectfully this is a ticking time bomb. It's a nasty post-mortem waiting to go viral on HN. We've been using Prisma for over a year at this point and have read a good chunk of this documentation. Somehow we're only learning about this behavior now. I'm guessing the same is true for a lot of other users.