2021-06-07 11:52:31 +03:00
|
|
|
const handler = require('serve-handler');
|
|
|
|
const http = require('http');
|
|
|
|
const chokidar = require('chokidar');
|
|
|
|
const chalk = require('chalk');
|
|
|
|
const {spawn} = require('child_process');
|
|
|
|
const minimist = require('minimist');
|
|
|
|
const ora = require('ora');
|
|
|
|
|
|
|
|
/* eslint-disable no-console */
|
|
|
|
const log = console.log;
|
|
|
|
/* eslint-enable no-console */
|
|
|
|
|
|
|
|
let buildProcess;
|
|
|
|
let fileChanges = [];
|
|
|
|
let spinner;
|
|
|
|
let stdOutChunks = [];
|
|
|
|
let stdErrChunks = [];
|
|
|
|
|
2021-11-02 07:45:35 +03:00
|
|
|
const {v, verbose, port = 5368, basic, b} = minimist(process.argv.slice(2));
|
2021-06-07 11:52:31 +03:00
|
|
|
const showVerbose = !!(v || verbose);
|
|
|
|
const showBasic = !!(b || basic);
|
|
|
|
|
|
|
|
function clearConsole({withHistory = true} = {}) {
|
|
|
|
if (!withHistory) {
|
|
|
|
process.stdout.write('\x1Bc');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
process.stdout.write(
|
|
|
|
process.platform === 'win32' ? '\x1B[2J\x1B[0f' : '\x1B[2J\x1B[3J\x1B[H'
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
function maybePluralize(count, noun, suffix = 's') {
|
|
|
|
return `${count} ${noun}${count !== 1 ? suffix : ''}`;
|
|
|
|
}
|
|
|
|
|
|
|
|
function printFileChanges() {
|
|
|
|
if (fileChanges.length > 0) {
|
|
|
|
const prefix = maybePluralize(fileChanges.length, 'file');
|
|
|
|
log(chalk.bold.hex('#ffa300').underline(`${prefix} changed`));
|
|
|
|
const message = fileChanges.map((path) => {
|
|
|
|
return chalk.hex('#ffa300').dim(`${path}`);
|
|
|
|
}).join('\n');
|
|
|
|
log(message);
|
|
|
|
log();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function printBuildSuccessDetails() {
|
|
|
|
if (showBasic) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ((stdOutChunks && stdOutChunks.length > 0)) {
|
2021-06-16 18:15:02 +03:00
|
|
|
const detail = Buffer.concat(stdOutChunks.slice(4,7)).toString();
|
2021-06-07 11:52:31 +03:00
|
|
|
log();
|
|
|
|
log(chalk.dim(detail));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function printBuildErrorDetails() {
|
|
|
|
if ((stdOutChunks && stdOutChunks.length > 0)) {
|
|
|
|
const failDetails = Buffer.concat(stdOutChunks.slice(4, stdOutChunks.length - 1)).toString().replace(/^(?=\n)$|\s*$|\n\n+/gm, '');
|
|
|
|
log(chalk(failDetails));
|
|
|
|
}
|
|
|
|
if (stdErrChunks && stdErrChunks.length > 0) {
|
|
|
|
const stderrContent = Buffer.concat(stdErrChunks).toString();
|
|
|
|
log(chalk.dim(stderrContent));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function printBuildComplete(code) {
|
|
|
|
if (code === 0) {
|
|
|
|
if (!showVerbose) {
|
|
|
|
spinner && spinner.succeed(chalk.greenBright.bold('Build finished'));
|
|
|
|
printBuildSuccessDetails();
|
|
|
|
} else {
|
|
|
|
log();
|
|
|
|
log(chalk.bold.greenBright.bgBlackBright(`${'-'.repeat(25)}Build Success${'-'.repeat(25)}`));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (!showVerbose) {
|
|
|
|
spinner && spinner.fail(chalk.redBright.bold('Build failed'));
|
|
|
|
printBuildErrorDetails();
|
|
|
|
} else {
|
|
|
|
log(chalk.bold.redBright.bgBlackBright(`${'-'.repeat(25)}Build finished: Failed${'-'.repeat(25)}`));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log();
|
|
|
|
}
|
|
|
|
|
|
|
|
function printConfigInstruction() {
|
|
|
|
const data = {
|
|
|
|
portal: {
|
2021-06-16 18:07:06 +03:00
|
|
|
url: `http://localhost:${port}/portal`
|
2021-06-07 11:52:31 +03:00
|
|
|
}
|
|
|
|
};
|
|
|
|
const stringifedData = JSON.stringify(data, null, 2);
|
|
|
|
const splitData = stringifedData.split('\n');
|
|
|
|
log();
|
2021-06-10 12:35:33 +03:00
|
|
|
splitData.forEach((_data, idx, arr) => {
|
2021-06-07 11:52:31 +03:00
|
|
|
if (idx === 0 || idx === arr.length - 1) {
|
2021-06-10 12:35:33 +03:00
|
|
|
log(chalk.grey(_data));
|
2021-06-07 11:52:31 +03:00
|
|
|
} else {
|
2021-06-10 12:35:33 +03:00
|
|
|
log(chalk.bold.whiteBright(_data));
|
2021-06-07 11:52:31 +03:00
|
|
|
}
|
|
|
|
});
|
|
|
|
log();
|
|
|
|
}
|
|
|
|
|
|
|
|
function printInstructions() {
|
|
|
|
log();
|
|
|
|
log(chalk.yellowBright.underline(`Add portal to your local Ghost config`));
|
|
|
|
printConfigInstruction();
|
|
|
|
log(chalk.cyanBright('='.repeat(50)));
|
|
|
|
log();
|
|
|
|
}
|
|
|
|
|
|
|
|
function printBuildStart() {
|
|
|
|
if (showVerbose) {
|
|
|
|
log(chalk.bold.greenBright.bgBlackBright(`${'-'.repeat(32)}Building${'-'.repeat(32)}`));
|
|
|
|
log();
|
|
|
|
} else {
|
|
|
|
spinner = ora(chalk.magentaBright.bold('Bundling files, hang on...')).start();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function onBuildComplete(code) {
|
|
|
|
buildProcess = null;
|
|
|
|
printBuildComplete(code);
|
|
|
|
stdErrChunks = [];
|
|
|
|
stdOutChunks = [];
|
|
|
|
if (fileChanges.length > 0) {
|
|
|
|
buildPortal();
|
|
|
|
} else {
|
|
|
|
log(chalk.yellowBright.bold.underline(`Watching file changes...\n`));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function getBuildOptions() {
|
|
|
|
process.env.FORCE_COLOR = 'true';
|
|
|
|
const options = {
|
|
|
|
shell: true,
|
|
|
|
env: process.env
|
|
|
|
};
|
|
|
|
if (showVerbose) {
|
|
|
|
options.stdio = 'inherit';
|
|
|
|
}
|
|
|
|
return options;
|
|
|
|
}
|
|
|
|
|
|
|
|
function buildPortal() {
|
|
|
|
if (buildProcess) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
printFileChanges();
|
|
|
|
printBuildStart();
|
|
|
|
fileChanges = [];
|
|
|
|
const options = getBuildOptions();
|
|
|
|
buildProcess = spawn('yarn build', options);
|
|
|
|
|
|
|
|
buildProcess.on('close', onBuildComplete);
|
|
|
|
|
|
|
|
if (!showVerbose) {
|
|
|
|
buildProcess.stdout.on('data', (data) => {
|
|
|
|
stdOutChunks.push(data);
|
|
|
|
});
|
|
|
|
buildProcess.stderr.on('data', (data) => {
|
|
|
|
stdErrChunks.push(data);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function watchFiles() {
|
|
|
|
const watcher = chokidar.watch('.', {
|
|
|
|
ignored: /build|node_modules|.git|public|umd|scripts|(^|[\/\\])\../
|
|
|
|
});
|
|
|
|
|
|
|
|
watcher.on('ready', () => {
|
|
|
|
buildPortal();
|
|
|
|
}).on('change', (path) => {
|
|
|
|
if (!fileChanges.includes(path)) {
|
|
|
|
fileChanges.push(path);
|
|
|
|
}
|
|
|
|
if (!buildProcess) {
|
|
|
|
buildPortal();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function startDevServer() {
|
|
|
|
const server = http.createServer((request, response) => {
|
2021-06-11 17:25:27 +03:00
|
|
|
return handler(request, response, {
|
|
|
|
rewrites: [
|
2021-06-16 18:07:06 +03:00
|
|
|
{source: '/portal', destination: 'umd/portal.min.js'},
|
2021-06-16 18:15:02 +03:00
|
|
|
{source: '/portal.min.js.map', destination: 'umd/portal.min.js.map'}
|
2021-06-11 17:25:27 +03:00
|
|
|
],
|
|
|
|
headers: [
|
|
|
|
{
|
|
|
|
source: '**',
|
|
|
|
headers: [{
|
|
|
|
key: 'Cache-Control',
|
|
|
|
value: 'no-cache'
|
2021-06-22 09:46:06 +03:00
|
|
|
},{
|
|
|
|
key: 'Access-Control-Allow-Origin',
|
|
|
|
value: '*'
|
2021-06-11 17:25:27 +03:00
|
|
|
}]
|
|
|
|
}
|
|
|
|
]
|
|
|
|
});
|
2021-06-07 11:52:31 +03:00
|
|
|
});
|
|
|
|
|
|
|
|
server.listen(port, () => {
|
|
|
|
log(chalk.whiteBright(`Portal dev server is running on http://localhost:${port}`));
|
|
|
|
printInstructions();
|
|
|
|
watchFiles();
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
clearConsole({withHistory: false});
|
|
|
|
startDevServer();
|