MCPcopy Create free account
hub / github.com/effect-app/libs / buildQueryFamily

Function buildQueryFamily

packages/vue/src/atomQuery.ts:416–493  ·  view source on GitHub ↗
(
  rt: AtomClientRuntime,
  self: {
    readonly id: string
    readonly handler: (i: I) => Effect.Effect<A, E, any>
    readonly options?: ClientForOptions
    readonly queryKeyProjectionHash?: string
  }
)

Source from the content-addressed store, hash-verified

414 if (opts.refetchInterval) atom = Atom.withRefresh(Duration.millis(opts.refetchInterval))(atom)
415 if (opts.structuralSharing ?? true) atom = structuralShare(atom)
416 return atom
417}
418
419/** Constant atom for disabled / `mode:"optional"`-None queries: stays Initial, never fetches. */
420export const disabledQueryAtom: Atom.Atom<AsyncResult.AsyncResult<any, any>> = Atom.readable(() =>
421 AsyncResult.initial(false)
422)
423
424/**
425 * Bumps when the browser regains connectivity (the `online` event) — the tanstack
426 * `refetchOnReconnect` trigger. One shared listener (module-level). SSR-guarded.
427 */
428const onlineSignal: Atom.Atom<number> = Atom.readable((get) => {
429 let count = 0
430 if (typeof window === "undefined") return count
431 const update = () => {
432 if (navigator.onLine) get.setSelf(++count)
433 }
434 window.addEventListener("online", update)
435 get.addFinalizer(() => window.removeEventListener("online", update))
436 return count
437})
438
439/**
440 * Focus OR reconnect, as a single signal for `swr` — both should stale-revalidate a query.
441 * swr takes one `focusSignal`, so we fold window-focus + reconnect into one derived atom;
442 * a bump from either triggers swr's stale check.
443 */
444const focusOrReconnectSignal: Atom.Atom<number> = Atom.make((get) => get(Atom.windowFocusSignal) + get(onlineSignal))
445
446/**
447 * Build the per-input atom family for a request handler — the query CACHE IDENTITY.
448 *
449 * This is the TanStack `queryKey = [handler, input]` equivalent and the piece that makes
450 * caching cross-component: `Atom.family` memoizes one atom per structurally-distinct input
451 * (v4 hashes the input via Hash/Equal), so every component querying the same handler+input
452 * reads the SAME atom instance => one fetch, one shared result in the global registry,
453 * ref-counted and GC'd on idle ttl. (The registry + ttl give lifetime; reactivity keys give
454 * invalidation; the family gives identity/sharing — all three are needed.)
455 *
456 * The family is created once per handler (see query.ts's per-handler cache), so it is shared
457 * process-wide via the registry.
458 *
459 * Invalidation is hierarchical: each atom registers under EVERY prefix of its full key
460 * `[...makeQueryKey(self), input]`. Since reactivity matches keys by exact hash, registering
461 * all prefixes means `invalidate(P)` refreshes every atom whose key starts with `P` — e.g.
462 * `["$X"]` refreshes all inputs, `["$X","$List",input]` only that input. (`makeQueryKey`'s
463 * collapsed form `getQueryKey` — what mutations invalidate by default — is one of the prefixes.)
464 */
465export const buildQueryFamily = <I, A, E>(
466 rt: AtomClientRuntime,
467 self: {
468 readonly id: string
469 readonly handler: (i: I) => Effect.Effect<A, E, any>
470 readonly options?: ClientForOptions
471 readonly queryKeyProjectionHash?: string
472 }
473) => {

Callers 7

getQueryFamilyFunction · 0.90
query-span.test.tsFile · 0.85
makeAtomHarnessFunction · 0.85
queryAtomFunction · 0.85

Calls 15

makeQueryKeyFunction · 0.90
setQueryReadDependenciesFunction · 0.90
reportRuntimeErrorFunction · 0.90
takeAtomQueryParentSpanFunction · 0.85
uniqueKeysFunction · 0.85
prefixesOfFunction · 0.85
trackByKeysFunction · 0.85
trackReadDependenciesFunction · 0.85
setAtomQueryMetadataFunction · 0.85
handlerMethod · 0.80
syncMethod · 0.80
makeMethod · 0.65

Tested by 2

makeAtomHarnessFunction · 0.68
queryAtomFunction · 0.68

Used in the wild real call sites across dependent graphs

searching dependent graphs…