"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.createCachedDescriptors = createCachedDescriptors; exports.createUncachedDescriptors = createUncachedDescriptors; exports.createDescriptor = createDescriptor; var _files = require("./files"); var _item = require("./item"); var _caching = require("./caching"); function isEqualDescriptor(a, b) { return a.name === b.name && a.value === b.value && a.options === b.options && a.dirname === b.dirname && a.alias === b.alias && a.ownPass === b.ownPass && (a.file && a.file.request) === (b.file && b.file.request) && (a.file && a.file.resolved) === (b.file && b.file.resolved); } function createCachedDescriptors(dirname, options, alias) { const { plugins, presets, passPerPreset } = options; return { options, plugins: plugins ? () => createCachedPluginDescriptors(plugins, dirname)(alias) : () => [], presets: presets ? () => createCachedPresetDescriptors(presets, dirname)(alias)(!!passPerPreset) : () => [] }; } function createUncachedDescriptors(dirname, options, alias) { let plugins; let presets; return { options, plugins: () => { if (!plugins) { plugins = createPluginDescriptors(options.plugins || [], dirname, alias); } return plugins; }, presets: () => { if (!presets) { presets = createPresetDescriptors(options.presets || [], dirname, alias, !!options.passPerPreset); } return presets; } }; } const PRESET_DESCRIPTOR_CACHE = new WeakMap(); const createCachedPresetDescriptors = (0, _caching.makeWeakCacheSync)((items, cache) => { const dirname = cache.using(dir => dir); return (0, _caching.makeStrongCacheSync)(alias => (0, _caching.makeStrongCacheSync)(passPerPreset => createPresetDescriptors(items, dirname, alias, passPerPreset).map(desc => loadCachedDescriptor(PRESET_DESCRIPTOR_CACHE, desc)))); }); const PLUGIN_DESCRIPTOR_CACHE = new WeakMap(); const createCachedPluginDescriptors = (0, _caching.makeWeakCacheSync)((items, cache) => { const dirname = cache.using(dir => dir); return (0, _caching.makeStrongCacheSync)(alias => createPluginDescriptors(items, dirname, alias).map(desc => loadCachedDescriptor(PLUGIN_DESCRIPTOR_CACHE, desc))); }); const DEFAULT_OPTIONS = {}; function loadCachedDescriptor(cache, desc) { const { value, options = DEFAULT_OPTIONS } = desc; if (options === false) return desc; let cacheByOptions = cache.get(value); if (!cacheByOptions) { cacheByOptions = new WeakMap(); cache.set(value, cacheByOptions); } let possibilities = cacheByOptions.get(options); if (!possibilities) { possibilities = []; cacheByOptions.set(options, possibilities); } if (possibilities.indexOf(desc) === -1) { const matches = possibilities.filter(possibility => isEqualDescriptor(possibility, desc)); if (matches.length > 0) { return matches[0]; } possibilities.push(desc); } return desc; } function createPresetDescriptors(items, dirname, alias, passPerPreset) { return createDescriptors("preset", items, dirname, alias, passPerPreset); } function createPluginDescriptors(items, dirname, alias) { return createDescriptors("plugin", items, dirname, alias); } function createDescriptors(type, items, dirname, alias, ownPass) { const descriptors = items.map((item, index) => createDescriptor(item, dirname, { type, alias: `${alias}$${index}`, ownPass: !!ownPass })); assertNoDuplicates(descriptors); return descriptors; } function createDescriptor(pair, dirname, { type, alias, ownPass }) { const desc = (0, _item.getItemDescriptor)(pair); if (desc) { return desc; } let name; let options; let value = pair; if (Array.isArray(value)) { if (value.length === 3) { [value, options, name] = value; } else { [value, options] = value; } } let file = undefined; let filepath = null; if (typeof value === "string") { if (typeof type !== "string") { throw new Error("To resolve a string-based item, the type of item must be given"); } const resolver = type === "plugin" ? _files.loadPlugin : _files.loadPreset; const request = value; ({ filepath, value } = resolver(value, dirname)); file = { request, resolved: filepath }; } if (!value) { throw new Error(`Unexpected falsy value: ${String(value)}`); } if (typeof value === "object" && value.__esModule) { if (value.default) { value = value.default; } else { throw new Error("Must export a default export when using ES6 modules."); } } if (typeof value !== "object" && typeof value !== "function") { throw new Error(`Unsupported format: ${typeof value}. Expected an object or a function.`); } if (filepath !== null && typeof value === "object" && value) { throw new Error(`Plugin/Preset files are not allowed to export objects, only functions. In ${filepath}`); } return { name, alias: filepath || alias, value, options, dirname, ownPass, file }; } function assertNoDuplicates(items) { const map = new Map(); for (const item of items) { if (typeof item.value !== "function") continue; let nameMap = map.get(item.value); if (!nameMap) { nameMap = new Set(); map.set(item.value, nameMap); } if (nameMap.has(item.name)) { const conflicts = items.filter(i => i.value === item.value); throw new Error([`Duplicate plugin/preset detected.`, `If you'd like to use two separate instances of a plugin,`, `they need separate names, e.g.`, ``, ` plugins: [`, ` ['some-plugin', {}],`, ` ['some-plugin', {}, 'some unique name'],`, ` ]`, ``, `Duplicates detected are:`, `${JSON.stringify(conflicts, null, 2)}`].join("\n")); } nameMap.add(item.name); } }