Skip to content

Instantly share code, notes, and snippets.

@gordonbrander
Last active November 6, 2024 02:14
Show Gist options
  • Save gordonbrander/0e3e9c7ac0e907a5120f614140f757ac to your computer and use it in GitHub Desktop.
Save gordonbrander/0e3e9c7ac0e907a5120f614140f757ac to your computer and use it in GitHub Desktop.
middleware.ts - functional-style middleware
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");
});
});
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