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
Add toString method #861
Add toString method #861
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great start!
The prettyPrint
api of find-my-way
is complex and needs to be refactored, you can try with https://github.com/substack/node-archy, which seems to be right for us :)
Oh great! Thanks for the tip. How do access the routes on a Fastify instance? Do I need to access it through |
|
Are Plugins tracked on the Fastify instance? AFAIK most plugins just decorate the instance (or the request/reply parts of the instance) and that is it. I wonder whats the best way to show that back to the user. -- Could this require editing |
@Ethan-Arrowood yes I think so. However we are loosing all these metadata about fastify after boot finishes. However, I would add all these stuff in steps, and this is a good one. You might want to add some events/or metadata info to https://github.com/mcollina/avvio as plugins are tracked there. (The code in avvio is very complex). |
toString.js
Outdated
}) | ||
|
||
console.log(`\nPlugins`) | ||
console.log(`${LINES.r} TODO`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should not use console.log
, but rather concatenate the string. In this way you can easily add a unit test.
toString.js
Outdated
console.log(`\nRoutes`) | ||
console.log(`${this.printRoutes()}`) | ||
|
||
console.log(`\nMiddleware`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be "top level middlewares". I don't think you can see middlewares that are wrapped within a plugin.
toString.js
Outdated
function toString() { | ||
console.log('Fastify Instance toString') | ||
/* Print hooks */ | ||
console.log(`\nHooks`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be "Top level Hooks". I don't think you can see hooks that are wrapped within a plugin.
Hello! I just got back from a 2 week trip and I'll be continuing work on this feature soon. |
@mcollina can you provide some insight into adding events/or metadata info to avvio? |
I would emit an event when a plugin start loading, and when a plugin finishes loading. However, there will be a to ton (every route is wrapped in a plugin) so some filtering might be needed. |
You were not kidding when you said this code is complex! I found this line in Line 397 in 953616f
However, it doesn't seem to be tracking plugins. Do you think I should try pumping plugin metadata into there? I've also begun cracking away at
I guess the next step is to listen for this event in the fastify object and then pipe the name of the function into the registeredPlugins list. |
26ab4fc
to
e418234
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for the long delay for a review, I’ve been on vacation and then catching up for a while (and traveling for work).
fastify.js
Outdated
|
||
>>>>>>> 43d9c92... prep for pull |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this expected?
fastify.js
Outdated
@@ -23,6 +24,7 @@ const Schemas = require('./lib/schemas') | |||
const loggerUtils = require('./lib/logger') | |||
const pluginUtils = require('./lib/pluginUtils') | |||
const runHooks = require('./lib/hookRunner').hookRunner | |||
const toString = require('./toString') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should live under lib/
toString.js
Outdated
output_string += `\n${LINES.r} TODO` | ||
console.log(`Registered Plugins: ${this[pluginUtils.registeredPlugins]}`) | ||
// console.log(this) | ||
console.log(output_string) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no console.log in this method
This needs unit tests. |
Not to worry about the delay. I've been quite busy myself. Thank you for the review. I'll make sure to fix these things soon, but can you please review my previous comment on this thread regarding |
The Line 397 in 953616f
I think you can extend that mechanism to track down the tree of loaded plugins, without touching avvio at all. |
Okay interesting. I'll mess around with that a bit more and see what I can make of it. |
(branch has been rebased properly) The way it works is the Also I didn't know what we should do about anonymously named plugins so I added two things:
You can check out this behavior by running the included If you think the |
2cf83cb
to
eb95b10
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tests are also failing
fastify.js
Outdated
fastify.avvioUse(plugin, options) | ||
if (plugin.name.length === 0) { | ||
log.warn('Warning: should not use anonymous plugins. Provide a function name on declaration.') | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don’t think emitting a warn is feasible. We should have default strategy (maybe the filename? or the closest name in package.json) in case there is no name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would this method have access to the filename? Even if the user uses:
// plugin.js
const fp = require('fastify-plugin')
module.exports = fp((instance, opts, next) => {
instance.decorate('mult', (a, b) => a * b)
next()
})
// app.js
fastify.register(require('plugin.js'))
The register
method will still receive an anonymous function.
Right now I am using 'anonymous'+plugin_index
fastify.js
Outdated
@@ -173,7 +173,14 @@ function build (options) { | |||
fastify.setSchemaCompiler(buildSchemaCompiler()) | |||
|
|||
// plugin | |||
fastify.register = fastify.use | |||
fastify.avvioUse = fastify.use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is no need to expose this, store it in a variable.
I'm not able to get the linter to successfully run. Not sure what I broke or what I'm doing wrong but this is my console output: Any idea whats going on here?
Made this into a proper issue (#968) |
@Ethan-Arrowood fastify-plugin 1.2.0 is out. |
docs/Plugins.md
Outdated
@@ -79,37 +79,27 @@ Sometimes, you will need to know when the server is about to close, for example | |||
|
|||
Do not forget that `register` will always create a new Fastify scope, if you don't need that, read the following section. | |||
|
|||
If you register an anonymous function using `fastify-plugin`, it will automatically gain a new property based on the file name the `.fp()` method was called from. You can access it using `Symbol.for('fastify.display-name')`. See the example below. | |||
If you register an anonymous function using `fastify-plugin`, it will automatically set the meta option `name` to the file name the `.fp()` method was called from. You can access it using `fn[Symbol.for('plugin-meta')].name` or `fn[Symbol.for('fastify.display-name')]`. See the example below. If you set the name using the meta property, the file name will be ignored and the `fastify.display-name` will be set to the meta name as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All references to fastify.display-name
should be removed since it will be removed in the next major version of fastify-plugin
.
Also, .fp()
should just be fp()
.
docs/Plugins.md
Outdated
name: 'my-plugin' | ||
})) | ||
``` | ||
It is recommended you use a named function, but anonymous functions are supported. This was added for use within `fastify.toString()`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO the recommended method of setting a plugin's name should be with the meta name option.
@nwoltman if we go with that plan, then we need to document |
Let me see what I can come up with for the documentation. Basic facts:
Here is an example: // toString.test.js
fastify.register(fp((instance, opts, next) => {
instance.decorate('anonymousPlugin', (a, b) => a + b)
next()
}))
fastify.register(fp(function standardPlugin (instance, opts, next) {
instance.decorate('standardPlugin', (a, b) => a - b)
next()
}))
fastify.register((instance, opts, next) => {
instance.decorate('anonWithoutFastifyPlugin', (a, b) => a * b)
next()
})
fastify.register(function namedWithoutFP (instance, opts, next) {
instance.decorate('namedWithoutFP', (a, b) => a / b)
next()
})
// fastify.toString() ->
let result = `...
Plugins
├── toString.test
├── standardPlugin
├── anonymous0
└── namedWithoutFP` |
@mcollina You're right. Using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with a nit
docs/Plugins.md
Outdated
fastify.register(fp(async () => {}, { name: 'myAsyncFunction' })) | ||
``` | ||
|
||
Internally, `fastify` will register this anonymous function as `'myAsyncFunction'`. `fastify-plugin` will always prioritize the meta property, even when supplied a named function. If you do not provide a `meta.name` to the `fp()` method, `fastify-plugin` will try and use the function name; if its an anonymous function it will use the file name from which the `fp()` method was called. See the examples below: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: if its
=> if it's
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hello! Nice work!
I have some questions, given the following example
'use strict'
const fastify = require('fastify')()
fastify.get('/', () => {})
fastify.get('/hello', () => {})
fastify.register((instance, opts, next) => {
instance.addHook('preHandler', () => {})
instance.get('/hello', () => {})
instance.register((i, opts, next) => {
i.addHook('preHandler', () => {})
i.get('/hello', () => {})
next()
}, { prefix: '/inside' })
next()
}, { prefix: '/v1' })
fastify.ready(() => {
console.log(fastify.toString())
})
I get
Top Level Hooks
├── onRequest (0 hooks): []
├── preHandler (0 hooks): []
├── onResponse (0 hooks): []
└── onSend (0 hooks): []
Routes
└── / (GET)
├── hello (GET)
└── v1/
├── hello (GET)
└── inside/ciao (GET)
Top Level Middleware
└── /: []
Plugins
└── anonymous0
As you can see the nested hooks (and probably the same for middlewares) are not present in the final string.
Why? Am I missing something?
If this is correct, I think we should not land this until we have a complete log of every level of Fastify, because we are not giving a complete overview of the application structure, but just a small part.
Nested hooks were intentionally left out as of right now. Looking back on your original issue I see how we may want to display this information. So per your example the expected out put might look like something like this?
If this is what you want it to be instead of what it currently is then this feature will need quite a bit more work (which I'm okay with doing). I do not know how Fastify exposes these things internally so I cannot gauge how difficult this change will be. |
@Ethan-Arrowood yes, kind of:
I think we can drop the use of Probably a nice solution could be add an internal event emitter which emits an event for every route/hook/middleware/plugin registered with its own context. If you want I can work on it :) |
Thank you for the recommendations. I think I'll take on the challenge and see how far I can go on my own. I'll make sure to ping here if i need help! |
this[registeredPlugins].push(name) | ||
const functionName = meta && meta.name ? meta.name : ( | ||
!fn.name ? `anonymous${anonFuncCount++}` : ( | ||
fn.name !== 'bound _after' ? fn.name : null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the 'bound _after' ? Could you use a constant for that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is some default name for one of things fastify
registers or uses. Will most likely change when I re implement this feature given the new constraints
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Sorry I haven't gotten back around to this yet. Been very busy with my new internship so i'm only just starting to find time for open source |
Completely understand. I'm right there with you. |
I vote yes for |
+1
Il giorno mar 9 ott 2018 alle 16:07 James Sumners <notifications@github.com>
ha scritto:
… I vote yes for toJSON.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#861 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AADL42tf3ZuUwIXhIQuJ896Y3o0ieTRlks5ujSxCgaJpZM4S5pUW>
.
|
I don't believe I'll be able to complete this feature. There is an |
@Ethan-Arrowood you/we can work on the toJSON if you have time. I opened the PR but failed to deliver due to my schedule. |
@cemremengu i'll look into it but I ran into a fair amount of discouraging issue trying to implement it before. Maybe after this time I'll have some new ideas, so we'll see, but I don't want to make any promises |
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Checklist
npm run test
andnpm run benchmark
Closes: #703
sandbox.js
will be removed when this feature is finished. It is a useful file for testing during development. I think I have to movetoString.js
intolib
as well.Some things to note:
fastify.printRoutes
but I'm not sure where to start with that as that method is coming fromfind-my-way
. (Should I try to copy that function and edit it to fit our needs?)json
output be structured?