Fork me on GitHub
#pathom
<
2020-04-11
>
kwladyka12:04:46

Is it fine to use for `:pc/input` vector instead of `#{}`? Or on the other hand for `:pc/output` use `#{}` instead of vector, which will be even more useful for me. It looks like it works, but do I miss something? There has to be some reason when it is done in that way in doc right?

souenzzo12:04:19

(s/describe ::pc/input)
=> (coll-of :com.wsscode.pathom.core/attribute :kind set?)
(s/describe ::pc/output)
=>
(or
 :attribute-list
 (coll-of :com.wsscode.pathom.connect/out-attribute :kind vector? :min-count 1)
 :union
 (map-of :com.wsscode.pathom.connect/attribute :com.wsscode.pathom.connect/output))
It's values are specified

👍 4
kwladyka12:04:09

ah I see. I had to close and run REPL again to crash evrything

kwladyka12:04:47

Do you see this patterns also for your app when you have to use:

(def shop-keys [:shop/uuid :shop/name :shop/engine :shop/config])
without uuid [:shop/name :shop/engine :shop/config] as a vector and set?

kwladyka12:04:58

so on the end it is a little redundant

kwladyka12:04:09

as long as it is macro anyway I would like to see this converting to the right type (set / vector)

kwladyka12:04:23

but maybe it is only my case

kwladyka13:04:22

(def shop-keys-without-uuid #{:shop/name :shop/engine :shop/config})
(def shop-keys (into [:shop/uuid] shop-keys-without-uuid))

(defn ->spec [shop]
  (s-utils/map-coercion
    {:shop/uuid uuid/as-uuid
     :shop/config json/read-str}
    shop))

(defn ->eql [shop]
  (-> (update shop :shop/uuid str)
      (dissoc :shop/created_at :shop/updated_at)))

(pc/defmutation create-shop! [env shop]
  {::pc/sym 'shop/create!
   ::pc/params shop-keys-without-uuid
   ::pc/output shop-keys}
  (->eql (shop-db/create-shop! (->spec shop))))

(pc/defmutation update-shop! [env shop]
  {::pc/sym 'shop/update!
   ::pc/params (set shop-keys)
   ::pc/output [:shop/uuid]}
  (shop-db/update-shop! (->spec shop))
  (select-keys shop [:shop/uuid]))

(pc/defresolver get-shop [env params]
  {::pc/input #{:shop/uuid}
   ::pc/output (vec shop-keys-without-uuid)
   ::pc/transform pc/transform-batch-resolver}
  (shop-db/get-shops-by-uuid (->> (map :shop/uuid params)
                                  (map (partial s-utils/safe-coercion uuid/as-uuid))
                                  (set))))

(pc/defresolver all-shops [env _]
  {::pc/output [{:shops shop-keys}]}
  {:shops (mapv ->eql (shop-db/get-all-shops))})

(pc/defmutation delete-shop [env {:shop/keys [uuid]}]
  {::pc/sym 'shop/delete
   ::pc/params #{:shop/uuid}
   ::pc/output [:deleted?]}
  {:deleted? (shop-db/delete-shop uuid)})
This dance with set and vec and how def looks show what I mean.

pithyless14:04:55

In your case, create-shop!, get-shop, and all-shops all return [:shop/name :shop/engine :shop/config]. I find this approach counter-intuitive, as subtle changes in implementation of these resolvers could hide bugs over time. I prefer to have create-shop!, all-shops , and update-shop! all return just :shop/uuid; and then you only need one get-shop that knows how to resolve all the other attributes. Easier to isolate logic/authorization/etc. to one place and you no longer have to worry about code redundancy. ;]

👍 4
kwladyka15:04:32

hmm while database performance and time response is not the issue, because of the 2x DB query it is a solution 🙂

myguidingstar19:04:42

@wilkerlucio regarding dynamic resolvers, do all items in ::pcp/requires have equivalence in ::pcp/foreign-ast and vice versa? Also, what is the use case for those ::pcp/requires?

wilkerlucio15:04:43

pcp/requires determines what is expected to be on the output of this node call

wilkerlucio15:04:16

for dynamic, yes, it should have the equivalent in foreign ast

👍 4