"use strict";

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

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

var _resolve = require("resolve");

var _assert = _interopRequireDefault(require("assert"));

var _fs = _interopRequireDefault(require("fs"));

var _path = _interopRequireDefault(require("path"));

Object.keys(_resolve.core).forEach(key => {
  // 'resolve' hardcodes the list to host's one, but i need
  // to be able to allow 'worker_threads' (target 12) on host 8
  (0, _assert.default)(typeof _resolve.core[key] === 'boolean');
  _resolve.core[key] = true;
});
const natives = _resolve.core;
exports.natives = natives;
const PROOF = 'a-proof-that-main-is-captured.js';

function parentDirectoriesContain(parent, directory) {
  while (true) {
    if (parent === directory) return true;

    const newParent = _path.default.dirname(parent);

    if (newParent === parent) return false;
    parent = newParent;
  }
}

function follow(x, opts) {
  // TODO async version
  return new Promise(resolve => {
    resolve((0, _resolve.sync)(x, {
      basedir: opts.basedir,
      extensions: opts.extensions,
      isFile: file => {
        if (opts.ignoreFile && _path.default.join(_path.default.dirname(opts.ignoreFile), PROOF) === file) return true;
        let stat;

        try {
          stat = _fs.default.statSync(file);
        } catch (e) {
          if (e && (e.code === 'ENOENT' || e.code === 'ENOTDIR')) return false;
          throw e;
        }

        return stat.isFile() || stat.isFIFO();
      },
      isDirectory: directory => {
        if (opts.ignoreFile && parentDirectoriesContain(opts.ignoreFile, directory)) return false;
        let stat;

        try {
          stat = _fs.default.statSync(directory);
        } catch (e) {
          if (e && (e.code === 'ENOENT' || e.code === 'ENOTDIR')) return false;
          throw e;
        }

        return stat.isDirectory();
      },
      readFileSync: file => {
        if (opts.ignoreFile && opts.ignoreFile === file) return Buffer.from(`{"main":"${PROOF}"}`);
        if (opts.readFile) opts.readFile(file);
        return _fs.default.readFileSync(file);
      },
      packageFilter: (config, base) => {
        if (opts.packageFilter) opts.packageFilter(config, base);
        return config;
      }
    }));
  });
}