const chokidar = require('chokidar') const bodyParser = require('body-parser') const chalk = require('chalk') function registerRoutes(app) { const { default: mocks } = require('./index.js') for (const mock of mocks) { app[mock.type](mock.url, mock.response) } return { mockRoutesLength: Object.keys(mocks).length } } function unregisterRoutes() { Object.keys(require.cache).forEach(i => { if (i.includes('/mock')) { delete require.cache[require.resolve(i)] } }) } function getPath(path) { var match = path.toString() .replace('\\/?', '') .replace('(?=\\/|$)', '$') .match(/^\/\^((?:\\[.*+?^${}()|[\]\\\/]|[^.*+?^${}()|[\]\\\/])*)\$\//) return match ? match[1].replace(/\\(.)/g, '$1').split('/') : path.toString() } function getMockRoutesIndex(app) { for (let index = 0; index <= app._router.stack.length; index++) { const r = app._router.stack[index] if (r.route && r.route.path) { const path = getPath(r.route.path) if (path.includes('mock')) { return index } } } } module.exports = app => { // es6 polyfill require('@babel/register') // parse app.body // http://expressjs.com/en/4x/api.html#req.body app.use(bodyParser.json()) app.use(bodyParser.urlencoded({ extended: true })) const { mockRoutesLength } = registerRoutes(app) // watch files, hot reload mock server chokidar.watch(('./mock'), { ignored: 'mock/mock-server.js', persistent: true, ignoreInitial: true }).on('all', (event, path) => { if (event === 'change' || event === 'add') { // find mock routes stack index const index = getMockRoutesIndex(app) // remove mock routes stack app._router.stack.splice(index, mockRoutesLength) // clear routes cache unregisterRoutes() registerRoutes(app) console.log(chalk.magentaBright(`\n > Mock Server hot reload success! changed ${path}`)) } }) }