UNPKG

mascot-app

Version:

Master ActionScript COnfigurator Tool. MASCOT automatically resolves ActionScript project dependencies and generates `asconfig.json` files for easy compilation with `asconfigc`.

251 lines (228 loc) 8.74 kB
const fs = require("fs"); const path = require("path"); const { cloneRepos, cloneRepo } = require("./clone_tools"); const { doShallowScan, doDeepScan } = require("./scan_tools"); const { manuallyAddDependencies } = require("./patch_tools"); const { buildDependencies, makeBuildTasks } = require("./dep_tools"); const { applyDirtinessFilter } = require("./dirty_tools"); const { writeConfig, writeVSCSettings, writeVSCTasks, } = require("./file_tools"); /** * This module houses the main entry point function (`cliMain`) used when MASCOT is invoked through CLI. * If you only want to use MASCOT through CLI, you do not need to require the "./core.js" module, * everything is handled automatically. * * However, if you want to use MASCOT programmatically (as opposed to using its CLI), then you should * require the "./core.js" module, as it also functions as a pass-through module which re-exports to * one place all the functions made available by all of the other specific modules. Consult each * individual function documentation for learning how to use it. * * NOTE: MASCOT uses "cli-primer" (https://www.npmjs.com/package/cli-primer) as a CLI wrapper * facility. See also "https://github.com/ciacob/cli-primer" for details. * * @param inputData {Object} * Merged dataset CLI-primer has built out of MASCOT configuration file and/or provided * command-line arguments, whichever given. * * @param utils {Object} * Merged set of the utility functions CLI-primer provides, across all of its modules. * * @param monitoringFn {Function} * All-purpose monitoringFn function defined by CLI-primer. Its signature is: * `function $m(info)`, where `info` is an Object containing the following keys: * - `type` (String): The type of message (`info`, `warn`, `error`, `debug`). * - `message` (String): The message content to be displayed. * - `data` (Object, optional): Additional data related to the message, displayed as an object. */ function cliMain(inputData, utils, monitoringFn) { const $m = monitoringFn || function () {}; // VALIDATE & PRE_PROCESS INPUT // ---------------------------- const appInfo = utils.getAppInfo(); // Check for no-op situation. if (!inputData.clone && !inputData.generate) { $m({ type: "error", message: `No actionable arguments received. Run "${appInfo.appPathName} --h" for documentation.`, }); return; } // Check for contextually mandatory arguments. if (inputData.clone && !inputData.c_user_name) { $m({ type: "error", message: `Missing mandatory argument "--c_user_name". Argument "--c_user_name" is mandatory when argument "--clone" is given.`, }); return; } if (inputData.generate && !inputData.g_sdk_directory) { $m({ type: "error", message: `Missing mandatory argument "--g_sdk_directory". Argument "--g_sdk_directory" is mandatory when argument "--generate" is given.`, }); return; } // Check if provided `workspace_directory` exist on disk. if ( inputData.workspace_directory && !fs.existsSync(inputData.workspace_directory) ) { $m({ type: "error", message: `Provided \`--workspace_directory\` "${inputData.workspace_directory}" does not exist on disk.`, }); return; } // Check if provided `g_sdk_directory` exists on disk. if (inputData.g_sdk_directory && !fs.existsSync(inputData.g_sdk_directory)) { $m({ type: "error", message: `Provided \`--g_sdk_directory\` "${inputData.g_sdk_directory}" does not exist on disk.`, }); return; } // Check/ensure that provided `c_programming_languages` and `g_manual_dependencies` are legitimate Arrays. function getArrayOrSerializedArray(val) { if (!val) { return null; } if (!Array.isArray(val) && typeof val !== "string") { return null; } if (!Array.isArray(val)) { try { val = JSON.parse(val); if (!Array.isArray(val)) { throw new Error("provided JSON does not resolve to an Array."); } } catch (e) { $m({ type: "error", message: e, }); return null; } } return val; } let programming_languages = null; if (inputData.c_programming_languages) { programming_languages = getArrayOrSerializedArray( inputData.c_programming_languages ); if (!programming_languages) { $m({ type: "error", message: `Provided \`--c_programming_languages\` is not an Array or serialized Array.`, }); return; } } let manual_dependencies = null; if (inputData.g_manual_dependencies) { manual_dependencies = getArrayOrSerializedArray( inputData.g_manual_dependencies ); if (!manual_dependencies) { $m({ type: "error", message: `Provided \`--g_manual_dependencies\` is not an Array or serialized Array.`, }); return; } } // Ensure the scratch folder is available const scratchDirName = `${appInfo.appPathName}.scratch`; utils.ensureSetup(utils.getUserHomeDirectory(), { content: [{ type: "folder", path: scratchDirName }], }); const scratchDirPath = path.normalize( path.join(utils.getUserHomeDirectory(), scratchDirName) ); // EXECUTE TASKS BASED ON INPUT // ---------------------------- const workspace_directory = path.normalize(inputData.workspace_directory); (async function () { // Do a GitHub clone if requested if (inputData.clone) { const queryResult = await cloneRepos( workspace_directory, inputData.c_user_name, programming_languages, inputData.c_forks_behavior === "mix" ? undefined : inputData.c_forks_behavior === "only" ? true : false, inputData.c_dry_mode === "yes" ? true : false ); $m({ type: "info", message: "Your GitHub query returned:", data: queryResult ? queryResult.report || {} : {}, }); if (queryResult && queryResult.repos) { $m({ type: "info", message: "Full list of matching repositories:", }); console.dir(queryResult.repos, { depth: null }); } } // Analyze workspace dependencies and generate `asconfig.json` files if requested. if (inputData.generate) { // Index all classes in all ActionScript projects. doShallowScan(workspace_directory, scratchDirPath, true); // Establish couplings at class levels (i.e., which class uses which other classes). doDeepScan(workspace_directory, scratchDirPath, true); // Patch couplings based on the `--g_manual_dependencies` argument, if provided. if (manual_dependencies && manual_dependencies.length > 0) { manuallyAddDependencies( workspace_directory, scratchDirPath, manual_dependencies ); } // Build project level dependencies, i.e., "this" project depends on "these other" projects. buildDependencies(workspace_directory, scratchDirPath, true); // Actually generate one `asconfig.json` file for each ActionScript project in the workspace. writeConfig(workspace_directory, scratchDirPath, true, null, inputData.g_asconfig_base); // Ensure each ActionScript project in the workspace has a `.vscode/settings.json` file containing, // at the very least the path to the AIR SDK to use. writeVSCSettings(workspace_directory, scratchDirPath, { $sdk: inputData.g_sdk_directory, }); // Create a blueprint for the actual build tasks to be generated. makeBuildTasks(workspace_directory, scratchDirPath, true); // Handle the `--g_rebuild` argument. if (!inputData.g_rebuild) { applyDirtinessFilter(workspace_directory, scratchDirPath); } // Update the `.vscode/tasks.json` of each ActionScript project in the workspace, so that it // includes tasks with building the current project and all dependencies, in one go. writeVSCTasks( workspace_directory, scratchDirPath, { path_to_air_sdk: inputData.g_sdk_directory }, true ); } })(); } module.exports = { cliMain, cloneRepos, cloneRepo, doShallowScan, doDeepScan, manuallyAddDependencies, buildDependencies, makeBuildTasks, applyDirtinessFilter, writeConfig, writeVSCSettings, writeVSCTasks, };