-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
340 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
--- | ||
icon: ri:addon | ||
--- | ||
|
||
# Server plugins | ||
|
||
Plugins allow creating reusable interceptors to modify server options and behavior. | ||
|
||
## Example | ||
|
||
This is a simple logging plugin: | ||
|
||
```ts | ||
import type { ServerPlugin } from "srvx"; | ||
|
||
export const logger: ServerPlugin = (server) => { | ||
console.log(`Logger plugin enabled for ${server.runtime}`); | ||
return { | ||
name: "logger", | ||
request: (req) => { | ||
console.log(`[request] [${req.method}] ${req.url}`); | ||
}, | ||
response: (req, res) => { | ||
console.log( | ||
`[response] [${req.method}] ${req.url} ${res.status} ${res.statusText}`, | ||
); | ||
}, | ||
}; | ||
}; | ||
``` | ||
|
||
We can use it in main server using `plugins` option: | ||
|
||
```ts | ||
import { serve } from "srvx"; | ||
|
||
import { logger } from "./plugins/logger"; | ||
|
||
const server = serve({ | ||
plugins: [logger], | ||
fetch(request) { | ||
return new Response(`👋 Hello there.`); | ||
}, | ||
}); | ||
|
||
await server.ready(); | ||
``` | ||
|
||
## Defining plugins | ||
|
||
```ts | ||
import type { ServerPlugin } from "srvx"; | ||
|
||
const myPlugin: ServerPlugin = async (server) => { | ||
// You can use server argument to: | ||
// - Modify global options using server.options | ||
// - Access to the runtime-specific server instance | ||
// - Decide hooks based on server.runtime value | ||
|
||
// Return plugin instance | ||
return { | ||
// Plugin display name | ||
name: "my-plugin", | ||
|
||
// Intercept incoming request | ||
// You can return a Response value to early return (eg: auth and validation) | ||
request: (request) => {}, | ||
|
||
// Intercept final response | ||
// You can use to modify response | ||
response: (request, response) => {}, | ||
}; | ||
}; | ||
``` |
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import type { ServerPluginInstance, ServerOptions, Server } from "./types.ts"; | ||
|
||
export async function applyPlugins(server: Server) { | ||
const options = server.options as ServerOptions; | ||
|
||
if (!options.plugins?.length) { | ||
return; | ||
} | ||
|
||
const requestHooks: NonNullable<ServerPluginInstance["request"]>[] = []; | ||
const responseHooks: NonNullable<ServerPluginInstance["response"]>[] = []; | ||
|
||
for (const ctor of options.plugins) { | ||
const plugin = typeof ctor === "function" ? await ctor(server) : ctor; | ||
if (plugin.request) { | ||
requestHooks.push(plugin.request); | ||
} | ||
if (plugin.response) { | ||
responseHooks.push(plugin.response); | ||
} | ||
} | ||
|
||
const hasRequestHooks = requestHooks.length > 0; | ||
const hasResponseHooks = responseHooks.length > 0; | ||
|
||
if (hasRequestHooks || hasResponseHooks) { | ||
server.fetch = (request) => { | ||
let resValue: undefined | Response; | ||
let resPromise: undefined | Promise<Response | void>; | ||
|
||
// Request hooks | ||
if (hasRequestHooks) { | ||
for (const reqHook of requestHooks) { | ||
if (resPromise) { | ||
resPromise = resPromise.then((res) => res || reqHook(request)); | ||
} else { | ||
const res = reqHook(request); | ||
if (res) { | ||
if (res instanceof Promise) { | ||
resPromise = res; | ||
} else { | ||
return res; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
// User handler | ||
if (resPromise) { | ||
resPromise = resPromise.then((res) => res || options.fetch(request)); | ||
} else { | ||
const res = options.fetch(request); | ||
if (res instanceof Promise) { | ||
resPromise = res; | ||
} else { | ||
resValue = res; | ||
} | ||
} | ||
|
||
// Response hooks | ||
if (hasResponseHooks) { | ||
for (const resHook of responseHooks) { | ||
if (resPromise) { | ||
resPromise = resPromise.then((res) => { | ||
if (res) { | ||
resValue = res; | ||
} | ||
return resHook(request, resValue!); | ||
}); | ||
} else { | ||
const res = resHook(request, resValue!); | ||
if (res) { | ||
if (res instanceof Promise) { | ||
resPromise = res; | ||
} else { | ||
resValue = res; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
return ( | ||
resPromise ? resPromise.then((res) => res || resValue) : resValue | ||
) as Response | Promise<Response>; | ||
}; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.