Skip to content

Commit

Permalink
feat: hide empty (#58)
Browse files Browse the repository at this point in the history
* feat: add hideEmpty option

* fix: remove expose head

* fix: rename to hideEmptyNodes

* Revert "fix: rename to hideEmptyNodes"

This reverts commit d899944.

* add: docs

* feat: better user API
  • Loading branch information
Eomm authored Sep 23, 2022
1 parent 4ca91d0 commit ce69238
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 3 deletions.
66 changes: 64 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ async function run() {

// read your application structure when fastify is ready
app.addHook('onReady', function showStructure (done) {
const appStructure = app.overview()
const appStructure = app.overview() // 🦄 Here is the magic!
console.log(JSON.stringify(appStructure, null, 2))
done(null)
})
Expand Down Expand Up @@ -166,7 +166,7 @@ You can see the previous code output running it on RunKit: [![runkit](https://im

## Options

You can pass the following options to the plugin:
You can pass the following options to the plugin or to the decorator:

```js
app.register(require('fastify-overview'), {
Expand All @@ -177,6 +177,10 @@ app.register(require('fastify-overview'), {
url: '/customUrl', // default: '/json-overview'
}
})

const appStructure = app.overview({
hideEmpty: true, // default: false
})
```

### addSource
Expand All @@ -201,6 +205,64 @@ Here an example of the structure with the `addSource` option:
}
```

### hideEmpty

To keep the structure light and clean, you can hide empty properties by providing this option to the `overview` decorator.
For example, if you do not have any decorator, the `decorators` property will not be present in the structure.

The properties that can be hidden are:
- `decorators` and/or its children
- `hooks` and/or its children
- `routes`

You can get both the structure by calling the `overview` method twice:

```js
const fullStructure = app.overview()
const lightStructure = app.overview({
hideEmpty: true, // default: false
})
```

Here an example of the cleaned output:

```json
{
"id": 0.38902288100060645,
"name": "fastify -> fastify-overview",
"children": [
{
"id": 0.7086786379705781,
"name": "function (instance, opts, next) { next() }"
},
{
"id": 0.6405610832733726,
"name": "async function (instance, opts) { -- instance.register(async function (instance, opts) {",
"children": [
{
"id": 0.8200459678409413,
"name": "async function (instance, opts) { -- instance.decorateReply('oneRep', {})",
"decorators": {
"decorateReply": [
{ "name": "oneRep" }
]
}
}
]
}
],
"hooks": {
"onRequest": [
{
"name": "hook1",
"hash": "31d31d981f412085927efb5e9f36be8ba905516a"
}
]
}
}
```


### exposeRoute

Optionally, you can expose a route that will return the JSON structure.
Expand Down
26 changes: 25 additions & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,33 @@ function fastifyOverview (fastify, options, next) {
done(null)
})

fastify.decorate('overview', function getOverview () {
fastify.decorate('overview', function getOverview (opts) {
if (!structure) {
throw new Error('Fastify must be in ready status to access the overview')
}

if (opts && opts.hideEmpty) {
const filterStructure = JSON.stringify(structure, (key, value) => {
switch (key) {
case 'decorators':
case 'hooks':
if (Object.entries(value).every(([, v]) => {
return Array.isArray(v) && v.length === 0
})) {
return undefined
}
break
default:
if (Array.isArray(value) && value.length === 0) {
return undefined
}
}

return value
})
return JSON.parse(filterStructure)
}

return structure
})

Expand All @@ -67,6 +90,7 @@ function fastifyOverview (fastify, options, next) {
const routeConfig = Object.assign(
{
method: 'GET',
exposeHeadRoute: false,
url: '/json-overview'
},
opts.exposeRouteOptions,
Expand Down
54 changes: 54 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,57 @@ test('register', async t => {
t.equal(reg1.children[2].name, 'register4')
t.equal(reg1.hooks.onRequest.length, 1)
})

test('hide empty', async t => {
const app = fastify()
await app.register(plugin)

app.decorate('emptyObject', {})
app.decorate('emptyArray', [])
app.decorateRequest('oneReqDecor', [])

app.addHook('onRequest', function hook1 () {})
app.addHook('preParsing', function hook2 () {})
app.addHook('preValidation', function hook3 () {})
app.addHook('onError', function hookSix () {})

app.register(function (instance, opts, next) { next() })
app.register(async function (instance, opts) {
instance.register(async function (instance, opts) {
instance.decorateReply('oneRep', {})
})
})

await app.ready()
const structure = app.overview({ hideEmpty: true })

t.strictSame(structure.decorators, {
decorate: [
{ name: 'emptyObject' },
{ name: 'emptyArray' }
],
decorateRequest: [
{ name: 'oneReqDecor' }
]
})

t.strictSame(structure.hooks, {
onRequest: [{ name: 'hook1', hash: '31d31d981f412085927efb5e9f36be8ba905516a' }],
preParsing: [{ name: 'hook2', hash: '07f8fc52f2a92adc80881b4c11ee61ab56ea42d1' }],
preValidation: [{ name: 'hook3', hash: '92b002434cd5d8481e7e5562b51df679e2f8d586' }],
onError: [{ name: 'hookSix', hash: '9398f5df01879094095221d86a544179e62cee12' }]
})

t.equal(structure.children.length, 2)

delete structure.children[0].id
t.same(structure.children[0], {
name: 'function (instance, opts, next) { next() }'
}, 'should have only the name')

t.strictSame(structure.children[1].children[0].decorators, {
decorateReply: [
{ name: 'oneRep' }
]
})
})

0 comments on commit ce69238

Please sign in to comment.