-
Notifications
You must be signed in to change notification settings - Fork 142
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(stencil-init): improve code style and test coverage
- Loading branch information
MaxGenash
committed
Aug 27, 2020
1 parent
b2f5337
commit 4ac65ff
Showing
5 changed files
with
490 additions
and
104 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,144 @@ | ||
'use strict'; | ||
const Fs = require('fs'); | ||
const Inquirer = require('inquirer'); | ||
const fsModule = require('fs'); | ||
const inquirerModule = require('inquirer'); | ||
|
||
const jsonLint = require('./json-lint'); | ||
const serverConfigModule = require('../server/config'); | ||
const jsonLintModule = require('./json-lint'); | ||
const { DEFAULT_CUSTOM_LAYOUTS_CONFIG } = require("../constants"); | ||
|
||
async function performAnswers(stencilConfig, dotStencilFilePath, answers) { | ||
const performedStencilConfig = { | ||
customLayouts: { | ||
'brand': {}, | ||
'category': {}, | ||
'page': {}, | ||
'product': {}, | ||
}, | ||
...stencilConfig, | ||
...answers, | ||
}; | ||
class StencilInit { | ||
/** | ||
* @param inquirer | ||
* @param jsonLint | ||
* @param fs | ||
* @param serverConfig | ||
* @param logger | ||
*/ | ||
constructor ({ | ||
inquirer = inquirerModule, | ||
jsonLint = jsonLintModule, | ||
fs = fsModule, | ||
serverConfig = serverConfigModule, | ||
logger = console, | ||
} = {}) { | ||
this.inquirer = inquirer; | ||
this.jsonLint = jsonLint; | ||
this.logger = logger; | ||
this.fs = fs; | ||
this.serverConfig = serverConfig; | ||
} | ||
|
||
Fs.writeFileSync(dotStencilFilePath, JSON.stringify(performedStencilConfig, null, 2)); | ||
} | ||
/** | ||
* @param {string} dotStencilFilePath | ||
* @param {object} cliOptions | ||
* @param {string} cliOptions.url | ||
* @param {string} cliOptions.token | ||
* @param {number} cliOptions.port | ||
* @returns {Promise<void>} | ||
*/ | ||
async run (dotStencilFilePath, cliOptions = {}) { | ||
const oldStencilConfig = this.readStencilConfig(dotStencilFilePath); | ||
const defaultAnswers = this.getDefaultAnswers(oldStencilConfig, cliOptions); | ||
const answers = await this.askQuestions(defaultAnswers); | ||
const updatedStencilConfig = this.applyAnswers(oldStencilConfig, answers); | ||
this.saveStencilConfig(updatedStencilConfig, dotStencilFilePath); | ||
|
||
async function run(dotStencilFilePath, url, token, port) { | ||
let stencilConfig = {}; | ||
this.logger.log('You are now ready to go! To start developing, run $ ' + 'stencil start'.cyan); | ||
} | ||
|
||
if (Fs.existsSync(dotStencilFilePath)) { | ||
const dotStencilFile = Fs.readFileSync(dotStencilFilePath, { encoding: 'utf-8' }); | ||
try { | ||
stencilConfig = jsonLint.parse(dotStencilFile, dotStencilFilePath); | ||
} catch (err) { | ||
console.error( | ||
'Detected a broken .stencil file: ', | ||
err, | ||
'\nThe file will be rewritten with your answers', | ||
); | ||
/** | ||
* @param {string} dotStencilFilePath | ||
* @returns {object} | ||
*/ | ||
readStencilConfig (dotStencilFilePath) { | ||
if (this.fs.existsSync(dotStencilFilePath)) { | ||
const dotStencilFile = this.fs.readFileSync(dotStencilFilePath, { encoding: 'utf-8' }); | ||
try { | ||
// We use jsonLint.parse instead of JSON.parse because jsonLint throws errors with better explanations what is wrong | ||
return this.jsonLint.parse(dotStencilFile, dotStencilFilePath); | ||
} catch (err) { | ||
this.logger.error( | ||
'Detected a broken .stencil file:\n', | ||
err, | ||
'\nThe file will be rewritten with your answers', | ||
); | ||
} | ||
} | ||
|
||
return {}; | ||
} | ||
|
||
const questions = [ | ||
{ | ||
type: 'input', | ||
name: 'normalStoreUrl', | ||
message: 'What is the URL of your store\'s home page?', | ||
validate: function (val) { | ||
if (/^https?:\/\//.test(val)) { | ||
return true; | ||
} else { | ||
return 'You must enter a URL'; | ||
} | ||
/** | ||
* @param {{port: (number), normalStoreUrl: (string), accessToken: (string)}} stencilConfig | ||
* @param {{port: (number), url: (string), token: (string)}} cliOptions | ||
* @returns {{port: (number), normalStoreUrl: (string), accessToken: (string)}} | ||
*/ | ||
getDefaultAnswers (stencilConfig, cliOptions) { | ||
return { | ||
normalStoreUrl: cliOptions.url || stencilConfig.normalStoreUrl, | ||
accessToken: cliOptions.token || stencilConfig.accessToken, | ||
port: cliOptions.port || stencilConfig.port || this.serverConfig.get('/server/port'), | ||
}; | ||
} | ||
|
||
/** | ||
* @param {{port: (number), normalStoreUrl: (string), accessToken: (string)}} defaultAnswers | ||
* @returns {Promise<object>} | ||
*/ | ||
async askQuestions (defaultAnswers) { | ||
return await this.inquirer.prompt([ | ||
{ | ||
type: 'input', | ||
name: 'normalStoreUrl', | ||
message: 'What is the URL of your store\'s home page?', | ||
validate: val => /^https?:\/\//.test(val) || 'You must enter a URL', | ||
default: defaultAnswers.normalStoreUrl, | ||
}, | ||
default: url || stencilConfig.normalStoreUrl, | ||
}, | ||
{ | ||
type: 'input', | ||
name: 'accessToken', | ||
message: 'What is your Stencil OAuth Access Token?', | ||
default: token || stencilConfig.accessToken, | ||
filter: function(val) { | ||
return val.trim(); | ||
{ | ||
type: 'input', | ||
name: 'accessToken', | ||
message: 'What is your Stencil OAuth Access Token?', | ||
default: defaultAnswers.accessToken, | ||
filter: val => val.trim(), | ||
}, | ||
}, | ||
{ | ||
type: 'input', | ||
name: 'port', | ||
message: 'What port would you like to run the server on?', | ||
default: port || stencilConfig.port || 3000, | ||
validate: function (val) { | ||
if (isNaN(val)) { | ||
return 'You must enter an integer'; | ||
} else if (val < 1024 || val > 65535) { | ||
return 'The port number must be between 1025 and 65535'; | ||
} else { | ||
return true; | ||
} | ||
{ | ||
type: 'input', | ||
name: 'port', | ||
message: 'What port would you like to run the server on?', | ||
default: defaultAnswers.port, | ||
validate: val => { | ||
if (isNaN(val)) { | ||
return 'You must enter an integer'; | ||
} else if (val < 1024 || val > 65535) { | ||
return 'The port number must be between 1025 and 65535'; | ||
} else { | ||
return true; | ||
} | ||
}, | ||
}, | ||
}, | ||
]; | ||
const answers = await Inquirer.prompt(questions); | ||
]); | ||
} | ||
|
||
await performAnswers(stencilConfig, dotStencilFilePath, answers); | ||
/** | ||
* @param {object} stencilConfig | ||
* @param {object} answers | ||
* @returns {object} | ||
*/ | ||
applyAnswers (stencilConfig, answers) { | ||
return { | ||
customLayouts: DEFAULT_CUSTOM_LAYOUTS_CONFIG, | ||
...stencilConfig, | ||
...answers, | ||
}; | ||
} | ||
|
||
console.log('You are now ready to go! To start developing, run $ ' + 'stencil start'.cyan); | ||
/** | ||
* @param {object} config | ||
* @param {string} path | ||
*/ | ||
saveStencilConfig (config, path) { | ||
this.fs.writeFileSync(path, JSON.stringify(config, null, 2)); | ||
} | ||
} | ||
|
||
module.exports = { | ||
performAnswers, | ||
run, | ||
}; | ||
module.exports = StencilInit; |
Oops, something went wrong.