Skill

Build Type-Safe Backend Services with fp-ts

fp-ts patterns for Node.js/Deno backends: ReaderTaskEither services, layered dependency injection, and typed error handling.

Works with githubnode.jsdenoprisma

81
Spark score
out of 100
Updated 19 days ago
Version 15.1.0

Add to Favorites

Why it matters

Implement robust, testable, and type-safe backend services using functional programming patterns with fp-ts. This asset provides architectural guidance and code examples for dependency injection, service composition, and error handling in Node.js and Deno environments.

Outcomes

What it gets done

01

Structure backend services using ReaderTaskEither for dependency management and error handling.

02

Implement functional patterns for dependency injection and service composition.

03

Define and manage typed domain errors for robust backend applications.

04

Generate boilerplate code for common backend service operations.

Install

Add it to your toolbox

Run in your project directory:

curl -fsSL https://spark.entire.vc/get/ag-fp-backend | bash

Overview

fp-ts Backend Patterns

A functional-programming reference for Node.js/Deno backends: ReaderTaskEither-based services, layered dependency injection, Prisma error wrapping, Express/Hono middleware, typed error hierarchies, and retry/fallback/circuit-breaker recovery patterns. Use it when building or refactoring a backend around fp-ts and need a full architecture - services, DI, database, middleware, error handling, and tests - not just a single isolated utility function.

What it does

This skill supplies a library of functional-programming backend patterns for Node.js/Deno services built on fp-ts, centered on the ReaderTaskEither<R, E, A> (RTE) type - R for injected dependencies (db, config, logger), E for a typed error, and A for the success value. It works through concrete, worked examples rather than isolated snippets.

Service Layer Patterns show how to structure services as modules of RTE functions (e.g. a user.service.ts with create, findById, and paginated findMany), and how to compose multiple services together (an order.service.ts that validates a user, validates and prices products, charges payment, and creates the order via RTE.Do/RTE.bind chaining).

Functional Dependency Injection is handled as a layered container: Layer 0 loads config from environment variables, Layer 1 builds infrastructure (Prisma client, Redis client, logger) from that config, and Layer 2 builds services (password hasher, JWT service, mailer) from the infrastructure - all composed via TaskEither into a single buildDeps()/destroyDeps() pair used to start and cleanly shut down the app in main.ts.

Database Operations cover a wrapPrisma helper that maps Prisma's error codes (P2002 unique violation, P2003 foreign-key violation, P2025 record not found) into a typed DbError union, a generic createRepository factory producing typed CRUD methods (with findUnique returning an Option) from any Prisma delegate, and a withTransaction wrapper that runs an RTE program inside db.$transaction, rolling back on a Left - demonstrated with a transferFunds example that debits and credits accounts and rejects insufficient-funds transfers.

Middleware Patterns include adapters that convert an RTE handler into Express (toHandler) or Hono (toHonoHandler) request handlers, each mapping domain error tags to HTTP status codes; Hono-specific middleware for storing dependencies in context, Zod-based request validation, and Bearer-token auth (requireAuth); and a request-context pattern that attaches a requestId, optional userId, and startTime to each request for structured, elapsed-time-aware logging.

Error Handling defines a typed DomainError hierarchy (NotFoundError, ValidationError, ConflictError, AuthError, InfrastructureError) with smart constructors and mappers to HTTP status and response body, plus recovery combinators: withRetry (exponential backoff with a shouldRetry predicate), withFallback (cache successful results, serve the cached value on failure), and a createCircuitBreaker (closed/open/half-open state machine that opens after a failure threshold and resets after a timeout).

Testing Strategies cover mocking dependencies with vi.fn() for unit tests, spinning up a real Postgres instance via @testcontainers/postgresql for integration tests, and property-based testing of validators with fast-check. A closing Quick Reference lists the common fp-ts imports, an RTE operator cheat sheet (right, left, ask, fromTaskEither, flatMap, map, mapLeft, tap, tapError, orElse, getOrElse, and more), and a blank service template to start a new module from.

When to use - and when NOT to

Use this skill when building or refactoring a Node.js or Deno backend with fp-ts, particularly when the task involves dependency injection, service composition, or typed backend errors modeled with ReaderTaskEither. Use it when you need a full functional backend architecture, not just an isolated utility snippet.

Inputs and outputs

Inputs: the backend feature or service being built (e.g. a CRUD service, an authenticated endpoint, a multi-step transactional operation) and its dependencies (database client, cache, logger, external services). Output: typed ReaderTaskEither-based service functions, a layered dependency container, Prisma error-wrapping utilities, Express/Hono middleware adapters, a typed domain-error hierarchy with HTTP mappings, retry/fallback/circuit-breaker recovery wrappers, and unit/integration/property-based tests for the resulting code.

Integrations

Built on fp-ts (ReaderTaskEither, TaskEither, Either, Option, Array), and demonstrated against Prisma (database access and transactions), Express and Hono (HTTP middleware), Zod (request validation), @testcontainers/postgresql (integration testing), and fast-check (property-based testing).

Who it's for

Backend developers building type-safe, testable Node.js or Deno services who want a consistent functional architecture for dependency injection, database access, middleware, error handling, and testing rather than assembling these patterns from scratch.

FAQ

Common questions

Discussion

Questions & comments ยท 0

Sign In Sign in to leave a comment.