"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.isDirectory = isDirectory;
exports.parseSdkMajorVersion = parseSdkMajorVersion;
exports.saveUrlToPathAsync = saveUrlToPathAsync;
exports.saveImageToPathAsync = saveImageToPathAsync;
exports.getManifestAsync = getManifestAsync;
exports.rimrafDontThrow = rimrafDontThrow;
exports.removeIfExists = removeIfExists;
exports.spawnAsyncThrowError = spawnAsyncThrowError;
exports.spawnAsync = spawnAsync;
exports.transformFileContentsAsync = transformFileContentsAsync;
exports.manifestUsesSplashApi = manifestUsesSplashApi;
exports.getResolvedLocalesAsync = getResolvedLocalesAsync;
exports.regexFileAsync = regexFileAsync;
exports.deleteLinesInFileAsync = deleteLinesInFileAsync;
exports.createSpawner = createSpawner;

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

  _path = function () {
    return data;
  };

  return data;
}

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

  _fsExtra = function () {
    return data;
  };

  return data;
}

function _requestPromiseNative() {
  const data = _interopRequireDefault(require("request-promise-native"));

  _requestPromiseNative = function () {
    return data;
  };

  return data;
}

function _request() {
  const data = _interopRequireDefault(require("request"));

  _request = function () {
    return data;
  };

  return data;
}

function _spawnAsync() {
  const data = _interopRequireDefault(require("@expo/spawn-async"));

  _spawnAsync = function () {
    return data;
  };

  return data;
}

function _lodash() {
  const data = _interopRequireDefault(require("lodash"));

  _lodash = function () {
    return data;
  };

  return data;
}

function _Logger() {
  const data = _interopRequireWildcard(require("./Logger"));

  _Logger = function () {
    return data;
  };

  return data;
}

function _XDLError() {
  const data = _interopRequireDefault(require("../XDLError"));

  _XDLError = function () {
    return data;
  };

  return data;
}

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

// `request-promise-native` discourages using pipe. Noticed some issues with
// error handling so when using pipe use the original request lib instead.
const request = _requestPromiseNative().default.defaults({
  resolveWithFullResponse: true
});

function _getFilesizeInBytes(path) {
  let stats = _fsExtra().default.statSync(path);

  let fileSizeInBytes = stats['size'];
  return fileSizeInBytes;
}

function parseSdkMajorVersion(expSdkVersion) {
  // We assume that the unversioned SDK is the latest
  if (expSdkVersion === 'UNVERSIONED') {
    return Infinity;
  }

  let sdkMajorVersion = 0;

  try {
    let versionComponents = expSdkVersion.split('.').map(number => parseInt(number, 10));
    sdkMajorVersion = versionComponents[0];
  } catch (_) {}

  return sdkMajorVersion;
}

function saveUrlToPathAsync(url, path) {
  return new Promise(function (resolve, reject) {
    let stream = _fsExtra().default.createWriteStream(path);

    stream.on('close', () => {
      if (_getFilesizeInBytes(path) < 10) {
        reject(new Error(`${url} is too small`));
      }

      resolve();
    });
    stream.on('error', reject);
    (0, _request().default)({
      url,
      timeout: 20000
    }).on('error', reject).pipe(stream);
  });
}

function saveImageToPathAsync(projectRoot, pathOrURL, outPath) {
  const localPath = _path().default.resolve(projectRoot, pathOrURL);

  return new Promise(function (resolve, reject) {
    let stream = _fsExtra().default.createWriteStream(outPath);

    stream.on('close', () => {
      if (_getFilesizeInBytes(outPath) < 10) {
        throw new Error(`{filename} is too small`);
      }

      resolve();
    });
    stream.on('error', reject);

    if (_fsExtra().default.existsSync(localPath)) {
      _fsExtra().default.createReadStream(localPath).pipe(stream);
    } else {
      (0, _request().default)(pathOrURL).pipe(stream);
    }
  });
}

async function getManifestAsync(url, headers, options = {}) {
  const buildPhaseLogger = options.logger || _Logger().default.withFields({
    buildPhase: 'reading manifest'
  });

  const requestOptions = {
    url: url.replace('exp://', 'http://'),
    headers
  };
  let response;

  try {
    response = await _retryPromise(() => request(requestOptions));
  } catch (err) {
    buildPhaseLogger.error(err);
    throw new Error('Failed to fetch manifest from www');
  }

  const responseBody = response.body;
  buildPhaseLogger.info('Using manifest:', responseBody);
  let manifest;

  try {
    manifest = JSON.parse(responseBody);
  } catch (e) {
    throw new Error(`Unable to parse manifest: ${e}`);
  }

  return manifest;
}

async function _retryPromise(fn, retries = 5) {
  try {
    return await fn();
  } catch (err) {
    if (retries-- > 0) {
      return await _retryPromise(fn, retries);
    } else {
      throw err;
    }
  }
}

async function spawnAsyncThrowError(command, args, options = {
  stdio: 'inherit',
  cwd: process.cwd()
}) {
  const {
    pipeToLogger
  } = options;

  if (pipeToLogger) {
    options.stdio = 'pipe';
    options.cwd = options.cwd || process.cwd();
  }

  const promise = (0, _spawnAsync().default)(command, args, options);

  if (pipeToLogger && promise.child) {
    let streams = {};

    if (pipeToLogger === true || pipeToLogger.stdout) {
      streams.stdout = promise.child.stdout;
    }

    if (pipeToLogger === true || pipeToLogger.stderr) {
      streams.stderr = promise.child.stderr;
    }

    (0, _Logger().pipeOutputToLogger)(streams, options.loggerFields, options);
  }

  return promise;
}

async function spawnAsync(command, args, options) {
  try {
    return await spawnAsyncThrowError(command, args, options);
  } catch (e) {
    _Logger().default.error(e.message);
  }
}

function createSpawner(buildPhase, logger) {
  return (command, ...args) => {
    const lastArg = _lodash().default.last(args);

    const optionsFromArg = _lodash().default.isObject(lastArg) ? args.pop() : {};
    const options = { ...optionsFromArg,
      pipeToLogger: true
    };

    if (buildPhase) {
      options.loggerFields = options.loggerFields ? options.loggerFields : {};
      options.loggerFields = { ...options.loggerFields,
        buildPhase
      };
    }

    if (logger) {
      logger.info('Executing command:', command, ...args);
    }

    return spawnAsyncThrowError(command, args, options);
  };
}

async function transformFileContentsAsync(filename, transform) {
  let fileString = await _fsExtra().default.readFile(filename, 'utf8');
  let newFileString = transform(fileString);

  if (newFileString !== null) {
    await _fsExtra().default.writeFile(filename, newFileString);
  }
}

function manifestUsesSplashApi(manifest, platform) {
  if (platform === 'ios') {
    return manifest.splash || manifest.ios && manifest.ios.splash;
  }

  if (platform === 'android') {
    return manifest.splash || manifest.android && manifest.android.splash;
  }

  return false;
}

function rimrafDontThrow(directory) {
  _fsExtra().default.removeSync(directory);
}

async function removeIfExists(file) {
  await _fsExtra().default.remove(file);
}

function isDirectory(dir) {
  try {
    if (_fsExtra().default.statSync(dir).isDirectory()) {
      return true;
    }

    return false;
  } catch (e) {
    return false;
  }
}

async function getResolvedLocalesAsync(exp) {
  const locales = {};

  if (exp.locales !== undefined) {
    for (const [lang, path] of Object.entries(exp.locales)) {
      const s = await _fsExtra().default.readFile(path, 'utf8');

      try {
        locales[lang] = JSON.parse(s);
      } catch (e) {
        throw new (_XDLError().default)('INVALID_JSON', JSON.stringify(e));
      }
    }
  }

  return locales;
}

async function regexFileAsync(regex, replace, filename) {
  let file = await _fsExtra().default.readFile(filename);
  let fileString = file.toString();
  await _fsExtra().default.writeFile(filename, fileString.replace(regex, replace));
} // Matches sed /d behavior


async function deleteLinesInFileAsync(startRegex, endRegex, filename) {
  let file = await _fsExtra().default.readFile(filename);
  let fileString = file.toString();
  let lines = fileString.split(/\r?\n/);
  let filteredLines = [];
  let inDeleteRange = false;

  for (let i = 0; i < lines.length; i++) {
    if (lines[i].match(startRegex)) {
      inDeleteRange = true;
    }

    if (!inDeleteRange) {
      filteredLines.push(lines[i]);
    }

    if (inDeleteRange && lines[i].match(endRegex)) {
      inDeleteRange = false;
    }
  }

  await _fsExtra().default.writeFile(filename, filteredLines.join('\n'));
}
//# sourceMappingURL=../__sourcemaps__/detach/ExponentTools.js.map