⚡︎ Simple, expressive middleware for NextJS Server Actions using Zact.
$ pnpm install exzact
Create simple middleware for zact functions:
import { z } from "zod"
import { exzact, Middleware } from "exzact"
interface Context {
thing?: string
something?: string
}
const app = exzact<Context>({
thing: "things",
})
const logMiddleware: Middleware = async (context, next) => {
console.log("Log Middleware (Pre): ", context.input)
await next()
console.log("Log Middleware (Post): ", context.input)
}
export const hello = app.zact(z.object({ stuff: z.string().min(1) }), {
something: "stuff",
})(async ({ stuff }, { thing, something }) => {
console.log(`Hello ${stuff}, you injected ${thing} and ${something}`)
})
app.use(logMiddleware)
hello({ stuff: "world" })
In the above example, the logging middleware will run before the action has executed.
The simple example above will log the following:
Log Middleware (Pre): { input: { stuff: 'world' }, thing: 'things', something: 'stuff' }
Log Middleware (Post): { input: { stuff: 'world' }, thing: 'things', something: 'stuff' }
Hello world, you injected things and stuff
Middleware can run during any of the following stages:
PRE_VALIDATE
: Before the Zact function Zod validation runs.PRE_EXECUTE
: Before the validated Zact function runs.POST_EXECUTE
: After the validated Zact runction runs.
Middleware defaults to PRE_EXECUTE
if no stage is manually set.
import { MiddlewareStage } from "exzact";
...
logMiddleware.stage = MiddlewareStage.POST_EXECUTE;
...
app.use(logMiddleware);
hello({ stuff: "world" });
In the above example, the logging middleware will run after the action has executed.
Rate-limiting can easily be added to Zact functions via middleware:
import { Ratelimit } from "@upstash/ratelimit"
import { Redis } from "@upstash/redis"
import { Middleware } from "zact"
/* Requires setting the following environment variables:
* - UPSTASH_REDIS_REST_URL
* - UPSTASH_REDIS_REST_TOKEN
You can find these in your Upstash console.
*/
const redis = Redis.fromEnv()
// Create a new ratelimiter, that allows 5 requests per 30 seconds
const ratelimit = new Ratelimit({
redis,
limiter: Ratelimit.fixedWindow(5, "30 s"),
})
const upstashMiddleware: Middleware = async (_, next) => {
const { success } = await ratelimit.limit("all")
if (!success) {
throw new Error("Unable to process at this time")
}
await next()
}
app.use(upstashMiddleware)
For more examples, check out the Code Examples.
Install the necessary libraries.
$ npm install
Run a simple example.
$ npm run example:simple
Run a complete example of the middleware suite (requires Upstash configuration).
$ npm run example:complete
- Fork it!
- Create your feature branch:
git checkout -b my-new-feature
- Add your changes:
git add .
- Commit your changes:
git commit -am 'Add some feature'
- Push to the branch:
git push origin my-new-feature
- Submit a pull request 😎
MIT License © Adam King