"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.NodePackageManager = void 0; function _core() { const data = require("@parcel/core"); _core = function () { return data; }; return data; } function _diagnostic() { const data = _interopRequireWildcard(require("@parcel/diagnostic")); _diagnostic = function () { return data; }; return data; } function _fs() { const data = _interopRequireDefault(require("fs")); _fs = function () { return data; }; return data; } function _module() { const data = _interopRequireDefault(require("module")); _module = function () { return data; }; return data; } function _path() { const data = _interopRequireDefault(require("path")); _path = function () { return data; }; return data; } function _semver() { const data = _interopRequireDefault(require("semver")); _semver = function () { return data; }; return data; } var _utils = require("./utils"); var _installPackage = require("./installPackage"); var _package = _interopRequireDefault(require("../package.json")); var _NodeResolver = require("./NodeResolver"); var _NodeResolverSync = require("./NodeResolverSync"); 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; } // There can be more than one instance of NodePackageManager, but node has only a single module cache. // Therefore, the resolution cache and the map of parent to child modules should also be global. const cache = new Map(); const children = new Map(); // This implements a package manager for Node by monkey patching the Node require // algorithm so that it uses the specified FileSystem instead of the native one. // It also handles installing packages when they are required if not already installed. // See https://github.com/nodejs/node/blob/master/lib/internal/modules/cjs/loader.js // for reference to Node internals. class NodePackageManager { invalidationsCache = new Map(); constructor(fs, projectRoot, installer) { this.fs = fs; this.projectRoot = projectRoot; this.installer = installer; this.resolver = new _NodeResolver.NodeResolver(this.fs, projectRoot); this.syncResolver = new _NodeResolverSync.NodeResolverSync(this.fs, projectRoot); } static deserialize(opts) { return new NodePackageManager(opts.fs, opts.projectRoot, opts.installer); } serialize() { return { $$raw: false, fs: this.fs, projectRoot: this.projectRoot, installer: this.installer }; } async require(name, from, opts) { let { resolved } = await this.resolve(name, from, opts); return this.load(resolved, from); } requireSync(name, from) { let { resolved } = this.resolveSync(name, from); return this.load(resolved, from); } load(filePath, from) { if (!_path().default.isAbsolute(filePath)) { // Node builtin module // $FlowFixMe return require(filePath); } // $FlowFixMe[prop-missing] const cachedModule = _module().default._cache[filePath]; if (cachedModule !== undefined) { return cachedModule.exports; } // $FlowFixMe let m = new (_module().default)(filePath, _module().default._cache[from] || module.parent); // $FlowFixMe[prop-missing] _module().default._cache[filePath] = m; // Patch require within this module so it goes through our require m.require = id => { return this.requireSync(id, filePath); }; // Patch `fs.readFileSync` temporarily so that it goes through our file system let readFileSync = _fs().default.readFileSync; // $FlowFixMe _fs().default.readFileSync = (filename, encoding) => { // $FlowFixMe _fs().default.readFileSync = readFileSync; return this.fs.readFileSync(filename, encoding); }; try { m.load(filePath); } catch (err) { // $FlowFixMe[prop-missing] delete _module().default._cache[filePath]; throw err; } return m.exports; } async resolve(name, from, options) { let basedir = _path().default.dirname(from); let key = basedir + ':' + name; let resolved = cache.get(key); if (!resolved) { try { resolved = await this.resolver.resolve(name, from); } catch (e) { if (e.code !== 'MODULE_NOT_FOUND' || (options === null || options === void 0 ? void 0 : options.shouldAutoInstall) !== true) { if (e.code === 'MODULE_NOT_FOUND' && (options === null || options === void 0 ? void 0 : options.shouldAutoInstall) !== true) { let err = new (_diagnostic().default)({ diagnostic: { message: (0, _diagnostic().escapeMarkdown)(e.message), hints: ['Autoinstall is disabled, please install this package manually and restart Parcel.'] } }); // $FlowFixMe - needed for loadParcelPlugin err.code = 'MODULE_NOT_FOUND'; throw err; } else { throw e; } } let conflicts = await (0, _utils.getConflictingLocalDependencies)(this.fs, name, from, this.projectRoot); if (conflicts == null) { var _options$saveDev; await this.install([{ name, range: options === null || options === void 0 ? void 0 : options.range }], from, { saveDev: (_options$saveDev = options === null || options === void 0 ? void 0 : options.saveDev) !== null && _options$saveDev !== void 0 ? _options$saveDev : true }); return this.resolve(name, from, { ...options, shouldAutoInstall: false }); } throw new (_diagnostic().default)({ diagnostic: conflicts.fields.map(field => ({ message: (0, _diagnostic().md)`Could not find module "${name}", but it was listed in package.json. Run your package manager first.`, origin: '@parcel/package-manager', codeFrames: [{ filePath: conflicts.filePath, language: 'json', code: conflicts.json, codeHighlights: (0, _diagnostic().generateJSONCodeHighlights)(conflicts.json, [{ key: `/${field}/${(0, _diagnostic().encodeJSONKeyComponent)(name)}`, type: 'key', message: 'Defined here, but not installed' }]) }] })) }); } let range = options === null || options === void 0 ? void 0 : options.range; if (range != null) { let pkg = resolved.pkg; if (pkg == null || !_semver().default.satisfies(pkg.version, range)) { let conflicts = await (0, _utils.getConflictingLocalDependencies)(this.fs, name, from, this.projectRoot); if (conflicts == null && (options === null || options === void 0 ? void 0 : options.shouldAutoInstall) === true) { await this.install([{ name, range }], from); return this.resolve(name, from, { ...options, shouldAutoInstall: false }); } else if (conflicts != null) { throw new (_diagnostic().default)({ diagnostic: { message: (0, _diagnostic().md)`Could not find module "${name}" satisfying ${range}.`, origin: '@parcel/package-manager', codeFrames: [{ filePath: conflicts.filePath, language: 'json', code: conflicts.json, codeHighlights: (0, _diagnostic().generateJSONCodeHighlights)(conflicts.json, conflicts.fields.map(field => ({ key: `/${field}/${(0, _diagnostic().encodeJSONKeyComponent)(name)}`, type: 'key', message: 'Found this conflicting local requirement.' }))) }] } }); } let version = pkg === null || pkg === void 0 ? void 0 : pkg.version; let message = (0, _diagnostic().md)`Could not resolve package "${name}" that satisfies ${range}.`; if (version != null) { message += (0, _diagnostic().md)` Found ${version}.`; } throw new (_diagnostic().default)({ diagnostic: { message, hints: ['Looks like the incompatible version was installed transitively. Add this package as a direct dependency with a compatible version range.'] } }); } } cache.set(key, resolved); this.invalidationsCache.clear(); // Add the specifier as a child to the parent module. // Don't do this if the specifier was an absolute path, as this was likely a dynamically resolved path // (e.g. babel uses require() to load .babelrc.js configs and we don't want them to be added as children of babel itself). if (!_path().default.isAbsolute(name)) { let moduleChildren = children.get(from); if (!moduleChildren) { moduleChildren = new Set(); children.set(from, moduleChildren); } moduleChildren.add(name); } } return resolved; } resolveSync(name, from) { let basedir = _path().default.dirname(from); let key = basedir + ':' + name; let resolved = cache.get(key); if (!resolved) { resolved = this.syncResolver.resolve(name, from); cache.set(key, resolved); this.invalidationsCache.clear(); if (!_path().default.isAbsolute(name)) { let moduleChildren = children.get(from); if (!moduleChildren) { moduleChildren = new Set(); children.set(from, moduleChildren); } moduleChildren.add(name); } } return resolved; } async install(modules, from, opts) { await (0, _installPackage.installPackage)(this.fs, this, modules, from, this.projectRoot, { packageInstaller: this.installer, ...opts }); } getInvalidations(name, from) { let key = name + ':' + from; let cached = this.invalidationsCache.get(key); if (cached != null) { return cached; } let res = { invalidateOnFileCreate: [], invalidateOnFileChange: new Set() }; let seen = new Set(); let addKey = (name, from) => { let basedir = _path().default.dirname(from); let key = basedir + ':' + name; if (seen.has(key)) { return; } seen.add(key); let resolved = cache.get(key); if (!resolved || !_path().default.isAbsolute(resolved.resolved)) { return; } res.invalidateOnFileCreate.push(...resolved.invalidateOnFileCreate); res.invalidateOnFileChange.add(resolved.resolved); for (let file of resolved.invalidateOnFileChange) { res.invalidateOnFileChange.add(file); } let moduleChildren = children.get(resolved.resolved); if (moduleChildren) { for (let specifier of moduleChildren) { addKey(specifier, resolved.resolved); } } }; addKey(name, from); this.invalidationsCache.set(key, res); return res; } invalidate(name, from) { let seen = new Set(); let invalidate = (name, from) => { let basedir = _path().default.dirname(from); let key = basedir + ':' + name; if (seen.has(key)) { return; } seen.add(key); let resolved = cache.get(key); if (!resolved || !_path().default.isAbsolute(resolved.resolved)) { return; } let module = require.cache[resolved.resolved]; if (module) { delete require.cache[resolved.resolved]; } let moduleChildren = children.get(resolved.resolved); if (moduleChildren) { for (let specifier of moduleChildren) { invalidate(specifier, resolved.resolved); } } children.delete(resolved.resolved); cache.delete(key); this.resolver.invalidate(resolved.resolved); this.syncResolver.invalidate(resolved.resolved); }; invalidate(name, from); } } exports.NodePackageManager = NodePackageManager; (0, _core().registerSerializableClass)(`${_package.default.version}:NodePackageManager`, NodePackageManager);