UNPKG

5.85 kBJavaScriptView Raw
1import { createClient } from '@urql/core';
2import { atom } from 'jotai';
3import { pipe, subscribe } from 'wonka';
4
5const DEFAULT_URL = (() => {
6 try {
7 return process.env.JOTAI_URQL_DEFAULT_URL;
8 } catch {
9 return void 0;
10 }
11})() || "/graphql";
12const clientAtom = atom(createClient({ url: DEFAULT_URL }));
13
14const isOperationResultWithData$1 = (result) => "data" in result && !result.error;
15function 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 baseResultAtom = atom(
24 new Promise((r) => {
25 resolve = r;
26 })
27 );
28 let setResult = () => {
29 throw new Error("setting result without mount");
30 };
31 const listener = (result) => {
32 if (result instanceof Promise) {
33 setResult(result);
34 return;
35 }
36 if (!isOperationResultWithData$1(result)) {
37 throw new Error("result does not have data");
38 }
39 if (resolve) {
40 resolve(result);
41 resolve = null;
42 } else {
43 setResult(result);
44 }
45 };
46 client.query(args.query, args.variables, {
47 ...args.requestPolicy && { requestPolicy: args.requestPolicy },
48 ...args.context
49 }).toPromise().then(listener).catch(() => {
50 });
51 baseResultAtom.onMount = (update) => {
52 setResult = update;
53 };
54 const subscriptionAtom = atom(null);
55 const resultAtom = atom(
56 (get2) => get2(baseResultAtom),
57 (get2, set, callback) => {
58 const subscription = pipe(
59 client.query(args.query, args.variables, {
60 ...args.requestPolicy && { requestPolicy: args.requestPolicy },
61 ...args.context
62 }),
63 subscribe(listener)
64 );
65 set(subscriptionAtom, subscription);
66 callback(() => {
67 var _a;
68 return (_a = get2(subscriptionAtom)) == null ? void 0 : _a.unsubscribe();
69 });
70 }
71 );
72 resultAtom.onMount = (init) => {
73 let cleanup;
74 init((c) => {
75 cleanup = c;
76 });
77 return cleanup;
78 };
79 return { args, client, resultAtom, subscriptionAtom, listener };
80 });
81 const queryAtom = atom(
82 (get) => {
83 const queryResult = get(queryResultAtom);
84 if (!queryResult) {
85 return null;
86 }
87 const { resultAtom } = queryResult;
88 return get(resultAtom);
89 },
90 (get, set, action) => {
91 switch (action.type) {
92 case "reexecute": {
93 const queryResult = get(queryResultAtom);
94 if (!queryResult) {
95 throw new Error("query is paused");
96 }
97 const { args, client, subscriptionAtom, listener } = queryResult;
98 listener(new Promise(() => {
99 }));
100 const newSubscription = pipe(
101 client.query(args.query, args.variables, {
102 ...args.requestPolicy && { requestPolicy: args.requestPolicy },
103 ...args.context,
104 ...action.opts
105 }),
106 subscribe(listener)
107 );
108 const oldSubscription = get(subscriptionAtom);
109 oldSubscription == null ? void 0 : oldSubscription.unsubscribe();
110 set(subscriptionAtom, newSubscription);
111 }
112 }
113 }
114 );
115 return queryAtom;
116}
117
118function atomWithMutation(createQuery, getClient = (get) => get(clientAtom)) {
119 const operationResultAtom = atom(
120 new Promise(() => {
121 })
122 );
123 const queryResultAtom = atom(
124 (get) => get(operationResultAtom),
125 (get, set, action) => {
126 set(
127 operationResultAtom,
128 new Promise(() => {
129 })
130 );
131 const client = getClient(get);
132 const query = createQuery(get);
133 client.mutation(query, action.variables, action.context).toPromise().then((result) => {
134 var _a;
135 set(operationResultAtom, result);
136 (_a = action.callback) == null ? void 0 : _a.call(action, result);
137 }).catch(() => {
138 });
139 }
140 );
141 return queryResultAtom;
142}
143
144const isOperationResultWithData = (result) => "data" in result;
145function atomWithSubscription(createSubscriptionArgs, getClient = (get) => get(clientAtom)) {
146 const queryResultAtom = atom((get) => {
147 const args = createSubscriptionArgs(get);
148 if (args.pause) {
149 return { args };
150 }
151 const client = getClient(get);
152 let resolve = null;
153 const resultAtom = atom(
154 new Promise((r) => {
155 resolve = r;
156 })
157 );
158 let setResult = () => {
159 throw new Error("setting result without mount");
160 };
161 let isMounted = false;
162 const listener = (result) => {
163 if (!isOperationResultWithData(result)) {
164 throw new Error("result does not have data");
165 }
166 if (resolve) {
167 if (!isMounted) {
168 subscription == null ? void 0 : subscription.unsubscribe();
169 subscription = null;
170 }
171 resolve(result);
172 resolve = null;
173 } else {
174 setResult(result);
175 }
176 };
177 let subscription = pipe(
178 client.subscription(args.query, args.variables, args.context),
179 subscribe(listener)
180 );
181 resultAtom.onMount = (update) => {
182 setResult = update;
183 isMounted = true;
184 if (!subscription) {
185 subscription = pipe(
186 client.subscription(args.query, args.variables, args.context),
187 subscribe(listener)
188 );
189 }
190 return () => subscription == null ? void 0 : subscription.unsubscribe();
191 };
192 return { resultAtom, args };
193 });
194 const queryAtom = atom((get) => {
195 const { resultAtom } = get(queryResultAtom);
196 return resultAtom ? get(resultAtom) : null;
197 });
198 return queryAtom;
199}
200
201export { atomWithMutation, atomWithQuery, atomWithSubscription, clientAtom };