Last active
February 23, 2023 17:28
-
-
Save lorisleiva/d0656b832f95c3d88ec2cf4c93e4a243 to your computer and use it in GitHub Desktop.
Laravel-like pipelines in JavaScript and TypeScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function pipeline(initialValue, pipes, then) { | |
then = then ?? ((t) => t); | |
const pipelineCallback = pipes | |
.slice() | |
.reverse() | |
.reduce((next, pipe) => (passable) => pipe(passable, next), then); | |
return pipelineCallback(initialValue); | |
} | |
export async function asyncPipeline(initialValue, pipes, then) { | |
then = then ?? (async (t) => t); | |
const pipelineCallback = pipes | |
.slice() | |
.reverse() | |
.reduce((next, pipe) => (async (passable) => pipe(await passable, next)), then); | |
return pipelineCallback(initialValue); | |
} | |
const pipeA = (x, next) => next(x + 1); | |
const pipeB = (x, next) => next(x * 2); | |
const result = pipeline(10, [pipeA, pipeB]); | |
console.log(result); | |
const asyncPipeA = async (x, next) => next(x + 1); | |
const asyncPipeB = async (x, next) => next(x * 2); | |
const asyncResult = asyncPipeline(10, [asyncPipeA, asyncPipeB]); | |
asyncResult.then((x) => { console.log(x); }); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
type Identity<T> = (t: T) => T | |
export type Pipe<T> = (t: T, next: Identity<T>) => T; | |
export function pipeline<T>(initialValue: T, pipes: Pipe<T>[], then: Identity<T> | null = null): T { | |
then = then ?? ((t) => t); | |
const pipelineCallback = pipes | |
.slice() | |
.reverse() | |
.reduce<Identity<T>>((next, pipe) => (passable: T) => pipe(passable, next), then); | |
return pipelineCallback(initialValue); | |
} | |
type AsyncIdentity<T> = (t: T) => Promise<T> | |
export type AsyncPipe<T> = (t: T, next: AsyncIdentity<T>) => Promise<T>; | |
export async function asyncPipeline<T>(initialValue: T, pipes: AsyncPipe<T>[], then: AsyncIdentity<T> | null = null): Promise<T> { | |
then = then ?? (async (t) => t); | |
const pipelineCallback = pipes | |
.slice() | |
.reverse() | |
.reduce<AsyncIdentity<T>>((next, pipe) => (async (passable: T) => pipe(await passable, next)), then); | |
return pipelineCallback(initialValue); | |
} | |
const pipeA: Pipe<number> = (x, next) => next(x + 1); | |
const pipeB: Pipe<number> = (x, next) => next(x * 2); | |
const result = pipeline<number>(10, [pipeA, pipeB]); | |
console.log(result); | |
const asyncPipeA: AsyncPipe<number> = async (x, next) => next(x + 1); | |
const asyncPipeB: AsyncPipe<number> = async (x, next) => next(x * 2); | |
const asyncResult = asyncPipeline<number>(10, [asyncPipeA, asyncPipeB]); | |
asyncResult.then((x) => { console.log(x); }); |
Thank you! Have been frustrated not having something like this haha. Was spoiled by Laravel's simple pipeline many years ago and here I am, finding this ! You should create a small package about this that can be scaled by community
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@tjventurini Do it! 🚀 😊