UNPKG

@nebulae/cli

Version:

Tools and code generators for microservices developed by Nebula Engineering (http://www.nebulae.com.co)

175 lines (162 loc) 7.43 kB
'use strict' const Rx = require('rxjs'); const jsonfile = require('jsonfile'); const gitRootDir = require('git-root-dir'); const TarTools = require('../crosscuting/TarTools'); const GitTools = require('../crosscuting/GitTools'); const MicroFrontEndsSetupCompendium = require('./MicroFrontEndsSetupCompendium'); const fs = require('fs-extra'); const os = require('os'); class DevelopmentUiComposition { constructor({ shellType, shellRepo, frontEndId, outputDir, setupFiles, shellRepoBranch = "master", shellRepoUser, shellRepoPsw }) { this.shellType = shellType; this.shellRepo = shellRepo; this.frontEndId = frontEndId; this.outputDir = outputDir; this.setupFiles = setupFiles.split(','); this.shellRepoBranch = shellRepoBranch; this.shellRepoUser = shellRepoUser; this.shellRepoPsw = shellRepoPsw; //define the shell to use switch (shellType) { case 'FUSE2_ANGULAR': const Fuse2AngularShell = require('./shell/Fuse2AngularShell'); this.shell = new Fuse2AngularShell(); break; case 'FUSE_REACT': const FuseReactShell = require('./shell/FuseReactShell'); this.shell = new FuseReactShell(); break; } } /** * Compose an integrated UI using all the micro-frontends fragments found in the store */ composeUI$() { /* - Donwload shell repo and put it in the output dir - process microfront-ends setup objects - Get every microfrontend setup - Apply each setup on a volatile object - List all the Micro-FrontEnds content directories - buil shell - create a soft link of each micro-frontend content to shell - apply setup object into shell (write changes to disk) - install dependencies - build integrated shell - run test */ return Rx.Observable.forkJoin( this.downloadShell$(this.outputDir), this.mergeMicroFrontendSetups$(), this.listMicroFrontEndsContentDirectories$(), this.listMicroFrontEndsAssetsDirectories$() ).mergeMap(([shellPath, mfeSetups, mfeContentPaths, mfeAssetsPaths]) => this.buildShell$(shellPath, mfeContentPaths, mfeAssetsPaths, mfeSetups)); } /** * Download the shell git repository, extract the shell and put it in the output dir * Returns an Observable that resolve to the shell path * @param {*} outputDir */ downloadShell$(outputDir) { const tmpDir = `${os.tmpdir()}/${Math.random()}/shell_project`; console.log(tmpDir); return Rx.Observable.fromPromise(fs.remove(outputDir).then(fs.ensureDir(tmpDir))) .mergeMap(() => GitTools.clone$(this.shellRepo, tmpDir, this.shellRepoBranch, this.shellRepoUser, this.shellRepoPsw)) .mergeMap(() => Rx.Observable.bindNodeCallback(fs.move)(`${tmpDir}/frontend/${this.frontEndId}`, outputDir)) .catch(error => { console.log(`GitTools.clone$: Error`,error); return Rx.Observable.throw(error) }) .mapTo(outputDir) } /** * Gets all the microservices MicroFront-end setup files, * and merge all of them. * return an observable that resolves to the merge setup */ mergeMicroFrontendSetups$() { return Rx.Observable.from(this.setupFiles) .mergeMap(setupFile => Rx.Observable.bindNodeCallback(jsonfile.readFile)(setupFile)) //Process each setup and build a ]Compendium .reduce((acc, mfeSetup) => { acc.processSetup(mfeSetup); return acc; }, new MicroFrontEndsSetupCompendium(this.setupFiles)); } /** * Extracts Micro-FrontEnd contents directories from the setup files. * Returns an Observable that resolve to an array of the content's local directories */ listMicroFrontEndsContentDirectories$() { //for each setup file return Rx.Observable.from(this.setupFiles) //infer the git directory where the file is and join them as { setupFile, gitRoot } .mergeMap(setupFile => Rx.Observable.fromPromise(gitRootDir(setupFile)) .map(gitRoot => { return { setupFile, gitRoot } }) ) //Read every file, transform in to JSON and join it with the gitRoot { setupArray, gitRoot } .mergeMap(({ setupFile, gitRoot }) => Rx.Observable.bindNodeCallback(jsonfile.readFile)(setupFile) .map(setupArray => { return { setupArray, gitRoot }; }) ) //unwrap the setup array and join them with the gitroot { mfeSetup, gitRoot } .mergeMap(({ setupArray, gitRoot }) => Rx.Observable.from(setupArray) .map(mfeSetup => { return { mfeSetup, gitRoot }; }) ) //Process each setup and build the compendium .reduce((acc, { mfeSetup, gitRoot }) => { acc.push(`${gitRoot}/${mfeSetup.src}`); return acc; }, []); } /** * Extracts Micro-FrontEnd assets directories from the setup files. * Returns an Observable that resolve to an array of the assets's local directories */ listMicroFrontEndsAssetsDirectories$() { //for each setup file return Rx.Observable.from(this.setupFiles) //infer the git directory where the file is and join them as { setupFile, gitRoot } .mergeMap(setupFile => Rx.Observable.fromPromise(gitRootDir(setupFile)) .map(gitRoot => { return { setupFile, gitRoot } }) ) //Read every file, transform in to JSON and join it with the gitRoot { setupArray, gitRoot } .mergeMap(({ setupFile, gitRoot }) => Rx.Observable.bindNodeCallback(jsonfile.readFile)(setupFile) .map(setupArray => { return { setupArray, gitRoot }; }) ) //unwrap the setup array and join them with the gitroot { mfeSetup, gitRoot } .mergeMap(({ setupArray, gitRoot }) => Rx.Observable.from(setupArray) .map(mfeSetup => { return { mfeSetup, gitRoot }; }) ) .filter(({ mfeSetup, gitRoot }) => mfeSetup.assets) //Process each setup and build the compendium .reduce((acc, { mfeSetup, gitRoot }) => { acc.push(`${gitRoot}/${mfeSetup.assets}`); return acc; }, []); } /** * Builds the shell using the downloaded shell, downloaded contents and the setup compendium * return an observable that resolves to the builded shell path * @param {string} shellPath * @param {string[]} mfeContentPaths * @param {MicroFrontEndsSetupCompendium} mfeSetups */ buildShell$(shellPath, mfeContentPaths, mfeAssetsPaths, mfeSetups) { return this.shell.buildShellDevelopment$(shellPath, mfeContentPaths, mfeAssetsPaths, mfeSetups); } } module.exports = DevelopmentUiComposition;