/
utils.js
159 lines (138 loc) 路 4.47 KB
/
utils.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
147
148
149
150
151
152
153
154
155
156
157
158
159
import inquirer from 'inquirer'
import path from 'path'
import cosmiconfig from 'cosmiconfig'
import { homedir } from 'os'
import { templateQuestions } from './questions'
import Logger from './logger'
import { getDirectories } from './files'
function isIISNode(main) {
return /\\iisnode\\/.test(main.filename)
}
function handleIISNode(main) {
if (!main.children.length) {
return main.filename
}
return main.children[0].filename
}
function getModulePath(_require = require) {
const main = _require.main
if (main && isIISNode(main)) {
return handleIISNode(main)
}
return main ? main.filename : process.cwd()
}
function getDefaultPathTemplates() {
return `${path.dirname(getModulePath())}/templates`
}
const DEFAULT_PATH_TEMPLATES = getDefaultPathTemplates()
/**
* If the user want to use custom templates, return filtered questions
* for only custom configuration
* @param {object} config
* @param {object} questions
*/
function generateQuestionsCustom(config, questions) {
const mandatoryQuestions = [questions.name, questions.path]
return mandatoryQuestions.filter((question) => {
if (config[question.name]) {
return false
}
return true
})
}
/**
* Generate questions filtered by the config file if exist
*
* @param {object} config
* @param {object} questions
* @returns {array}
*/
function generateQuestions(config = {}, questions = {}) {
const questionKeys = Object.keys(questions)
if (!config) {
return questionKeys.map(question => questions[question])
}
// If type is custom, filter question mandatory to work
if (config.type === 'custom') {
return generateQuestionsCustom(config, questions)
}
// filter questions from config object
const filteredQuestions = []
questionKeys.forEach((question) => {
if (!(question in config)) {
filteredQuestions.push(questions[question])
}
})
return filteredQuestions
}
/**
* Reduce callback to reduce the list of directories
* @param {object} prev
* @param {array} dir
*/
function createListOfDirectories(prev, dir) {
return {
...prev,
[dir.split(path.sep).pop()]: dir,
}
}
/**
* Returns the list of templates available
* @param {any} customPath
*/
function getTemplatesList(customPath = null) {
const predefined = getDirectories(DEFAULT_PATH_TEMPLATES).reduce(createListOfDirectories, {})
try {
const custom = customPath ? getDirectories(customPath).reduce(createListOfDirectories, {}) : []
return { ...predefined, ...custom }
} catch (error) {
Logger.warn('The custom templates path that you supply is unreachable')
Logger.warn('falling back to defaults templates')
return predefined
}
}
/**
* Dynamically import a config file if exist
*
* @param {any} configPath
* @param {any} [searchPath=process.cwd()]
* @param {any} [stopDir=homedir()]
* @returns {Object} config
*/
function getConfig(configPath, searchPath = process.cwd(), stopDir = homedir()) {
const useCustomPath = !!configPath
const explorer = cosmiconfig('cca', { sync: true, stopDir })
try {
const searchPathAbsolute = !useCustomPath && searchPath
const configPathAbsolute = useCustomPath && path.join(process.cwd(), configPath)
// search from the root of the process if the user didnt specify a config file,
// or use the custom path if a file is passed.
const result = explorer.load(searchPathAbsolute, configPathAbsolute)
// dont throw if the explorer didnt find a configfile,
// instead use default config
const config = result ? result.config : {}
const filepath = result ? result.filepath : {}
if (!result) Logger.log('No config file detected, using defaults.')
return { ...config, filepath }
} catch (error) {
Logger.error('An error occured while parsing your config file. Using defaults...\n\n', error.message)
}
return {}
}
/**
* List templates on terminal or get the template (templateName config) from the folder of templates
* @param {array} templatesList to filter
* @param {string} templateName
*/
async function getTemplate(templatesList, templateName = null) {
if (!templateName) {
const templatesArray = Object.entries(templatesList).map(([name, value]) => ({ name, value }))
const { template } = await inquirer.prompt(templateQuestions.template(templatesArray))
return template
}
if (templateName in templatesList) {
return templatesList[templateName]
}
throw Error(`The template '${templateName}' does't exists`)
}
export { generateQuestions, getTemplatesList, getConfig, getTemplate }