UNPKG

@parcel/core

Version:
195 lines (191 loc) • 8.54 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = loadPlugin; 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; } function _logger() { const data = _interopRequireDefault(require("@parcel/logger")); _logger = function () { return data; }; return data; } function _nullthrows() { const data = _interopRequireDefault(require("nullthrows")); _nullthrows = function () { return data; }; return data; } function _diagnostic() { const data = _interopRequireWildcard(require("@parcel/diagnostic")); _diagnostic = function () { return data; }; return data; } function _utils() { const data = require("@parcel/utils"); _utils = function () { return data; }; return data; } var _projectPath = require("./projectPath"); var _package = require("../package.json"); function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; } const NODE_MODULES = `${_path().default.sep}node_modules${_path().default.sep}`; const CONFIG = Symbol.for('parcel-plugin-config'); async function loadPlugin(pluginName, configPath, keyPath, options) { let resolveFrom = configPath; let range; let isOptional = false; if (resolveFrom.includes(NODE_MODULES) || "production" !== 'production' && /packages[/\\]configs/.test(resolveFrom)) { var _configPkg$config$dep; // Config packages can reference plugins, but cannot contain other plugins within them. // This forces every published plugin to be published separately so they can be mixed and matched if needed. if (pluginName.startsWith('.')) { let configContents = await options.inputFS.readFile(configPath, 'utf8'); throw new (_diagnostic().default)({ diagnostic: { message: (0, _diagnostic().md)`Local plugins are not supported in Parcel config packages. Please publish "${pluginName}" as a separate npm package.`, origin: '@parcel/core', codeFrames: keyPath ? [{ filePath: configPath, language: 'json5', code: configContents, codeHighlights: (0, _diagnostic().generateJSONCodeHighlights)(configContents, [{ key: keyPath, type: 'value' }]) }] : undefined } }); } let configPkg = await (0, _utils().loadConfig)(options.inputFS, resolveFrom, ['package.json'], options.projectRoot); if (configPkg != null && ((_configPkg$config$dep = configPkg.config.dependencies) === null || _configPkg$config$dep === void 0 ? void 0 : _configPkg$config$dep[pluginName]) == null) { var _configPkg$config$par; // If not in the config's dependencies, the plugin will be auto installed with // the version declared in "parcelDependencies". range = (_configPkg$config$par = configPkg.config.parcelDependencies) === null || _configPkg$config$par === void 0 ? void 0 : _configPkg$config$par[pluginName]; isOptional = Array.isArray(configPkg.config.optionalParcelDependencies) && configPkg.config.optionalParcelDependencies.includes(pluginName); if (range == null && !isOptional) { let contents = await options.inputFS.readFile(configPkg.files[0].filePath, 'utf8'); throw new (_diagnostic().default)({ diagnostic: { message: (0, _diagnostic().md)`Could not determine version of ${pluginName} in ${_path().default.relative(process.cwd(), resolveFrom)}. Either include it in "dependencies" or "parcelDependencies".`, origin: '@parcel/core', codeFrames: configPkg.config.dependencies || configPkg.config.parcelDependencies ? [{ filePath: configPkg.files[0].filePath, language: 'json5', code: contents, codeHighlights: (0, _diagnostic().generateJSONCodeHighlights)(contents, [{ key: configPkg.config.parcelDependencies ? '/parcelDependencies' : '/dependencies', type: 'key' }]) }] : undefined } }); } // Resolve from project root if not in the config's dependencies. resolveFrom = _path().default.join(options.projectRoot, 'index'); } } let resolved, pkg; try { ({ resolved, pkg } = await options.packageManager.resolve(pluginName, resolveFrom, { shouldAutoInstall: options.shouldAutoInstall && !isOptional, range })); } catch (err) { if (err.code !== 'MODULE_NOT_FOUND') { throw err; } if (isOptional) { return null; } let configContents = await options.inputFS.readFile(configPath, 'utf8'); let alternatives = await (0, _utils().findAlternativeNodeModules)(options.inputFS, pluginName, _path().default.dirname(resolveFrom)); throw new (_diagnostic().default)({ diagnostic: { message: (0, _diagnostic().md)`Cannot find Parcel plugin "${pluginName}"`, origin: '@parcel/core', codeFrames: keyPath ? [{ filePath: configPath, language: 'json5', code: configContents, codeHighlights: (0, _diagnostic().generateJSONCodeHighlights)(configContents, [{ key: keyPath, type: 'value', message: (0, _diagnostic().md)`Cannot find module "${pluginName}"${alternatives[0] ? `, did you mean "${alternatives[0]}"?` : ''}` }]) }] : undefined } }); } // Remove plugin version compatiblility validation in canary builds as they don't use semver if (!pluginName.startsWith('.')) { // Validate the engines.parcel field in the plugin's package.json let parcelVersionRange = pkg && pkg.engines && pkg.engines.parcel; if (!parcelVersionRange) { _logger().default.warn({ origin: '@parcel/core', message: `The plugin "${pluginName}" needs to specify a \`package.json#engines.parcel\` field with the supported Parcel version range.` }); } if (parcelVersionRange && !_semver().default.satisfies(_package.version, parcelVersionRange)) { let pkgFile = (0, _nullthrows().default)(await (0, _utils().resolveConfig)(options.inputFS, resolved, ['package.json'], options.projectRoot)); let pkgContents = await options.inputFS.readFile(pkgFile, 'utf8'); throw new (_diagnostic().default)({ diagnostic: { message: (0, _diagnostic().md)`The plugin "${pluginName}" is not compatible with the current version of Parcel. Requires "${parcelVersionRange}" but the current version is "${_package.version}".`, origin: '@parcel/core', codeFrames: [{ filePath: pkgFile, language: 'json5', code: pkgContents, codeHighlights: (0, _diagnostic().generateJSONCodeHighlights)(pkgContents, [{ key: '/engines/parcel' }]) }] } }); } } let plugin = await options.packageManager.require(pluginName, resolveFrom, { shouldAutoInstall: options.shouldAutoInstall }); plugin = plugin.default ? plugin.default : plugin; if (!plugin) { throw new Error(`Plugin ${pluginName} has no exports.`); } plugin = plugin[CONFIG]; if (!plugin) { throw new Error(`Plugin ${pluginName} is not a valid Parcel plugin, should export an instance of a Parcel plugin ex. "export default new Reporter({ ... })".`); } return { plugin, version: (0, _nullthrows().default)(pkg).version, resolveFrom: (0, _projectPath.toProjectPath)(options.projectRoot, resolveFrom), range }; }