Skip to content

Commit 6e2aa7d

Browse files
authored
Merge pull request #651 from MaxGenash/STRF-8672_update_fs_utils
Refactor fsUtils to be async and refactor stencil-start
2 parents e76d89e + bcab218 commit 6e2aa7d

17 files changed

Lines changed: 563 additions & 637 deletions

bin/stencil-bundle.js

Lines changed: 26 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ const program = require('../lib/commander');
66
const { THEME_PATH, PACKAGE_INFO } = require('../constants');
77
const ThemeConfig = require('../lib/theme-config');
88
const Bundle = require('../lib/stencil-bundle');
9+
const { printCliResultErrorAndExit } = require('../lib/cliCommon');
910
const { checkNodeVersion } = require('../lib/cliCommon');
1011

1112
program
@@ -27,29 +28,35 @@ program
2728
const cliOptions = program.opts();
2829
const themeConfig = ThemeConfig.getInstance(THEME_PATH);
2930

30-
checkNodeVersion();
31+
async function run() {
32+
try {
33+
checkNodeVersion();
3134

32-
if (cliOptions.dest === true) {
33-
throw new Error('You have to specify a value for -d or --dest'.red);
34-
}
35+
if (cliOptions.dest === true) {
36+
throw new Error('You have to specify a value for -d or --dest'.red);
37+
}
3538

36-
if (cliOptions.name === true) {
37-
throw new Error('You have to specify a value for -n or --name'.red);
38-
}
39+
if (cliOptions.name === true) {
40+
throw new Error('You have to specify a value for -n or --name'.red);
41+
}
3942

40-
if (!themeConfig.configExists()) {
41-
throw new Error(
42-
`${'You must have a '.red + 'config.json'.cyan} file in your top level theme directory.`,
43-
);
44-
}
43+
if (!themeConfig.configExists()) {
44+
throw new Error(
45+
`${
46+
'You must have a '.red + 'config.json'.cyan
47+
} file in your top level theme directory.`,
48+
);
49+
}
4550

46-
const rawConfig = themeConfig.getRawConfig();
47-
const bundle = new Bundle(THEME_PATH, themeConfig, rawConfig, cliOptions);
51+
const rawConfig = await themeConfig.getRawConfig();
52+
const bundle = new Bundle(THEME_PATH, themeConfig, rawConfig, cliOptions);
4853

49-
bundle.initBundle((err, bundlePath) => {
50-
if (err) {
51-
throw err;
54+
const bundlePath = await bundle.initBundle();
55+
56+
console.log(`Bundled saved to: ${bundlePath.cyan}`);
57+
} catch (err) {
58+
printCliResultErrorAndExit(err);
5259
}
60+
}
5361

54-
console.log(`Bundled saved to: ${bundlePath.cyan}`);
55-
});
62+
run();

bin/stencil-start.js

Lines changed: 6 additions & 274 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,10 @@
11
#!/usr/bin/env node
22

33
require('colors');
4-
const bs = require('browser-sync').create();
5-
const recursiveRead = require('recursive-readdir');
6-
const async = require('async');
7-
const fetch = require('node-fetch');
8-
const fs = require('fs');
9-
const path = require('path');
10-
11-
const Cycles = require('../lib/Cycles');
12-
const templateAssembler = require('../lib/template-assembler');
13-
const { PACKAGE_INFO, DOT_STENCIL_FILE_PATH, THEME_PATH } = require('../constants');
4+
const { PACKAGE_INFO, DOT_STENCIL_FILE_PATH } = require('../constants');
145
const program = require('../lib/commander');
15-
const Server = require('../server');
16-
const ThemeConfig = require('../lib/theme-config');
17-
const BuildConfigManager = require('../lib/BuildConfigManager');
18-
const { parseJsonFile } = require('../lib/utils/fsUtils');
19-
const { checkNodeVersion } = require('../lib/cliCommon');
6+
const StencilStart = require('../lib/stencil-start');
7+
const { printCliResultErrorAndExit } = require('../lib/cliCommon');
208

219
program
2210
.version(PACKAGE_INFO.version)
@@ -32,262 +20,6 @@ program
3220
)
3321
.parse(process.argv);
3422

35-
const cliOptions = program.opts();
36-
const templatePath = path.join(THEME_PATH, 'templates');
37-
const themeConfig = ThemeConfig.getInstance(THEME_PATH);
38-
39-
// tunnel value should be true/false or a string with name
40-
// https://browsersync.io/docs/options#option-tunnel
41-
// convert undefined/true -> false/true
42-
const tunnel =
43-
typeof cliOptions.tunnel === 'string' ? cliOptions.tunnel : Boolean(cliOptions.tunnel);
44-
45-
checkNodeVersion();
46-
47-
if (!fs.existsSync(DOT_STENCIL_FILE_PATH)) {
48-
throw new Error('Please run'.red + ' $ stencil init'.cyan + ' first.'.red);
49-
}
50-
51-
if (!fs.existsSync(themeConfig.configPath)) {
52-
throw new Error(
53-
`${'You must have a '.red + 'config.json'.cyan} file in your top level theme directory.`,
54-
);
55-
}
56-
57-
// If the value is true it means that no variation was passed in.
58-
if (cliOptions.variation === true) {
59-
throw new Error('You have to specify a value for -v or --variation'.red);
60-
}
61-
62-
if (cliOptions.variation) {
63-
try {
64-
themeConfig.setVariationByName(cliOptions.variation);
65-
} catch (err) {
66-
throw new Error(
67-
'Error: The variation '.red +
68-
cliOptions.variation +
69-
' does not exists in your config.json file'.red,
70-
);
71-
}
72-
}
73-
74-
const dotStencilFile = parseJsonFile(DOT_STENCIL_FILE_PATH);
75-
const browserSyncPort = dotStencilFile.port;
76-
dotStencilFile.port = Number(dotStencilFile.port) + 1;
77-
78-
if (!dotStencilFile.normalStoreUrl || !dotStencilFile.customLayouts) {
79-
throw new Error(
80-
'Error: Your stencil config is outdated. Please run'.red +
81-
' $ stencil init'.cyan +
82-
' again.'.red,
83-
);
84-
}
85-
86-
/**
87-
*
88-
* @param {object} stencilConfig
89-
* @param {string} currentCliVersion
90-
* @returns {Promise<object>}
91-
*/
92-
async function runAPICheck(stencilConfig, currentCliVersion) {
93-
const staplerUrl = stencilConfig.staplerUrl
94-
? stencilConfig.staplerUrl
95-
: stencilConfig.normalStoreUrl;
96-
const reqUrl = new URL(`/stencil-version-check?v=${currentCliVersion}`, staplerUrl);
97-
let payload;
98-
99-
const headers = {
100-
'stencil-cli': currentCliVersion,
101-
};
102-
if (stencilConfig.staplerUrl) {
103-
headers['stencil-store-url'] = stencilConfig.normalStoreUrl;
104-
}
105-
106-
try {
107-
const response = await fetch(reqUrl, { headers });
108-
if (!response.ok) {
109-
throw new Error(response.statusText);
110-
}
111-
payload = await response.json();
112-
if (!payload) {
113-
throw new Error('Empty payload in the server response');
114-
}
115-
} catch (err) {
116-
throw new Error(
117-
'The BigCommerce Store you are pointing to either does not exist or is not available at this time.'
118-
.red +
119-
'\nError details:\n' +
120-
err.message,
121-
);
122-
}
123-
if (payload.error) {
124-
throw new Error(payload.error.red);
125-
}
126-
if (payload.status !== 'ok') {
127-
throw new Error(
128-
'Error: You are using an outdated version of stencil-cli, please run '.red +
129-
'$ npm install -g @bigcommerce/stencil-cli'.cyan,
130-
);
131-
}
132-
return payload;
133-
}
134-
135-
/**
136-
* Assembles all the needed templates and resolves their partials.
137-
* @param {string} templatesPath
138-
* @param {function} callback
139-
*/
140-
function assembleTemplates(templatesPath, callback) {
141-
recursiveRead(templatesPath, ['!*.html'], (err, files) => {
142-
const templateNames = files.map((file) =>
143-
file.replace(templatesPath + templatesPath.sep, '').replace('.html', ''),
144-
);
145-
146-
async.map(
147-
templateNames,
148-
templateAssembler.assemble.bind(null, templatesPath),
149-
(err2, results) => {
150-
if (err2) {
151-
callback(err2);
152-
}
153-
callback(null, results);
154-
},
155-
);
156-
});
157-
}
158-
159-
/**
160-
* Displays information about your environment and configuration.
161-
* @returns {string}
162-
*/
163-
function getStartUpInfo() {
164-
let information = '\n';
165-
166-
information += '-----------------Startup Information-------------\n'.gray;
167-
information += '\n';
168-
information += `.stencil location: ${DOT_STENCIL_FILE_PATH.cyan}\n`;
169-
information += `config.json location: ${themeConfig.configPath.cyan}\n`;
170-
information += `Store URL: ${dotStencilFile.normalStoreUrl.cyan}\n`;
171-
172-
if (dotStencilFile.staplerUrl) {
173-
information += `Stapler URL: ${dotStencilFile.staplerUrl.cyan}\n`;
174-
}
175-
176-
information += `SSL Store URL: ${dotStencilFile.storeUrl.cyan}\n`;
177-
information += `Node Version: ${process.version.cyan}\n`;
178-
information += '\n';
179-
information += '-------------------------------------------------\n'.gray;
180-
181-
return information;
182-
}
183-
184-
/**
185-
* Starts up the local Stencil Server as well as starts up BrowserSync and sets some watch options.
186-
*/
187-
async function startServer() {
188-
await Server.create({
189-
dotStencilFile,
190-
variationIndex: themeConfig.variationIndex || 0,
191-
useCache: cliOptions.cache,
192-
themePath: THEME_PATH,
193-
});
194-
195-
const buildConfigManger = new BuildConfigManager();
196-
let watchFiles = ['/assets', '/templates', '/lang', '/.config'];
197-
let watchIgnored = ['/assets/scss', '/assets/css'];
198-
199-
// Display Set up information
200-
console.log(getStartUpInfo());
201-
202-
// Watch sccs directory and automatically reload all css files if a file changes
203-
bs.watch(path.join(THEME_PATH, 'assets/scss'), (event) => {
204-
if (event === 'change') {
205-
bs.reload('*.css');
206-
}
207-
});
208-
209-
bs.watch('config.json', (event) => {
210-
if (event === 'change') {
211-
themeConfig.resetVariationSettings();
212-
bs.reload();
213-
}
214-
});
215-
216-
bs.watch('.config/storefront.json', (event, file) => {
217-
if (event === 'change') {
218-
console.log('storefront json changed');
219-
bs.emitter.emit('storefront_config_file:changed', {
220-
event,
221-
path: file,
222-
namespace: '',
223-
});
224-
bs.reload();
225-
}
226-
});
227-
228-
bs.watch(templatePath, { ignoreInitial: true }, () => {
229-
assembleTemplates(templatePath, (err, results) => {
230-
if (err) {
231-
console.error(err);
232-
return;
233-
}
234-
235-
try {
236-
new Cycles(results).detect();
237-
} catch (e) {
238-
console.error(e);
239-
}
240-
});
241-
});
242-
243-
if (buildConfigManger.watchOptions && buildConfigManger.watchOptions.files) {
244-
watchFiles = buildConfigManger.watchOptions.files;
245-
}
246-
247-
if (buildConfigManger.watchOptions && buildConfigManger.watchOptions.ignored) {
248-
watchIgnored = buildConfigManger.watchOptions.ignored;
249-
}
250-
251-
bs.init({
252-
open: !!cliOptions.open,
253-
port: browserSyncPort,
254-
files: watchFiles.map((val) => path.join(THEME_PATH, val)),
255-
watchOptions: {
256-
ignoreInitial: true,
257-
ignored: watchIgnored.map((val) => path.join(THEME_PATH, val)),
258-
},
259-
proxy: `localhost:${dotStencilFile.port}`,
260-
tunnel,
261-
});
262-
263-
// Handle manual reloading of browsers by typing 'rs';
264-
// Borrowed from https://github.com/remy/nodemon
265-
process.stdin.resume();
266-
process.stdin.setEncoding('utf8');
267-
process.stdin.on('data', (data) => {
268-
const normalizedData = `${data}`.trim().toLowerCase();
269-
270-
// if the keys entered match the restartable value, then restart!
271-
if (normalizedData === 'rs') {
272-
bs.reload();
273-
}
274-
});
275-
276-
if (buildConfigManger.development) {
277-
buildConfigManger.initWorker().development(bs);
278-
}
279-
}
280-
281-
async function run() {
282-
try {
283-
const storeInfoFromAPI = await runAPICheck(dotStencilFile, PACKAGE_INFO.version);
284-
dotStencilFile.storeUrl = storeInfoFromAPI.sslUrl;
285-
dotStencilFile.normalStoreUrl = storeInfoFromAPI.baseUrl;
286-
287-
await startServer();
288-
} catch (err) {
289-
console.error(err.message);
290-
}
291-
}
292-
293-
run();
23+
new StencilStart()
24+
.run(program.opts(), DOT_STENCIL_FILE_PATH, PACKAGE_INFO.version)
25+
.catch(printCliResultErrorAndExit);

0 commit comments

Comments
 (0)