diff --git a/src/commands/dev/index.js b/src/commands/dev/index.js index a0ea3e4..9c5f4e4 100644 --- a/src/commands/dev/index.js +++ b/src/commands/dev/index.js @@ -1,13 +1,13 @@ -const { flags } = require('@oclif/command') -const { spawn } = require('child_process') +const {flags} = require('@oclif/command') +const {spawn} = require('child_process') const http = require('http') const httpProxy = require('http-proxy') const waitPort = require('wait-port') const getPort = require('get-port') -const { serveFunctions } = require('@netlify/zip-it-and-ship-it') -const { serverSettings } = require('../../detect-server') +const {serveFunctions} = require('@netlify/zip-it-and-ship-it') +const {serverSettings} = require('../../detect-server') const Command = require('@netlify/cli-utils') -const { getAddons } = require('netlify/src/addons') +const {getAddons} = require('netlify/src/addons') function cleanExit() { process.exit() @@ -26,45 +26,47 @@ function addonUrl(addonUrls, req) { async function startProxy(settings, addonUrls) { const rulesProxy = require('netlify-rules-proxy') - await waitPort({ port: settings.proxyPort }) + await waitPort({port: settings.proxyPort}) if (settings.functionsPort) { - await waitPort({ port: settings.functionsPort }) + await waitPort({port: settings.functionsPort}) } - const port = await getPort({ port: settings.port }) - const functionsServer = settings.functionsPort ? `http://localhost:${settings.functionsPort}` : null + const port = await getPort({port: settings.port}) + const functionsServer = settings.functionsPort ? + `http://localhost:${settings.functionsPort}` : + null const proxy = httpProxy.createProxyServer({ target: { host: 'localhost', - port: settings.proxyPort - } + port: settings.proxyPort, + }, }) - const rewriter = rulesProxy({ publicFolder: settings.dist }) + const rewriter = rulesProxy({publicFolder: settings.dist}) - const server = http.createServer(function(req, res) { + const server = http.createServer(function (req, res) { if (isFunction(settings, req)) { - return proxy.web(req, res, { target: functionsServer }) + return proxy.web(req, res, {target: functionsServer}) } let url = addonUrl(addonUrls, req) if (url) { - return proxy.web(req, res, { target: url }) + return proxy.web(req, res, {target: url}) } rewriter(req, res, () => { if (isFunction(settings, req)) { - return proxy.web(req, res, { target: functionsServer }) + return proxy.web(req, res, {target: functionsServer}) } url = addonUrl(addonUrls, req) if (url) { - return proxy.web(req, res, { target: url }) + return proxy.web(req, res, {target: url}) } - proxy.web(req, res, { target: `http://localhost:${settings.proxyPort}` }) + proxy.web(req, res, {target: `http://localhost:${settings.proxyPort}`}) }) }) - server.on('upgrade', function(req, socket, head) { + server.on('upgrade', function (req, socket, head) { proxy.ws(req, socket, head) }) @@ -80,17 +82,17 @@ function startDevServer(settings, log, error) { name: 'netlify-dev', port: settings.proxyPort, templates: { - notFound: '404.html' - } + notFound: '404.html', + }, }) - server.start(function() { + server.start(function () { log('Server listening to', settings.proxyPort) }) return } - const ps = spawn(settings.cmd, settings.args, { env: settings.env }) + const ps = spawn(settings.cmd, settings.args, {env: settings.env}) ps.stdout.on('data', data => { log(`${data}`.replace(settings.urlRegexp, `$1$2${settings.port}$3`)) @@ -110,23 +112,26 @@ function startDevServer(settings, log, error) { class DevCommand extends Command { async run() { - const { flags, args } = this.parse(DevCommand) - const { api, site, config } = this.netlify - const functionsDir = flags.functions || (config.build && config.build.functions) + const {flags, args} = this.parse(DevCommand) + const {api, site, config} = this.netlify + const functionsDir = + flags.functions || (config.build && config.build.functions) const addonUrls = {} if (site.id && !flags.offline) { const accessToken = await this.authenticate() const addons = await getAddons(site.id, accessToken) if (Array.isArray(addons)) { addons.forEach(addon => { - addonUrls[addon.slug] = `${addon.config.site_url}/.netlify/${addon.slug}` + addonUrls[addon.slug] = `${addon.config.site_url}/.netlify/${ + addon.slug + }` for (const key in addon.env) { process.env[key] = process.env[key] || addon.env[key] } }) } const api = this.netlify.api - const apiSite = await api.getSite({ site_id: site.id }) + const apiSite = await api.getSite({site_id: site.id}) // TODO: We should move the environment outside of build settings and possibly have a // `/api/v1/sites/:site_id/environment` endpoint for it that we can also gate access to // In the future and that we could make context dependend @@ -137,19 +142,19 @@ class DevCommand extends Command { } } process.env.NETLIFY_DEV = 'true' - let settings = serverSettings() + let settings = serverSettings(config.dev) if (!(settings && settings.cmd)) { this.log('No dev server detected, using simple static server') settings = { noCmd: true, port: 8888, proxyPort: 3999, - dist: config.build && config.build.publish + dist: config.build && config.build.publish, } } startDevServer(settings, this.log, this.error) if (functionsDir) { - const fnSettings = await serveFunctions({ functionsDir }) + const fnSettings = await serveFunctions({functionsDir}) settings.functionsPort = fnSettings.port } @@ -162,26 +167,30 @@ DevCommand.description = `Local dev server The dev command will run a local dev server with Netlify's proxy and redirect rules ` -DevCommand.examples = ['$ netlify dev', '$ netlify dev -c "yarn start"', '$ netlify dev -c hugo'] +DevCommand.examples = [ + '$ netlify dev', + '$ netlify dev -c "yarn start"', + '$ netlify dev -c hugo', +] DevCommand.strict = false DevCommand.flags = { - cmd: flags.string({ char: 'c', description: 'command to run' }), + cmd: flags.string({char: 'c', description: 'command to run'}), devport: flags.integer({ char: 'd', - description: 'port of the dev server started by command' + description: 'port of the dev server started by command', }), - port: flags.integer({ char: 'p', description: 'port of netlify dev' }), - dir: flags.integer({ char: 'd', description: 'dir with static files' }), + port: flags.integer({char: 'p', description: 'port of netlify dev'}), + dir: flags.integer({char: 'd', description: 'dir with static files'}), functions: flags.string({ char: 'f', - description: 'Specify a functions folder to serve' + description: 'Specify a functions folder to serve', }), offline: flags.boolean({ char: 'o', - description: 'disables any features that require network access' - }) + description: 'disables any features that require network access', + }), } module.exports = DevCommand diff --git a/src/detect-server.js b/src/detect-server.js index 88423e5..16f5b77 100644 --- a/src/detect-server.js +++ b/src/detect-server.js @@ -5,15 +5,38 @@ const hugoDetector = require('./detectors/hugo') const eleventyDetector = require('./detectors/eleventy') const jekyllDetector = require('./detectors/jekyll') -const detectors = [gatsbyDetector, reactStaticDetector, hugoDetector, jekyllDetector, eleventyDetector, craDetector] +const detectors = [ + gatsbyDetector, + reactStaticDetector, + hugoDetector, + jekyllDetector, + eleventyDetector, + craDetector, +] -module.exports.serverSettings = () => { +module.exports.serverSettings = devConfig => { + let settings = null for (const i in detectors) { - const settings = detectors[i]() + settings = detectors[i]() if (settings) { - return settings + break } } - return null + if (devConfig) { + settings = settings || {} + if (devConfig.cmd) { + settings.cmd = devConfig.cmd.split(/\s/)[0] + settings.args = devConfig.cmd.split(/\s/).slice(1) + } + if (devConfig.port) { + settings.proxyPort = devConfig.port + settings.urlRegexp = + devConfig.urlRegexp || + new RegExp(`(http://)([^:]+:)${devConfig.port}(/)?`, 'g') + } + settings.dist = devConfig.publish || settings.dist + } + + return settings }