Skip to content

Commit

Permalink
Rework example
Browse files Browse the repository at this point in the history
  • Loading branch information
benjie committed Nov 19, 2024
1 parent e77bcab commit 4cac754
Showing 1 changed file with 44 additions and 34 deletions.
78 changes: 44 additions & 34 deletions utils/website/graphile-config/middleware.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,70 +184,80 @@ something along these lines (replacing `libraryName` with the name of your
library):

```ts
import { Middleware, orderedApply, resolvePresets } from "graphile-config";

// Get the user's Graphile Config from somewhere, e.g.
import config from "./graphile.config.js";

// Resolve the above config, recursively applying all the presets it extends from
const resolvedPreset = resolvePresets([config]);

/***** interfaces.ts *****/
export type PromiseOrDirect<T> = Promise<T> | T;

// Define the middlewares that you support, their event type and their return type
interface MyMiddleware {
export interface MyMiddleware {
someAction(event: SomeActionEvent): PromiseOrDirect<SomeActionResult>;
}
interface SomeActionEvent {
someParameter: unknown;
someParameter: number;
/*
* Use a per-middleware-method interface to define the various pieces of
* data relevant to this event. **ALWAYS** use the event as an abstraction
* so that new information can be added in future without causing any
* knock-on consequences. Note that these parameters of the event may be
* mutated.
* mutated. The values here can be anything, they don't need to be simple
* values.
*/
}
// Middleware wraps a function call; this represents whatever the function returns
type SomeActionResult = unknown;

/***** resolveMiddleware.ts *****/

// Create your middleware instance. The generic describes the events supported
const middleware = new Middleware<MyMiddleware>();
// Now apply the relevant middlewares registered by each plugin (if any) to the
// Middleware instance
orderedApply(
resolvedPreset.plugins,
(plugin) => plugin.libraryName?.middleware,
(name, fn, _plugin) => {
middleware.register(name, fn as any);
},
);
type SomeActionResult = number;

/***** someAction.ts *****/
export type PromiseOrDirect<T> = Promise<T> | T;

/***** getMiddleware.ts *****/

import { Middleware, orderedApply, resolvePresets } from "graphile-config";

export function getMiddleware(resolvedPreset: GraphileConfig.ResolvedPreset) {
// Create your middleware instance. The generic describes the events supported
const middleware = new Middleware<MyMiddleware>();
// Now apply the relevant middlewares registered by each plugin (if any) to the
// Middleware instance
orderedApply(
resolvedPreset.plugins,
(plugin) => plugin.libraryName?.middleware,
(name, fn, _plugin) => {
middleware.register(name, fn as any);
},
);
}

/***** main.ts *****/

// Get the user's Graphile Config from somewhere, e.g.
import config from "./graphile.config.js";

// Resolve the above config, recursively applying all the presets it extends from
const resolvedPreset = resolvePresets([config]);

// Get the middleware for this preset
const middleware = getMiddleware(resolvedPreset);

// Then in the relevant place in your code, call the middleware around the
// relevant functionality
const result = await middleware.run(
"someAction",
{
/* event details here */
someParameter: 42,
},
{ someParameter: 42 }, // < `event` object
async (event) => {
// Call the underlying method to perform the action.
// Note: `event` will be the same object as above, but its contents may
// have been modified.
// have been modified by middlewares.
return await someAction(event.someParameter);
},
);
// The value of `result` should match the return value of `doSomeAction`
// The value of `result` should match the return value of `someAction(...)`
// (unless a middleware tweaked or replaced it, of course!)

// This is the thing that your middleware wraps. It can do anything, it's just
// an arbitrary JavaScript function.
function someAction(someParameter: number): PromiseOrDirect<SomeActionResult> {
// Do something here...
if (Math.random() < 0.5) {
return someParameter;
} else {
return sleep(200).then(() => someParameter);
}
}
```

0 comments on commit 4cac754

Please sign in to comment.