Skip to content

Commit

Permalink
feat: STRF-9757 Add some "stencil debug" command which dumps system i…
Browse files Browse the repository at this point in the history
…nfo useful for troubleshooting in a user-friendly way
  • Loading branch information
jairo-bc committed Apr 21, 2022
1 parent b012aa7 commit d8c36ca
Show file tree
Hide file tree
Showing 6 changed files with 1,564 additions and 2,172 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
### Draft

- feat: STRF-9757 Introduced "stencil debug" ([x](https://github.com/bigcommerce/stencil-cli/pull/x))

Available options: --output [filename] (-o)
If not provided, will be logged to std

### 4.0.0 (2022-04-11)

- Added support for node 14 and drop node 10
Expand Down
15 changes: 15 additions & 0 deletions bin/stencil-debug.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
require('colors');
const program = require('../lib/commander');

const StencilDebug = require('../lib/StencilDebug');
const { PACKAGE_INFO } = require('../constants');
const { printCliResultErrorAndExit } = require('../lib/cliCommon');

program
.version(PACKAGE_INFO.version)
.option('-o, --output [filename]', 'If provided will write to file')
.parse(process.argv);

const cliOptions = program.opts();

new StencilDebug().run(cliOptions).catch(printCliResultErrorAndExit);
113 changes: 113 additions & 0 deletions lib/StencilDebug.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
const fsModule = require('fs');
const path = require('path');
const osModule = require('os');

const { PACKAGE_INFO, THEME_PATH } = require('../constants');
const ThemeConfig = require('./theme-config');
const StencilConfigManager = require('./StencilConfigManager');

class StencilDebug {
constructor({
fs = fsModule,
os = osModule,
logger = console,
themeConfig = ThemeConfig.getInstance(THEME_PATH),
stencilConfigManager = new StencilConfigManager(),
} = {}) {
this._fs = fs;
this._os = os;
this._logger = logger;
this._themeConfig = themeConfig;
this._stencilConfigManager = stencilConfigManager;
}

async run(options) {
const platform = this.getPlatformInfo();
const nodeVersion = this.getNodeJsVersion();
const version = this.getCliVersion();
const theme = await this.getThemeInfo();
const stencil = await this.getStencilInfo();
const info = {
platform,
version,
nodeVersion,
stencil,
theme,
};
const result = this.prepareResult(info);
await this.printResult(result, options);
}

getPlatformInfo() {
return {
type: this._os.type(),
version: this._os.version(),
};
}

getNodeJsVersion() {
return process.version;
}

getCliVersion() {
return PACKAGE_INFO.version;
}

async getThemeInfo() {
this.checkExecutableLocation(this._themeConfig);

const rawConfig = await this._themeConfig.getRawConfig();
const {
name,
version,
/* eslint-disable camelcase */
template_engine,
css_compiler,
meta: { author_name },
/* eslint-enable camelcase */
} = rawConfig;
return {
name,
version,
template_engine,
css_compiler,
author_name,
};
}

async getStencilInfo() {
const { apiHost, normalStoreUrl, port } = await this._stencilConfigManager.read();
return {
apiHost,
normalStoreUrl,
port,
};
}

checkExecutableLocation(themeConfig) {
if (!themeConfig.configExists()) {
throw new Error(
`${
'You must have a '.red + 'config.json'.cyan
} file in your top level theme directory.`,
);
}
}

prepareResult(data) {
return JSON.stringify(data);
}

async printResult(result, options) {
if (options.output) {
const filePath = options.output.startsWith('/')
? options.output
: path.join(process.cwd(), options.output);
await this._fs.promises.writeFile(filePath, result);
} else {
this._logger.log(result);
}
}
}

module.exports = StencilDebug;
87 changes: 87 additions & 0 deletions lib/StencilDebug.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
const StencilDebug = require('./StencilDebug');
const { PACKAGE_INFO } = require('../constants');

describe('StencilDebug', () => {
const name = 'Cornerstone';
const version = '6.3.0';
/* eslint-disable-next-line camelcase */
const template_engine = 'handlebars_v4';
/* eslint-disable-next-line camelcase */
const css_compiler = 'scss';
/* eslint-disable-next-line camelcase */
const author_name = 'Bigcommerce';
const port = 3000;
const apiHost = 'https://api.bigcommerce.com';
const normalStoreUrl = 'https://shop.bigcommerce.com';
const osType = 'Darwin';
const osVersion =
'Darwin Kernel Version 21.3.0: Wed Jan 5 21:37:58 PST 2022; root:xnu-8019.80.24~20/RELEASE_X86_64';

let logger;
let themeConfig;
let stencilConfigManager;
let os;
beforeEach(() => {
logger = {
log: jest.fn(),
};
themeConfig = {
configExists: () => true,
getRawConfig: () => ({
name,
version,
template_engine,
css_compiler,
meta: {
author_name,
},
}),
};
stencilConfigManager = {
read: () => ({
port,
apiHost,
normalStoreUrl,
}),
};
os = {
type: () => osType,
version: () => osVersion,
};
});

afterEach(() => {
jest.restoreAllMocks();
});

it('should return stencil debug information', async () => {
await new StencilDebug({ logger, themeConfig, stencilConfigManager, os }).run({
output: false,
});
const result = {
platform: {
type: osType,
version: osVersion,
},
version: PACKAGE_INFO.version,
nodeVersion: process.version,
stencil: {
apiHost,
normalStoreUrl,
port,
},
theme: {
name,
version,
template_engine,
css_compiler,
author_name,
},
};
expect(logger.log).toHaveBeenCalledWith(JSON.stringify(result));
});

it('should throw an error, when command is run outside theme location', async () => {
await expect(new StencilDebug().run()).rejects.toThrow();
});
});
Loading

0 comments on commit d8c36ca

Please sign in to comment.