flatten/flattener.js

const truffleFlattener = require('truffle-flattener');
const Compiler = require('../compile/compiler');
const Logger = require('../logging/logger');
const fs = require('fs');
const path = require('path');
const ora = require('ora');

/** Flattener class. Abstracts flattener functionality for the use of the user, as well as general code modularity. */
class Flattener {

  /**
   * Initializes a Flattener instance.
   *
   * @param {object} options - Options object.
   * @param {Logger.state.ENUM) logSetting - Log setting to use with all class functions.
   */
  constructor(options, logSetting = Logger.state.NORMAL) {
    this.options = options;
    this.log = new Logger(logSetting);
    this.compiler = new Compiler(options, logSetting);
  }

  /**
   * ASYNC - Flattens all files passed, and optionally writes to file. Generic function in order to work with various kinds of flatteners (truffle-flattener is currently the only one used, but will very likely introduce more options for users in the near future)
   *
   * @param {string[]} files - Files to flatten; an array of filepaths to be passed, e.g. (['./contracts/meme.sol'])
(note; this should usually only be one in most instances; this piece of the API may change soon)
   * @param {string} filepath - Filepath to write flattened contract to.
   * @param {boolean} [writeToFile=false]
   * 
   * @return {string} flattened - Flattened contract.
   * [NOTE FOR DEV]: Seems to be a conflict in using this.options to determine write location, or even whether to write at all; return to this later, commenting out "const dir" line.
   */
  async flatten(files = [], filepath = null, writeToFile = false) {
    const spinner = ora('Flattening .sol file ' + filepath + '...').start();
    const flattened = await truffleFlattener(files);
    if(writeToFile){
      //const dir = this.options.flatten.writeLocation;
      fs.writeFileSync(filepath, flattened);
      spinner.succeed();
      this.log.print(Logger.state.NORMAL, "Flattened file \"" + filepath + "\" written!");
    } else {
      spinner.fail();
    }
    return flattened;
  }


  /**
   * ASYNC - Flattens the contract at the specified filepath, and compiles the flattened output, returning the compiler.compileSource() output.
   * 
   * @param {string} filepath - Filepath of the single contract to flatten and compile.
   * @param {boolean} [writeToFile=false]
   * 
   * @return {object} compiled - See Compiler class for what the output of this may look like.
   */
  async flattenAndCompile(filepath, writeToFile = false) {
    const root = this.options.root;

    const base = path.basename(filepath);
    //TODO: Throw error if not an array
    const src = writeToFile ? await this.flatten([filepath], path.resolve(this.options.flatten.writeLocation, base), true) : await this.flatten([filepath]);

    const compiled = this.compiler.compileSource(base, src);
    return compiled;
  }


}

module.exports = Flattener;