deno.land / x / jotai@v1.8.4 / src / urql / atomWithQuery.ts
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176import type { AnyVariables, Client, OperationContext, OperationResult, RequestPolicy, TypedDocumentNode,} from '@urql/core'import { pipe, subscribe } from 'wonka'import type { Subscription } from 'wonka'import { atom } from 'jotai'import type { Getter, WritableAtom } from 'jotai'import { clientAtom } from './clientAtom'
type Timeout = ReturnType<typeof setTimeout>
/* * @deprecated use 'refetch' action */type DeprecatedAtomWithQueryAction = { type: 'reexecute' opts?: Partial<OperationContext>}
type AtomWithQueryAction = | { type: 'refetch' opts?: Partial<OperationContext> } | DeprecatedAtomWithQueryAction
type OperationResultWithData<Data, Variables extends AnyVariables> = Omit< OperationResult<Data, Variables>, 'data'> & { data: Data }
const isOperationResultWithData = <Data, Variables extends AnyVariables>( result: OperationResult<Data, Variables>): result is OperationResultWithData<Data, Variables> => 'data' in result && !result.error
type QueryArgs<Data, Variables extends AnyVariables> = { query: TypedDocumentNode<Data, Variables> | string variables: Variables requestPolicy?: RequestPolicy context?: Partial<OperationContext>}
type QueryArgsWithPause<Data, Variables extends AnyVariables> = QueryArgs< Data, Variables> & { pause: boolean }
export function atomWithQuery<Data, Variables extends AnyVariables>( createQueryArgs: (get: Getter) => QueryArgs<Data, Variables>, getClient?: (get: Getter) => Client): WritableAtom<OperationResultWithData<Data, Variables>, AtomWithQueryAction>
export function atomWithQuery<Data, Variables extends AnyVariables>( createQueryArgs: (get: Getter) => QueryArgsWithPause<Data, Variables>, getClient?: (get: Getter) => Client): WritableAtom< OperationResultWithData<Data, Variables> | null, AtomWithQueryAction>
export function atomWithQuery<Data, Variables extends AnyVariables>( createQueryArgs: (get: Getter) => QueryArgs<Data, Variables>, getClient: (get: Getter) => Client = (get) => get(clientAtom)) { type Result = OperationResult<Data, Variables> const queryResultAtom = atom((get) => { const args = createQueryArgs(get) if ((args as { pause?: boolean }).pause) { return null } const client = getClient(get) let resolve: ((result: Result) => void) | null = null const makePending = () => new Promise<Result>((r) => { resolve = r }) const resultAtom = atom<Result | Promise<Result>>(makePending()) let setResult: ((result: Result) => void) | null = null const listener = (result: Result) => { if (!resolve && !setResult) { throw new Error('setting result without mount') } if (resolve) { resolve(result) resolve = null } if (setResult) { setResult(result) } } let subscription: Subscription | null = null let timer: Timeout | undefined const startQuery = (opts?: Partial<OperationContext>) => { 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) { // not mounted yet timer = setTimeout(() => { if (subscription) { subscription.unsubscribe() subscription = null } }, 1000) } } startQuery() resultAtom.onMount = (update) => { setResult = update if (subscription) { clearTimeout(timer as Timeout) } 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(result)) { throw result.error } return result }, (get, set, action: AtomWithQueryAction) => { if (action.type === 'reexecute') { console.warn( 'DEPRECATED [atomWithQuery] use refetch instead of reexecute' ) ;(action as AtomWithQueryAction).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}
Version Info