api-filters

Implement composable filters and router-service-repository structure for paginated Drizzle list APIs.

Updated May 7, 2026
One-click install
npx skills add https://github.com/johinsDev/loyalty-app --skill api-filters
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: api-filters
Source: https://github.com/johinsDev/loyalty-app/tree/main/.claude/skills/api-filters
Command: npx skills add https://github.com/johinsDev/loyalty-app --skill api-filters

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

It solves the problem of messy, duplicated list-query logic by providing a consistent three-layer feature structure and a reusable filtering mechanism for paginated endpoints.

Core Features & Use Cases

  • Router → Service → Repository separation: keep tRPC wiring, business rules, and Drizzle database access cleanly partitioned so each layer is easier to evolve and test.
  • Composable filter classes: implement one filter per key and apply them consistently across both row queries and total-count queries.
  • Pagination contract with filtered totals: return { rows, total } where the total matches the active filters, using the same filter set for both queries.
  • Use case: refactor an existing inline Drizzle router into a features/<name>/ folder shape, then add new list filters without touching unrelated router/service code.

Quick Start

Tell the AI to scaffold a new @loyalty/api feature folder using the filters pattern so a list endpoint supports filterable search and returns paginated rows plus a filter-aware total count.

Frequently Asked Questions about api-filters

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I structure tRPC list endpoints with composable Drizzle filters?

Structure tRPC list endpoints using a router-service-repository pattern where composable filter classes handle Drizzle query chaining. This separates tRPC wiring, business rules, and database access into clean layers for easier testing and evolution.

What is the repository pattern for tRPC and Drizzle pagination?

The repository pattern for tRPC and Drizzle pagination isolates database access in repository classes using Drizzle's $dynamic() method. This allows services to instantiate repositories per request, ensuring safe context-bound database usage while maintaining clean separation.

How do I keep filtered total counts consistent with list rows in paginated APIs?

Keep filtered total counts consistent by applying the same composable filter set to both row queries and total-count queries. This ensures the returned total matches the active filters, providing accurate pagination metadata for the displayed results.

Can I refactor an existing inline Drizzle router into a feature folder structure?

Yes, you can refactor inline Drizzle routers into a features/<name>/ folder structure containing router, service, and repository files. This allows you to add new list filters without touching unrelated router or service code, improving maintainability.

Does this composable filter approach work without external dependencies?

Yes, the composable filter approach works without external dependencies by implementing a shared Filters base class with allowed filter keys and per-feature filter subclasses. It relies solely on tRPC and Drizzle ORM already present in your stack.

When should I use dynamic query building for API filters in Drizzle?

Use dynamic query building for API filters in Drizzle when adding or refactoring list endpoints with optional filters. Drizzle's $dynamic() method enables deterministic query chaining, allowing composable filter classes to conditionally apply where clauses.