text: "use strict";
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.default = void 0;
  
  var _diagnostic = _interopRequireWildcard(require("@parcel/diagnostic"));
  
  var _utils = require("@parcel/utils");
  
  var _Environment = require("./Environment");
  
  var _path = _interopRequireDefault(require("path"));
  
  var _browserslist = _interopRequireDefault(require("browserslist"));
  
  var _jsonSourceMap = _interopRequireDefault(require("json-source-map"));
  
  var _assert = _interopRequireDefault(require("assert"));
  
  var _TargetDescriptor = require("./TargetDescriptor.schema");
  
  var _Environment2 = require("./public/Environment");
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
  
  function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  const DEFAULT_DEVELOPMENT_ENGINES = {
    node: 'current',
    browsers: ['last 1 Chrome version', 'last 1 Safari version', 'last 1 Firefox version', 'last 1 Edge version']
  };
  const DEFAULT_PRODUCTION_ENGINES = {
    browsers: ['>= 0.25%'],
    node: '8'
  };
  const DEFAULT_DIST_DIRNAME = 'dist';
  const COMMON_TARGETS = ['main', 'module', 'browser', 'types'];
  
  class TargetResolver {
    constructor(options) {
      _defineProperty(this, "fs", void 0);
  
      _defineProperty(this, "options", void 0);
  
      this.fs = options.inputFS;
      this.options = options;
    }
  
    async resolve(rootDir) {
      let optionTargets = this.options.targets;
      let packageTargets = await this.resolvePackageTargets(rootDir);
      let targets;
      let files = [];
  
      if (optionTargets) {
        if (Array.isArray(optionTargets)) {
          if (optionTargets.length === 0) {
            throw new _diagnostic.default({
              diagnostic: {
                message: `Targets option is an empty array`,
                origin: '@parcel/core'
              }
            });
          } // If an array of strings is passed, it's a filter on the resolved package
          // targets. Load them, and find the matching targets.
  
  
          targets = optionTargets.map(target => {
            let matchingTarget = packageTargets.targets.get(target);
  
            if (!matchingTarget) {
              throw new _diagnostic.default({
                diagnostic: {
                  message: `Could not find target with name "${target}"`,
                  origin: '@parcel/core'
                }
              });
            }
  
            return matchingTarget;
          });
          files = packageTargets.files;
        } else {
          // Otherwise, it's an object map of target descriptors (similar to those
          // in package.json). Adapt them to native targets.
          targets = Object.entries(optionTargets).map(([name, _descriptor]) => {
            var _descriptor$publicUrl;
  
            let {
              distDir,
              ...descriptor
            } = parseDescriptor(name, _descriptor, null, {
              targets: optionTargets
            });
  
            if (!distDir) {
              let optionTargetsString = JSON.stringify(optionTargets, null, '\t');
              throw new _diagnostic.default({
                diagnostic: {
                  message: `Missing distDir for target "${name}"`,
                  origin: '@parcel/core',
                  codeFrame: {
                    code: optionTargetsString,
                    codeHighlights: (0, _diagnostic.generateJSONCodeHighlights)(optionTargetsString, [{
                      key: `/${name}`,
                      type: 'value'
                    }])
                  }
                }
              });
            }
  
            return {
              name,
              distDir: _path.default.resolve(this.fs.cwd(), distDir),
              publicUrl: (_descriptor$publicUrl = descriptor.publicUrl) !== null && _descriptor$publicUrl !== void 0 ? _descriptor$publicUrl : this.options.publicUrl,
              env: (0, _Environment.createEnvironment)({
                engines: descriptor.engines,
                context: descriptor.context,
                isLibrary: descriptor.isLibrary,
                includeNodeModules: descriptor.includeNodeModules,
                outputFormat: descriptor.outputFormat,
                minify: this.options.minify && descriptor.minify !== false,
                scopeHoist: this.options.scopeHoist && descriptor.scopeHoist !== false
              }),
              sourceMap: normalizeSourceMap(this.options, descriptor.sourceMap)
            };
          });
        }
  
        let serve = this.options.serve;
  
        if (serve) {
          // In serve mode, we only support a single browser target. If the user
          // provided more than one, or the matching target is not a browser, throw.
          if (targets.length > 1) {
            throw new _diagnostic.default({
              diagnostic: {
                message: `More than one target is not supported in serve mode`,
                origin: '@parcel/core'
              }
            });
          }
  
          if (!_Environment2.BROWSER_ENVS.has(targets[0].env.context)) {
            throw new _diagnostic.default({
              diagnostic: {
                message: `Only browser targets are supported in serve mode`,
                origin: '@parcel/core'
              }
            });
          }
  
          targets[0].distDir = serve.distDir;
        }
      } else {
        // Explicit targets were not provided. Either use a modern target for server
        // mode, or simply use the package.json targets.
        if (this.options.serve) {
          var _this$options$publicU;
  
          // In serve mode, we only support a single browser target. Since the user
          // hasn't specified a target, use one targeting modern browsers for development
          targets = [{
            name: 'default',
            distDir: this.options.serve.distDir,
            publicUrl: (_this$options$publicU = this.options.publicUrl) !== null && _this$options$publicU !== void 0 ? _this$options$publicU : '/',
            sourceMap: this.options.sourceMaps ? {} : undefined,
            env: (0, _Environment.createEnvironment)({
              context: 'browser',
              engines: {
                browsers: DEFAULT_DEVELOPMENT_ENGINES.browsers
              },
              minify: this.options.minify,
              scopeHoist: this.options.scopeHoist
            })
          }];
        } else {
          targets = Array.from(packageTargets.targets.values());
          files = packageTargets.files;
        }
      }
  
      return {
        targets,
        files
      };
    }
  
    async resolvePackageTargets(rootDir) {
      var _this$options$default;
  
      let conf = await (0, _utils.loadConfig)(this.fs, _path.default.join(rootDir, 'index'), ['package.json']);
      let pkg;
      let pkgContents;
      let pkgFilePath;
      let pkgDir;
      let pkgMap;
  
      if (conf) {
        pkg = conf.config;
        let pkgFile = conf.files[0];
  
        if (pkgFile == null) {
          throw new _diagnostic.default({
            diagnostic: {
              message: `Expected package.json file in ${rootDir}`,
              origin: '@parcel/core'
            }
          });
        }
  
        pkgFilePath = pkgFile.filePath;
        pkgDir = _path.default.dirname(pkgFilePath);
        pkgContents = await this.fs.readFile(pkgFilePath, 'utf8');
        pkgMap = _jsonSourceMap.default.parse(pkgContents.replace(/\t/g, ' '));
      } else {
        pkg = {};
        pkgDir = this.fs.cwd();
      }
  
      let pkgTargets = pkg.targets || {};
      let pkgEngines = parseEngines(pkg.engines, pkgFilePath, pkgContents, '/engines', 'Invalid engines in package.json') || {};
  
      if (!pkgEngines.browsers) {
        let browserslistBrowsers = _browserslist.default.loadConfig({
          path: rootDir
        });
  
        if (browserslistBrowsers) {
          pkgEngines = { ...pkgEngines,
            browsers: browserslistBrowsers
          };
        }
      }
  
      let targets = new Map();
      let node = pkgEngines.node;
      let browsers = pkgEngines.browsers; // If there is a separate `browser` target, or an `engines.node` field but no browser targets, then
      // the `main` and `module` targets refer to node, otherwise browser.
  
      let mainContext = pkg.browser || pkgTargets.browser || node && !browsers ? 'node' : 'browser';
      let moduleContext = pkg.browser || pkgTargets.browser ? 'browser' : mainContext;
      let defaultEngines = (_this$options$default = this.options.defaultEngines) !== null && _this$options$default !== void 0 ? _this$options$default : this.options.mode === 'production' ? DEFAULT_PRODUCTION_ENGINES : DEFAULT_DEVELOPMENT_ENGINES;
      let context = browsers || !node ? 'browser' : 'node';
  
      if (context === 'browser' && pkgEngines.browsers == null) {
        pkgEngines = { ...pkgEngines,
          browsers: defaultEngines.browsers
        };
      } else if (context === 'node' && pkgEngines.node == null) {
        pkgEngines = { ...pkgEngines,
          node: defaultEngines.node
        };
      }
  
      for (let targetName of COMMON_TARGETS) {
        let targetDist;
        let pointer;
  
        if (targetName === 'browser' && pkg[targetName] != null && typeof pkg[targetName] === 'object') {
          // The `browser` field can be a file path or an alias map.
          targetDist = pkg[targetName][pkg.name];
          pointer = `/${targetName}/${pkg.name}`;
        } else {
          targetDist = pkg[targetName];
          pointer = `/${targetName}`;
        }
  
        if (typeof targetDist === 'string' || pkgTargets[targetName]) {
          var _pkgTargets$targetNam, _descriptor$publicUrl2, _descriptor$engines, _descriptor$context, _descriptor$includeNo, _descriptor$outputFor;
  
          let distDir;
          let distEntry;
          let loc;
          (0, _assert.default)(typeof pkgFilePath === 'string');
          (0, _assert.default)(pkgMap != null);
  
          let _descriptor = (_pkgTargets$targetNam = pkgTargets[targetName]) !== null && _pkgTargets$targetNam !== void 0 ? _pkgTargets$targetNam : {};
  
          if (typeof targetDist === 'string') {
            distDir = _path.default.resolve(pkgDir, _path.default.dirname(targetDist));
            distEntry = _path.default.basename(targetDist);
            loc = {
              filePath: pkgFilePath,
              ...(0, _diagnostic.getJSONSourceLocation)(pkgMap.pointers[pointer], 'value')
            };
          } else {
            var _this$options$distDir;
  
            distDir = (_this$options$distDir = this.options.distDir) !== null && _this$options$distDir !== void 0 ? _this$options$distDir : _path.default.join(pkgDir, DEFAULT_DIST_DIRNAME, targetName);
          }
  
          let descriptor = parseCommonTargetDescriptor(targetName, _descriptor, pkgFilePath, pkgContents);
          if (!descriptor) continue;
          let isLibrary = typeof distEntry === 'string' ? _path.default.extname(distEntry) === '.js' : false;
          targets.set(targetName, {
            name: targetName,
            distDir,
            distEntry,
            publicUrl: (_descriptor$publicUrl2 = descriptor.publicUrl) !== null && _descriptor$publicUrl2 !== void 0 ? _descriptor$publicUrl2 : this.options.publicUrl,
            env: (0, _Environment.createEnvironment)({
              engines: (_descriptor$engines = descriptor.engines) !== null && _descriptor$engines !== void 0 ? _descriptor$engines : pkgEngines,
              context: (_descriptor$context = descriptor.context) !== null && _descriptor$context !== void 0 ? _descriptor$context : targetName === 'browser' ? 'browser' : targetName === 'module' ? moduleContext : mainContext,
              includeNodeModules: (_descriptor$includeNo = descriptor.includeNodeModules) !== null && _descriptor$includeNo !== void 0 ? _descriptor$includeNo : !isLibrary,
              outputFormat: (_descriptor$outputFor = descriptor.outputFormat) !== null && _descriptor$outputFor !== void 0 ? _descriptor$outputFor : isLibrary ? targetName === 'module' ? 'esmodule' : 'commonjs' : 'global',
              isLibrary: isLibrary,
              minify: this.options.minify && descriptor.minify !== false,
              scopeHoist: this.options.scopeHoist && descriptor.scopeHoist !== false
            }),
            sourceMap: normalizeSourceMap(this.options, descriptor.sourceMap),
            loc
          });
        }
      }
  
      let customTargets = Object.keys(pkgTargets).filter(targetName => !COMMON_TARGETS.includes(targetName)); // Custom targets
  
      for (let targetName of customTargets) {
        let distPath = pkg[targetName];
        let distDir;
        let distEntry;
        let loc;
  
        if (distPath == null) {
          var _this$options$distDir2;
  
          distDir = (_this$options$distDir2 = this.options.distDir) !== null && _this$options$distDir2 !== void 0 ? _this$options$distDir2 : _path.default.join(pkgDir, DEFAULT_DIST_DIRNAME);
  
          if (customTargets.length >= 2) {
            distDir = _path.default.join(distDir, targetName);
          }
        } else {
          if (typeof distPath !== 'string') {
            let contents = typeof pkgContents === 'string' ? pkgContents : // $FlowFixMe
            JSON.stringify(pkgContents, null, '\t');
            throw new _diagnostic.default({
              diagnostic: {
                message: `Invalid distPath for target "${targetName}"`,
                origin: '@parcel/core',
                language: 'json',
                filePath: pkgFilePath || undefined,
                codeFrame: {
                  code: contents,
                  codeHighlights: (0, _diagnostic.generateJSONCodeHighlights)(contents, [{
                    key: `/${targetName}`,
                    type: 'value',
                    message: 'Expected type string'
                  }])
                }
              }
            });
          }
  
          distDir = _path.default.resolve(pkgDir, _path.default.dirname(distPath));
          distEntry = _path.default.basename(distPath);
          (0, _assert.default)(typeof pkgFilePath === 'string');
          (0, _assert.default)(pkgMap != null);
          loc = {
            filePath: pkgFilePath,
            ...(0, _diagnostic.getJSONSourceLocation)(pkgMap.pointers[`/${targetName}`], 'value')
          };
        }
  
        if (targetName in pkgTargets) {
          var _descriptor$publicUrl3, _descriptor$engines2;
  
          let descriptor = parseDescriptor(targetName, pkgTargets[targetName], pkgFilePath, pkgContents);
          targets.set(targetName, {
            name: targetName,
            distDir,
            distEntry,
            publicUrl: (_descriptor$publicUrl3 = descriptor.publicUrl) !== null && _descriptor$publicUrl3 !== void 0 ? _descriptor$publicUrl3 : this.options.publicUrl,
            env: (0, _Environment.createEnvironment)({
              engines: (_descriptor$engines2 = descriptor.engines) !== null && _descriptor$engines2 !== void 0 ? _descriptor$engines2 : pkgEngines,
              context: descriptor.context,
              includeNodeModules: descriptor.includeNodeModules,
              outputFormat: descriptor.outputFormat,
              isLibrary: descriptor.isLibrary,
              minify: this.options.minify && descriptor.minify !== false,
              scopeHoist: this.options.scopeHoist && descriptor.scopeHoist !== false
            }),
            sourceMap: normalizeSourceMap(this.options, descriptor.sourceMap),
            loc
          });
        }
      } // If no explicit targets were defined, add a default.
  
  
      if (targets.size === 0) {
        var _this$options$distDir3;
  
        targets.set('default', {
          name: 'default',
          distDir: (_this$options$distDir3 = this.options.distDir) !== null && _this$options$distDir3 !== void 0 ? _this$options$distDir3 : _path.default.join(pkgDir, DEFAULT_DIST_DIRNAME),
          publicUrl: this.options.publicUrl,
          env: (0, _Environment.createEnvironment)({
            engines: pkgEngines,
            context,
            minify: this.options.minify,
            scopeHoist: this.options.scopeHoist
          }),
          sourceMap: this.options.sourceMaps ? {} : undefined
        });
      }
  
      assertNoDuplicateTargets(targets, pkgFilePath, pkgContents);
      return {
        targets,
        files: conf ? conf.files : []
      };
    }
  
  }
  
  exports.default = TargetResolver;
  
  function parseEngines(engines, pkgPath, pkgContents, prependKey, message) {
    if (engines === undefined) {
      return engines;
    } else {
      _utils.validateSchema.diagnostic(_TargetDescriptor.ENGINES_SCHEMA, engines, pkgPath, pkgContents, '@parcel/core', prependKey, message); // $FlowFixMe we just verified this
  
  
      return engines;
    }
  }
  
  function parseDescriptor(targetName, descriptor, pkgPath, pkgContents) {
    _utils.validateSchema.diagnostic(_TargetDescriptor.DESCRIPTOR_SCHEMA, descriptor, pkgPath, pkgContents, '@parcel/core', `/targets/${targetName}`, `Invalid target descriptor for target "${targetName}"`); // $FlowFixMe we just verified this
  
  
    return descriptor;
  }
  
  function parseCommonTargetDescriptor(targetName, descriptor, pkgPath, pkgContents) {
    _utils.validateSchema.diagnostic(_TargetDescriptor.COMMON_TARGET_DESCRIPTOR_SCHEMA, descriptor, pkgPath, pkgContents, '@parcel/core', `/targets/${targetName}`, `Invalid target descriptor for target "${targetName}"`); // $FlowFixMe we just verified this
  
  
    return descriptor;
  }
  
  function assertNoDuplicateTargets(targets, pkgFilePath, pkgContents) {
    // Detect duplicate targets by destination path and provide a nice error.
    // Without this, an assertion is thrown much later after naming the bundles and finding duplicates.
    let targetsByPath = new Map();
  
    for (let target of targets.values()) {
      if (target.distEntry) {
        var _targetsByPath$get;
  
        let distPath = _path.default.join(target.distDir, target.distEntry);
  
        if (!targetsByPath.has(distPath)) {
          targetsByPath.set(distPath, []);
        }
  
        (_targetsByPath$get = targetsByPath.get(distPath)) === null || _targetsByPath$get === void 0 ? void 0 : _targetsByPath$get.push(target.name);
      }
    }
  
    let diagnostics = [];
  
    for (let [targetPath, targetNames] of targetsByPath) {
      if (targetNames.length > 1 && pkgContents && pkgFilePath) {
        diagnostics.push({
          message: `Multiple targets have the same destination path "${_path.default.relative(_path.default.dirname(pkgFilePath), targetPath)}"`,
          origin: '@parcel/core',
          language: 'json',
          filePath: pkgFilePath || undefined,
          codeFrame: {
            code: pkgContents,
            codeHighlights: (0, _diagnostic.generateJSONCodeHighlights)(pkgContents, targetNames.map(t => ({
              key: `/${t}`,
              type: 'value'
            })))
          }
        });
      }
    }
  
    if (diagnostics.length > 0) {
      // Only add hints to the last diagnostic so it isn't duplicated on each one
      diagnostics[diagnostics.length - 1].hints = ['Try removing the duplicate targets, or changing the destination paths.'];
      throw new _diagnostic.default({
        diagnostic: diagnostics
      });
    }
  }
  
  function normalizeSourceMap(options, sourceMap) {
    if (options.sourceMaps) {
      if (typeof sourceMap === 'boolean') {
        return sourceMap ? {} : undefined;
      } else {
        return sourceMap !== null && sourceMap !== void 0 ? sourceMap : {};
      }
    } else {
      return undefined;
    }
  }