Hey there. I’m building an ecommerce app using Pr...
# orm-help
w
Hey there. I’m building an ecommerce app using Prisma, which will in the end have several shops. Do you think it’d be better to gather everything on the same prisma api/db (using a
Shop
model that would have it’s own products/orders/customers etc, etc (like Shopify is doing)), or to split all shops into their own prisma/db, and when the user choose his shop (on sign-in), store a link on the
User
model that would contain let’s say the graphql-endpoint of the chosen shop ?
k
I may be wrong, but it seems like creating a separate Prisma/DB for each shop would introduce quite a lot of overhead. What would you see as benefits for that approach?
w
Completely separated data (less overhead to fetch the right data/update the right data etc, etc) + adding another shop = simply spawning a new prisma instance + better performance (because of less data stored)
I think gathering everything on the same api is the right approach, I just didn’t have that constraint at first, and that is gonna cause heavy refactoring 😭
a
Gathering everything on the same api is definitely simpler, but why did you separate them? Was anything except the data different?
I mean: there is nothing wrong (in my mind) with multiple instances of your app (one for each customer)
w
No, everything will be the same in the end, except indeed the data. Again, I just didn’t have that constraint at first, and designed everything for one shop only. By customer you mean each “shop”, or the shop customers? 🙄
a
I mean your customer (as in the "shop" )
w
I see. That customer have several shops, and users will need to be able to choose on which shop they’re willing to order. That could be an easy fix by putting ONLY the products within the
Shop
model, and then linking every Users to a Shop. I need to investigate though what will happen when users will want to switch from one shop to another 😕
a
I worked for a company where we had separate installations of the same webapp, but when the user logged on, they usually chose a "marketplace" as we called it. After authentication / authorization, we simply redirected them to the correct installation of the webapp
w
Well, that is exactly the way I saw it. The problem though, is that users aren’t shared between installations. So how do I know on which marketplace he has signed-up ?
Oh, my bad. The user choose on which marketplace he’s willing to sign-in
a
Well, you can also share users, but that is a bit more complicated
If you do that, you'd have to extract authentication/authorization from your app (which is probably a good thing)
w
But then, It’d be way easier gathering everything on the same API, and splitting things by a
Shop
model. Otherwise that means once a user will wanna switch from one shop to another, I would have to migrate all its data
h
You can just add to query shopname and you are almost gucci 🙂 I have something similar 🙂
gucci 1
Copy code
{
  products(shopName:"Prisma") {
     name
  }
}
a
But if you're gonna do that, you might as well add a context
Context meaning, the logged in user has a
shopName
set somewhere and you use that to determine what data they get. The advantage being that they can't just do a random query on a shop they shouldn't be able to access
w
What I’m gonna do: 1. Link all the Products, Brands, Options, and Orders to a Shop. 3. Set a shopId to every users so that indeed, I can get the right shop data based on the Context. This way, users data aren’t bounded to any shop.
When a user switch from one shop to another, I just update his shopId, refetch everything, and I’m good to go.
Prisma is so wonderful. Did the whole refacto using context to grab user’s
shopId
. Not entirely sure if everything’s safe yet, but refacto done, in 20mn, as I have nothing to change anywhere in my apps 😍
a
That's GraphQL in general tbh, not prisma per se
w
Knew you were gonna say that, yeah, that’s true, but changing your whole data model + updating almost 25 resolvers wouldn’t have taken so little time. With prisma it was just a matter of adding
connect: { shop: { id: shopId  }
to every
createMutations
And adding
where: { shop: { id: shopId } }
to every queries. c&p’ed everywhere and done.
a
Multiple cursors in your editor my man
Get an IDE that takes care of such things 😛
w
Well, multiple cursors don’t work across several files 😛
a
search-replace all?
w
By the way, regarding “contextual queries”. How can we add context to a sub-field of a query ? Like, The model
User
is linked to a model
Order
. When the user fetches his orders,
me { id, orders { id ... } }
, I’d like to grab only the orders made on one
Shop
without having to pass a
shopId
everytime to my queries. Is it possible this way ?
My guess is that I have to make a resolver on the
orders
field of the parent field
me
, but I’m not sure how to do that.
h
Its not possible, because you don't know what orders to filter you need to provide from what shop you want orders 🙂
w
I know that information, Users are linked to a
Shop
, so I can grab their
shopId
by querying
ctx.db.query.user({ where: { id: userId }  }, ' { shop { id } } ')
.
a
well if you know the user id
then you can also resolve the user and therefore the shop
Can't you resolve their user id from the context of the query?
w
I can do all of that
But if a apply a filter on the
me
resolver (parent of
orders
), then I have to provide a custom
info
ctx.db.query.user({ where: { id: userId }}, '{ orders(where: { shopId: userShopId }  ) })
. And I don’t want to do that, otherwise the resolver won’t return what’s queried from the clients
h
I thought user can be linked to multiple shops :X
w
Their link to
Shop
can be changed. As all my resolvers are contextual, if they wanna switch from one shop to another, I just
updateUser
and connect it to another Shop.
The only thing that really needs to be linked to a
Shop
without ever being changed, are their orders.
This way, if I want to grab the customers of a
Shop
, I look for all users that have at least one order sent to that Shop. The link between a
Shop
and a
User
could be name
selectedShop
. It’s completely changeable and not bounded forever. But because of that, when a user switch from one shop to another, I need to grab ONLY the orders sent to the
selectedShop
. Otherwise, as user can add to their cart some of their previous orders, they could potentially add some products that aren’t available on their current
selectedShop
. Hopefully I’m being clear, it’s quite tough to explain 😞
User: { async orders(parent, args, ctx: Context, info) { const userId = getUserId(ctx); const shopId = await getShopId(ctx); return ctx.db.query.orders({ where: { owner: { id: userId }, receiver: { id: shopId } } }, info) } } ^ This is what I was looking for. Hooking into the
orders
sub-field of the model
User