Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transformRouteOptions plugin option #96

Merged
merged 4 commits into from
Feb 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Doing so you will get a complete overview of your application and you can:

- optimize your code
- optimize your application structure
- find out the application structure (expecially if you have joined a new team)
- find out the application structure (especially if you have joined a new team)
- automate some documentation tasks

This plugin is intended to be run only for _development_ purposes.
Expand Down Expand Up @@ -176,6 +176,11 @@ app.register(require('fastify-overview'), {
exposeRouteOptions: {
method: 'POST', // default: 'GET'
url: '/customUrl', // default: '/json-overview'
},
onRouteDefinition: (opts) => {
return {
schema: opts.schema
}
}
})

Expand Down Expand Up @@ -294,6 +299,25 @@ By default the route is exposed at `GET /json-overview`.
You can customize the route's options when `exposeRoute` is set to `true`.
You can provide all the [fastify route's options](https://www.fastify.io/docs/latest/Reference/Routes/#routes-options) except the `handler`.

### onRouteDefinition

This option can be used to determine which properties of the route options are additional included in the overview.
The function receives the [RouteOptions](https://github.com/fastify/fastify/blob/62f564d965949bc123184a27a610f214f23e9a49/types/hooks.d.ts#L695)
object as the only parameter and must return an object with the desired properties. You can also overwrite the properties
that are included in the route overview by default (namely `url`, `method`, `prefix` and `hooks`). You cannot
override the `source` property.
```js
onRouteDefinition: (routeOptions) => {
return {
method: routeOptions.method,
url: routeOptions.url.length,
prefix: routeOptions.prefix,
schema: routeOptions.schema
}
}
```
In this example, the `url` property is overridden and the `url` length is returned instead of the `url`.

## License

Copyright [Manuel Spigolon](https://github.com/Eomm), Licensed under [MIT](./LICENSE).
13 changes: 9 additions & 4 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,18 +50,18 @@ interface RouteItem {
source?: OverviewStructureSource,
}

export interface OverviewStructure {
export interface OverviewStructure<T = {}> {
id: Number,
name: string,
source?: OverviewStructureSource,
children?: OverviewStructure[],
children?: OverviewStructure<T>[],
decorators?: {
decorate: OverviewStructureDecorator[],
decorateRequest: OverviewStructureDecorator[],
decorateReply: OverviewStructureDecorator[]
},
hooks?: OverviewStructureHooks,
routes?: RouteItem[]
routes?: (Omit<RouteItem, keyof T> & T)[]
}

export interface FastifyOverviewOptions {
Expand All @@ -82,6 +82,11 @@ export interface FastifyOverviewOptions {
* Customize the route's options when `exposeRoute` is set to `true`
*/
exposeRouteOptions?: Partial<RouteOptions>,

/**
* Customise which properties of the route options will be included in the overview
*/
onRouteDefinition?: (routeOptions: RouteOptions & { routePath: string; path: string; prefix: string }) => Record<string, unknown>
}

export interface FastifyOverviewDecoratorOptions {
Expand All @@ -98,7 +103,7 @@ export interface FastifyOverviewDecoratorOptions {

declare module 'fastify' {
export interface FastifyInstance {
overview: (opts?: FastifyOverviewDecoratorOptions) => OverviewStructure;
overview: <T = {}>(opts?: FastifyOverviewDecoratorOptions) => OverviewStructure<T>;
}
}

Expand Down
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function fastifyOverview (fastify, options, next) {
})

fastify.addHook('onRoute', function markRoute (routeOpts) {
const routeNode = transformRoute(routeOpts)
const routeNode = Object.assign(transformRoute(routeOpts), opts.onRouteDefinition?.(routeOpts))
if (opts.addSource) {
routeNode.source = routeOpts.handler[kSourceRoute]

Expand Down
1 change: 0 additions & 1 deletion lib/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ function getFunctionName (func) {

function transformRoute (routeOpts) {
const hooks = getEmptyHookRoute()

for (const hook of Object.keys(hooks)) {
if (routeOpts[hook]) {
if (Array.isArray(routeOpts[hook])) {
Expand Down
42 changes: 42 additions & 0 deletions test/fixture/routes.04.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
[
{
"method": "GET",
"url":"/get",
"prefix":"",
"bodySchema": null,
"hooks":{
"onRequest":[ ],
"preParsing":[ ],
"preValidation":[ ],
"preHandler":[ ],
"preSerialization":[ ],
"onError":[ ],
"onSend":[ ],
"onResponse":[ ],
"onTimeout":[ ],
"onRequestAbort":[ ]
}
},
{
"method": "POST",
"url":"/post",
"prefix":"",
"bodySchema": {
"test": {
"type": "string"
}
},
"hooks":{
"onRequest":[ ],
"preParsing":[ ],
"preValidation":[ ],
"preHandler":[ ],
"preSerialization":[ ],
"onError":[ ],
"onSend":[ ],
"onResponse":[ ],
"onTimeout":[ ],
"onRequestAbort":[ ]
}
}
]
20 changes: 20 additions & 0 deletions test/fixture/routes.05.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[
{
"method": "PUT",
"url":"/api/plugin",
"prefix":"/api",
"bodySchema": null,
"hooks":{
"onRequest":[ ],
"preParsing":[ ],
"preValidation":[ ],
"preHandler":[ ],
"preSerialization":[ ],
"onError":[ ],
"onSend":[ ],
"onResponse":[ ],
"onTimeout":[ ],
"onRequestAbort":[ ]
}
}
]
24 changes: 24 additions & 0 deletions test/fixture/routes.06.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[
{
"method": "PATCH",
"url":"/api/patch/:param",
"prefix":"/api",
"bodySchema": {
"text": {
"type": "boolean"
}
},
"hooks":{
"onRequest":[ ],
"preParsing":[ ],
"preValidation":[ ],
"preHandler":[ ],
"preSerialization":[ ],
"onError":[ ],
"onSend":[ ],
"onResponse":[ ],
"onTimeout":[ ],
"onRequestAbort":[ ]
}
}
]
36 changes: 36 additions & 0 deletions test/fixture/routes.07.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
[
{
"method": "GETGET",
"url":"static url",
"prefix":"",
"hooks":{
"onRequest":[ ],
"preParsing":[ ],
"preValidation":[ ],
"preHandler":[ ],
"preSerialization":[ ],
"onError":[ ],
"onSend":[ ],
"onResponse":[ ],
"onTimeout":[ ],
"onRequestAbort":[ ]
}
},
{
"method": "POSTPOST",
"url":"static url",
"prefix":"",
"hooks":{
"onRequest":[ ],
"preParsing":[ ],
"preValidation":[ ],
"preHandler":[ ],
"preSerialization":[ ],
"onError":[ ],
"onSend":[ ],
"onResponse":[ ],
"onTimeout":[ ],
"onRequestAbort":[ ]
}
}
]
76 changes: 76 additions & 0 deletions test/routes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,79 @@ test('routes', async t => {
t.same(reg3.routes.length, 9)
t.same(reg3.routes, require('./fixture/routes.03.json'))
})

test('custom onRouteDefinition', async t => {
const app = fastify({ exposeHeadRoutes: false })

await app.register(plugin, {
onRouteDefinition: (opts) => {
return {
bodySchema: opts.schema ? opts.schema.body : undefined
}
}
})

app.get('/get', noop)
app.post('/post', { schema: { body: { test: { type: 'string' } } } }, noop)

app.register(async (instance) => {
instance.put('/plugin', { schema: { querystring: { size: { type: 'integer' } } } }, noop)

instance.register(async function (instance2) {
instance2.patch('/patch/:param', {
schema: {
params: {
param: {
type: 'string'
}
},
body: {
text: {
type: 'boolean'
}
}
}
}, noop)
})
}, { prefix: 'api' })

await app.ready()

const root = app.overview()

t.equal(root.children.length, 1)
t.equal(root.routes.length, 2)
t.same(root.routes, require('./fixture/routes.04.json'))

t.equal(root.children[0].routes.length, 1)
t.equal(root.children[0].children.length, 1)
t.same(root.children[0].routes, require('./fixture/routes.05.json'))

t.equal(root.children[0].children[0].routes.length, 1)
t.equal(root.children[0].children[0].children.length, 0)
t.same(root.children[0].children[0].routes, require('./fixture/routes.06.json'))
})

test('custom onRouteDefinition with overriding', async t => {
const app = fastify({ exposeHeadRoutes: false })

await app.register(plugin, {
onRouteDefinition: (opts) => {
return {
url: 'static url',
method: opts.method + opts.method
}
}
})

app.get('/get', noop)
app.post('/post', { schema: { body: { test: { type: 'string' } } } }, noop)

await app.ready()

const root = app.overview()

t.equal(root.children.length, 0)
t.equal(root.routes.length, 2)
t.same(root.routes, require('./fixture/routes.07.json'))
})
30 changes: 30 additions & 0 deletions test/types/index.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,33 @@ app
expectType<OverviewStructure>(data)
})
.ready()

app
.register(fastifyOverview, {
onRouteDefinition: (routeOptions) => {
return {
bodySchema: routeOptions.schema?.body,
headerNames: Object.keys(routeOptions.schema?.headers ?? {})
}
}
})
.after((_) => {
const data = app.overview<{ bodySchema: {}, headerNames: string[] }>()
expectType<OverviewStructure<{ bodySchema: {}, headerNames: string[] }>>(data)
})
.ready()

app
.register(fastifyOverview, {
onRouteDefinition: (routeOptions) => {
return {
url: routeOptions.url.length
}
}
})
.after((_) => {
const data = app.overview<{ url: number }>()
expectType<OverviewStructure<{ url: number }>>(data)
expectType<number>(data.routes![0].url)
})
.ready()
Loading