Skip to content

Commit

Permalink
Add print-plugins command
Browse files Browse the repository at this point in the history
It runs the printPlugins method and prints the results. No arguments.

Closes #636
  • Loading branch information
bcomnes committed Jul 20, 2023
1 parent cd34f63 commit 6832715
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Fastify command line interface, available commands are:
* generate-swagger generate Swagger/OpenAPI schema for a project using @fastify/swagger
* readme generate a README.md for the plugin
* print-routes prints the representation of the internal radix tree used by the router, useful for debugging.
* print-plugins prints the representation of the internal plugin tree used by avvio, useful for debugging.
* version the current fastify-cli version
* help help about commands
Expand Down
1 change: 1 addition & 0 deletions help/help.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Fastify command line interface available commands are:
* generate-swagger generate Swagger/OpenAPI schema for a project using @fastify/swagger
* readme generate a README.md for the plugin
* print-routes prints the representation of the internal radix tree used by the router, useful for debugging.
* print-plugins prints the representation of the internal plugin tree used by avvio, useful for debugging.
* version the current fastify-cli version
* help help about commands

Expand Down
1 change: 1 addition & 0 deletions help/print-plugins.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Usage: fastify print-plugins <file>
82 changes: 82 additions & 0 deletions print-plugins.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
#! /usr/bin/env node

'use strict'

const parseArgs = require('./args')
const log = require('./log')
const {
exit,
requireFastifyForModule,
requireServerPluginFromPath,
showHelpForCommand
} = require('./util')

let Fastify = null

function loadModules (opts) {
try {
Fastify = requireFastifyForModule(opts._[0]).module
} catch (e) {
module.exports.stop(e)
}
}

function printPlugins (args) {
const opts = parseArgs(args)
if (opts.help) {
return showHelpForCommand('print-plugins')
}

if (opts._.length !== 1) {
console.error('Missing the required file parameter\n')
return showHelpForCommand('print-plugins')
}

// we start crashing on unhandledRejection
require('make-promises-safe')

loadModules(opts)

return runFastify(opts)
}

async function runFastify (opts) {
require('dotenv').config()

let file = null

try {
file = await requireServerPluginFromPath(opts._[0])
} catch (e) {
return module.exports.stop(e)
}

const fastify = Fastify(opts.options)

const pluginOptions = {}
if (opts.prefix) {
pluginOptions.prefix = opts.prefix
}

await fastify.register(file, pluginOptions)
await fastify.ready()
log('debug', fastify.printPlugins())

return fastify
}

function stop (message) {
exit(message)
}

function cli (args) {
return printPlugins(args).then(fastify => {
if (fastify) return fastify.close()
})
}

module.exports = { cli, stop, printPlugins }

if (require.main === module) {
cli(process.argv.slice(2))
}
112 changes: 112 additions & 0 deletions test/print-plugins.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
'use strict'

const proxyquire = require('proxyquire')
const tap = require('tap')
const sinon = require('sinon')
const { execSync } = require('child_process')

const printPlugins = require('../print-plugins')

const test = tap.test

test('should print plugins', async t => {
t.plan(3)

const spy = sinon.spy()
const command = proxyquire('../print-plugins', {
'./log': spy
})
const fastify = await command.printPlugins(['./examples/plugin.js'])

await fastify.close()
t.ok(spy.called)
t.same(spy.args[0][0], 'debug')
t.match(spy.args[0][1], /bound root \d+ ms\n├── bound _after \d+ ms\n├─┬ function \(fastify, options, next\) { -- fastify\.decorate\('test', true\) \d+ ms\n│ ├── bound _after \d+ ms\n│ ├── bound _after \d+ ms\n│ └── bound _after \d+ ms\n└── bound _after \d+ ms\n/)
})

test('should plugins routes via cli', async t => {
t.plan(1)
const output = execSync('node cli.js print-plugins ./examples/plugin.js', { encoding: 'utf-8' })
t.match(
output,
/bound root \d+ ms\n├── bound _after \d+ ms\n├─┬ function \(fastify, options, next\) { -- fastify\.decorate\('test', true\) \d+ ms\n│ ├── bound _after \d+ ms\n│ ├── bound _after \d+ ms\n│ └── bound _after \d+ ms\n└── bound _after \d+ ms\n\n/
)
})

test('should warn on file not found', t => {
t.plan(1)

const oldStop = printPlugins.stop
t.teardown(() => { printPlugins.stop = oldStop })
printPlugins.stop = function (message) {
t.ok(/not-found.js doesn't exist within/.test(message), message)
}

const argv = ['./data/not-found.js']
printPlugins.printPlugins(argv)
})

test('should throw on package not found', t => {
t.plan(1)

const oldStop = printPlugins.stop
t.teardown(() => { printPlugins.stop = oldStop })
printPlugins.stop = function (err) {
t.ok(/Cannot find module 'unknown-package'/.test(err.message), err.message)
}

const argv = ['./test/data/package-not-found.js']
printPlugins.printPlugins(argv)
})

test('should throw on parsing error', t => {
t.plan(1)

const oldStop = printPlugins.stop
t.teardown(() => { printPlugins.stop = oldStop })
printPlugins.stop = function (err) {
t.equal(err.constructor, SyntaxError)
}

const argv = ['./test/data/parsing-error.js']
printPlugins.printPlugins(argv)
})

test('should exit without error on help', t => {
const exit = process.exit
process.exit = sinon.spy()

t.teardown(() => {
process.exit = exit
})

const argv = ['-h', 'true']
printPlugins.printPlugins(argv)

t.ok(process.exit.called)
t.equal(process.exit.lastCall.args[0], undefined)

t.end()
})

test('should print plugins of server with an async/await plugin', async t => {
const nodeMajorVersion = process.versions.node.split('.').map(x => parseInt(x, 10))[0]
if (nodeMajorVersion < 7) {
t.pass('Skip because Node version < 7')
return t.end()
}

t.plan(3)

const spy = sinon.spy()
const command = proxyquire('../print-plugins', {
'./log': spy
})
const argv = ['./examples/async-await-plugin.js']
const fastify = await command.printPlugins(argv)

await fastify.close()
t.ok(spy.called)
t.same(spy.args[0][0], 'debug')
t.match(spy.args[0][1], /bound root \d+ ms\n├── bound _after \d+ ms\n├─┬ async function \(fastify, options\) { -- fastify\.get\('\/', async function \(req, reply\) { \d+ ms\n│ ├── bound _after \d+ ms\n│ └── bound _after \d+ ms\n└── bound _after \d+ ms\n/)
})

0 comments on commit 6832715

Please sign in to comment.