1 | import { createClient } from '@urql/core';
|
2 | import { atom } from 'jotai';
|
3 | import { pipe, subscribe } from 'wonka';
|
4 |
|
5 | const DEFAULT_URL = (() => {
|
6 | try {
|
7 | return process.env.JOTAI_URQL_DEFAULT_URL;
|
8 | } catch {
|
9 | return void 0;
|
10 | }
|
11 | })() || "/graphql";
|
12 | const clientAtom = atom(createClient({ url: DEFAULT_URL }));
|
13 |
|
14 | const isOperationResultWithData$1 = (result) => "data" in result && !result.error;
|
15 | function atomWithQuery(createQueryArgs, getClient = (get) => get(clientAtom)) {
|
16 | const queryResultAtom = atom((get) => {
|
17 | const args = createQueryArgs(get);
|
18 | if (args.pause) {
|
19 | return null;
|
20 | }
|
21 | const client = getClient(get);
|
22 | let resolve = null;
|
23 | const makePending = () => new Promise((r) => {
|
24 | resolve = r;
|
25 | });
|
26 | const resultAtom = atom(makePending());
|
27 | let setResult = null;
|
28 | const listener = (result) => {
|
29 | if (!resolve && !setResult) {
|
30 | throw new Error("setting result without mount");
|
31 | }
|
32 | if (resolve) {
|
33 | resolve(result);
|
34 | resolve = null;
|
35 | }
|
36 | if (setResult) {
|
37 | setResult(result);
|
38 | }
|
39 | };
|
40 | let subscription = null;
|
41 | let timer;
|
42 | const startQuery = (opts) => {
|
43 | if (subscription) {
|
44 | clearTimeout(timer);
|
45 | subscription.unsubscribe();
|
46 | }
|
47 | subscription = pipe(
|
48 | client.query(args.query, args.variables, {
|
49 | ...args.requestPolicy && { requestPolicy: args.requestPolicy },
|
50 | ...args.context,
|
51 | ...opts
|
52 | }),
|
53 | subscribe(listener)
|
54 | );
|
55 | if (!setResult) {
|
56 | timer = setTimeout(() => {
|
57 | if (subscription) {
|
58 | subscription.unsubscribe();
|
59 | subscription = null;
|
60 | }
|
61 | }, 1e3);
|
62 | }
|
63 | };
|
64 | startQuery();
|
65 | resultAtom.onMount = (update) => {
|
66 | setResult = update;
|
67 | if (subscription) {
|
68 | clearTimeout(timer);
|
69 | } else {
|
70 | startQuery();
|
71 | }
|
72 | return () => {
|
73 | setResult = null;
|
74 | if (subscription) {
|
75 | subscription.unsubscribe();
|
76 | subscription = null;
|
77 | }
|
78 | };
|
79 | };
|
80 | return { resultAtom, makePending, startQuery };
|
81 | });
|
82 | const queryAtom = atom(
|
83 | (get) => {
|
84 | const queryResult = get(queryResultAtom);
|
85 | if (!queryResult) {
|
86 | return null;
|
87 | }
|
88 | const { resultAtom } = queryResult;
|
89 | const result = get(resultAtom);
|
90 | if (!isOperationResultWithData$1(result)) {
|
91 | throw result.error;
|
92 | }
|
93 | return result;
|
94 | },
|
95 | (get, set, action) => {
|
96 | if (action.type === "reexecute") {
|
97 | console.warn(
|
98 | "DEPRECATED [atomWithQuery] use refetch instead of reexecute"
|
99 | );
|
100 | action.type = "refetch";
|
101 | }
|
102 | switch (action.type) {
|
103 | case "refetch": {
|
104 | const queryResult = get(queryResultAtom);
|
105 | if (!queryResult) {
|
106 | throw new Error("query is paused");
|
107 | }
|
108 | const { resultAtom, makePending, startQuery } = queryResult;
|
109 | set(resultAtom, makePending());
|
110 | startQuery(action.opts);
|
111 | return;
|
112 | }
|
113 | }
|
114 | }
|
115 | );
|
116 | return queryAtom;
|
117 | }
|
118 |
|
119 | function atomWithMutation(createQuery, getClient = (get) => get(clientAtom)) {
|
120 | const operationResultAtom = atom(
|
121 | new Promise(() => {
|
122 | })
|
123 | );
|
124 | const queryResultAtom = atom(
|
125 | (get) => get(operationResultAtom),
|
126 | async (get, set, action) => {
|
127 | set(
|
128 | operationResultAtom,
|
129 | new Promise(() => {
|
130 | })
|
131 | );
|
132 | const client = getClient(get);
|
133 | const query = createQuery(get);
|
134 | return client.mutation(query, action.variables, action.context).toPromise().then((result) => {
|
135 | var _a;
|
136 | (_a = action.callback) == null ? void 0 : _a.call(action, result);
|
137 | if (result.error) {
|
138 | throw result.error;
|
139 | }
|
140 | set(operationResultAtom, result);
|
141 | });
|
142 | }
|
143 | );
|
144 | return queryResultAtom;
|
145 | }
|
146 |
|
147 | const isOperationResultWithData = (result) => "data" in result && !result.error;
|
148 | function atomWithSubscription(createSubscriptionArgs, getClient = (get) => get(clientAtom)) {
|
149 | const queryResultAtom = atom((get) => {
|
150 | const args = createSubscriptionArgs(get);
|
151 | if (args.pause) {
|
152 | return null;
|
153 | }
|
154 | const client = getClient(get);
|
155 | let resolve = null;
|
156 | const makePending = () => new Promise((r) => {
|
157 | resolve = r;
|
158 | });
|
159 | const resultAtom = atom(makePending());
|
160 | let setResult = null;
|
161 | const listener = (result) => {
|
162 | if (resolve) {
|
163 | resolve(result);
|
164 | resolve = null;
|
165 | }
|
166 | if (setResult) {
|
167 | setResult(result);
|
168 | }
|
169 | };
|
170 | let subscription = null;
|
171 | let timer;
|
172 | const startSub = () => {
|
173 | if (subscription) {
|
174 | clearTimeout(timer);
|
175 | subscription.unsubscribe();
|
176 | }
|
177 | subscription = pipe(
|
178 | client.subscription(args.query, args.variables, args.context),
|
179 | subscribe(listener)
|
180 | );
|
181 | if (!setResult) {
|
182 | timer = setTimeout(() => {
|
183 | if (subscription) {
|
184 | subscription.unsubscribe();
|
185 | subscription = null;
|
186 | }
|
187 | }, 1e3);
|
188 | }
|
189 | };
|
190 | startSub();
|
191 | resultAtom.onMount = (update) => {
|
192 | setResult = update;
|
193 | if (subscription) {
|
194 | clearTimeout(timer);
|
195 | } else {
|
196 | startSub();
|
197 | }
|
198 | return () => {
|
199 | setResult = null;
|
200 | if (subscription) {
|
201 | subscription.unsubscribe();
|
202 | subscription = null;
|
203 | }
|
204 | };
|
205 | };
|
206 | return { resultAtom, makePending, startSub };
|
207 | });
|
208 | const queryAtom = atom(
|
209 | (get) => {
|
210 | const queryResult = get(queryResultAtom);
|
211 | if (!queryResult) {
|
212 | return null;
|
213 | }
|
214 | const { resultAtom } = queryResult;
|
215 | const result = get(resultAtom);
|
216 | if (!isOperationResultWithData(result)) {
|
217 | throw result.error;
|
218 | }
|
219 | return result;
|
220 | },
|
221 | (get, set, action) => {
|
222 | switch (action.type) {
|
223 | case "refetch": {
|
224 | const queryResult = get(queryResultAtom);
|
225 | if (!queryResult) {
|
226 | throw new Error("query is paused");
|
227 | }
|
228 | const { resultAtom, makePending, startSub } = queryResult;
|
229 | set(resultAtom, makePending());
|
230 | startSub();
|
231 | return;
|
232 | }
|
233 | }
|
234 | }
|
235 | );
|
236 | return queryAtom;
|
237 | }
|
238 |
|
239 | export { atomWithMutation, atomWithQuery, atomWithSubscription, clientAtom };
|