Skip to content

Instantly share code, notes, and snippets.

@slavafomin
Last active November 30, 2024 16:07
Show Gist options
  • Save slavafomin/855065298c275f7cad83dc01bc32f2f2 to your computer and use it in GitHub Desktop.
Save slavafomin/855065298c275f7cad83dc01bc32f2f2 to your computer and use it in GitHub Desktop.
grammY middleware runner
import type { Context, Middleware } from 'grammy';
import type { MaybeArray } from '../types/maybe-array';
import { middlewareToFn } from './middleware-to-fn';
/**
* Middleware tree execution result. Equals `true` when
* all middleware in the tree were executed and the chain
* hasn't been broken, `false` otherwise.
*/
export type RunMiddlewareResult = boolean;
/**
* Executes the specified middleware with the specified
* context.
*/
export async function runMiddleware<C extends Context>(
middleware: MaybeArray<Middleware<C>>,
context: C
): Promise<RunMiddlewareResult> {
let isComplete = false;
const leaf = async () => {
isComplete = true;
};
const middlewareFn = middlewareToFn(middleware);
await middlewareFn(context, leaf);
return isComplete;
}
import type { Context, Middleware, MiddlewareFn } from 'grammy';
import { Composer } from 'grammy';
import type { MaybeArray } from '../types/maybe-array';
export function middlewareToFn<C extends Context>(
middleware: MaybeArray<Middleware<C>>
): MiddlewareFn<C> {
const middlewareList = (
Array.isArray(middleware) ? middleware : [middleware]
);
// Using composer to reduce all the middleware to
// a function (sadly grammY doesn't export low-level
// utilities for this).
return (new Composer(...middlewareList)
.middleware()
);
}
@rayz1065
Copy link

You could simplify this as

export type AnyMiddleware<C extends Context> = Middleware<C>[] | Middleware<C>;

export function anyMiddlewareToFn<C extends Context>(
  middleware: AnyMiddleware<C>
): MiddlewareFn<C> {
  const middlewareList = Array.isArray(middleware) ? middleware : [middleware];
  const composer = new Composer(...middlewareList);
  return composer.middleware();
}

// example
anyMiddlewareToFn([new Composer<MyContext>()]);

If you're willing to change the interface you can also do

export function anyMiddlewareToFn<C extends Context>(
  ...middlewares: Middleware<C>[]
): MiddlewareFn<C> {
  const composer = new Composer(...middlewares);
  return composer.middleware();
}

// example
anyMiddlewareToFn(new Composer<MyContext>(), (ctx, next) => next());

@slavafomin
Copy link
Author

You could simplify this as …

Thank you for giving me the idea. I didn't realize at first that Composer IS a middleware. This simplifies things a lot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment