/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * strict * @format */ "use strict"; function _toConsumableArray(arr) { return ( _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread() ); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } function _iterableToArray(iter) { if ( Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]" ) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } } const fs = require("fs"); const path = require("path"); class Package { constructor(_ref) { let file = _ref.file; this.path = path.resolve(file); this._root = path.dirname(this.path); this._content = null; } /** * The `browser` field and replacement behavior is specified in * https://github.com/defunctzombie/package-browser-field-spec. */ getMain(mainFields) { const json = this.read(); let main; for (const name of mainFields) { if (typeof json[name] === "string") { main = json[name]; break; } } if (!main) { main = "index"; } const replacements = getReplacements(json, mainFields); if (replacements) { const variants = [main]; if (main.slice(0, 2) === "./") { variants.push(main.slice(2)); } else { variants.push("./" + main); } for (const variant of variants) { const winner = replacements[variant] || replacements[variant + ".js"] || replacements[variant + ".json"] || replacements[variant.replace(/(\.js|\.json)$/, "")]; if (winner) { main = winner; break; } } } /* $FlowFixMe: `getReplacements` doesn't validate the return value. */ return path.join(this._root, main); } invalidate() { this._content = null; } redirectRequire(name, mainFields) { const json = this.read(); const replacements = getReplacements(json, mainFields); if (!replacements) { return name; } if (!name.startsWith(".") && !path.isAbsolute(name)) { const replacement = replacements[name]; // support exclude with "someDependency": false return replacement === false ? false : replacement || name; } let relPath = "./" + path.relative(this._root, path.resolve(this._root, name)); if (path.sep !== "/") { relPath = relPath.replace(new RegExp("\\" + path.sep, "g"), "/"); } let redirect = replacements[relPath]; // false is a valid value if (redirect == null) { redirect = replacements[relPath + ".js"]; if (redirect == null) { redirect = replacements[relPath + ".json"]; } } // support exclude with "./someFile": false if (redirect === false) { return false; } if (redirect) { return path.join(this._root, redirect); } return name; } read() { if (this._content == null) { this._content = JSON.parse(fs.readFileSync(this.path, "utf8")); } return this._content; } } function getReplacements(pkg, mainFields) { const replacements = mainFields .map(name => { // If the field is a string, that doesn't mean we want to redirect the // `main` file itself to anything else. See the spec. if (!pkg[name] || typeof pkg[name] === "string") { return null; } return pkg[name]; }) .filter(Boolean); if (!replacements.length) { return null; } return Object.assign.apply( Object, [{}].concat(_toConsumableArray(replacements.reverse())) ); } module.exports = Package;