const path = require("path"); const fs = require("fs"); const del = require("del"); const { src, dest, series, parallel, watch } = require("gulp"); const child_process = require("child_process"); const glob = require("glob"); /* * We'll want a flexible glob down the road, but for now there are no * un-built visualizations in the repository; for performance and * simplicity just add them one at a time until we upgrade older viz's. */ const PLUGIN_BUILD_IDS = [ "annotate_image", "chiraviz", "editor", "heatmap/heatmap_default", "hyphyvision", "media_player", "mvpapp", "ngl", "openlayers", "openseadragon", "pv", "nora", ]; const paths = { node_modules: "./node_modules", plugin_dirs: [ "../config/plugins/{visualizations,interactive_environments}/*/static/**/*", "../config/plugins/{visualizations,interactive_environments}/*/*/static/**/*", ], plugin_build_modules: [`../config/plugins/visualizations/{${PLUGIN_BUILD_IDS.join(",")}}/package.json`], lib_locs: { // This is a stepping stone towards having all this staged // automatically. Eventually, this dictionary and staging step will // not be necessary. backbone: ["backbone.js", "backbone.js"], "bootstrap-tour": ["build/js/bootstrap-tour.js", "bootstrap-tour.js"], jquery: ["dist/jquery.js", "jquery/jquery.js"], "jquery.complexify": ["jquery.complexify.js", "jquery/jquery.complexify.js"], "jquery.cookie": ["jquery.cookie.js", "jquery/jquery.cookie.js"], "jquery-migrate": ["dist/jquery-migrate.js", "jquery/jquery.migrate.js"], "jquery-mousewheel": ["jquery.mousewheel.js", "jquery/jquery.mousewheel.js"], requirejs: ["require.js", "require.js"], underscore: ["underscore.js", "underscore.js"], }, libs: ["src/libs/**/*.js"], }; function stageLibs(callback) { Object.keys(paths.lib_locs).forEach((lib) => { var p1 = path.resolve(path.join(paths.node_modules, lib, paths.lib_locs[lib][0])); var p2 = path.resolve(path.join("src", "libs", paths.lib_locs[lib][1])); if (fs.existsSync(p1)) { del.sync(p2); fs.createReadStream(p1).pipe(fs.createWriteStream(p2)); } else { callback( p1 + " does not exist, yet it is a required library. This is an error. Check that the package in question exists in node_modules." ); } }); return callback(); } function fonts() { return src(path.resolve(path.join(paths.node_modules, "font-awesome/fonts/**/*"))).pipe( dest("../static/images/fonts") ); } function stagePlugins() { return src(paths.plugin_dirs).pipe(dest("../static/plugins/")); } function buildPlugins(callback) { /* * Walk plugin_build_modules glob and attempt to build modules. * */ paths.plugin_build_modules.map((build_module) => { glob(build_module, {}, (er, files) => { files.map((file) => { let skip_build = false; const f = path.join(process.cwd(), file).slice(0, -12); const plugin_name = path.dirname(file).split(path.sep).pop(); const hash_file_path = path.join(f, "static", "plugin_build_hash.txt"); if (fs.existsSync(hash_file_path)) { skip_build = child_process.spawnSync("git", ["diff", "--quiet", `$(cat ${hash_file_path})`, "--", f], { stdio: "inherit", shell: true, }).status === 0; } else { console.log(`No build hashfile detected for ${plugin_name}, generating now.`); } if (skip_build) { console.log(`No changes detected for ${plugin_name}`); } else { console.log(`Installing Dependencies for ${plugin_name}`); child_process.spawnSync( "yarn", ["install", "--production=false", "--network-timeout=300000", "--check-files"], { cwd: f, stdio: "inherit", shell: true, } ); console.log(`Building ${plugin_name}`); child_process.spawnSync("yarn", ["build"], { cwd: f, stdio: "inherit", shell: true }); child_process.exec(`(git rev-parse HEAD 2>/dev/null || echo \`\`) > ${hash_file_path}`); } }); }); }); return callback(); } function cleanPlugins() { return del(["../static/plugins/{visualizations,interactive_environments}/*"], { force: true }); } const client = parallel(fonts, stageLibs); const plugins = series(buildPlugins, cleanPlugins, stagePlugins); function watchPlugins() { const BUILD_PLUGIN_WATCH_GLOB = [`../config/plugins/visualizations/{${PLUGIN_BUILD_IDS.join(",")}}/**/*`]; watch(BUILD_PLUGIN_WATCH_GLOB, { queue: false }, plugins); } module.exports.client = client; module.exports.plugins = plugins; module.exports.watchPlugins = watchPlugins; module.exports.default = parallel(client, plugins);