-
Notifications
You must be signed in to change notification settings - Fork 366
/
build-info.ts
106 lines (95 loc) · 3.57 KB
/
build-info.ts
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
import { Settings } from '@netlify/build-info'
import fuzzy from 'fuzzy'
import inquirer from 'inquirer'
import BaseCommand from '../commands/base-command.js'
import { chalk, log } from './command-helpers.js'
/**
* Filters the inquirer settings based on the input
*/
const filterSettings = function (
scriptInquirerOptions: ReturnType<typeof formatSettingsArrForInquirer>,
input: string,
) {
const filterOptions = scriptInquirerOptions.map((scriptInquirerOption) => scriptInquirerOption.name)
// TODO: remove once https://github.com/sindresorhus/eslint-plugin-unicorn/issues/1394 is fixed
// eslint-disable-next-line unicorn/no-array-method-this-argument
const filteredSettings = fuzzy.filter(input, filterOptions)
const filteredSettingNames = new Set(
filteredSettings.map((filteredSetting) => (input ? filteredSetting.string : filteredSetting)),
)
return scriptInquirerOptions.filter((t) => filteredSettingNames.has(t.name))
}
/**
* Formats the settings to present it as an array for the inquirer input so that it can choose one
*/
const formatSettingsArrForInquirer = function (settings: Settings[], type = 'dev') {
return settings.map((setting) => {
const cmd = type === 'dev' ? setting.devCommand : setting.buildCommand
return {
name: `[${chalk.yellow(setting.framework.name)}] '${cmd}'`,
value: { ...setting, commands: [cmd] },
short: `${setting.name}-${cmd}`,
}
})
}
/**
* Detects and filters the build setting for a project and a command
*/
export async function detectBuildSettings(command: BaseCommand): Promise<Settings[]> {
const { project, workspacePackage } = command
const buildSettings = await project.getBuildSettings(project.workspace ? workspacePackage : '')
return buildSettings
.filter((setting) => {
if (project.workspace && project.relativeBaseDirectory && setting.packagePath) {
return project.relativeBaseDirectory.startsWith(setting.packagePath)
}
return true
})
.filter((setting) => setting.devCommand)
}
/**
* Uses `@netlify/build-info` to detect the dev settings and port based on the framework
* and the build system that is used.
* @param command The base command
* @param type The type of command (dev or build)
*/
export const detectFrameworkSettings = async (
command: BaseCommand,
type: 'dev' | 'build' = 'dev',
): Promise<Settings | undefined> => {
const { relConfigFilePath } = command.netlify
const settings = await detectBuildSettings(command)
if (settings.length === 1) {
return settings[0]
}
if (type === 'build' && command.netlify.config?.build?.command?.length) {
return {
...settings[0],
buildCommand: command.netlify.config.build.command,
}
}
if (settings.length > 1) {
// multiple matching detectors, make the user choose
const scriptInquirerOptions = formatSettingsArrForInquirer(settings, type)
const { chosenSettings } = await inquirer.prompt<{ chosenSettings: Settings }>({
name: 'chosenSettings',
message: `Multiple possible ${type} commands found`,
// @ts-expect-error is not known by the types as it uses the autocomplete plugin
type: 'autocomplete',
source(_: string, input = '') {
if (!input) return scriptInquirerOptions
// only show filtered results
return filterSettings(scriptInquirerOptions, input)
},
})
log(`
Update your ${relConfigFilePath} to avoid this selection prompt next time:
[build]
command = "${chosenSettings.buildCommand}"
publish = "${chosenSettings.dist}"
[dev]
command = "${chosenSettings.devCommand}"
`)
return chosenSettings
}
}