Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ You can pass the following options via CLI arguments. You can also use `--config
| Set the inspector host to listen on (default: loopback address or `0.0.0.0` inside Docker) | | `--debug-host` | `FASTIFY_DEBUG_HOST` |
| Prints pretty logs | `-P` | `--pretty-logs` | `FASTIFY_PRETTY_LOGS` |
| Watch process.cwd() directory for changes, recursively; when that happens, the process will auto reload | `-w` | `--watch` | `FASTIFY_WATCH` |
| When watch triggers a restart, run a command. | `-e` | `--on-watch-event` | `FASTIFY_ON_WATCH_EVENT ` |
| Ignore changes to the specified files or directories when watch is enabled. (e.g. `--ignore-watch='node_modules .git logs/error.log'` ) | | `--ignore-watch` | `FASTIFY_IGNORE_WATCH` |
| Prints events triggered by watch listener (useful to debug unexpected reload when using `--watch` ) | `-V` | `--verbose-watch` | `FASTIFY_VERBOSE_WATCH` |
| Use custom options | `-o` | `--options` | `FASTIFY_OPTIONS` |
Expand Down
5 changes: 4 additions & 1 deletion args.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const DEFAULT_ARGUMENTS = {
prettyLogs: false,
watch: false,
verboseWatch: false,
onWatchEvent: '',
debug: false,
debugPort: 9320,
options: false,
Expand All @@ -27,7 +28,7 @@ module.exports = function parseArgs (args) {
'populate--': true
},
number: ['port', 'inspect-port', 'body-limit', 'plugin-timeout', 'close-grace-delay'],
string: ['log-level', 'address', 'socket', 'prefix', 'ignore-watch', 'logging-module', 'debug-host', 'lang', 'require', 'config'],
string: ['log-level', 'address', 'socket', 'prefix', 'ignore-watch', 'on-watch-event', 'logging-module', 'debug-host', 'lang', 'require', 'config'],
boolean: ['pretty-logs', 'options', 'watch', 'verbose-watch', 'debug', 'standardlint'],
envPrefix: 'FASTIFY_',
alias: {
Expand All @@ -41,6 +42,7 @@ module.exports = function parseArgs (args) {
prefix: ['x'],
require: ['r'],
debug: ['d'],
'on-watch-event': ['e'],
'debug-port': ['I'],
'log-level': ['l'],
'pretty-logs': ['P'],
Expand Down Expand Up @@ -81,6 +83,7 @@ module.exports = function parseArgs (args) {
debugHost: parsedArgs.debugHost,
ignoreWatch,
verboseWatch: parsedArgs.verboseWatch,
onWatchEvent: parsedArgs.onWatchEvent,
logLevel: parsedArgs.logLevel,
address: parsedArgs.address,
socket: parsedArgs.socket,
Expand Down
4 changes: 4 additions & 0 deletions help/start.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ OPTS
[env: FASTIFY_WATCH]
Watch process.cwd() directory for changes, recursively; when that happens, the process will auto reload.

-e, --on-watch-event
[env: FASTIFY_ON_WATCH_EVENT]
When watch triggers a restart, run a command.

-x, --prefix
[env: FASTIFY_PREFIX]
Set the prefix
Expand Down
7 changes: 7 additions & 0 deletions lib/watch/fork.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use strict'

const { execSync } = require('child_process')
const chalk = require('chalk')
const { stop, runFastify } = require('../../start')

Expand Down Expand Up @@ -37,6 +38,12 @@ process.on('uncaughtException', (err) => {
})

const main = async () => {

if (process.env.onWatchEvent) {
const output = execSync(process.env.onWatchEvent).toString()
process.send(output)
}

fastify = await runFastify(process.argv.splice(2))
const type = process.env.childEvent

Expand Down
8 changes: 5 additions & 3 deletions lib/watch/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const EventEmitter = require('events')
const chokidar = require('chokidar')
const forkPath = path.join(__dirname, './fork.js')

const watch = function (args, ignoreWatch, verboseWatch) {
const watch = function (args, ignoreWatch, verboseWatch, onWatchEvent) {
const emitter = new EventEmitter()
let allStop = false
let childs = []
Expand Down Expand Up @@ -38,12 +38,13 @@ const watch = function (args, ignoreWatch, verboseWatch) {
let readyEmitted = false

const run = (event) => {
const childEvent = { childEvent: event }
const childEvent = { childEvent: event, onWatchEvent }
const env = Object.assign({}, require('dotenv').config().parsed, process.env, childEvent)
const _child = cp.fork(forkPath, args, {
env,
cwd: process.cwd(),
encoding: 'utf8'
encoding: 'utf8',
stdio: 'inherit'
})

_child.on('exit', function (code, signal) {
Expand Down Expand Up @@ -106,6 +107,7 @@ const watch = function (args, ignoreWatch, verboseWatch) {
})

emitter.stop = stop.bind(null, watcher)
emitter.childs = childs

return emitter
}
Expand Down
2 changes: 1 addition & 1 deletion start.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ async function start (args) {
loadModules(opts)

if (opts.watch) {
return watch(args, opts.ignoreWatch, opts.verboseWatch)
return watch(args, opts.ignoreWatch, opts.verboseWatch, opts.onWatchEvent)
}

return runFastify(args)
Expand Down
14 changes: 13 additions & 1 deletion test/args.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ test('should parse args correctly', t => {
'--log-level', 'info',
'--pretty-logs', 'true',
'--watch', 'true',
'--on-watch-event', 'echo changed',
'--ignore-watch', 'ignoreme.js',
'--verbose-watch', 'true',
'--options', 'true',
Expand All @@ -34,6 +35,7 @@ test('should parse args correctly', t => {
prettyLogs: true,
options: true,
watch: true,
onWatchEvent: 'echo changed',
ignoreWatch: 'node_modules build dist .git bower_components logs .swp .nyc_output ignoreme.js',
verboseWatch: true,
port: 7777,
Expand Down Expand Up @@ -65,6 +67,7 @@ test('should parse args with = assignment correctly', t => {
'--log-level=info',
'--pretty-logs=true',
'--watch=true',
'--on-watch-event="echo changed"',
'--ignore-watch=ignoreme.js',
'--verbose-watch=true',
'--options=true',
Expand All @@ -86,6 +89,7 @@ test('should parse args with = assignment correctly', t => {
prettyLogs: true,
options: true,
watch: true,
onWatchEvent: 'echo changed',
ignoreWatch: 'node_modules build dist .git bower_components logs .swp .nyc_output ignoreme.js',
verboseWatch: true,
port: 7777,
Expand Down Expand Up @@ -116,6 +120,7 @@ test('should parse env vars correctly', t => {
process.env.FASTIFY_LOG_LEVEL = 'info'
process.env.FASTIFY_PRETTY_LOGS = 'true'
process.env.FASTIFY_WATCH = 'true'
process.env.FASTIFY_ON_WATCH_EVENT = 'echo changed'
process.env.FASTIFY_IGNORE_WATCH = 'ignoreme.js'
process.env.FASTIFY_VERBOSE_WATCH = 'true'
process.env.FASTIFY_OPTIONS = 'true'
Expand All @@ -136,6 +141,7 @@ test('should parse env vars correctly', t => {
delete process.env.FASTIFY_LOG_LEVEL
delete process.env.FASTIFY_PRETTY_LOGS
delete process.env.FASTIFY_WATCH
delete process.env.FASTIFY_ON_WATCH_EVENT
delete process.env.FASTIFY_IGNORE_WATCH
delete process.env.FASTIFY_VERBOSE_WATCH
delete process.env.FASTIFY_OPTIONS
Expand All @@ -156,6 +162,7 @@ test('should parse env vars correctly', t => {
prettyLogs: true,
options: true,
watch: true,
onWatchEvent: 'echo changed',
ignoreWatch: 'node_modules build dist .git bower_components logs .swp .nyc_output ignoreme.js',
verboseWatch: true,
address: 'fastify.io:9999',
Expand All @@ -177,7 +184,7 @@ test('should parse env vars correctly', t => {
})

test('should respect default values', t => {
t.plan(13)
t.plan(14)

const argv = [
'app.js'
Expand All @@ -189,6 +196,7 @@ test('should respect default values', t => {
t.equal(parsedArgs.options, false)
t.equal(parsedArgs.prettyLogs, false)
t.equal(parsedArgs.watch, false)
t.equal(parsedArgs.onWatchEvent, '')
t.equal(parsedArgs.ignoreWatch, 'node_modules build dist .git bower_components logs .swp .nyc_output')
t.equal(parsedArgs.verboseWatch, false)
t.equal(parsedArgs.logLevel, 'fatal')
Expand All @@ -211,6 +219,7 @@ test('should parse custom plugin options', t => {
'--log-level', 'info',
'--pretty-logs', 'true',
'--watch', 'true',
'--on-watch-event', 'echo changed',
'--ignore-watch', 'ignoreme.js',
'--verbose-watch', 'true',
'--options', 'true',
Expand Down Expand Up @@ -239,6 +248,7 @@ test('should parse custom plugin options', t => {
prettyLogs: true,
options: true,
watch: true,
onWatchEvent: 'echo changed',
ignoreWatch: 'node_modules build dist .git bower_components logs .swp .nyc_output ignoreme.js',
verboseWatch: true,
port: 7777,
Expand Down Expand Up @@ -284,6 +294,7 @@ test('should parse config file correctly and prefer config values over default o
prettyLogs: true,
options: false,
watch: true,
onWatchEvent: '',
debug: false,
debugPort: 4000,
debugHost: '1.1.1.1',
Expand Down Expand Up @@ -323,6 +334,7 @@ test('should prefer command line args over config file options', t => {
prettyLogs: true,
options: false,
watch: true,
onWatchEvent: '',
debug: false,
debugPort: 9320,
debugHost: '1.1.1.1',
Expand Down
15 changes: 13 additions & 2 deletions test/start.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ test('should start the server with watch options that the child process restart
})

test('should start the server with watch and verbose-watch options that the child process restart when directory changed with console message about changes ', { skip: process.platform === 'win32' }, async (t) => {
t.plan(4)
t.plan(5)

const spy = sinon.spy()
const watch = proxyquire('../lib/watch', {
Expand All @@ -582,7 +582,7 @@ test('should start the server with watch and verbose-watch options that the chil
const port = getPort()

await writeFile(tmpjs, 'hello world')
const argv = ['-p', port, '-w', '--verbose-watch', './examples/plugin.js']
const argv = ['-p', port, '-w', '--verbose-watch', '--on-watch-event="echo changed"', './examples/plugin.js']
const fastifyEmitter = await start.start(argv)

t.teardown(async () => {
Expand All @@ -592,12 +592,23 @@ test('should start the server with watch and verbose-watch options that the chil
await fastifyEmitter.stop()
})

// listen for any of the forked processes messages
const onChanges = new Promise((resolve, reject) => {
for (const child of fastifyEmitter.childs) {
child.on('message', resolve)
setTimeout(reject, 300)
}
})

await once(fastifyEmitter, 'ready')
t.pass('should receive ready event')

await writeFile(tmpjs, 'hello fastify', { flag: 'a+' }) // chokidar watch can't catch change event in CI, but local test is all ok. you can remove annotation in local environment.
t.pass('change tmpjs')

const message = await onChanges
t.ok(message.includes('changed'), 'forked process sends "changed" message')

// this might happen more than once but does not matter in this context
await once(fastifyEmitter, 'restart')
t.pass('should receive restart event')
Expand Down