Teardown

Core Concepts

QueryClient architecture, key generation, and type system.

QueryClient Class

The QueryClient is an abstract base class for organizing queries and mutations within a specific resource domain. Each resource (projects, users, orgs) gets its own client.

import { QueryClient, type TanstackQueryClient } from "@teardown/queries";

class ProjectsClient extends QueryClient<"projects"> {
  constructor(tanstackClient: TanstackQueryClient) {
    super(tanstackClient, "projects", {
      staleTime: 5 * 60 * 1000,
      gcTime: 30 * 60 * 1000,
    });
  }
}

Constructor Parameters

ParameterTypeDescription
clientTanstackQueryClientTanStack Query's QueryClient instance
resourcestringResource name (e.g., "projects", "users")
defaultOptionsDefaultOptionsOptional default staleTime and gcTime

Query Key Architecture

Queries are organized in a hierarchical structure:

  • Resource - Top-level domain (e.g., "projects", "teams")
  • Sub-resource - Query type within domain (e.g., "list", "byId")
  • Arguments - Additional parameters for uniqueness

Query Key Format

["@teardown", resource, "query", subResource, ...args]

// Examples:
["@teardown", "projects", "query", "list", { page: 1 }]
["@teardown", "projects", "query", "byId", "proj-123"]
["@teardown", "users", "query", "profile", "user-456"]

Mutation Key Format

["@teardown", resource, "mutation", mutationKey, ...args]

// Examples:
["@teardown", "projects", "mutation", "create"]
["@teardown", "projects", "mutation", "update", "proj-123"]

Type System

QueryKey Type

type QueryKey<Resource, SubResource, Args> = [
  "@teardown",
  Resource,
  "query",
  SubResource,
  ...Args
];

MutationKey Type

type MutationKey<Resource, SubResource, Args> = [
  "@teardown",
  Resource,
  "mutation",
  SubResource,
  ...Args
];

DefaultOptions

interface DefaultOptions {
  staleTime?: number;  // How long data stays fresh (ms)
  gcTime?: number;     // How long unused data is kept (ms)
}

Key Generation Methods

The QueryClient provides methods for generating consistent keys:

class ProjectsClient extends QueryClient<"projects"> {
  someMethod() {
    // Generate query key
    const queryKey = this.queryKeyGen("list", userId);
    // Result: ["@teardown", "projects", "query", "list", userId]

    // Generate mutation key
    const mutationKey = this.mutationKeyGen("create");
    // Result: ["@teardown", "projects", "mutation", "create"]
  }
}

Query Result Interface

The query() method returns an enhanced result with utility methods:

interface CreateQueryResult<Resource, SubResource, Args, TData, TError> {
  // Standard TanStack Query options
  queryKey: QueryKey;
  queryFn: QueryFunction<TData>;

  // Convenience methods
  fetch(): Promise<TData>;       // One-time fetch
  prefetch(): Promise<void>;     // Populate cache without subscribing
  get(): TData | undefined;      // Read current cache value
  set(param): void;              // Update cache value
  refresh(): Promise<void>;      // Invalidate and refetch
}

Cache Invalidation

The refresh() method invalidates queries at different levels:

// Invalidate specific query with args
await projectsClient.refresh("list", userId);

// Invalidate all queries for a sub-resource
await projectsClient.refresh("list");

// Invalidate entire resource domain
await projectsClient.refresh();

Multiple QueryClients

Organize multiple resources with a container class:

class QueryClients {
  projects: ProjectsClient;
  users: UsersClient;
  orgs: OrgsClient;

  constructor(tanstackClient: TanstackQueryClient) {
    this.projects = new ProjectsClient(tanstackClient);
    this.users = new UsersClient(tanstackClient);
    this.orgs = new OrgsClient(tanstackClient);
  }

  shutdown() {
    this.projects.shutdown();
    this.users.shutdown();
    this.orgs.shutdown();
  }
}