Nano Banana Pro
Agent skill for nano-banana-pro
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Sign in to like and favorite skills
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
typed-handler is a TypeScript library that provides a fluent, type-safe API for building request handlers with automatic validation and framework-agnostic design. The library allows developers to create handlers that work with any validation library (Zod, Joi, Yup, etc.) and any web framework (Express, Fastify, Hono, etc.).
Key Design Principles:
This project uses pnpm (version 8.15.0). Always use pnpm, never npm or yarn.
# Install dependencies pnpm install # Set up git hooks (run after install) pnpm prepare
# Run development server (watches examples/express-zod/index.ts) pnpm dev # Type checking pnpm type-check
# Run tests (Vitest) pnpm test # Run tests in watch mode pnpm test:watch # Run tests with coverage (requires 90% coverage threshold) pnpm test:coverage # Run type tests (tsd) pnpm test:types
# Build library (uses tsup) pnpm build # Output: dist/ directory with CommonJS, ESM, and TypeScript declarations # Entry points: src/index.ts and src/adapters/index.ts
# Lint (Biome) pnpm lint # Lint and auto-fix pnpm lint:fix # Format code pnpm format
pnpm lint-staged (lints staged files with Biome)pnpm type-check && pnpm test --run# Create changeset pnpm changeset # Version packages pnpm version # Release (builds and publishes) pnpm release
Handler Class (
src/handler.ts): Main builder class using immutable chain construction. Each method clones the handler and returns a new instance.
Validator System (
src/validators/): Auto-detects validation libraries (Zod, Joi, Yup) and provides adapter registration for custom validators.
Framework Adapters (
src/adapters/): Bridge handlers to web frameworks (Express, Fastify, Hono, Raw).
Type System (
src/types.ts): TypeScript types for full type inference throughout the handler chain.
Configuration (
src/config.ts): Global and per-handler configuration with pluggable logger interface.
Input Data → Validate Input → Run Middleware (build context) → Execute Handler → Validate Output → Return Result
Each step:
validateInput (default: true)validateOutput (default: off in production)The library detects if input schema is an object with
body, query, params, or headers keys. When detected, framework adapters extract the appropriate data from the request object.
Critical implementation detail: All builder methods (
.input(), .use(), .handle(), .output()) must:
this.clone()This ensures handlers can be reused and composed without mutations.
src/ ├── index.ts # Main exports ├── handler.ts # Handler class (core builder) ├── types.ts # Core types and type inference ├── config.ts # Configuration system ├── validators/ │ └── registry.ts # Custom validator registration ├── adapters/ │ ├── index.ts # Adapter exports │ ├── express.ts # Express integration │ ├── fastify.ts # Fastify integration │ ├── hono.ts # Hono integration │ └── raw.ts # Raw handler (custom integration) ├── errors/ │ ├── index.ts │ ├── validation.ts # ValidationError │ └── handler.ts # HandlerError └── utils/ └── response.ts # ResponseObject helpers
Current Status: Core handler implementation is complete, including all builder methods, validation system, and framework adapters.
The technical specification (
TECHSPEC.md) provides the complete design. Reference it when implementing features.
tsdTest files go in
tests/ directory:
tests/ ├── unit/ ├── integration/ └── types/
When implementing or modifying code:
.use() must merge context types: Handler<TInput, TContext & TNewContext, TOutput>tsd tests for any new type inference scenariosconst h = handler() .input(zodSchema) // Infer input type from schema .use(async () => ({ user })) // Add context .handle(async (input, ctx) => result) // Handler function .output(zodSchema); // Validate output
// Adapters check for multi-input and extract appropriately const input = handler.expectsMultiInput() ? { body: req.body, query: req.query, params: req.params, headers: req.headers } : req.body; const result = await handler.execute(input, { req, res });
configure({ validateOutput: false })handler({ logger: customLogger })This project uses Biome for linting and formatting. Common lint ignores in the codebase:
noExplicitAny: Required for registry and type inference flexibilitynoStaticOnlyClass: For factory pattern placeholderscomplexity/noStaticOnlyClass: For handler factoryTECHSPEC.md) for detailed design decisions