UNPKG

5.91 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.createCachedDescriptors = createCachedDescriptors;
7exports.createUncachedDescriptors = createUncachedDescriptors;
8exports.createDescriptor = createDescriptor;
9
10var _files = require("./files");
11
12var _item = require("./item");
13
14var _caching = require("./caching");
15
16function isEqualDescriptor(a, b) {
17 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);
18}
19
20function createCachedDescriptors(dirname, options, alias) {
21 const {
22 plugins,
23 presets,
24 passPerPreset
25 } = options;
26 return {
27 options,
28 plugins: plugins ? () => createCachedPluginDescriptors(plugins, dirname)(alias) : () => [],
29 presets: presets ? () => createCachedPresetDescriptors(presets, dirname)(alias)(!!passPerPreset) : () => []
30 };
31}
32
33function createUncachedDescriptors(dirname, options, alias) {
34 let plugins;
35 let presets;
36 return {
37 options,
38 plugins: () => {
39 if (!plugins) {
40 plugins = createPluginDescriptors(options.plugins || [], dirname, alias);
41 }
42
43 return plugins;
44 },
45 presets: () => {
46 if (!presets) {
47 presets = createPresetDescriptors(options.presets || [], dirname, alias, !!options.passPerPreset);
48 }
49
50 return presets;
51 }
52 };
53}
54
55const PRESET_DESCRIPTOR_CACHE = new WeakMap();
56const createCachedPresetDescriptors = (0, _caching.makeWeakCacheSync)((items, cache) => {
57 const dirname = cache.using(dir => dir);
58 return (0, _caching.makeStrongCacheSync)(alias => (0, _caching.makeStrongCacheSync)(passPerPreset => createPresetDescriptors(items, dirname, alias, passPerPreset).map(desc => loadCachedDescriptor(PRESET_DESCRIPTOR_CACHE, desc))));
59});
60const PLUGIN_DESCRIPTOR_CACHE = new WeakMap();
61const createCachedPluginDescriptors = (0, _caching.makeWeakCacheSync)((items, cache) => {
62 const dirname = cache.using(dir => dir);
63 return (0, _caching.makeStrongCacheSync)(alias => createPluginDescriptors(items, dirname, alias).map(desc => loadCachedDescriptor(PLUGIN_DESCRIPTOR_CACHE, desc)));
64});
65const DEFAULT_OPTIONS = {};
66
67function loadCachedDescriptor(cache, desc) {
68 const {
69 value,
70 options = DEFAULT_OPTIONS
71 } = desc;
72 if (options === false) return desc;
73 let cacheByOptions = cache.get(value);
74
75 if (!cacheByOptions) {
76 cacheByOptions = new WeakMap();
77 cache.set(value, cacheByOptions);
78 }
79
80 let possibilities = cacheByOptions.get(options);
81
82 if (!possibilities) {
83 possibilities = [];
84 cacheByOptions.set(options, possibilities);
85 }
86
87 if (possibilities.indexOf(desc) === -1) {
88 const matches = possibilities.filter(possibility => isEqualDescriptor(possibility, desc));
89
90 if (matches.length > 0) {
91 return matches[0];
92 }
93
94 possibilities.push(desc);
95 }
96
97 return desc;
98}
99
100function createPresetDescriptors(items, dirname, alias, passPerPreset) {
101 return createDescriptors("preset", items, dirname, alias, passPerPreset);
102}
103
104function createPluginDescriptors(items, dirname, alias) {
105 return createDescriptors("plugin", items, dirname, alias);
106}
107
108function createDescriptors(type, items, dirname, alias, ownPass) {
109 const descriptors = items.map((item, index) => createDescriptor(item, dirname, {
110 type,
111 alias: `${alias}$${index}`,
112 ownPass: !!ownPass
113 }));
114 assertNoDuplicates(descriptors);
115 return descriptors;
116}
117
118function createDescriptor(pair, dirname, {
119 type,
120 alias,
121 ownPass
122}) {
123 const desc = (0, _item.getItemDescriptor)(pair);
124
125 if (desc) {
126 return desc;
127 }
128
129 let name;
130 let options;
131 let value = pair;
132
133 if (Array.isArray(value)) {
134 if (value.length === 3) {
135 [value, options, name] = value;
136 } else {
137 [value, options] = value;
138 }
139 }
140
141 let file = undefined;
142 let filepath = null;
143
144 if (typeof value === "string") {
145 if (typeof type !== "string") {
146 throw new Error("To resolve a string-based item, the type of item must be given");
147 }
148
149 const resolver = type === "plugin" ? _files.loadPlugin : _files.loadPreset;
150 const request = value;
151 ({
152 filepath,
153 value
154 } = resolver(value, dirname));
155 file = {
156 request,
157 resolved: filepath
158 };
159 }
160
161 if (!value) {
162 throw new Error(`Unexpected falsy value: ${String(value)}`);
163 }
164
165 if (typeof value === "object" && value.__esModule) {
166 if (value.default) {
167 value = value.default;
168 } else {
169 throw new Error("Must export a default export when using ES6 modules.");
170 }
171 }
172
173 if (typeof value !== "object" && typeof value !== "function") {
174 throw new Error(`Unsupported format: ${typeof value}. Expected an object or a function.`);
175 }
176
177 if (filepath !== null && typeof value === "object" && value) {
178 throw new Error(`Plugin/Preset files are not allowed to export objects, only functions. In ${filepath}`);
179 }
180
181 return {
182 name,
183 alias: filepath || alias,
184 value,
185 options,
186 dirname,
187 ownPass,
188 file
189 };
190}
191
192function assertNoDuplicates(items) {
193 const map = new Map();
194
195 for (const item of items) {
196 if (typeof item.value !== "function") continue;
197 let nameMap = map.get(item.value);
198
199 if (!nameMap) {
200 nameMap = new Set();
201 map.set(item.value, nameMap);
202 }
203
204 if (nameMap.has(item.name)) {
205 const conflicts = items.filter(i => i.value === item.value);
206 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"));
207 }
208
209 nameMap.add(item.name);
210 }
211}
\No newline at end of file