-
Notifications
You must be signed in to change notification settings - Fork 10.3k
/
plugin-options-form.ts
111 lines (100 loc) · 2.7 KB
/
plugin-options-form.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
107
108
109
110
111
import { stripIndent } from "common-tags"
import terminalLink from "terminal-link"
import Joi from "joi"
import pluginSchemas from "./plugin-schemas.json"
import cmses from "./cmses.json"
import styles from "./styles.json"
import c from "ansi-colors"
const supportedOptionTypes = [`string`, `boolean`, `number`]
type Schema = Joi.Description & {
// Limitation in Joi typings
// eslint-disable-next-line @typescript-eslint/no-explicit-any
flags?: Record<string, any>
}
type PluginName = keyof typeof pluginSchemas
interface IFormPrompt {
type: string
name: string
multiple: boolean
message: string
choices: Array<{
name: string
initial: unknown
message: string
hint?: string
}>
}
function getName(key: string): string | undefined {
const plugins = [cmses, styles] // "features" doesn't map to names
for (const types of plugins) {
if (key in types) {
return types[key as keyof typeof types].message
}
}
return key
}
function docsLink(pluginName: string): string {
return c.blueBright(
terminalLink(
`the plugin docs`,
`https://www.gatsbyjs.com/plugins/${pluginName}/`,
{ fallback: (_, url) => url }
)
)
}
export const makePluginConfigQuestions = (
selectedPlugins: Array<string>
): Array<IFormPrompt> => {
const formPrompts: Array<IFormPrompt> = []
selectedPlugins.forEach((pluginName: string): void => {
const schema = pluginSchemas[pluginName as PluginName]
if (!schema || typeof schema === `string` || !(`keys` in schema)) {
return
}
const options: Record<string, Schema> | undefined = schema?.keys
const choices: Array<{
name: string
initial: string
message: string
hint?: string
}> = []
if (!options) {
return
}
Object.entries(options).forEach(([name, option]) => {
if (option?.flags?.presence !== `required`) {
return
}
choices.push({
name,
initial:
option.flags?.default &&
supportedOptionTypes.includes(typeof option.flags?.default)
? option.flags?.default.toString()
: undefined,
message: name,
hint: option.flags?.description,
})
})
if (choices.length) {
formPrompts.push({
type: `forminput`,
name: pluginName,
multiple: true,
message: stripIndent`
Configure the ${getName(pluginName)} plugin.
See ${docsLink(pluginName)} for help.
${
choices.length > 1
? c.green(
`Use arrow keys to move between fields, and enter to finish`
)
: ``
}
`,
choices,
})
}
})
return formPrompts
}