npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@rudenko/call-chain

v1.0.0

Published

Switch from imperative chained calls to declarative chain description and invocation

Readme

call-chain

Convert imperative code that chains a number of method calls into declarative code.

Table of Contents

Examples

Example 1. Impractical demo

Doesn't make much sense, just a demo on a commonly known pattern for an array transformation.

const inputArray = [1, 2, 3, 4, 5, 6, 7, 8, 9]
const reducer = (acc, e, i) => {
  // keep elements with odd indices only
  if (i%2) acc.push(e)
  return acc
}

// classical approach
inputArray
  .filter(e => e % 2)
  .map(e => e * 2)
  .reduce(reducer, [])

// call-chain fantasy approach
callChain(inputArray, [
  ["filter", e => e % 2],
  ["map", e => e * 2],
  ["reduce", [reducer, []]]
])

Example 2. Practical demo

KnexJS offers a query builder that is a set of chainable methods to construct SQL queries.

You will prefer declarative approach if you need to import table schemas or other queries from files or provide by users (and you do now want users to provide runnable code).

In the scenario below employeeTableSchema could have been imported from a module or JSON.

// KnexJS
table
  .integer("employee_id")
  .unsigned()
  .notNullable()
  .references("id")
  .inTable("employees")

// same code with chainCall
const employeeTableSchema = [
  ["integer", "employee_id"],
  ["unsigned", []],
  ["notNullable", []],
  ["references", "id"],
  ["inTable", "employees"]
]

chainCall(table, employeeTableSchema)

Usage. Chain description conventions and flags

const callChain = (object, chain, allPropertiesAreMethods = false, useOptionalChaining = false)

Parameters:

  • object to apply chain of calls to
  • chain is an array of chain elements where each element represents an object field (state) or method (behavior represented by a function).
  • allPropertiesAreMethods flag: if true then each property in chain description is treated as a callable method
  • useOptionalChaining flag: if true then undefined properties do not break code execution by usage of optional chaining operator ?.

Use flags with caution.

Canonical chain element description is

[
  [fieldName], // for a field
  [methodName, [callArguments]] // for a method
  // wrap all arguments into array; use empty array if no arguments to be passed
]

Canonization rules for non-canonical descriptions

[
  propertyName,           // => [propertyName] or, if allPropertiesAreMethods === true, [propertyName, []]
  [propertyName],         // => if allPropertiesAreMethods === true, [propertyName, []]
  [methodName, argument]  // => [methodName, [argument]]
]

FAQ

Q1. Why don't you use call-chain in the modules tests?

A. We do. call-chain.self.test.mjs uses chain-call to test chain-call. Although we consider this approach