Middleware

The structure of a middleware function


Here is the most basic middleware (mdw) function in starfx:

1function* (ctx, next) {
2  yield* next();
3}

Thunks and endpoints are just thin wrappers around a mdw stack:

For example, the recommended mdw stack for createApi() looks like this:

 1import { createApi, mdw } from "starfx";
 2import { schema } from "./schema";
 3
 4// this api:
 5const api = createApi();
 6api.use(mdw.api({ schema }));
 7api.use(api.routes());
 8api.use(mdw.fetch({ baseUrl: "https://api.com" }));
 9
10// looks like this:
11[
12  mdw.err,
13  mdw.queryCtx,
14  mdw.customKey,
15  mdw.nameParser,
16  mdw.actions,
17  mdw.loaderApi({ schema }),
18  mdw.cache({ schema }),
19  api.routes(),
20  mdw.composeUrl("https://api.com"),
21  mdw.payload,
22  mdw.request,
23  mdw.json,
24];

When a mdw function calls yield* next(), all it does it call the next mdw in the stack. When that yield point resolves, it means all the mdw functions after it have been called. This doesn't necessarily mean all mdw in the stack will be called, because like koa, you can return early inside a mdw function, essentially cancelling all subsequent mdw.

Context #

The context object is just a plain javascript object that gets passed to every mdw. The type of ctx depends ... on the context. But for thunks, we have this basic structure:

 1interface Payload<P> {
 2  payload: P;
 3}
 4
 5interface ThunkCtx<P = any> extends Payload<P> {
 6  name: string;
 7  key: string;
 8  action: ActionWithPayload<CreateActionPayload<P>>;
 9  actionFn: IfAny<
10    P,
11    CreateAction<ThunkCtx>,
12    CreateActionWithPayload<ThunkCtx<P>, P>
13  >;
14  result: Result<void>;
15}

There are three very important properties that you should know about:

  • name - the name you provided when creating the thunk
  • payload - the arbitrary data you passed into the thunk
  • key - a hash of name and payload
NEXT >>
Loaders