UNPKG

jotai

Version:

👻 Next gen state management that will spook you

240 lines (234 loc) • 6.33 kB
import { createClient } from '@urql/core'; import { atom } from 'jotai'; import { pipe, subscribe } from 'wonka'; const DEFAULT_URL = (() => { try { return process.env.JOTAI_URQL_DEFAULT_URL; } catch { return void 0; } })() || "/graphql"; const clientAtom = atom(createClient({ url: DEFAULT_URL })); const isOperationResultWithData$1 = (result) => "data" in result && !result.error; function atomWithQuery(createQueryArgs, getClient = (get) => get(clientAtom)) { const queryResultAtom = atom((get) => { const args = createQueryArgs(get); if (args.pause) { return null; } const client = getClient(get); let resolve = null; const makePending = () => new Promise((r) => { resolve = r; }); const resultAtom = atom(makePending()); let setResult = null; const listener = (result) => { if (!resolve && !setResult) { throw new Error("setting result without mount"); } if (resolve) { resolve(result); resolve = null; } if (setResult) { setResult(result); } }; let subscription = null; let timer; const startQuery = (opts) => { if (subscription) { clearTimeout(timer); subscription.unsubscribe(); } subscription = pipe( client.query(args.query, args.variables, { ...args.requestPolicy && { requestPolicy: args.requestPolicy }, ...args.context, ...opts }), subscribe(listener) ); if (!setResult) { timer = setTimeout(() => { if (subscription) { subscription.unsubscribe(); subscription = null; } }, 1e3); } }; startQuery(); resultAtom.onMount = (update) => { setResult = update; if (subscription) { clearTimeout(timer); } else { startQuery(); } return () => { setResult = null; if (subscription) { subscription.unsubscribe(); subscription = null; } }; }; return { resultAtom, makePending, startQuery }; }); const queryAtom = atom( (get) => { const queryResult = get(queryResultAtom); if (!queryResult) { return null; } const { resultAtom } = queryResult; const result = get(resultAtom); if (!isOperationResultWithData$1(result)) { throw result.error; } return result; }, (get, set, action) => { if (action.type === "reexecute") { console.warn( "DEPRECATED [atomWithQuery] use refetch instead of reexecute" ); action.type = "refetch"; } switch (action.type) { case "refetch": { const queryResult = get(queryResultAtom); if (!queryResult) { throw new Error("query is paused"); } const { resultAtom, makePending, startQuery } = queryResult; set(resultAtom, makePending()); startQuery(action.opts); return; } } } ); return queryAtom; } function atomWithMutation(createQuery, getClient = (get) => get(clientAtom)) { const operationResultAtom = atom( new Promise(() => { }) ); const queryResultAtom = atom( (get) => get(operationResultAtom), async (get, set, action) => { set( operationResultAtom, new Promise(() => { }) ); const client = getClient(get); const query = createQuery(get); return client.mutation(query, action.variables, action.context).toPromise().then((result) => { var _a; (_a = action.callback) == null ? void 0 : _a.call(action, result); if (result.error) { throw result.error; } set(operationResultAtom, result); }); } ); return queryResultAtom; } const isOperationResultWithData = (result) => "data" in result && !result.error; function atomWithSubscription(createSubscriptionArgs, getClient = (get) => get(clientAtom)) { const queryResultAtom = atom((get) => { const args = createSubscriptionArgs(get); if (args.pause) { return null; } const client = getClient(get); let resolve = null; const makePending = () => new Promise((r) => { resolve = r; }); const resultAtom = atom(makePending()); let setResult = null; const listener = (result) => { if (resolve) { resolve(result); resolve = null; } if (setResult) { setResult(result); } }; let subscription = null; let timer; const startSub = () => { if (subscription) { clearTimeout(timer); subscription.unsubscribe(); } subscription = pipe( client.subscription(args.query, args.variables, args.context), subscribe(listener) ); if (!setResult) { timer = setTimeout(() => { if (subscription) { subscription.unsubscribe(); subscription = null; } }, 1e3); } }; startSub(); resultAtom.onMount = (update) => { setResult = update; if (subscription) { clearTimeout(timer); } else { startSub(); } return () => { setResult = null; if (subscription) { subscription.unsubscribe(); subscription = null; } }; }; return { resultAtom, makePending, startSub }; }); const queryAtom = atom( (get) => { const queryResult = get(queryResultAtom); if (!queryResult) { return null; } const { resultAtom } = queryResult; const result = get(resultAtom); if (!isOperationResultWithData(result)) { throw result.error; } return result; }, (get, set, action) => { switch (action.type) { case "refetch": { const queryResult = get(queryResultAtom); if (!queryResult) { throw new Error("query is paused"); } const { resultAtom, makePending, startSub } = queryResult; set(resultAtom, makePending()); startSub(); return; } } } ); return queryAtom; } export { atomWithMutation, atomWithQuery, atomWithSubscription, clientAtom };