Skip to content

Commit

Permalink
refactor(stencil-init): improve code style and test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
MaxGenash committed Aug 27, 2020
1 parent b2f5337 commit 4ac65ff
Show file tree
Hide file tree
Showing 5 changed files with 490 additions and 104 deletions.
10 changes: 7 additions & 3 deletions bin/stencil-init
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#!/usr/bin/env node

require('colors');
const Program = require('commander');
const _ = require('lodash');

const StencilInit = require('../lib/stencil-init');
const pkg = require('../package.json');
const Program = require('commander');
const dotStencilFilePath = './.stencil';
const versionCheck = require('../lib/version-check');

Program
Expand All @@ -18,4 +19,7 @@ if (!versionCheck()) {
return;
}

StencilInit.run(dotStencilFilePath, Program.url, Program.token, Program.port);
const dotStencilFilePath = './.stencil';
const cliOptions = _.pick(Program, ['url', 'token', 'port']);

new StencilInit().run(dotStencilFilePath, cliOptions);
12 changes: 11 additions & 1 deletion constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,14 @@ const path = require('path');
const packagePath = path.join(process.cwd(), 'package.json');
const packageInfo = require(packagePath);

module.exports = { packageInfo };
const DEFAULT_CUSTOM_LAYOUTS_CONFIG = {
'brand': {},
'category': {},
'page': {},
'product': {},
};

module.exports = {
packageInfo,
DEFAULT_CUSTOM_LAYOUTS_CONFIG,
};
199 changes: 128 additions & 71 deletions lib/stencil-init.js
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;
Loading

0 comments on commit 4ac65ff

Please sign in to comment.