Fork me on GitHub
#pathom
<
2021-01-08
>
wilkerlucio02:01:33

and to start the good year, another processing feature: now Pathom 3 supports optional inputs! https://pathom3.wsscode.com/docs/resolvers/#optional-inputs

👍 21
souenzzo11:01:44

@wilkerlucio in situations like

;; resolver 1
{:input [:a :b]
 :ouput [:c]}
;; resolver 2
{:input [:a]
 :ouput [:c]}
;; entity
{:a 1 :b 2}
Will resolver 1 *always* be called? If possible, answer both in pathom2 and pathom3 😜

wilkerlucio12:01:02

quick answer: no

wilkerlucio12:01:31

in pathom2 that depends on the resolver weight, whatever Pathom things is the faster path, it will take it

wilkerlucio12:01:18

in pathom3 there still no prioritization yet (altough that's the next thing I'll be working on), so in Pathom 3 its kind random, but will always be same, for now

👍 3
wilkerlucio18:01:08

will be merged soon

wilkerlucio18:01:40

(in this value2 is always tried first, default priority is 0, higher numbers go first)

wilkerlucio18:01:53

ok, I think I'm getting somewhere, this is a way to force one path to be preferred over another:

(is (= (run-graph
                   (pci/register
                     [(pco/resolver `value
                        {::pco/input  [:a :b]
                         ::pco/output [:value]}
                        (fn [_ _]
                          {:value 1}))
                      (pco/resolver `value2
                        {::pco/input    [:c]
                         ::pco/output   [:value]
                         ::pcr/priority 1}
                        (fn [_ _]
                          {:value 2}))
                      (pbir/constant-resolver :a 1)
                      (pbir/constant-resolver :b 2)
                      (pbir/constant-resolver :c 3)])
                   [:value]
                   {})
                 {:c     3
                  :value 2}))

jmayaalv15:01:00

@wilkerlucio will there be an alternative for :com.wsscode.pathom.core/not-found on pathom3? starting to migrate a green field app to pathom3 and we are really happy with the simplicity 🙂

wilkerlucio15:01:31

@jmayaalv the alternative is check if the key is in the response, in case of not-found, the attribute is gonna be absent, I guess that can solve for most cases, if not, troubleshooting will come as an extension of the new "run stats" thing, hard to explain in brief, but there you can find most data needed to figure any situation, you can take a look at that by checking the meta on the responses (for EQL interface)

wilkerlucio15:01:20

important thing to take note: each response map has its on run stats (each is a different run context), so if you have a response like {:foo {:bar "baz"}}, there are 2 run stats, one for the outermost map, and one for the inner, in cases of collections, each entry has its own stats

jmayaalv15:01:05

i will check the plugins out, although absent of value should be good enough for us. Thank you !

👍 3
imre15:01:45

Is there any way for a resolver to set a parameter on one of its outputs?

wilkerlucio15:01:21

what you mean set a parameter on its outputs?

imre15:01:51

just trying to come up with a proper example 🙂

imre15:01:03

so, assuming I have the following resolver:

imre15:01:08

(pc/defresolver output-resolver
  [env {value :foo/intermediate}]
  {::pc/input  #{:foo/intermediate}
   ::pc/output [:foo/output]}
  {:foo/output [value (-> env :ast :params :some-param)]})

imre15:01:32

I can use the query

[{[:foo/intermediate 123]
  [(:foo/output {:some-param "value"})]}]

imre15:01:59

and get {:foo/output [123 "value"]} back

imre15:01:20

(not guaranteed to be correct, I'm just typing this into a text editor)

imre15:01:44

I want to create an intermediate resolver, like

(pc/defresolver intermediate-resolver
  [_ {value :foo/input}]
  {::pc/input  #{:foo/input}
   ::pc/output [:foo/intermediate]}
  {:foo/intermediate value})

imre15:01:39

And within this resolver I want to determine a value for :some-param and pass it on to output-resolver

imre16:01:14

so a query of `[{[:foo/input 123] [:foo/output]}]` could return {:foo/output [123 "value-set-by-intermediate-resolver"]}

wilkerlucio16:01:35

no, you can't change things like this sideways, if you need information to flow, add new attributes to the system, make the output of the resolver respond with more keys, and use those keys in the input forward, makes sense?

imre16:01:16

It does I guess, I primarily just wanted to find out whether it was possible. So for example, if there's a resolver that supports pagination via a parameter, and some other resolver wants to call it with pagination, then pagination will need to be made an input. Is that correct?

csgero16:01:36

for context, this came up while experimenting with foreign-resolvers, and the second resolver is actually implemented in a different service

wilkerlucio16:01:18

ok, foreign is still a very exploratory area, but I would try to avoid going too deep on this idea, since from the Pathom perpective that is hard to happen, one way to think of it is that params are always a "local" thing, while inputs are things that flow across

imre16:01:19

The concept of parameters is interesting in that it's orthogonal to outputs. However, if they cannot be built on with other resolvers, that could make it risky to depend on them

wilkerlucio16:01:46

one acceptable thing is for a resolver to accept some data as input OR params, this way you can have both options

wilkerlucio16:01:15

the just released optional inputs on Pathom 3 can help with that, so you can have soft dependencies on specific attributes

wilkerlucio16:01:06

but about foreign, its still experimental area, more work on it will come in Pathom 3, and feedback is very appreciated, if you have some cases you like to share, I'll love to hear about them

wilkerlucio16:01:48

another alternative to sideways communication is to have some mutable state in the env, you can add a new atom there, modify from one resolver and read in the other, this is a tricky option and I suggest a lot of care if you try this path, but its there

imre17:01:52

Thank you for the insight. Fortunately in this case the foreign service is under control so we can change it. Will be a bit of extra work but I certainly wouldn't want to use the lib in a non-intended way. I'm sure we'll get back to you wrt foreign resolvers 😉

Ian Fernandez16:01:50

Any thoughts about using it? (pathom2 examples could be interesting too 🙂 )

Ian Fernandez16:01:16

I'm looking for a db component + http component service just to example 😄

Ian Fernandez16:01:37

I'll do some comparison between Integrant and this approach

Ian Fernandez16:01:49

I was looking for some tips about this

wilkerlucio16:01:55

@d.ian.b dependency injection in Pathom is accomplished by env, you can add things to env at call time (when calling the parser), or in any point you want, so you can pull those in any part of the system, makes sense?

parrot 3
Ian Fernandez17:01:22

I will try doing some comparison between Integrant / Pathom then 😄

myguidingstar17:01:00

imo dependency injection is quite easy in Clojure because of immutable data structure. You can use Pathom, Prismatic Plumbing, Integrant or even Datascript. The (harder) related problem is starting/stopping components and that's what Integrant (and Duct) does

Ian Fernandez17:01:45

why not start / stopping components via pathom?

wilkerlucio17:01:07

you can, and for that I suggest you can use the https://pathom3.wsscode.com/docs/cache#custom-cache-store-per-resolver to share a cache on the resolvers that are for building up initialization

wilkerlucio17:01:24

this way you can make them persistent, at the same time they will delay initialization until something in the system needs them

parrot 3
wilkerlucio17:01:01

@d.ian.b if you want I can review the code with you once you have it

wilkerlucio17:01:32

altough, there is no stop 😛

Ian Fernandez18:01:56

and if I want to use pathom2 for this?

wilkerlucio18:01:53

again, altough you can, I think something like "component" still a better option, because on Pathom you can't stop in reverse order, so not as good to this kind of initialization

3
royalaid17:01:38

Hey @wilkerlucio I kinda did some cursory poking around and couldn’t find anything analogous to async parsing in pathom2 so that I can use core.async with pathom3. Any pointers?

wilkerlucio17:01:03

its on the backlog, but not available in Pathom 3 yet

wilkerlucio17:01:32

but I hope an initial version of it should land in the next few weeks

👍 9
wilkerlucio18:01:53

ok, I think I'm getting somewhere, this is a way to force one path to be preferred over another:

(is (= (run-graph
                   (pci/register
                     [(pco/resolver `value
                        {::pco/input  [:a :b]
                         ::pco/output [:value]}
                        (fn [_ _]
                          {:value 1}))
                      (pco/resolver `value2
                        {::pco/input    [:c]
                         ::pco/output   [:value]
                         ::pcr/priority 1}
                        (fn [_ _]
                          {:value 2}))
                      (pbir/constant-resolver :a 1)
                      (pbir/constant-resolver :b 2)
                      (pbir/constant-resolver :c 3)])
                   [:value]
                   {})
                 {:c     3
                  :value 2}))

kendall.buchanan20:01:20

Does anyone know where an example is in the documentation (or anywhere, really) about how to construct a query for a resolver with two items in ::pc/input?

kendall.buchanan20:01:45

e.g. ::pc/input #{:item-1 :item-2}

kendall.buchanan20:01:11

https://blog.wsscode.com/pathom/#_multiple_inputs indicates that it can be done, as the “input to a resolver is a set”, but I can’t find any examples anywhere.

wilkerlucio20:01:57

@kendall.buchanan the example you sent is correct, are you having troubles to make it work?

kendall.buchanan20:01:32

I just don’t know what a query looks like that resolves to that resolver.

kendall.buchanan20:01:20

[{[[:item-1 "hello"] [:item-2 "world"]] [:what-im-fetching]}]

kendall.buchanan20:01:28

This doesn’t appear to work.

kendall.buchanan20:01:25

The best I can come up with is to combine them into a single ::pc/input #{:item-1+2} with a query like [{[:item-1+2 {:item-1 "hello" :item-2 "world"] [:what-im-fetching]}]

kendall.buchanan20:01:53

Good to hear from you @wilkerlucio, by the way—we had dinner together a couple years ago at Clojure/conj 👋. One of our devs has jumped all in with Pathom; I’m just getting my feet wet.

wilkerlucio20:01:31

glad to hear about you too, great times at Conj, can't wait for us to be able to do another one of those again 🙂

wilkerlucio20:01:56

but other than a query itself, you could start from one data point, then a resolver realizes those 2 attributes, which then calls the next one

kendall.buchanan21:01:08

Okay, I’m wondering if I’m genuinely not understanding…

kendall.buchanan21:01:27

`[{([:customer/id 123] {:pathom/context {:customer/first-name “Foo” :customer/last-name “Bar”}}) [:customer/full-name]}]`

wilkerlucio21:01:52

lets go by steps 🙂

wilkerlucio21:01:24

the [:customer/id 123] will set the :customer/id value, and the :pathom-context (when sent as a param to the ident) merges that data in as well

kendall.buchanan21:01:48

::pc/input #{:customer/id :customer/first-name :customer/last-name}

wilkerlucio21:01:05

you probably don't need those 3, you could use any ident there

wilkerlucio21:01:21

Pathom is about "shape matching", so imagine that if you have enough to trigger a resolver, pathom will do it

kendall.buchanan21:01:42

But some data requires more than one input.

kendall.buchanan21:01:07

Here’s a more concrete example…

kendall.buchanan21:01:27

I have a user with multiple logins across multiple apps.

kendall.buchanan21:01:37

Trying to fetch a record of the most recent login.

kendall.buchanan21:01:02

I can build a chain of resolvers that will eventually get me that information, from a single user ID…

kendall.buchanan21:01:27

But that inevitably passes through many more layers than is necessary.

kendall.buchanan21:01:37

Assuming I can pass a user ID, and an app ID.

kendall.buchanan21:01:49

(This is not my exact situation, but it simplifies it.)

wilkerlucio21:01:00

here is a full example:

wilkerlucio21:01:02

(ns com.wsscode.demos.multiple-inputs
  (:require [com.wsscode.pathom.core :as p]
            [com.wsscode.pathom.connect :as pc]))

(def users-db
  {1 {:user/first-name "Sam"
      :user/last-name  "Rock"}})

(pc/defresolver user-by-id [env {:keys [user/id]}]
  {::pc/input  #{:user/id}
   ::pc/output [:user/first-name :user/last-name]}
  (get users-db id))

(pc/defresolver full-name [env {:user/keys [first-name last-name]}]
  {::pc/input  #{:user/first-name :user/last-name}
   ::pc/output [:user/full-name]}
  {:user/full-name (str first-name " " last-name)})

(def registry
  [user-by-id full-name])

(def parser
  (p/parser
    {::p/env     {::p/reader               [p/map-reader
                                            pc/reader2
                                            pc/open-ident-reader
                                            p/env-placeholder-reader]
                  ::p/placeholder-prefixes #{">"}}
     ::p/mutate  pc/mutate
     ::p/plugins [(pc/connect-plugin {::pc/register registry})
                  p/error-handler-plugin
                  p/trace-plugin]}))

(comment
  ; just use the ident, pull name from resolver
  (parser {} '[{[:user/id 1] [:user/full-name]}])

  ; provide data, note we use an id that dont even exist
  (parser {} '[{([:user/id 3] {:pathom/context {:user/first-name "Foo" :user/last-name "Bar"}})
                [:user/full-name]}])

  ; to show the ident doesn't matter, changing it for anything else
  (parser {} '[{([:whatever-we-want "bla"] {:pathom/context {:user/first-name "Foo" :user/last-name "Bar"}})
                [:user/full-name]}]))

wilkerlucio21:01:50

the :user/full-name does what you said, depending on multiple attributes, and getting then from the fake db load

kendall.buchanan21:01:11

But what if this person has multiple names he goes by. You know what I mean?

kendall.buchanan21:01:23

In this example, the first and last name are derived automatically.

wilkerlucio21:01:39

not sure if I get what you mean

wilkerlucio21:01:44

what you mean multiple names?

kendall.buchanan21:01:47

(def users-db
  {1 {:public-name {:user/first-name "Sam"
                    :user/last-name  "Rock"}
      :secret-name {:user/first-name "Ram"
                    :user/last-name  "Sock"}}})

wilkerlucio21:01:11

in the core its about attribute relations, and how one attribute relates to another, so in this case we are expressing what a full name means

wilkerlucio21:01:37

that example you just sent is a different thing

kendall.buchanan21:01:56

That’s what I’m trying to get at: how do I get to my data assuming there is no derivation for the second piece of data.

wilkerlucio21:01:08

its not just multiple inputs, but nested inputs, when you need to depend on some deeper shape, you would have to make a decision of which to pick in the end somehow

kendall.buchanan21:01:11

That the query is fundamentally incomplete without two data points.

wilkerlucio21:01:34

I woulnd't say incomplete, it just depends on your system

wilkerlucio21:01:48

that example I show on full name is a common one, and in most systems the user will only have one field for it

wilkerlucio21:01:03

then its about modeling the semantics of your system

wilkerlucio21:01:18

the nested thing you sent is possible in Pathom 3: https://pathom3.wsscode.com/docs/resolvers#nested-inputs

wilkerlucio21:01:50

but I feel like this is not what you thinking about, I fell like you have some misconception we didn't figure here yet

kendall.buchanan21:01:05

I see where you’re going about nested resolvers…

kendall.buchanan21:01:09

Or subqueries, I suppose.

kendall.buchanan21:01:21

But, why is a subquery necessary if I already have my data?

kendall.buchanan21:01:40

If I know X and Y, why can I not write a resolver that reacts to the existence of X and Y?

wilkerlucio21:01:41

sometimes you dont

wilkerlucio21:01:46

as the aggrgation example I show in the docs

wilkerlucio21:01:57

I still dont understand what you are trying to do

kendall.buchanan21:01:09

Take the example you posted here…

wilkerlucio21:01:12

what is the shape you have? what do you want in the end?

kendall.buchanan21:01:30

Assume I’m looking up a name, based on an ID.

kendall.buchanan21:01:41

(Not caring for :customer/full-name, just looking up a name.)

kendall.buchanan21:01:47

But the user has multiple names, of different types.

wilkerlucio21:01:58

lets give names, you want :user/name, you have :user/id

kendall.buchanan21:01:08

No… not quite…

wilkerlucio21:01:15

what you mean multiple names? are from multiple sources?

wilkerlucio21:01:31

can you give an example?

kendall.buchanan21:01:39

Yeah, lemme write out some data…

wilkerlucio21:01:07

its helps to think about the output shape you want, so we can build the chain from it, and in the end you have to give names to every attribute you want to return, thinking like that often helps me figure it out

kendall.buchanan21:01:12

You know what, I think you’re right: it’s about the semantics of the keys.

kendall.buchanan21:01:52

I’m imagining my resolver working with this:

kendall.buchanan21:01:54

(def users-db
  {1 {:public-name {:user/first-name "Sam"
                    :user/last-name  "Rock"}
      :secret-name {:user/first-name "Ram"
                    :user/last-name  "Sock"}}})

kendall.buchanan21:01:01

When, I think what you’re saying is…

kendall.buchanan21:01:25

(def users-db
  {1 {:user.public/first-name "Sam"
      :user.secret/first-name "Ram"}})

kendall.buchanan21:01:38

In other words…

wilkerlucio21:01:42

in Pathom its good to keep things as flat as possible

kendall.buchanan21:01:46

It pushes the burden of shaping the data further down into the system.

wilkerlucio21:01:51

gives more leverage

kendall.buchanan21:01:52

(In my real world example.)

kendall.buchanan21:01:39

But how would that work when user.x is unknown/

kendall.buchanan21:01:48

:user.x/first-name

kendall.buchanan21:01:10

Or infinite options.

wilkerlucio21:01:18

you can't do that, Pathom must know about the attributes of the system, infinite attributes is not a thing

kendall.buchanan21:01:18

I’ll have to think on that.

wilkerlucio21:01:30

because Pathom is based on index processing, it has to know ahead of time about all relationships

wilkerlucio21:01:56

I'm curious where you land, IME this has never been a limitation so far, maybe you find one, hehe

kendall.buchanan21:01:35

The situation I have is this…

kendall.buchanan21:01:46

We have an infinite number of users (with ids)…

kendall.buchanan21:01:59

And they play “games”, I suppose you could call them.

kendall.buchanan21:01:05

And the number of games they play is infinite.

kendall.buchanan21:01:18

But the number of times they play the game is also infinite.

kendall.buchanan21:01:33

So, I’m trying to fetch a record of their most recent session, given a user ID, and a game ID.

kendall.buchanan21:01:49

Simple SQL query.

kendall.buchanan21:01:54

WHERE clause takes two params.

kendall.buchanan21:01:04

But I can’t understand how this translates to Pathom.

kendall.buchanan21:01:37

Takes two joins in SQL across three tables. It’s a junction, essentially.

kendall.buchanan21:01:57

And I don’t see how Pathom handles a junction—where two indexes are required to resolve it.

kendall.buchanan21:01:18

(Thank you for all this attention, by the way—surely you have important things to be doing.)

wilkerlucio21:01:36

it really helps if you start naming the attributes that participates in this query, I dont see any unbounded attributes in what you said, from the messages I can extract: :user/id :game/id, :session/id (maybe), I mean, Pathom is a connector, you can make the resolver do anything

wilkerlucio21:01:43

what you described looks like a resolver with a query

wilkerlucio21:01:54

the session is another table?

kendall.buchanan21:01:16

The “client” has the :user/id and :game/id, and is seeking a :session/id.

wilkerlucio21:01:17

what you want to get select * from game_session where userid = 10 AND gameid= 20, like this?

wilkerlucio21:01:38

and then, from the session, what data you expect out (name in attributes)

kendall.buchanan21:01:38

Yeah, more or less.

kendall.buchanan21:01:58

That is what’s needed.

wilkerlucio21:01:09

(pc/defresolver user-session [env {user-id :user/id game-id :game/id}]
  {::pc/input  #{:user/id :game/id}
   ::pc/output [:session/id]}
  (let [res (fake-sql (str "select session_id from sessions where user_id=" user-id " and game_id = " game-id))]
    {:session/id (:session_id res)}))

wilkerlucio21:01:16

something like this

wilkerlucio21:01:46

you probably want a different resolver to generate those combinations

wilkerlucio21:01:49

something like:

kendall.buchanan21:01:07

Yeah. My original question was how to construct the EQL for that: ::pc/input #{:user/id :game/id}

wilkerlucio21:01:11

(pc/defresolver games-from-user [env {:keys [user/id]}]
  {::pc/input  #{:user/id}
   ::pc/output [{:user/games [:user/id :game/id]}]}
  ; assume this returns a list of game ids
  (let [res (find-games-from-user env id)]
    {:user/games (mapv #(hash-map :user/id id :game/id %) res)}))

wilkerlucio21:01:28

now you can run: [{[:user/id 1] [{:user/games [:session/id]}]}]

wilkerlucio21:01:23

its really up to you to model, its just different, and takes some practice to adjust

kendall.buchanan21:01:34

Yeah. IMO, this is constraint that I don’t understand.

kendall.buchanan21:01:50

Two constraints it imposes…

kendall.buchanan21:01:01

Prevents the resolver writer from tailoring more performant resolvers.

wilkerlucio21:01:22

I suggest you take a read on this page: https://pathom3.wsscode.com/docs/planner

kendall.buchanan21:01:27

And limits the type granularity of responses for the client.

wilkerlucio21:01:59

this explains how pathom 3 plans for the graph, pathom 2 is bit different, but the main idea is the same, when it sees something the user wants, it traverses the indexes for that attribute, to figure how to reach it

kendall.buchanan21:01:00

But if I have a SQL query that can fetch one item faster than N, your example suggests it can’t be used.

wilkerlucio21:01:23

you can create as many paths as you want, so you can make a direct one if you want to

wilkerlucio21:01:34

and we are limiting our chat here around "static resolvers"

wilkerlucio21:01:22

to get as efficient as what you saying, there are the dynamic resolvers (still getting mature), but their ability is to have dynamic inputs and outputs, that responds depending on the user requirement (and dependencies requirements)

wilkerlucio21:01:39

this is done to call GraphQL for example, where it would be very inneficient if each attribute made its own call

kendall.buchanan21:01:41

In other words…

kendall.buchanan21:01:46

::pc/input #{:user/id :game/id}

wilkerlucio21:01:51

so the dynamic resolvers have a different thing, they can optimize laterally

kendall.buchanan21:01:58

There is no way to satisfy this, correct?

wilkerlucio21:01:11

what you mean you can't satisfy?

kendall.buchanan21:01:17

In a single trip to the resolver index.

wilkerlucio21:01:19

you can provide the data for it, or provide resolvers to reach it

kendall.buchanan21:01:30

you can provide the data for it

wilkerlucio21:01:34

have you seen what the indexes look like?

kendall.buchanan21:01:36

What does the query look like?

wilkerlucio21:01:00

I sent you at the two final examples:

(comment
  ; just use the ident, pull name from resolver
  (parser {} '[{[:user/id 1] [:user/full-name]}])

  ; provide data, note we use an id that dont even exist
  (parser {} '[{([:user/id 3] {:pathom/context {:user/first-name "Foo" :user/last-name "Bar"}})
                [:user/full-name]}])

  ; to show the ident doesn't matter, changing it for anything else
  (parser {} '[{([:whatever-we-want "bla"] {:pathom/context {:user/first-name "Foo" :user/last-name "Bar"}})
                [:user/full-name]}]))

wilkerlucio21:01:06

using :pathom/context param is a way

wilkerlucio21:01:23

you can also provide though the env, setting ::p/entity (atom {:data "here"}

kendall.buchanan21:01:35

And either key can be in the tuple?

wilkerlucio21:01:59

yeah, the key there doesn't matter

wilkerlucio21:01:25

this is more a legacy from Fulcro integration, in this case (for Fulcro) the ident part can tell which local table it should use, without matter what the rest of the context is

wilkerlucio21:01:33

this an example providing data via env:

wilkerlucio21:01:35

(parser {::p/entity (atom {:user/first-name "Foo" :user/last-name "Bar"})}
    '[:user/full-name])

kendall.buchanan21:01:39

([:user/id 3] {:pathom/context {:game/id 1}}]) is the same as ([:game/id 1] {:pathom/context {:user/id 3}}])

kendall.buchanan21:01:57

Okay. I’m assuming that was never desirable, right?

wilkerlucio21:01:01

it only shapes your output shape (which will match the ident)

kendall.buchanan21:01:02

Just… legacy, like you say.

wilkerlucio21:01:18

its was a later addition to support extra inputs at query level

kendall.buchanan21:01:53

K, I’ll give all your feedback some thought for how I construct our actual resolvers. Thank you again. Big help. Love the project.

🙏 3
kendall.buchanan21:01:12

If I had any feedback, it seems to me that multiple params in the queries ought to be natively supported, but perhaps I just have more adjusting to do.

wilkerlucio21:01:44

in Pathom 3 you can use placeholders for a simpler version of it

kendall.buchanan21:01:02

You feel like it’s ready for real use?

wilkerlucio21:01:33

not yet, but its quite easy to implement that feature in Pathom 2, I think I'll do that today, because you are not the first person asking, hehe

kendall.buchanan21:01:45

Oh good, hehe. Thank you !

wilkerlucio21:01:48

Pathom 3 is getting there, I think its good for experiments and small usages, but its lacking tooling, so when things start to get complicated, the tooling can be quite missed

wilkerlucio21:01:18

but in terms of core features, it has a lot done already

wilkerlucio21:01:33

hello everyone, another feature out 🎉! Now you can express different priorities for resolvers, so in cases that pathom need to choose, you can have a say on it: https://pathom3.wsscode.com/docs/resolvers#prioritization

🙏 9
🎉 6
👏 3