"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

function _objectSpread2() {
  const data = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread"));

  _objectSpread2 = function () {
    return data;
  };

  return data;
}

function _bluebird() {
  const data = require("bluebird");

  _bluebird = function () {
    return data;
  };

  return data;
}

function _fsExtra() {
  const data = _interopRequireDefault(require("fs-extra"));

  _fsExtra = function () {
    return data;
  };

  return data;
}

function _path() {
  const data = _interopRequireDefault(require("path"));

  _path = function () {
    return data;
  };

  return data;
}

function _ramda() {
  const data = _interopRequireDefault(require("ramda"));

  _ramda = function () {
    return data;
  };

  return data;
}

function _detectIndent() {
  const data = _interopRequireDefault(require("detect-indent"));

  _detectIndent = function () {
    return data;
  };

  return data;
}

function _detectNewline() {
  const data = _interopRequireDefault(require("detect-newline"));

  _detectNewline = function () {
    return data;
  };

  return data;
}

function _stringifyPackage() {
  const data = _interopRequireDefault(require("stringify-package"));

  _stringifyPackage = function () {
    return data;
  };

  return data;
}

function _constants() {
  const data = require("../../constants");

  _constants = function () {
    return data;
  };

  return data;
}

function _logger() {
  const data = _interopRequireDefault(require("../../logger/logger"));

  _logger = function () {
    return data;
  };

  return data;
}

function _consumerComponent() {
  const data = _interopRequireDefault(require("./consumer-component"));

  _consumerComponent = function () {
    return data;
  };

  return data;
}

function _componentIdToPackageName() {
  const data = _interopRequireDefault(require("../../utils/bit/component-id-to-package-name"));

  _componentIdToPackageName = function () {
    return data;
  };

  return data;
}

function _packageJsonVinyl() {
  const data = _interopRequireDefault(require("./package-json-vinyl"));

  _packageJsonVinyl = function () {
    return data;
  };

  return data;
}

/**
 * when a package.json file is loaded, we save the indentation and the type of newline it uses, so
 * then we could preserve it later on while writing the file. this is same process used by NPM when
 * writing the package.json file
 */
class PackageJsonFile {
  // default when writing (in stringifyPackage) is "  ". (two spaces).
  // whether "\n" or "\r\n", default when writing (in stringifyPackage) is "\n"
  constructor(filePath, packageJsonObject, fileExist, workspaceDir, indent, newline) {
    this.filePath = filePath;
    this.packageJsonObject = packageJsonObject;
    this.fileExist = fileExist;
    this.workspaceDir = workspaceDir;
    this.indent = indent;
    this.newline = newline;
  }

  write() {
    var _this = this;

    return (0, _bluebird().coroutine)(function* () {
      if (!_this.workspaceDir) throw new Error('PackageJsonFile is unable to write, workspaceDir is not defined');

      const pathToWrite = _path().default.join(_this.workspaceDir, _this.filePath);

      _logger().default.debug(`package-json-file.write, path ${pathToWrite}`);

      const packageJsonStr = (0, _stringifyPackage().default)(_this.packageJsonObject, _this.indent, _this.newline);
      yield _fsExtra().default.outputFile(pathToWrite, packageJsonStr);
      _this.fileExist = true;
    })();
  }
  /**
   * load from the given dir, if not exist, don't throw an error, just set packageJsonObject as an
   * empty object
   */


  static load(workspaceDir, componentDir = '.') {
    return (0, _bluebird().coroutine)(function* () {
      const filePath = composePath(componentDir);

      const filePathAbsolute = _path().default.join(workspaceDir, filePath);

      const packageJsonStr = yield PackageJsonFile.getPackageJsonStrIfExist(filePathAbsolute);

      if (!packageJsonStr) {
        return new PackageJsonFile(filePath, {}, false, workspaceDir);
      }

      const packageJsonObject = PackageJsonFile.parsePackageJsonStr(packageJsonStr, componentDir);
      const indent = (0, _detectIndent().default)(packageJsonStr).indent;
      const newline = (0, _detectNewline().default)(packageJsonStr);
      return new PackageJsonFile(filePath, packageJsonObject, true, workspaceDir, indent, newline);
    })();
  }

  static createFromComponent(componentDir, component, excludeRegistryPrefix = false) {
    const filePath = composePath(componentDir);
    const name = excludeRegistryPrefix ? (0, _componentIdToPackageName().default)(component.id, component.bindingPrefix, false) : (0, _componentIdToPackageName().default)(component.id, component.bindingPrefix);
    const packageJsonObject = {
      name,
      version: component.version,
      homepage: component._getHomepage(),
      main: component.mainFile,
      dependencies: component.packageDependencies,
      devDependencies: (0, _objectSpread2().default)({}, component.devPackageDependencies, component.compilerPackageDependencies, component.testerPackageDependencies),
      peerDependencies: component.peerPackageDependencies,
      license: `SEE LICENSE IN ${!_ramda().default.isEmpty(component.license) ? 'LICENSE' : 'UNLICENSED'}`
    };
    return new PackageJsonFile(filePath, packageJsonObject, false);
  }

  toVinylFile() {
    return _packageJsonVinyl().default.load({
      base: _path().default.dirname(this.filePath),
      path: this.filePath,
      content: this.packageJsonObject,
      indent: this.indent,
      newline: this.newline
    });
  }

  addDependencies(dependencies) {
    this.packageJsonObject.dependencies = Object.assign({}, this.packageJsonObject.dependencies, dependencies);
  }

  addDevDependencies(dependencies) {
    this.packageJsonObject.devDependencies = Object.assign({}, this.packageJsonObject.devDependencies, dependencies);
  }

  addOrUpdateProperty(propertyName, propertyValue) {
    this.packageJsonObject[propertyName] = propertyValue;
  }

  getProperty(propertyName) {
    return this.packageJsonObject[propertyName];
  }

  mergePackageJsonObject(packageJsonObject) {
    if (!packageJsonObject || _ramda().default.isEmpty(packageJsonObject)) return;
    this.packageJsonObject = Object.assign(this.packageJsonObject, packageJsonObject);
  }

  static propsNonUserChangeable() {
    return ['name', 'version', 'main', 'dependencies', 'devDependencies', 'peerDependencies', 'license', 'bit'];
  }

  static parsePackageJsonStr(str, dir) {
    try {
      return JSON.parse(str);
    } catch (err) {
      throw new Error(`failed parsing package.json file at ${dir}. original error: ${err.message}`);
    }
  }

  static getPackageJsonStrIfExist(filePath) {
    return (0, _bluebird().coroutine)(function* () {
      try {
        return yield _fsExtra().default.readFile(filePath, 'utf-8');
      } catch (err) {
        if (err.code === 'ENOENT') {
          return null; // file not found
        }

        throw err;
      }
    })();
  }

}

exports.default = PackageJsonFile;

function composePath(componentRootFolder) {
  return _path().default.join(componentRootFolder, _constants().PACKAGE_JSON);
}