mirror of https://github.com/embarklabs/embark.git
199 lines
5.1 KiB
JavaScript
199 lines
5.1 KiB
JavaScript
|
/* global Buffer __dirname module process require */
|
||
|
|
||
|
const filterPackages = require('@lerna/filter-packages');
|
||
|
const {fork, spawn} = require('child_process');
|
||
|
const {sync: findUp} = require('find-up');
|
||
|
const {readJsonSync} = require('fs-extra');
|
||
|
const {sync: glob} = require('glob');
|
||
|
const minimist = require('minimist');
|
||
|
const {dirname, join, normalize, relative} = require('path');
|
||
|
const { Transform } = require('stream');
|
||
|
|
||
|
module.exports = function (cliArgs = []) {
|
||
|
const {action, exclude, include, showPrivate} = processArgs(cliArgs);
|
||
|
|
||
|
const allPackages = findAllMonorepoPackages();
|
||
|
const allPkgJsons = allPackages.map(path => readJsonSync(path));
|
||
|
|
||
|
const filteredPkgJsons = filterPkgJsons(
|
||
|
allPkgJsons,
|
||
|
{action, exclude, include, showPrivate}
|
||
|
);
|
||
|
|
||
|
const pkgJsonDict = makePkgJsonDict(
|
||
|
allPackages,
|
||
|
allPkgJsons,
|
||
|
filteredPkgJsons
|
||
|
);
|
||
|
|
||
|
switch (action) {
|
||
|
case 'build:browser':
|
||
|
buildBrowser(cliArgs.slice(1), pkgJsonDict);
|
||
|
break;
|
||
|
case 'build:node':
|
||
|
buildNode(cliArgs.slice(1), pkgJsonDict);
|
||
|
break;
|
||
|
default:
|
||
|
throw new Error(`no implementation for ${action} action`);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
function processArgs(cliArgs) {
|
||
|
let options;
|
||
|
if (process.env.EMBARK_COLLECTIVE_OPTIONS) {
|
||
|
options = JSON.parse(process.env.EMBARK_COLLECTIVE_OPTIONS);
|
||
|
} else {
|
||
|
options = {};
|
||
|
}
|
||
|
|
||
|
const solo = !!process.env.EMBARK_SOLO;
|
||
|
|
||
|
const args = minimist(cliArgs);
|
||
|
|
||
|
Object.keys(args).forEach(key => {
|
||
|
const invKey = key.slice(3);
|
||
|
if (key.startsWith('no-') && args.hasOwnProperty(invKey)) {
|
||
|
args[key] = !args[invKey];
|
||
|
delete args[invKey];
|
||
|
}
|
||
|
});
|
||
|
|
||
|
const np = 'no-private';
|
||
|
args.ignore = [].concat(options.ignore || [], args.ignore || []);
|
||
|
args[np] = !!options[np];
|
||
|
args.scope = [].concat(options.scope || [], args.scope || []);
|
||
|
if (!args._[0]) args._[0] = 'start';
|
||
|
|
||
|
// scripts/monorun.js (in the monorepo root) forwards other `lerna run`
|
||
|
// options as well, e.g. `stream` and `parallel`; for now only make use of
|
||
|
// ignore, scope, and no-private; can consider implementing support for the
|
||
|
// others if desirable/needed in the context of collective actions
|
||
|
|
||
|
const {_: [action], ignore: exclude, [np]: noPrivate, scope: include} = args;
|
||
|
const showPrivate = !noPrivate;
|
||
|
|
||
|
return {action, exclude, include, showPrivate};
|
||
|
}
|
||
|
|
||
|
let _monorepoRootPath = null;
|
||
|
const lernaJson = 'lerna.json';
|
||
|
function monorepoRootPath() {
|
||
|
if (_monorepoRootPath === null) {
|
||
|
_monorepoRootPath = dirname(findUp(lernaJson, {cwd: __dirname}));
|
||
|
}
|
||
|
|
||
|
return _monorepoRootPath;
|
||
|
}
|
||
|
|
||
|
const globArgs = [
|
||
|
'**/package.json',
|
||
|
{
|
||
|
cwd: monorepoRootPath(),
|
||
|
ignore: [
|
||
|
'**/node_modules/**',
|
||
|
'package.json',
|
||
|
'scripts/**',
|
||
|
'site/**'
|
||
|
]
|
||
|
}
|
||
|
];
|
||
|
|
||
|
function findAllMonorepoPackages() {
|
||
|
return glob(...globArgs).map(path => join(monorepoRootPath(), path));
|
||
|
}
|
||
|
|
||
|
function filterPkgJsons(pkgJsons, {action, exclude, include, showPrivate}) {
|
||
|
const embarkCollective = 'embark-collective';
|
||
|
return filterPackages(
|
||
|
pkgJsons,
|
||
|
include,
|
||
|
exclude,
|
||
|
showPrivate
|
||
|
).filter(pkgJson => (
|
||
|
pkgJson && pkgJson[embarkCollective] && pkgJson[embarkCollective][action] &&
|
||
|
!(pkgJson.scripts && pkgJson.scripts[action])
|
||
|
));
|
||
|
}
|
||
|
|
||
|
function makePkgJsonDict(allPackages, allPkgJsons, filteredPkgJsons) {
|
||
|
const allPkgJsonDict = {};
|
||
|
const filteredPkgJsonDict = {};
|
||
|
|
||
|
allPkgJsons.forEach(({name}, index) => {
|
||
|
allPkgJsonDict[name] = allPackages[index];
|
||
|
});
|
||
|
|
||
|
filteredPkgJsons.forEach(({name}) => {
|
||
|
filteredPkgJsonDict[name] = allPkgJsonDict[name];
|
||
|
});
|
||
|
|
||
|
return filteredPkgJsonDict;
|
||
|
}
|
||
|
|
||
|
function labeler(label) {
|
||
|
return new Transform({
|
||
|
transform(chunk, _encoding, callback) {
|
||
|
chunk = Buffer.from(
|
||
|
`[${label}] ${chunk.toString()}`
|
||
|
);
|
||
|
callback(null, chunk);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
function build(babelEnv, outDir, cliArgs, pkgJsonDict) {
|
||
|
const rootPath = monorepoRootPath();
|
||
|
|
||
|
const babelCmd = process.platform === 'win32' ? 'babel.cmd': 'babel';
|
||
|
const babelBinPath = join(__dirname, 'node_modules', '.bin', babelCmd);
|
||
|
const babelConfigPath = join(rootPath, 'babel.config.js');
|
||
|
|
||
|
const sources = Object.values(pkgJsonDict).map(
|
||
|
path => relative(rootPath, join(dirname(path), 'src'))
|
||
|
);
|
||
|
|
||
|
if (!sources.length) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
process.chdir(rootPath);
|
||
|
|
||
|
const subp = spawn(babelBinPath, [
|
||
|
...sources,
|
||
|
'--config-file',
|
||
|
babelConfigPath,
|
||
|
'--extensions',
|
||
|
'.js,.ts',
|
||
|
'--out-dir',
|
||
|
normalize(`../${outDir}`),
|
||
|
'--relative',
|
||
|
'--source-maps',
|
||
|
...cliArgs
|
||
|
], {
|
||
|
env: {
|
||
|
...process.env,
|
||
|
BABEL_ENV: babelEnv
|
||
|
},
|
||
|
stdio: ['inherit', 'pipe', 'pipe']
|
||
|
});
|
||
|
|
||
|
subp.stdout.pipe(labeler(`build:${babelEnv}`)).pipe(process.stdout);
|
||
|
subp.stderr.pipe(labeler(`build:${babelEnv}`)).pipe(process.stderr);
|
||
|
}
|
||
|
|
||
|
function buildBrowser(cliArgs, pkgJsonDict) {
|
||
|
build('browser', 'dist/browser', cliArgs, pkgJsonDict);
|
||
|
}
|
||
|
|
||
|
function buildNode(cliArgs, pkgJsonDict) {
|
||
|
build('node', 'dist', cliArgs, pkgJsonDict);
|
||
|
}
|
||
|
|
||
|
const embarkInsidePkg = 'embark-inside-monorepo';
|
||
|
try {
|
||
|
require.resolve(embarkInsidePkg, {paths: [__dirname]});
|
||
|
} catch (err) {
|
||
|
const dir = dirname(findUp('package.json', {cwd: __dirname}));
|
||
|
throw new Error(`package at ${dir} is not inside embark's monorepo`);
|
||
|
}
|