Fork me on GitHub
#pathom
<
2023-01-24
>
Tommy15:01:46

How do you guys tend to write your sql queries for pathom resolvers? Something like hugsql makes sense to me, but each query behind a resolver already seems to isolate them pretty well. Honeysql for dynamically creating queries, but I don't ever find that to be necesary (in simple cases), and you also risk it's DSL having a a gap where you have to peer behind the curtain (it does seem that it is fairly comprehensive though). I think im leaning towards hugsql because my data definitions are in .sql files as migrations, so I like the symmetry of queries in .sql files

danieroux16:01:40

HugSQL, and https://pathom3.wsscode.com/docs/resolvers/#batch-resolvers to minimise the queries is working well for us

👍 2
J17:01:20

Yeah same a @U9E8C7QRJ with use batch-resolvers a lot. We have hugsql queries but we want to migrate into honeysql (it’s just data)

Tommy17:01:42

why do you want to migrate? what benefits would honey have @UHZPYLPU1

Eric Dvorsak17:01:41

My experience was honey then hug then back to honey. I found that hug gets too much in the way when you start to need a bit of parameters, and at this point it doesn't look as neat and having clojure code in you templates is really hard to debug. For most attributes in my current codebase I don't even write any SQL directly and instead use Fulcro rad defattr to define the model, and a custom version of fulcro-rad-sql so the sql writes itself.

👍 2
☝️ 2
J07:01:58

@UBT7FH96Z for me the benefits of honey over hugsql is that honey is just data and you can create directly sql into a .clj. Hugsql doesn’t play well with the repl too.

👍 2
Tommy16:01:47

I do like being able to just (h/values [map]) my data into the database.. @UHZPYLPU1

robert-stuttaford18:01:29

hoping a fellow Pathom3 user who's further along can help a noob. i have been butting my head against this for a good few hours. what could i be doing wrong?

robert-stuttaford18:01:49

btw @U066U8JQJ, if you've advice for how i should involve a Datomic db in a pathom resolver index, i'd love your advice! i can't use the viz tool (i crash it with all the datomic internal data), and any exception i get happens to print the whole Datomic database out, making the feedback loop truly horrible (because Emacs does Not Deal With Big Text Well)

robert-stuttaford18:01:18

I reallllly want to use Pathom3, i want what it offers

caleb.macdonaldblack18:01:12

user-entity-resolver only has one param when it should probably have two

caleb.macdonaldblack18:01:30

db will be in first env param and user-id in the second input param

caleb.macdonaldblack18:01:56

Resolvers can take a single input arg or two args of env & input

robert-stuttaford18:01:06

so i did try that, with {:db db} as an env and the rest as input, but it didn't seem to make much difference. super happy to give it another shot though.

caleb.macdonaldblack18:01:22

Can you post a snippet?

caleb.macdonaldblack18:01:08

(pco/defresolver user-entity-resolver
  [{:keys [db]} {:user/keys [id]}]
  {:user/entity (d/entity db id)})

caleb.macdonaldblack18:01:18

That’s what that resolver should look like

caleb.macdonaldblack18:01:28

Well it should look like that if you’re query is this: `

[{[:user/id user-id] [:user/entity]}]

caleb.macdonaldblack18:01:16

However if you’re wanting to fetch the user-id from your env, you would do this:

(pco/defresolver user-entity-resolver
  [{:keys [db user-id]} _input]
  {:user/entity (d/entity db user-id)})

caleb.macdonaldblack18:01:40

and it’s user-id, which is in the env, not user/id

caleb.macdonaldblack18:01:38

Also in your p.eql/process you’re confusing naming here with pathom conventions. indexes is the env. And that is where you would put the db. where you have env you instead want that to be the entity or input.

caleb.macdonaldblack18:01:54

And you can simply put {} if you don’t have any input. You can also omit that entirely and just call it as (p.eql/process indexes eql)

caleb.macdonaldblack18:01:57

You could also do this and drop the full-name and email resolvers

(pco/defresolver user-entity-resolver
  [{:keys [db user-id]} _input]
  {::pco/output [:user/full-name :user/email]}
  (d/entity db user-id))

caleb.macdonaldblack18:01:57

Assuming you want the user-id in the env and not the input. Which is safer if you’re allowing eql queries from the client, where the client can put whatever they want in the input.

robert-stuttaford18:01:06

thanks Caleb, i'm going to work through your notes. hopefully all i've done is misunderstand something, and success is close!

caleb.macdonaldblack18:01:18

No worries. Specifically the misunderstanding is that env/indexes are the same thing. And entity/input is a different thing. Resolvers can take either just the input/entity with one arg [input]. Or both env & input with two args. [env input]

caleb.macdonaldblack18:01:55

EQL queries only have access to data from the input.

caleb.macdonaldblack18:01:28

You cannot write an eql query that can access data from the env param unless you write a resolver specifically to do this

wilkerlucio21:01:02

@U0509NKGK like @U3XCG2GBZ said, the user-entity-resolver is probably better separating the env and id, glad to assist in case its not working yet

gratitude-thank-you 2
wilkerlucio21:01:37

the db is better on env due to its being a constant across the processing, while :user/id is better as input, since its very context dependent (also allowing things like ident query)

c0rrzin11:01:01

one question about this: if I want to model a domain or set of domains that depend on the context of a user/customer, would it make sense to put them in the env instead of the input? Or is it a better practice to just replicate this parameter as an input in all resolvers?

wilkerlucio12:01:32

@U0UA5TB2L not really, if you think the graph of entities, the relationships of a user/customer will already set the proper boundaries, that should allow for navigation in context, without having to rely on global definitions (like env stuff)

Eric Dvorsak22:01:24

If I have 2 entities "user" and "organization" with eg user1 and org1, and I want a resolver for "user/seen-org-prop", the only way to provide the "org" for that resolver in a query is through params, right?

wilkerlucio22:01:16

no, you can always use some other input for it

wilkerlucio22:01:36

but maybe I don't fully understand, can you give a concrete example?

Eric Dvorsak22:01:24

yes, do you mean resolvers and queries? or a more precise description? basically I want to return true/false if there is a new data-policy available that the user hasn't seen right now I'm not doing it with a resolver but instead I do a query first then a bit of filtering, this is my query:

[{org-ident [{:organization/latest-data-privacy [:data-privacy/id]}]}
 {user-ident [{:user/data-privacy [:data-privacy/id
                                                        :data-privacy/organization-id
                                                        :data-privacy/version]}]}]

wilkerlucio22:01:25

what user/seen-org-prop is about, what does it mean?

Eric Dvorsak22:01:06

to be more correct it would be user/seen-latest-privacy-policy?

Eric Dvorsak22:01:58

would be true if the data-privacy/id of the user/data-privacy with the highest version for this org matches the one from organization/latest-data-privacy

wilkerlucio22:01:54

maybe a nested input to load the depths from data-privacy and bring it up?

Eric Dvorsak22:01:25

what do you mean by load the depths?

wilkerlucio22:01:36

I'm still trying to figure the relationship of your data

wilkerlucio22:01:27

its really about it having a way to trace from the user (maybe from user id) to the final data you need

wilkerlucio22:01:51

but I see your query has an org-ident outside the user-ident boundary, are you trying to relate those separated pieces inside the user-ident?

Eric Dvorsak22:01:01

organization has a one to many relationship with data-privacy (an org can have multiple data-privacy versions) user has a many to many relationship (a user can have approved data-privacy from multiple orgs and multiple versions)

Eric Dvorsak22:01:52

yes the first subquery with the org ident is using a resolver that returns the most recent data-privacy policy of the org

wilkerlucio22:01:28

you need to get a way to ask for that from inside the user context, acessing things that are outside the boundary is not really possible

wilkerlucio22:01:47

the user must have a way to link to that order-ident, from inside it

Eric Dvorsak22:01:10

user-ident [{:user/data-privacy [:data-privacy/id
                                 :data-privacy/organization-id
                                 :organization/latest-data-privacy
                                 :data-privacy/version]}

Eric Dvorsak22:01:16

i could have it like this

Eric Dvorsak22:01:56

but then I resolve it for each version of the data policy of each org which I don't care about

Eric Dvorsak23:01:57

I guess if I have a user/last-data-privacy resolver as well then it's not a problem anymore

Eric Dvorsak23:01:25

the last piece is about passing the organization-id, which again I suppose needs to be done via params?

wilkerlucio23:01:21

depends on how you wanna handle it, if the question is based on some user input in the EQL request (like: I want to check this property in relation to this specific org id), them yes, you should use a param

Eric Dvorsak23:01:59

yeah makes sense, user/has-seen-latest-data-policy would return the answer for all the orgs the user is part of unless org-id is provided via params to filter