-
-
Notifications
You must be signed in to change notification settings - Fork 29
/
error.cljc
142 lines (122 loc) · 4.94 KB
/
error.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
(ns com.wsscode.pathom3.error
(:require
[clojure.spec.alpha :as s]
[com.fulcrologic.guardrails.core :refer [<- => >def >defn >fdef ? |]]
[com.wsscode.misc.coll :as coll]
[com.wsscode.pathom3.attribute :as p.attr]
[com.wsscode.pathom3.connect.planner :as pcp]
[com.wsscode.pathom3.plugin :as p.plugin]
#?(:cljs [goog.object :as gobj]))
#?(:clj
(:import
(java.io
PrintWriter
StringWriter))))
(>def ::phase keyword?)
(>def ::cause
(s/and keyword?
#{::attribute-unreachable
::attribute-not-requested
::attribute-missing
::ancestor-error
::node-errors
::node-exception
::plugin-missing-id
::missing-output}))
(>def ::lenient-mode? boolean?)
(defn- optional? [index-ast attribute]
(get-in index-ast [attribute :params :com.wsscode.pathom3.connect.operation/optional?]))
(defn attribute-node-error
[{:com.wsscode.pathom3.connect.runner/keys [node-run-stats]
::p.attr/keys [attribute]
::pcp/keys [index-ast]
:as graph} node-id]
(let [{:com.wsscode.pathom3.connect.runner/keys [node-error node-run-finish-ms]} (get node-run-stats node-id)]
(cond
node-error
(coll/make-map-entry
node-id
{::cause ::node-exception
::exception node-error})
node-run-finish-ms
(if-not (optional? index-ast attribute)
(coll/make-map-entry
node-id
{::cause ::attribute-missing}))
:else
(if-let [[node-id' error] (->> (pcp/node-ancestors graph node-id)
(keep (fn [node-id]
(if-let [error (get-in node-run-stats [node-id :com.wsscode.pathom3.connect.runner/node-error])]
[node-id error])))
first)]
(coll/make-map-entry
node-id
{::cause ::ancestor-error
::error-ancestor-id node-id'
::exception error})))))
(defn attribute-error
"Return the attribute error, in case it failed."
[response attribute]
(if (contains? response attribute)
nil
(let [{:com.wsscode.pathom3.connect.planner/keys [index-ast index-attrs] :as run-stats}
(-> response meta :com.wsscode.pathom3.connect.runner/run-stats)]
(if (contains? index-ast attribute)
(if-let [nodes (get index-attrs attribute)]
(let [run-stats (assoc run-stats ::p.attr/attribute attribute)
errors (into {} (keep #(attribute-node-error run-stats %)) nodes)]
(if (seq errors)
{::cause ::node-errors
::node-error-details errors}))
(if-not (optional? index-ast attribute)
{::cause ::attribute-unreachable}))
{::cause ::attribute-not-requested}))))
(defn scan-for-errors? [response]
; some node error?
; something unreachable?
; is there a way to know if there wasn't any error without checking each attribute?
; check if map has meta
(some-> response meta (contains? :com.wsscode.pathom3.connect.runner/run-stats)))
(defn process-entity-errors [env entity]
(if (scan-for-errors? entity)
(let [ast (-> entity meta
:com.wsscode.pathom3.connect.runner/run-stats
:com.wsscode.pathom3.connect.planner/index-ast)
errors (into {}
(keep (fn [k]
(if-let [error (p.plugin/run-with-plugins env ::wrap-attribute-error
attribute-error entity k)]
(coll/make-map-entry k error))))
(keys ast))]
(cond-> entity
(seq errors)
(assoc :com.wsscode.pathom3.connect.runner/attribute-errors errors)))
entity))
#?(:clj
(defn error-stack [^Throwable err]
(let [sw (StringWriter.)
pw (PrintWriter. sw)]
(.printStackTrace err pw)
(.toString sw)))
:cljs
(defn error-stack [err]
(gobj/get err "stack")))
(defn datafy-processor-error* [env]
(-> env
(select-keys [::error-message
::error-stack
::pcp/graph
:com.wsscode.pathom3.connect.runner/processor-error?
;:com.wsscode.pathom3.connect.runner/processor-error-parent-env
:com.wsscode.pathom3.entity-tree/entity-tree
:com.wsscode.pathom3.path/path])
(coll/update-if
:com.wsscode.pathom3.connect.runner/processor-error-parent-env
datafy-processor-error*)))
(defn datafy-processor-error [^Throwable err]
(let [env (ex-data err)]
(if (some-> env :com.wsscode.pathom3.connect.runner/processor-error?)
(datafy-processor-error* env)
{::error-message (ex-message err)
::error-data (ex-data err)
::error-stack (error-stack err)})))