Skip to content

Commit

Permalink
feat: onRoute tracking (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
Eomm authored Nov 13, 2021
1 parent 0d91d7a commit d5db60e
Show file tree
Hide file tree
Showing 7 changed files with 314 additions and 115 deletions.
111 changes: 23 additions & 88 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@

[![JavaScript Style Guide](https://img.shields.io/badge/code_style-standard-brightgreen.svg)](https://standardjs.com)
[![ci](https://github.com/Eomm/fastify-overview/actions/workflows/ci.yml/badge.svg)](https://github.com/Eomm/fastify-overview/actions/workflows/ci.yml)
[![runkit](https://img.shields.io/badge/try%20on-runkit-blue)](https://runkit.com/eomm/fastify-overview-readme)

Get a complete overview of your fastify application!
It gives you a tree structure to understand all the relations between your routes and plugins.

It tracks:

- **ALL** the Fastify plugins
- **ALL** the Fastify decorators
- **ALL** the Fastify hooks
- 🛣 **ALL** the Fastify routes
- 🍱 **ALL** the Fastify plugins
- 🎨 **ALL** the Fastify decorators
- 🪝 **ALL** the Fastify hooks

Doing so you will get a complete overview of your application and you can:

Expand Down Expand Up @@ -101,103 +103,36 @@ The JSON structure returned by the `overview` method is like the following:
"onClose": [],
"onRoute": [],
"onRegister": []
}
}
```

Notice that an hook that appears in the parent node, is inherited by the children but it is not listed in the
children's hooks node.

For example, the previous code returns:

```json
{
"name": "fastify-overview",
"children": [
},
"routes": [ // an array within all the routes in that fastify context
{
"name": "register1",
"children": [
{
"name": "register2",
"children": [],
"decorators": {
"decorate": [],
"decorateRequest": [],
"decorateReply": []
},
"hooks": {
"onRequest": [
"function hook2 () {}"
],
"preParsing": [],
"preValidation": [],
"preHandler": [],
"preSerialization": [],
"onError": [],
"onSend": [],
"onResponse": [],
"onTimeout": [],
"onReady": [],
"onClose": [],
"onRoute": [],
"onRegister": []
}
}
],
"decorators": {
"decorate": [],
"decorateRequest": [],
"decorateReply": []
},
"hooks": {
"onRequest": [
"function hook1 () {}"
],
"method": "GET",
"url": "/prefix/hello", // the complete route's url
"prefix": "/prefix", // the plugin prefix
"hooks": { // the hooks that are registered in that single route using the route's options
"onRequest": [],
"preParsing": [],
"preValidation": [],
"preHandler": [],
"preValidation": [
"Anonymous function"
],
"preHandler": [
"hook1"
],
"preSerialization": [],
"onError": [],
"onSend": [],
"onResponse": [],
"onTimeout": [],
"onReady": [],
"onClose": [],
"onRoute": [],
"onRegister": []
"onTimeout": []
}
}
],
"decorators": {
"decorate": [],
"decorateRequest": [],
"decorateReply": []
},
"hooks": {
"onRequest": [],
"preParsing": [],
"preValidation": [],
"preHandler": [],
"preSerialization": [],
"onError": [],
"onSend": [ "hookRoot" ],
"onResponse": [],
"onTimeout": [],
"onReady": [],
"onClose": [],
"onRoute": [],
"onRegister": []
}
]
}
```

## Roadmap

What this plugin should track that is missing:
Notice that an hook that appears in the parent node, is inherited by the children but it is not listed in the
children's hooks node.

- [ ] routes
- [ ] errorHandler
- [ ] 404 handler
You can see the previous code output running it on RunKit: [![runkit](https://img.shields.io/badge/try%20on-runkit-blue)](https://runkit.com/eomm/fastify-overview-readme)


## License
Expand Down
25 changes: 12 additions & 13 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ const fp = require('fastify-plugin')
const kTrackerMe = Symbol('fastify-overview.track-me')
const kStructure = Symbol('fastify-overview.structure')

const { getEmptyTree } = require('./lib/utils')
const {
getFunctionName,
transformRoute,
getEmptyTree
} = require('./lib/utils')

function fastifyOverview (fastify, opts, next) {
const contextMap = new Map()
Expand All @@ -15,6 +19,10 @@ function fastifyOverview (fastify, opts, next) {
manInTheMiddle(instance, parent[kTrackerMe])
})

fastify.addHook('onRoute', function markRoute (routeOptions) {
this[kStructure].routes.push(transformRoute(routeOptions))
})

fastify.addHook('onReady', function hook (done) {
const root = contextMap.get(rootToken)
structure = root
Expand Down Expand Up @@ -66,21 +74,11 @@ function wrapFastify (instance) {

const originalHook = instance.addHook
instance.addHook = function wrapAddHook (name, hook) {
this[kStructure].hooks[name].push(getFuncTitle(hook.toString()))
this[kStructure].hooks[name].push(getFunctionName(hook.toString()))
return originalHook.call(this, name, hook)
}
}

function getFuncTitle (func) {
const funcReg = /\s*function\s*(\S+)\s*\(.*\)\s*{.*/gi
const m = funcReg.exec(func)
if (m && m.length >= 1) {
return m[1]
} else {
return 'Anonymous function'
}
}

function wrapDecorator (instance, type) {
const originalDecorate = instance[type]
instance[type] = function wrapDecorate (name, value) {
Expand All @@ -90,5 +88,6 @@ function wrapDecorator (instance, type) {
}

module.exports = fp(fastifyOverview, {
name: 'fastify-overview'
name: 'fastify-overview',
fastify: '>=3.x'
})
78 changes: 64 additions & 14 deletions lib/utils.js
Original file line number Diff line number Diff line change
@@ -1,28 +1,78 @@
'use strict'

module.exports.getEmptyTree = function getEmptyTree (name) {
module.exports = {
getFunctionName,
transformRoute,
getEmptyTree
}

function getFunctionName (func) {
const funcReg = /\s*function\s*(\S+)\s*\(.*\)\s*{.*/gi
const m = funcReg.exec(func)
if (m && m.length >= 1) {
return m[1]
} else {
return 'Anonymous function'
}
}

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

for (const hook of Object.keys(hooks)) {
if (routeOpts[hook]) {
if (Array.isArray(routeOpts[hook])) {
hooks[hook] = routeOpts[hook].map(getFunctionName)
} else {
hooks[hook].push(getFunctionName(routeOpts[hook]))
}
}
}

return {
method: routeOpts.method,
url: routeOpts.url,
prefix: routeOpts.prefix,
hooks
}
}

function getEmptyTree (name) {
return {
name,
children: [],
routes: [],
decorators: {
decorate: [],
decorateRequest: [],
decorateReply: []
},
hooks: {
onRequest: [],
preParsing: [],
preValidation: [],
preHandler: [],
preSerialization: [],
onError: [],
onSend: [],
onResponse: [],
onTimeout: [],
onReady: [],
onClose: [],
onRoute: [],
onRegister: []
...getEmptyHookRoute(),
...getEmptyHookApplication()
}
}
}

function getEmptyHookRoute () {
return {
onRequest: [],
preParsing: [],
preValidation: [],
preHandler: [],
preSerialization: [], //
onError: [], //
onSend: [],
onResponse: [],
onTimeout: [] //
}
}

function getEmptyHookApplication () {
return {
onReady: [],
onClose: [],
onRoute: [],
onRegister: []
}
}
66 changes: 66 additions & 0 deletions test/fixture/routes.00.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
[
{
"method": "GET",
"url": "/get",
"prefix": "",
"hooks": {
"onRequest": [],
"preParsing": [],
"preValidation": [],
"preHandler": [],
"preSerialization": [],
"onError": [],
"onSend": [],
"onResponse": [],
"onTimeout": []
}
},
{
"method": "POST",
"url": "/post",
"prefix": "",
"hooks": {
"onRequest": [],
"preParsing": [],
"preValidation": [],
"preHandler": [],
"preSerialization": [],
"onError": [],
"onSend": [],
"onResponse": [],
"onTimeout": []
}
},
{
"method": "PUT",
"url": "/put",
"prefix": "",
"hooks": {
"onRequest": [],
"preParsing": [],
"preValidation": [],
"preHandler": [],
"preSerialization": [],
"onError": [],
"onSend": [],
"onResponse": [],
"onTimeout": []
}
},
{
"method": "OPTIONS",
"url": "/options",
"prefix": "",
"hooks": {
"onRequest": [],
"preParsing": [],
"preValidation": [],
"preHandler": [],
"preSerialization": [],
"onError": [],
"onSend": [],
"onResponse": [],
"onTimeout": []
}
}
]
Loading

0 comments on commit d5db60e

Please sign in to comment.