This repository was archived by the owner on Sep 12, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy pathdetect-server.js
146 lines (140 loc) · 4.95 KB
/
detect-server.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
const path = require("path");
const chalk = require("chalk");
const {
// NETLIFYDEV,
NETLIFYDEVLOG
// NETLIFYDEVWARN,
// NETLIFYDEVERR
} = require("netlify-cli-logo");
const inquirer = require("inquirer");
const fs = require("fs");
const detectors = fs
.readdirSync(path.join(__dirname, "detectors"))
.filter(x => x.endsWith(".js")) // only accept .js detector files
.map(det => require(path.join(__dirname, `detectors/${det}`)));
module.exports.serverSettings = async devConfig => {
let settingsArr = [];
let settings = null;
for (const i in detectors) {
const detectorResult = detectors[i]();
if (detectorResult) settingsArr.push(detectorResult);
}
if (settingsArr.length === 1) {
// vast majority of projects will only have one matching detector
settings = settingsArr[0];
settings.args = settings.possibleArgsArrs[0]; // just pick the first one
if (!settings.args) {
const { scripts } = JSON.parse(
fs.readFileSync("package.json", { encoding: "utf8" })
);
// eslint-disable-next-line no-console
console.error(
"empty args assigned, this is an internal Netlify Dev bug, please report your settings and scripts so we can improve",
{ scripts, settings }
);
// eslint-disable-next-line no-process-exit
process.exit(1);
}
} else if (settingsArr.length > 1) {
/** multiple matching detectors, make the user choose */
// lazy loading on purpose
inquirer.registerPrompt(
"autocomplete",
require("inquirer-autocomplete-prompt")
);
const fuzzy = require("fuzzy");
const scriptInquirerOptions = formatSettingsArrForInquirer(settingsArr);
const { chosenSetting } = await inquirer.prompt({
name: "chosenSetting",
message: `Multiple possible start commands found`,
type: "autocomplete",
source: async function(_, input) {
if (!input || input === "") {
return scriptInquirerOptions;
}
// only show filtered results
return filterSettings(scriptInquirerOptions, input);
}
});
settings = chosenSetting; // finally! we have a selected option
// TODO: offer to save this setting to netlify.toml so you dont keep doing this
/** utiltities for the inquirer section above */
function filterSettings(scriptInquirerOptions, input) {
const filteredSettings = fuzzy.filter(
input,
scriptInquirerOptions.map(x => x.name)
);
const filteredSettingNames = filteredSettings.map(x =>
input ? x.string : x
);
return scriptInquirerOptions.filter(t =>
filteredSettingNames.includes(t.name)
);
}
/** utiltities for the inquirer section above */
function formatSettingsArrForInquirer(settingsArr) {
let ans = [];
settingsArr.forEach(setting => {
setting.possibleArgsArrs.forEach(args => {
ans.push({
name: `[${chalk.yellow(setting.type)}] ${
setting.command
} ${args.join(" ")}`,
value: { ...setting, args },
short: setting.type + "-" + args.join(" ")
});
});
});
return ans;
}
}
/** everything below assumes we have settled on one detector */
const tellUser = settingsField => dV =>
// eslint-disable-next-line no-console
console.log(
`${NETLIFYDEVLOG} Overriding ${chalk.yellow(
settingsField
)} with setting derived from netlify.toml [dev] block: `,
dV
);
if (devConfig) {
settings = settings || {};
if (devConfig.command) {
settings.command = assignLoudly(
devConfig.command.split(/\s/)[0],
settings.command || null,
tellUser("command")
); // if settings.command is empty, its bc no settings matched
let devConfigArgs = devConfig.command.split(/\s/).slice(1);
if (devConfigArgs[0] === "run") devConfigArgs = devConfigArgs.slice(1);
settings.args = assignLoudly(
devConfigArgs,
settings.command || null,
tellUser("command")
); // if settings.command is empty, its bc no settings matched
}
if (devConfig.port) {
settings.proxyPort = devConfig.port || settings.proxyPort;
const regexp =
devConfig.urlRegexp ||
new RegExp(`(http://)([^:]+:)${devConfig.port}(/)?`, "g");
settings.urlRegexp = settings.urlRegexp || regexp;
}
settings.dist = devConfig.publish || settings.dist; // dont loudassign if they dont need it
}
return settings;
};
// if first arg is undefined, use default, but tell user about it in case it is unintentional
function assignLoudly(
optionalValue,
defaultValue,
// eslint-disable-next-line no-console
tellUser = dV => console.log(`No value specified, using fallback of `, dV)
) {
if (defaultValue === undefined) throw new Error("must have a defaultValue");
if (defaultValue !== optionalValue && optionalValue === undefined) {
tellUser(defaultValue);
return defaultValue;
}
return optionalValue;
}