Skip to content

chlbri/pipe-machine

Repository files navigation

@bemedev/pipe-machine

Features

  • 3-Step Builder - Separate type declaration from implementation for maximum clarity: createPipe → type → define
  • Strongly-Typed Pipes - Full TypeScript type inference and validation throughout the pipeline
  • Named-Step Support - Create named pipeline steps for better code clarity and partial overrides
  • Explicit Type Spec - Declare input/output types before providing implementations
  • Async Support - Handle both synchronous and asynchronous function pipelines
  • Duplicate Key Support - Reuse a step name to run the same function multiple times in the pipeline

Installation

npm install @bemedev/pipe-machine
# or
pnpm add @bemedev/pipe-machine

Quick Start

import { createPipe } from '@bemedev/pipe-machine';

const pipe = createPipe('double', 'add10')
  .type<{
    double: { parameters: [number]; return: number };
    add10: number;
  }>()
  .define({
    double: x => x * 2,
    add10: x => x + 10,
  });

pipe(5); // 20

The 3-Step Flow

Step 1 — createPipe(...keys)

Declares the ordered list of named steps in the pipeline.

const builder = createPipe('parse', 'validate', 'transform');

Step 2 — .type<TypeSpec>()

Declares the TypeScript types for the pipeline — no runtime argument, pure generic. Only the first key is required and must have the shape { parameters: [...], return: ... }. All other keys are optional and specify just their return type. Unspecified keys default to identity typing (pass-through: same input and output type as the previous step).

const typed = builder.type<{
  parse: { parameters: [string]; return: number };
  validate: number; // (n: number) => number
  // 'transform' not listed → identity: (n: number) => number
}>();

Step 3 — .define(impl)

Provides the function implementation for every unique key. Types are enforced by the spec from .type<T>().

const pipeline = typed.define({
  parse: s => parseInt(s, 10),
  validate: n => Math.abs(n),
  transform: n => n * 100, // (number) => number — identity-typed
});

pipeline('−42'); // 4200

Advanced Usage

Duplicate keys

Repeat a key name to run that function more than once:

const fn = createPipe('add1', 'double', 'add1', 'double', 'add1')
  .type<{
    add1: { parameters: [number]; return: number };
    double: number;
  }>()
  .define({ add1: x => x + 1, double: x => x * 2 });

fn(2); // ((((2+1)*2)+1)*2)+1 = 15

When a key appears more than once, its DefineImpl slot is typed as IdentityFn<PrevReturn> — an identity function (x: T) => T — enforcing that a duplicated step passes its input value through unchanged in type. When the first key is duplicated, its parameters type is restricted to a single-element tuple to prevent ambiguous multi-arg signatures.

Multi-argument first step

const fn = createPipe('hypot', 'double')
  .type<{
    hypot: { parameters: [number, number]; return: number };
    double: number;
  }>()
  .define({
    hypot: (a, b) => Math.hypot(a, b),
    double: x => x * 2,
  });

fn(3, 4); // 10

Async pipelines

If any step returns a Promise, the entire pipeline becomes async:

const fn = createPipe('fetch', 'parse')
  .type<{
    fetch: { parameters: [string]; return: Promise<string> };
    parse: number;
  }>()
  .define({
    fetch: async url => (await fetch(url)).text(),
    parse: s => parseInt(s, 10),
  });

await fn('https://example.com/value'); // number

Partial overrides

After building a pipeline, create variants by overriding specific steps:

const base = createPipe('add1', 'double')
  .type<{
    add1: { parameters: [number]; return: number };
    double: number;
  }>()
  .define({ add1: x => x + 1, double: x => x * 2 });

base(5); // 12

const tripled = base.define({ double: x => x * 3 });
tripled(5); // 18

API

createPipe(...keys: Describer[]): MachineCreated

Creates a pipeline builder with named steps. Each key can be a plain string or a { name: string; description: string } object to attach a human-readable description. Throws if called with no keys. Returns an object with a .type<T>() method.

.type<T extends MachineTypeSpec>(schema?: StandardSchemaV1): MachineTyped

Declares types for the pipeline. T is a pure TypeScript generic with shape { params: any[]; context: Record<string, any> }. An optional StandardSchemaV1-compatible schema (e.g. a zod, a @bemedev/typings object, or valibot object) may be passed as a runtime argument for schema-based validation. Returns an object with only a .define(impl) method.

.define(impl: MachineDefineInput): MachinePipeline

Provides implementations for actions and configuration. Returns the completed, callable pipeline.

pipeline(...params): Context | Promise<Context>

Calls the composed pipeline. Returns a Promise if any step is async, otherwise returns synchronously. The return type matches the context type from the MachineTypeSpec.

pipeline.define(overrides: Partial<MachineDefineInput>): MachinePipeline

Creates a new pipeline with some actions or guards replaced. Original pipeline is unchanged.

pipeline.build<T>(select: (ctx: Context) => T): (params) => T

Transforms the output of the pipeline using a selector function.

Exported Types

Type Description
MachineCreated Returned by createPipe()
MachineTyped Returned by .type<T>()
MachinePipeline Completed callable pipeline
MachineTypeSpec Type spec shape: { params: any[]; context: Record<string, any> }
MachineDefineInput Shape of the .define(impl) argument
Describer Step key type: string or { name: string; description: string }
FromDescriber<D> Extracts the string key name from a Describer
Config Configuration object shape for guards and delays
Condition Guard condition type
Delayed Delayed action configuration with delay timing
GuardConfig Shape for guard configuration
ExtractActions<C> Extracts action names from a config
ExtractGuards<C> Extracts guard names from a config
ExtractDelays<C> Extracts delay names from a config
SoA Struct-of-Arrays utility type

Licence

MIT

CHANGE_LOG

Read CHANGELOG.md for more details about the changes.


Author

chlbri (bri_lvi@icloud.com)

My github


Links

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Generated from chlbri/new-package