@alessiofrittoli/chain-functions

中文文档
2.8.0发布于 2026/10/25MITTypeScriptESM + CJS零依赖近 30 天下载 2994

Functions chaining made easy

原始使用文档
文档目录8 节
  1. Functions chaining made easy
  2. Table of Contents
  3. Getting started
  4. Development
  5. API Reference
  6. Key Features
  7. Examples
  8. Made with ☕

Chain Functions ⛓️

Functions chaining made easy

The Chain class provides a utility for managing and executing chains of functions. Each function in the chain can optionally invoke the next function, enabling a flexible and composable flow of execution. This is particularly useful for scenarios such as middleware processing, data transformations, or handling asynchronous operations in a structured manner.

Latest version Test coverage Socket Security score npm downloads Dependencies Dependencies status

minified minizipped Tree shakable

Fund this package

Table of Contents


Getting started

Run the following command to start using chain-functions in your projects:

npm i @alessiofrittoli/chain-functions

or using pnpm

pnpm i @alessiofrittoli/chain-functions

Development

Run the following to start development

nvm use

pnpm i

Local development

Run the following

pnpm dev

This will generate unminified output code, sourcemaps and will enable source file watcher.


Production build

Run the following to create a local production build

pnpm build

This will generate minified output code without sourcemaps.


Unit tests

Run all the defined test suites by running the following:

# Run tests and watch file changes.
pnpm test:watch

# Run tests in a CI environment.
pnpm test:ci

Run tests with coverage

An HTTP server is then started to serve coverage files from ./coverage folder.

⚠️ You may see a blank page the first time you run this command. Simply refresh the browser to see the updates.

pnpm test:coverage:serve

Contributing

Contributions are truly welcome!

Please refer to the Contributing Doc for more information on how to start contributing to this project.

Help keep this project up to date with GitHub Sponsor.

GitHub Sponsor


Security

If you believe you have found a security vulnerability, we encourage you to responsibly disclose this and NOT open a public issue. We will investigate all legitimate reports. Email [email protected] to disclose any security vulnerabilities.


API Reference

Chain class

A utility class for managing and executing chains of functions.

Static Methods
Chain.functions()

Recursively executes a chain of functions.

Parameters
ParameterTypeDefaultDescription
chainChainFactory<T,U>-The chain of functions to execute.
This must be an array of functions (ChainLink<T>), where the last function is of type LastChainLink. See Types section for further informations about.
indexnumber0(Optional) The starting index for execution.

Returns

Type: T | U

The result of the chain execution, which matches the type of the chain's functions (T or U).

See Types section for further informations about.


Throws

Error if no function is found at the specified index.


Example
import type { ChainLink, LastChainLink, ChainFactory } from '@alessiofrittoli/chain-functions/types'
import { Chain } from '@alessiofrittoli/chain-functions'

type ChainFunction = () => string

const function1: ChainLink<ChainFunction> = next => () => `1-${next()}`
const function2: ChainLink<ChainFunction> = next => () => `2-${next()}`
const function3: LastChainLink<ChainFunction> = () => () => 'end'

const chain: ChainFactory<ChainFunction> = [function1, function2, function3]
const result = Chain.functions(chain)()

console.log(result) // Output: '1-2-end'

Chain.isLast()

Determines if the given function is the last function in the chain needed to type cast the last function with LastChainLink<U>.

This method is primarily used internally by the Chain.functions() method to determine when the chain execution should terminate.

Parameters
ParameterTypeDefaultDescription
chainChainFactory<T,U>-The chain of functions. See Types section for further informations about.
fnChainLink<T>|LastChainLink<U>-The function to type cast. This can be either a regular chain link or the last chain link. See Types section for further informations about.
indexnumber0(Optional) The current index of the function in the Chain.functions() recursion.

Returns

Type: boolean

Returns true if the given function is the last function in the chain, false otherwise.


Types

ChainFunction

Represents any callable function that can be invoked as part of the chain.

This is used internally to type cast other types template parameters.

ChainLink<T extends ChainFunction = ChainFunction>

Represents a single link in a chain of functions.

Parameters
ParameterTypeDescription
nextTThe next function in the chain. Its return type must be of type of T.

Returns

Type: T

A function that can be invoked as part of the chain.


LastChainLink<T extends ChainFunction = ChainFunction>

Represents the last link in a chain of functions. Unlike ChainLink, it does not accept a next parameter.

Returns

Type: T

A function that can be invoked as the final step in the chain.


ChainFactory<T extends ChainFunction = ChainFunction, U extends ChainFunction = T>

Represents the complete chain of functions as an array.

Structure
  • Can contain any number of ChainLink<T> functions.
  • The last element in the array must be a LastChainLink<U>.

Key Features

  • Chain link functions are highly customizeable.
  • Chain link functions can be async functions.
  • The last chain link could return a different type (U) other than T from a standard ChainLink.

Examples

Importing the library

// importing the main `Chain` class
// importing types
import type { ChainLink, LastChainLink, ChainFactory } from '@alessiofrittoli/chain-functions/types'
import { Chain } from '@alessiofrittoli/chain-functions'
Basic usage
// define the chain link function type
type ChainFunction = () => string

// declare chain link functions
const function1: ChainLink<ChainFunction> = next => () => `1-${next()}`
const function2: ChainLink<ChainFunction> = next => () => `2-${next()}`
// declare the last chain function
const function3: LastChainLink<ChainFunction> = () => () => 'end'

// declare the chain array
const chain: ChainFactory<ChainFunction> = [function1, function2, function3]
// execute the chain array
const result = Chain.functions(chain)()

console.log(result) // Output: '1-2-end'

Advance usage
type ChainFunctionProps = {
  someProperty: string
  firstFunction?: boolean
  secondFunction?: boolean
  thirdFunction?: boolean
}
// define the chain link function type
type ChainFunction = (props: ChainFunctionProps) => ChainFunctionProps

// declare chain link functions
const function1: ChainLink<ChainFunction> = next => props => {
  // edit properties
  props.someProperty = 'Edited by 1st function'
  props.firstFunction = true
  // call the next function in the chain
  return next(props)
}

const function2: ChainLink<ChainFunction> = next => props => {
  props.secondFunction = true

  if (props.someProperty === 'Edited by 1st function') {
    // stop chain execution if some condition is met.
    return props
  }

  // call the next function in the chain
  return next(props)
}

// declare the last chain function
const function3: LastChainLink<ChainFunction> = () => props => {
  props.thirdFunction = true
  return props
}

// declare the chain array
const chain: ChainFactory<ChainFunction> = [function1, function2, function3]
// declare the initial state
const initialState: ChainFunctionProps = {
  someProperty: 'Initial value',
  firstFunction: false,
  secondFunction: false,
  thirdFunction: false,
}
// execute the chain array with initial state
const result = Chain.functions(chain)(initialState)

console.log(result)
// Output: {
//  someProperty    : 'Edited by 1st function',
//  firstFunction   : true,
//  secondFunction  : true,
//  thirdFunction   : false,
// }

`LastChainLink` with custom return type
type ChainFunction = () => string
type LastChainFunction = () => boolean

const function1: ChainLink<ChainFunction> = next => () => `1-${next()}`
const function2: ChainLink<ChainFunction> = next => () => `2-${next()}`
const function3: LastChainLink<LastChainFunction> = () => () => true

const chain: ChainFactory<ChainFunction, LastChainFunction> = [function1, function2, function3]
const result = Chain.functions(chain)()

console.log(result) // Outputs: '1-2-true'

`ChainLink` functions with promises
type ChainFunction = () => string | Promise<string>

const function1: ChainLink<ChainFunction> = next => async () => {
  // simulate a long task running
  await new Promise<void>(resolve => setTimeout(resolve, 5000))
  return `1-${next()}`
}
// this function is executed once `function1` Promise get resolved.
const function2: ChainLink<ChainFunction> = next => () => `2-${next()}`
const function3: LastChainLink<ChainFunction> = () => () => 'end'

const chain: ChainFactory<ChainFunction> = [function1, function2, function3]
const result = Chain.functions(chain)() // `result` is now a promise

console.log(await result) // Outputs: '1-2-end'

Next.js middleware chain
// src/middleware.ts

import type { ChainFactory, ChainLink, LastChainLink } from '@alessiofrittoli/chain-functions/types'
import { NextMiddleware, NextResponse } from 'next/server'
import { Chain } from '@alessiofrittoli/chain-functions'

type Middleware = ChainLink<NextMiddleware>
type LastMiddleware = () => NextResponse<unknown>
type MiddlewareFactory = ChainFactory<NextMiddleware, LastMiddleware>

const middleware1: Middleware = next => async (request, event) => {
  const { nextUrl } = request

  if (nextUrl === '...') {
    const rewriteUrl = '...'
    return NextResponse.rewrite(rewriteUrl)
  }

  return next(request, event)
}

const middleware2: Middleware = next => async (request, event) => {
  const response = await next(request, event)

  // do something with `response` returned by the next middleware.
  // ...

  return response
}

// ensures `NextResponse.next()` is called if no one stops the chain.
const lastMiddleware: LastChainLink<LastMiddleware> = () => () => NextResponse.next()

const middlewares: MiddlewareFactory = [middleware1, middleware2, lastMiddleware]

export const config = {
  matcher: [
    /**
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico (favicon file)
     */
    '/((?!api/|_next|.*\\..*).*)',
  ],
}

// note that we do not execute the chain like in the previous examples since Next.js is responsible for the execution, providing `request` and `event` parameters to the `middleware` functions.
export default Chain.functions(middlewares)

Made with ☕

avatar
Alessio Frittoli
https://alessiofrittoli.it | [email protected]

版本与发布记录

@alessiofrittoli/chain-functions 共发布 13 个版本,首次发布于 2024/12/22;过去 12 个月发布了 4 个版本。

版本发布日期距今
2.8.0latest2026/10/2514 天前
2.7.02026/10/061 个月前
2.6.02026/10/061 个月前
2.5.02025/12/0411 个月前
2.4.02025/07/211.3 年前
2.3.02025/05/021.5 年前

关于 @alessiofrittoli/chain-functions 的常见问题

@alessiofrittoli/chain-functions 是什么?

Functions chaining made easy

如何安装 @alessiofrittoli/chain-functions?

在项目目录运行 npm install @alessiofrittoli/chain-functions,或使用 pnpm add / yarn add / bun add。

@alessiofrittoli/chain-functions 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@alessiofrittoli/chain-functions 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@alessiofrittoli/chain-functions 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=24.15.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@alessiofrittoli/chain-functions 可以商用吗?

@alessiofrittoli/chain-functions 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@alessiofrittoli/chain-functions 的下载量有多少?

根据 npm 官方下载统计,@alessiofrittoli/chain-functions 在 2026/10/06 – 2026/11/04 这 30 天内被下载 2,994 次,日均约 100 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@alessiofrittoli/chain-functions 还在维护吗?

最新版本 2.8.0 发布于 2026/10/25(14 天前);至今共发布 13 个版本,其中过去 12 个月发布了 4 个;首次发布于 2024/12/22。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。