1 | const path = require('path')
|
2 | const chalk = require('chalk')
|
3 | const { NETLIFYDEVLOG } = require('./logo')
|
4 | const inquirer = require('inquirer')
|
5 | const fuzzy = require('fuzzy')
|
6 | const fs = require('fs')
|
7 |
|
8 | module.exports.serverSettings = async devConfig => {
|
9 | const detectors = fs
|
10 | .readdirSync(path.join(__dirname, '..', 'detectors'))
|
11 | .filter(x => x.endsWith('.js'))
|
12 | .map(det => {
|
13 | try {
|
14 | return require(path.join(__dirname, '..', `detectors/${det}`))
|
15 | } catch (err) {
|
16 | console.error(
|
17 | `failed to load detector: ${chalk.yellow(
|
18 | det
|
19 | )}, this is likely a bug in the detector, please file an issue in netlify-dev-plugin`,
|
20 | err
|
21 | )
|
22 | return null
|
23 | }
|
24 | })
|
25 | .filter(Boolean)
|
26 | let settingsArr = []
|
27 | let settings = null
|
28 | for (const i in detectors) {
|
29 | const detectorResult = detectors[i]()
|
30 | if (detectorResult) settingsArr.push(detectorResult)
|
31 | }
|
32 | if (settingsArr.length === 1) {
|
33 |
|
34 | settings = settingsArr[0]
|
35 | settings.args = settings.possibleArgsArrs[0]
|
36 | if (!settings.args) {
|
37 | const { scripts } = JSON.parse(fs.readFileSync('package.json', { encoding: 'utf8' }))
|
38 |
|
39 | console.error(
|
40 | 'empty args assigned, this is an internal Netlify Dev bug, please report your settings and scripts so we can improve',
|
41 | { scripts, settings }
|
42 | )
|
43 |
|
44 | process.exit(1)
|
45 | }
|
46 | } else if (settingsArr.length > 1) {
|
47 |
|
48 |
|
49 | inquirer.registerPrompt('autocomplete', require('inquirer-autocomplete-prompt'))
|
50 | const scriptInquirerOptions = formatSettingsArrForInquirer(settingsArr)
|
51 | const { chosenSetting } = await inquirer.prompt({
|
52 | name: 'chosenSetting',
|
53 | message: `Multiple possible start commands found`,
|
54 | type: 'autocomplete',
|
55 | source: async function(_, input) {
|
56 | if (!input || input === '') {
|
57 | return scriptInquirerOptions
|
58 | }
|
59 |
|
60 | return filterSettings(scriptInquirerOptions, input)
|
61 | }
|
62 | })
|
63 | settings = chosenSetting
|
64 |
|
65 | }
|
66 |
|
67 |
|
68 | const tellUser = settingsField => dV =>
|
69 |
|
70 | console.log(
|
71 | `${NETLIFYDEVLOG} Overriding ${chalk.yellow(settingsField)} with setting derived from netlify.toml [dev] block: `,
|
72 | dV
|
73 | )
|
74 |
|
75 | if (devConfig) {
|
76 | settings = settings || {}
|
77 | if (devConfig.command) {
|
78 | settings.command = assignLoudly(devConfig.command.split(/\s/)[0], settings.command || null, tellUser('command'))
|
79 | let devConfigArgs = devConfig.command.split(/\s/).slice(1)
|
80 | if (devConfigArgs[0] === 'run') devConfigArgs = devConfigArgs.slice(1)
|
81 | settings.args = assignLoudly(devConfigArgs, settings.command || null, tellUser('command'))
|
82 | }
|
83 | if (devConfig.port) settings.port = devConfig.port
|
84 | if (devConfig.targetPort) {
|
85 | settings.proxyPort = devConfig.targetPort
|
86 | settings.urlRegexp = devConfig.urlRegexp || new RegExp(`(http://)([^:]+:)${devConfig.targetPort}(/)?`, 'g')
|
87 | }
|
88 | if (devConfig.functionsPort) settings.functionsPort = devConfig.functionsPort
|
89 | settings.dist = devConfig.publish || settings.dist
|
90 |
|
91 | if (devConfig.jwtRolePath) settings.jwtRolePath = devConfig.jwtRolePath
|
92 | }
|
93 | return settings
|
94 | }
|
95 |
|
96 |
|
97 | function filterSettings(scriptInquirerOptions, input) {
|
98 | const filteredSettings = fuzzy.filter(input, scriptInquirerOptions.map(x => x.name))
|
99 | const filteredSettingNames = filteredSettings.map(x => (input ? x.string : x))
|
100 | return scriptInquirerOptions.filter(t => filteredSettingNames.includes(t.name))
|
101 | }
|
102 |
|
103 |
|
104 | function formatSettingsArrForInquirer(settingsArr) {
|
105 | let ans = []
|
106 | settingsArr.forEach(setting => {
|
107 | setting.possibleArgsArrs.forEach(args => {
|
108 | ans.push({
|
109 | name: `[${chalk.yellow(setting.type)}] ${setting.command} ${args.join(' ')}`,
|
110 | value: { ...setting, args },
|
111 | short: setting.type + '-' + args.join(' ')
|
112 | })
|
113 | })
|
114 | })
|
115 | return ans
|
116 | }
|
117 |
|
118 | function assignLoudly(
|
119 | optionalValue,
|
120 | defaultValue,
|
121 | // eslint-disable-next-line no-console
|
122 | tellUser = dV => console.log(`No value specified, using fallback of `, dV)
|
123 | ) {
|
124 | if (defaultValue === undefined) throw new Error('must have a defaultValue')
|
125 | if (defaultValue !== optionalValue && optionalValue === undefined) {
|
126 | tellUser(defaultValue)
|
127 | return defaultValue
|
128 | }
|
129 | return optionalValue
|
130 | }
|