Quick Start
🎯 Build your business logic like building blocks
💡 Type Safety + Functional = Elegant Middleware Pipeline
Hey! 👋 Welcome to the world of farrow-pipeline. If you've ever:
- 🤯 Been tortured by callback hell
- 😵 Lost
thisin asynchronous code - 😤 Debugged middleware order issues late into the night
- 🥲 Written spaghetti code that's hard to test
Then congratulations, you've found the right place! farrow-pipeline is here to save you.
🚀 Installation
As simple as installing any npm package:
npm install farrow-pipeline
# Or use your favorite package manager
pnpm add farrow-pipeline
yarn add farrow-pipeline⚠️ Note: farrow-pipeline can only run in Node.js environments (depends on AsyncLocalStorage), browser environments should detour.
🎨 Your First Pipeline
Imagine you're doing a math problem: double a number, then format the output. Writing it the traditional way is boring, but with Pipeline it's as fun as building blocks:
import { createPipeline } from 'farrow-pipeline'
// Create a number processing pipeline (input number, output string)
const pipeline = createPipeline<number, string>()
// First block: double the number
pipeline.use((input, next) => {
console.log('Received number:', input)
return next(input * 2) // Pass to next block
})
// Second block: format output
pipeline.use((input) => {
return `Result: ${input}`
})
// 🎉 Run!
const result = pipeline.run(5)
console.log(result) // "Result: 10"That's it! You just created your first Pipeline. Doesn't that feel pretty simple? 😎
Basic Usage
Creating Pipeline
Super simple, just specify input and output types:
// Simplest way
const pipeline = createPipeline<InputType, OutputType>()
// Example: receive string, return number
const parser = createPipeline<string, number>()Adding Middleware
Method 1: Add one by one
pipeline.use((input, next) => {
// Do something
return next(input)
})
pipeline.use((input, next) => {
// Do something else
return next(input)
})Method 2: Add in batch
pipeline.use(
middleware1,
middleware2,
middleware3
)Method 3: Chain calls (most elegant)
createPipeline<number, string>()
.use((x, next) => next(x + 1))
.use((x, next) => next(x * 2))
.use((x) => `Result: ${x}`)💡 Tip: Chain calls look like a pipeline, very intuitive!
Running Pipeline
// Basic run
const result = pipeline.run(input)
// Run with default handler
const result = pipeline.run(input, {
onLast: (input) => `If all middleware call next, execute me`
})Quick Example Collection
Example 1: Data Transformation Pipeline
const dataProcessor = createPipeline<string, number>()
.use((input, next) => {
// Remove whitespace
return next(input.trim())
})
.use((input, next) => {
// Convert to number
const num = parseInt(input, 10)
return next(num)
})
.use((input) => {
// Double
return input * 2
})
console.log(dataProcessor.run(' 42 ')) // 84Example 2: Validation Pipeline
const validator = createPipeline<any, string>()
.use((input, next) => {
if (typeof input !== 'object') {
return 'Input must be an object'
}
return next(input)
})
.use((input, next) => {
if (!input.name) {
return 'Missing name field'
}
return next(input)
})
.use((input) => {
return 'Validation passed'
})
console.log(validator.run({ name: 'Alice' })) // "Validation passed"
console.log(validator.run('invalid')) // "Input must be an object"Example 3: Logging Pipeline
const logger = createPipeline<string, string>()
.use((input, next) => {
console.log('📥 Input:', input)
const result = next(input.toUpperCase())
console.log('📤 Output:', result)
return result
})
.use((input) => {
return `[Completed] ${input}`
})
logger.run('hello')
// 📥 Input: hello
// 📤 Output: [COMPLETED] HELLONext Steps
Now that you've mastered the basics, let's learn:
- Core Concepts - Deep understanding of the onion model
- Context System - Elegantly share state
- Async Processing - Promises are no longer scary
