const fs = require('fs'); const path = require('path'); const chalk = require('chalk'); const rollup = require('rollup'); const { execSync } = require('child_process'); const log = console.log; // eslint-disable-line const { get_build_json, get_app_path, apps_list, run_serially, assets_path, sites_path } = require('./rollup.utils'); const { get_options_for, get_options } = require('./config'); const skip_frappe = process.argv.includes("--skip_frappe") if (skip_frappe) { let idx = apps_list.indexOf("frappe"); if (idx > -1) { apps_list.splice(idx, 1); } } const exists = (flag) => process.argv.indexOf(flag) != -1 const value = (flag) => (process.argv.indexOf(flag) != -1) ? process.argv[process.argv.indexOf(flag) + 1] : null; const files = exists("--files") ? value("--files").split(",") : false; const build_for_app = exists("--app") ? value("--app") : null; const concat = !exists("--no-concat"); if (!files) show_production_message(); ensure_js_css_dirs(); if (concat) concatenate_files(); create_build_file(); if (files) { build_files(files); } else if (build_for_app) { build_assets_for_app(build_for_app) .then(() => { run_build_command_for_app(build_for_app); }) } else { build_assets_for_all_apps() .then(() => { run_build_command_for_apps() }); } function build_assets_for_all_apps() { return run_serially( apps_list.map(app => () => build_assets(app)) ); } function build_assets_for_app(app) { return build_assets(app) } function build_from_(options) { const promises = options.map(({ inputOptions, outputOptions, output_file}) => { return build(inputOptions, outputOptions) .then(() => { log(`${chalk.green('✔')} Built ${output_file}`); }); }); const start = Date.now(); return Promise.all(promises) .then(() => { const time = Date.now() - start; log(chalk.green(`✨ Done in ${time / 1000}s`)); }); } function build_assets(app) { const options = get_options_for(app); if (!options.length) return Promise.resolve(); log(chalk.yellow(`\nBuilding ${app} assets...\n`)); return build_from_(options); } function build_files(files, app="frappe") { let ret; for (let file of files) { let options = get_options(file, app); if (!options.length) return Promise.resolve(); ret += build_from_(options); } return ret; } function build(inputOptions, outputOptions) { return rollup.rollup(inputOptions) .then(bundle => bundle.write(outputOptions)) .catch(err => { log(chalk.red(err)); // Kill process to fail in a CI environment if (process.env.CI) { process.kill(process.pid) } }); } function concatenate_files() { // only concatenates files, not processed through rollup const files_to_concat = Object.keys(get_build_json('frappe')) .filter(filename => filename.startsWith('concat:')); files_to_concat.forEach(output_file => { const input_files = get_build_json('frappe')[output_file]; const file_content = input_files.map(file_name => { let prefix = get_app_path('frappe'); if (file_name.startsWith('node_modules/')) { prefix = path.resolve(get_app_path('frappe'), '..'); } const full_path = path.resolve(prefix, file_name); return `/* ${file_name} */\n` + fs.readFileSync(full_path); }).join('\n\n'); const output_file_path = output_file.slice('concat:'.length); const target_path = path.resolve(assets_path, output_file_path); fs.writeFileSync(target_path, file_content); log(`${chalk.green('✔')} Built ${output_file_path}`); }); } function create_build_file() { const touch = require('touch'); touch(path.join(sites_path, '.build'), { force: true }); } function run_build_command_for_apps() { let cwd = process.cwd(); apps_list.map(app => run_build_command_for_app(app)) process.chdir(cwd); } function run_build_command_for_app(app) { if (app === 'frappe') return; let root_app_path = path.resolve(get_app_path(app), '..'); let package_json = path.resolve(root_app_path, 'package.json'); if (fs.existsSync(package_json)) { let package = require(package_json); if (package.scripts && package.scripts.build) { console.log('\nRunning build command for', chalk.bold(app)); process.chdir(root_app_path); execSync('yarn build', { encoding: 'utf8', stdio: 'inherit' }); } } } function ensure_js_css_dirs() { const paths = [ path.resolve(assets_path, 'js'), path.resolve(assets_path, 'css') ]; paths.forEach(path => { if (!fs.existsSync(path)) { fs.mkdirSync(path); } }); } function show_production_message() { const production = process.env.FRAPPE_ENV === 'production'; log(chalk.yellow(`${production ? 'Production' : 'Development'} mode`)); }