Skip to content

Commit

Permalink
feat: added re-integration script with new command download
Browse files Browse the repository at this point in the history
  • Loading branch information
martinchuka committed Apr 24, 2020
1 parent a1c61e7 commit dc6df02
Show file tree
Hide file tree
Showing 6 changed files with 400 additions and 0 deletions.
1 change: 1 addition & 0 deletions bin/stencil
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ program
.command('release', 'Create a new release in the theme\'s github repository.')
.command('push', 'Bundles up the theme into a zip file and uploads it to your store.')
.command('pull', 'Pulls currently active theme config files and overwrites local copy')
.command('download', 'Downloads all the theme files')
.parse(process.argv);
62 changes: 62 additions & 0 deletions bin/stencil-download.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/usr/bin/env node

require('colors');
const apiHost = 'https://api.bigcommerce.com';
const dotStencilFilePath = './.stencil';
const options = { dotStencilFilePath };
const pkg = require('../package.json');
const Program = require('commander');
const stencilDownload = require('../lib/stencil-download');
const versionCheck = require('../lib/version-check');
const themeApiClient = require('../lib/theme-api-client');
const inquirer = require('inquirer');

Program
.version(pkg.version)
.option('--host [hostname]', 'specify the api host', apiHost)
.option('--file [filename]', 'specify the filename to download only')
.option('--exclude [exclude]', 'specify a directory to exclude from download')
.parse(process.argv);

if (!versionCheck()) {
process.exit(2);
}

const overwriteType = Program.file ? Program.file : 'files';

Object.assign(options, {
exclude: ['parsed', 'manifest.json'],
});

inquirer.prompt([{
message: `${'Warning'.yellow} -- overwrite local with remote ${overwriteType}?`,
name: 'overwrite',
type: 'checkbox',
choices: ['Yes', 'No'],
}], answers => {

if (answers.overwrite.indexOf('Yes') > -1) {
console.log(`${'ok'.green} -- ${overwriteType} will be overwritten by change`);

if (Program.exclude) {
options.exclude.push(Program.exclude);
}

stencilDownload(Object.assign({}, options, {
apiHost: Program.host || apiHost,
file: Program.file,
// eslint-disable-next-line no-unused-vars
}), (err, result) => {
if (err) {
console.log("\n\n" + 'not ok'.red + ` -- ${err} see details below:`);
themeApiClient.printErrorMessages(err.messages);
console.log('If this error persists, please visit https:/bigcommerce/stencil-cli/issues and submit an issue.');
} else {
console.log('ok'.green + ` -- Theme file(s) updated from remote`);
}
});

} else {
console.log('Request cancelled by user '+ ('No'.red));
}
});
21 changes: 21 additions & 0 deletions lib/stencil-download.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict';
const async = require('async');
let stencilPushUtils = require('./stencil-push.utils');
let stencilPullUtils = require('./stencil-pull.utils');
let stencilDownloadUtil = require('./stencil-download.utils');

module.exports = stencilDownload;

function stencilDownload(options, callback) {
async.waterfall(
[
async.constant(options),
stencilPushUtils.readStencilConfigFile,
stencilPushUtils.getStoreHash,
stencilPushUtils.getThemes,
stencilPullUtils.selectActiveTheme,
stencilPullUtils.startThemeDownloadJob,
stencilPushUtils.pollForJobCompletion(({download_url: downloadUrl}) => ({downloadUrl})),
stencilDownloadUtil.downloadThemeFiles,
], callback);
}
138 changes: 138 additions & 0 deletions lib/stencil-download.utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
const request = require("request");
const yauzl = require('yauzl');
const fs = require('fs');
const tmp = require('tmp');
const path = require('path');
const utils = {};

module.exports = utils;

utils.downloadThemeFiles = (options, callback) => {
tmp.file(function _tempFileCreated(err, tempThemePath, fd, cleanupCallback) {
if (err) {
callback(err);
}

(
new Promise(
(resolve, reject) =>
request(options.downloadUrl)
.pipe(fs.createWriteStream(tempThemePath))
.on('finish', () => resolve(tempThemePath))
.on('error', reject),
)
)
.then(tempThemePath =>
new Promise(
(resolve, reject) => {
let foundMatch = false;

console.log('ok'.green + ' -- Theme files downloaded');
console.log('ok'.green + ' -- Extracting theme files');

yauzl.open(tempThemePath, {lazyEntries: true}, (error, zipFile) => {

if (error) {
return reject(error);
}

zipFile.on('entry', entry => {

zipFile.openReadStream(entry, (readStreamError, readStream) => {
if (readStreamError) {
return reject(readStreamError);
}

let configFileData = '';

if (options.file && options.file.length) {

if (options.file !== entry.fileName) {
zipFile.readEntry();
return;
}
foundMatch = true;

} else if (options.exclude && options.exclude.length) {

/**
* Do not process any file or directory within the exclude option
*/
for (let i = 0; i < options.exclude.length; i++) {
if ((entry.fileName).startsWith(options.exclude[i])) {
zipFile.readEntry();
return;
}
}
}

/**
* Create a directory if the parent directory does not exists
*/
const parsedPath = path.parse(entry.fileName);

if (parsedPath.dir && !fs.existsSync(parsedPath.dir)) {
fs.mkdirSync(parsedPath.dir, {recursive: true});
}

/**
* If file is a directory, then move to next
*/
if (/\/$/.test(entry.fileName)) {
zipFile.readEntry();
return;
}

readStream.on('end', () => {
if (entry.fileName.endsWith('.json')) {
configFileData = JSON.stringify(JSON.parse(configFileData), null, 2);
}

fs.writeFile(entry.fileName, configFileData, {flag: 'w+'}, error => {
if (error) {
reject(error);
}

/**
* Close read if file requested is found
*/
if (options.file && options.file.length) {
console.log('ok'.green + ' -- Theme files extracted');
zipFile.close();
resolve(options);
} else {
zipFile.readEntry();
}
});
});

readStream.on('data', chunk => {
configFileData += chunk;
});
});
});

zipFile.readEntry();

zipFile.once('end', function () {
if (!foundMatch && (options.file && options.file.length)) {
console.log('Warning'.yellow + ` -- ${options.file} not found!`);
reject(`${options.file} not found`);
return;
}

console.log('ok'.green + ' -- Theme files extracted');
zipFile.close();
resolve(options);
});
});
},
),
)
.then(() => {
cleanupCallback();
callback(null, options);
})
.catch(callback);
});
};
Loading

0 comments on commit dc6df02

Please sign in to comment.