Skip to content

Query Definitions

Query definitions are how you tell QueryCache what data you want to cache and how it relates to your tags. You define them once, and they become methods on your cache instance. They handle all the caching machinery for you.

import { QueryCache, at, wild, MemoryAdapter } from '@t87s/core';
const cache = QueryCache({
schema: at('users', () => wild),
adapter: new MemoryAdapter(),
defaultTtl: '1m',
defaultGrace: '5m',
queries: (tags) => ({
getUser: (id: string) => ({
tags: [tags.users(id)],
fn: () => db.users.findById(id),
}),
getUserWithPosts: (id: string) => ({
tags: [tags.users(id)],
ttl: '30s', // override the default for this query
fn: () => db.users.findByIdWithPosts(id),
}),
}),
});
// Now use those methods to...
await cache.getUser('123'); // get a user
await cache.getUserWithPosts('123'); // get their posts

Remember that schema you defined in the last section? It gets injected into your query constructor as a tag constructor, where anything that was marked wild becomes a function accepting a string.

Tag constructors are typesafe, meaning if you try to construct a tag that’s not defined in your schema, your type checker will yell at you. If you try to pass anything other than a valid tag to a query, your type checker will yell at you. If you abandon t87s for another caching library, your type checker will yell at you. Basically, schemas generate tag constructors that allow you to feed tags to queries.

As we’ll see in the next section, you can invalidate a tag at any time. Any query that is marked with that tag, or any of its descendants, is invalidated.