Last active
November 6, 2024 02:14
-
-
Save gordonbrander/0e3e9c7ac0e907a5120f614140f757ac to your computer and use it in GitHub Desktop.
middleware.ts - functional-style middleware
This file contains hidden or 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
import { strict as assert } from "assert"; | |
import { createMiddleware, Msg } from "./middleware.js"; | |
describe("createMiddleware", () => { | |
it("should create middleware with empty initial state", () => { | |
const middleware = createMiddleware(); | |
assert.deepEqual(middleware("test"), "test"); | |
}); | |
it("should execute single middleware", () => { | |
const middleware = createMiddleware<string>(); | |
middleware.add((msg: Msg<string>) => ({ | |
value: msg.value.toUpperCase(), | |
done: false, | |
})); | |
assert.equal(middleware("hello"), "HELLO"); | |
}); | |
it("should execute multiple middleware in order", () => { | |
const middleware = createMiddleware<string>(); | |
middleware.add((msg: Msg<string>) => ({ | |
value: msg.value.toUpperCase(), | |
done: false, | |
})); | |
middleware.add((msg: Msg<string>) => ({ | |
value: `${msg.value}!`, | |
done: false, | |
})); | |
assert.equal(middleware("hello"), "HELLO!"); | |
}); | |
it("should stop execution when done is true", () => { | |
const middleware = createMiddleware<string>(); | |
middleware.add((msg: Msg<string>) => ({ | |
value: msg.value.toUpperCase(), | |
done: true, | |
})); | |
middleware.add((msg: Msg<string>) => ({ | |
value: `${msg.value}!`, | |
done: false, | |
})); | |
assert.equal(middleware("hello"), "HELLO"); | |
}); | |
it("should clear all middleware", () => { | |
const middleware = createMiddleware<string>(); | |
middleware.add((msg: Msg<string>) => ({ | |
value: msg.value.toUpperCase(), | |
done: false, | |
})); | |
middleware.clear(); | |
assert.equal(middleware("hello"), "hello"); | |
}); | |
it("should work with different types", () => { | |
const middleware = createMiddleware<number>(); | |
middleware.add((msg: Msg<number>) => ({ | |
value: msg.value * 2, | |
done: false, | |
})); | |
middleware.add((msg: Msg<number>) => ({ | |
value: msg.value + 1, | |
done: false, | |
})); | |
assert.equal(middleware(5), 11); | |
}); | |
it("should allow adding middleware after creation", () => { | |
const middleware = createMiddleware<string>(); | |
assert.equal(middleware("hello"), "hello"); | |
middleware.add((msg: Msg<string>) => ({ | |
value: msg.value.toUpperCase(), | |
done: false, | |
})); | |
assert.equal(middleware("hello"), "HELLO"); | |
}); | |
}); |
This file contains hidden or 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 type Middleware<T> = (msg: Msg<T>) => Msg<T>; | |
export type Msg<T> = { | |
value: T; | |
done: boolean; | |
}; | |
export const createMiddleware = <T>(...middleware: Array<Middleware<T>>) => { | |
const add = (ware: Middleware<T>) => { | |
middleware.push(ware); | |
}; | |
const clear = () => { | |
middleware.length = 0; | |
}; | |
const run = (value: T): T => { | |
let msg = { value, done: false }; | |
for (const ware of middleware) { | |
msg = ware(msg); | |
if (msg.done) return msg.value; | |
} | |
return msg.value; | |
}; | |
run.clear = clear; | |
run.add = add; | |
return run; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment