All files / src/file packCovenants.js

100% Statements 36/36
0% Branches 0/1
100% Functions 4/4
100% Lines 36/36
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 892x 2x 2x 2x     2x   2x 2x                                   2x 2x 2x   2x 2x 2x 2x 2x 2x   2x     2x   2x     2x     2x 4x   4x     4x 4x       4x 4x   4x           2x 2x   2x         2x   2x     2x 2x   2x      
const fs = require('fs-extra')
const promisify = require('util').promisify
const exec = promisify(require('child_process').exec)
const path = require('path')
const {
  constants: { ROOT_CHAIN_ALIAS }
} = require('interbit-covenant-tools')
 
const log = require('../log')
const { startInterbit } = require('../chainManagement')
 
// Note: Because interbit-core does not expose it's hashing function (yet) we ned to
// start a cli and deploy the covenants to get a valid hash that is in sync with interbit
// TODO: update this to use the hashing function instead of starting a CLI -- Blocked until core releases hashing algo in API
/**
 * NPM packs the covenants specified in `covenantConfig` and stores them in the artifacts
 * folder for future deployment to an Interbit node.
 * @param {String} location - The file location to work from.
 * @param {Object} covenantConfig - Configuration for the covenants to pack,
 *    typically from an interbit config file.
 * @param {Object} options - Options for packing this covenant.
 * @param {Object} options.keyPair - Public private key pair to start the node for packing.
 * @param {String|number} options.port - Port for this node to bind to.
 * @param {String} options.dbPath - Filepath to hold this node's database.
 * @returns {Object} A map of the covenant aliases to the NPM packed file location
 *  and a hash of the binary file.
 */
const packCovenants = async (location, covenantConfig, options = {}) => {
  const { cli, cleanup } = await startInterbit(undefined, options)
  const packedCovenants = {}
 
  try {
    const covenants = Object.entries(covenantConfig)
    log.info('PACKING COVENANTS', covenants)
    for (const [covenantAlias, config] of covenants) {
      log.info(`...packing ${covenantAlias} from ${config.location}`)
      const packedCovenant = await packCovenant(cli, location, config.location)
 
      packedCovenants[covenantAlias] = packedCovenant
    }
 
    packedCovenants[ROOT_CHAIN_ALIAS] = await packRootCovenant(cli, location)
  } finally {
    await cleanup()
  }
 
  return packedCovenants
}
 
const packCovenant = async (cli, location, covenantFileLocation) => {
  const covenantLocation = path.relative(process.cwd(), covenantFileLocation)
 
  await exec(`npm pack ./${covenantLocation}`)
 
  // eslint-disable-next-line
  const covenantPackageJson = require(`${covenantFileLocation}/package.json`)
  const packedFilename = `${covenantPackageJson.name}-${
    covenantPackageJson.version
  }.tgz`
 
  const hash = await cli.deployCovenant(covenantFileLocation)
  await fs.move(packedFilename, `${location}/covenants/${hash}.tgz`)
 
  return {
    hash,
    filename: `covenants/${hash}.tgz`
  }
}
 
const packRootCovenant = async (cli, location) => {
  const packageName = 'interbit-covenant-tools'
 
  const rootCovenantLocation = path.join(
    getPackageDirFromFilePath(packageName, require.resolve(packageName)),
    '/src/rootCovenant'
  )
 
  const covenantInfo = await packCovenant(cli, location, rootCovenantLocation)
 
  return covenantInfo
}
 
const getPackageDirFromFilePath = (packageName, filepath) =>
  filepath.substr(0, filepath.indexOf(packageName) + packageName.length)
 
module.exports = {
  packCovenants
}