@putout/engine-loader 11.0.2 → 11.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/lib/index.js +3 -25
- package/lib/load-plugins-async.js +132 -0
- package/lib/merge-rules.js +26 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -59,6 +59,28 @@ const plugins = loadPlugins({
|
|
|
59
59
|
});
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
+
### loadPluginsAsync
|
|
63
|
+
|
|
64
|
+
Load **ESM** plugins:
|
|
65
|
+
|
|
66
|
+
```js
|
|
67
|
+
const {loadPluginsAsync} = require('@putout/engine-loader');
|
|
68
|
+
|
|
69
|
+
const pluginNames = [
|
|
70
|
+
'remove-unusede-variables',
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
const rules = {
|
|
74
|
+
'remove-unused-variables': 'on',
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const plugins = await loadPluginsAsync({
|
|
78
|
+
cache: true, //default
|
|
79
|
+
pluginNames,
|
|
80
|
+
rules,
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
62
84
|
### loadProcessorsAsync
|
|
63
85
|
|
|
64
86
|
```js
|
package/lib/index.js
CHANGED
|
@@ -10,38 +10,16 @@ const parseProcessorNames = require('./parse-processor-names');
|
|
|
10
10
|
const parseRules = require('./parse-rules');
|
|
11
11
|
const validateRules = require('./validate-rules');
|
|
12
12
|
const validatePlugin = require('./validate-plugin');
|
|
13
|
+
const {mergeRules} = require('./merge-rules');
|
|
14
|
+
const {loadPluginsAsync} = require('./load-plugins-async');
|
|
13
15
|
|
|
14
16
|
const isString = (a) => typeof a === 'string';
|
|
15
|
-
const defaultOptions = () => Object.create(null);
|
|
16
|
-
|
|
17
|
-
const mergeRules = ([rule, plugin], rules) => {
|
|
18
|
-
for (const currentRule of rules) {
|
|
19
|
-
if (currentRule.rule !== rule)
|
|
20
|
-
continue;
|
|
21
|
-
|
|
22
|
-
const {msg, options} = currentRule;
|
|
23
|
-
|
|
24
|
-
return {
|
|
25
|
-
rule,
|
|
26
|
-
plugin,
|
|
27
|
-
msg,
|
|
28
|
-
options,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return {
|
|
33
|
-
rule,
|
|
34
|
-
plugin,
|
|
35
|
-
msg: '',
|
|
36
|
-
options: defaultOptions(),
|
|
37
|
-
};
|
|
38
|
-
};
|
|
39
17
|
|
|
18
|
+
module.exports.loadPluginsAsync = loadPluginsAsync;
|
|
40
19
|
module.exports.loadProcessorsAsync = nanomemoize(async (options, load) => {
|
|
41
20
|
check(options);
|
|
42
21
|
|
|
43
22
|
const {processors = []} = options;
|
|
44
|
-
|
|
45
23
|
const parsedProcessors = parseProcessorNames(processors);
|
|
46
24
|
const loadProcessor = createAsyncLoader('processor');
|
|
47
25
|
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const isEnabled = require('./is-enabled');
|
|
4
|
+
const parseRules = require('./parse-rules');
|
|
5
|
+
const {nanomemoize} = require('nano-memoize');
|
|
6
|
+
const {createAsyncLoader} = require('./async-loader');
|
|
7
|
+
const parsePluginNames = require('./parse-plugin-names');
|
|
8
|
+
const validateRules = require('./validate-rules');
|
|
9
|
+
const validatePlugin = require('./validate-plugin');
|
|
10
|
+
const {mergeRules} = require('./merge-rules');
|
|
11
|
+
|
|
12
|
+
const isString = (a) => typeof a === 'string';
|
|
13
|
+
|
|
14
|
+
module.exports.loadPluginsAsync = nanomemoize(async (options) => {
|
|
15
|
+
check(options);
|
|
16
|
+
|
|
17
|
+
const {pluginNames = [], rules = {}} = options;
|
|
18
|
+
|
|
19
|
+
const cookedRules = parseRules(rules);
|
|
20
|
+
const loadedRules = getLoadedRules(cookedRules);
|
|
21
|
+
|
|
22
|
+
const items = parsePluginNames(pluginNames);
|
|
23
|
+
|
|
24
|
+
const plugins = await loadPlugins({
|
|
25
|
+
items,
|
|
26
|
+
loadedRules,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
validateRules({
|
|
30
|
+
rules,
|
|
31
|
+
items,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const result = [];
|
|
35
|
+
|
|
36
|
+
// Would be great to have ability to filter
|
|
37
|
+
// disabled plugins and prevent them from loading
|
|
38
|
+
// but we can't because of a way multi-rule plugins
|
|
39
|
+
// works. We can't determine count and names of all
|
|
40
|
+
// rules of a plugin before load.
|
|
41
|
+
for (const [name, plugin] of plugins) {
|
|
42
|
+
if (!isEnabled(name, cookedRules))
|
|
43
|
+
continue;
|
|
44
|
+
|
|
45
|
+
result.push(mergeRules(
|
|
46
|
+
[name, plugin],
|
|
47
|
+
cookedRules,
|
|
48
|
+
));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return result;
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
function splitRule(rule) {
|
|
55
|
+
return [rule, 'putout'];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
async function loadPlugins({items, loadedRules}) {
|
|
59
|
+
const loadPlugin = createAsyncLoader('plugin');
|
|
60
|
+
const promises = [];
|
|
61
|
+
|
|
62
|
+
for (const [rule, itemPlugin] of items) {
|
|
63
|
+
if (!isEnabled(rule, loadedRules))
|
|
64
|
+
continue;
|
|
65
|
+
|
|
66
|
+
checkRule(rule);
|
|
67
|
+
|
|
68
|
+
const [name] = splitRule(rule);
|
|
69
|
+
const plugin = itemPlugin || loadPlugin(name);
|
|
70
|
+
|
|
71
|
+
promises.push(plugin);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const resolvedPlugins = await Promise.all(promises);
|
|
75
|
+
const plugins = [];
|
|
76
|
+
|
|
77
|
+
for (const [i, [rule]] of items.entries()) {
|
|
78
|
+
const plugin = resolvedPlugins[i];
|
|
79
|
+
|
|
80
|
+
validatePlugin({
|
|
81
|
+
plugin,
|
|
82
|
+
rule,
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const {rules} = plugin;
|
|
86
|
+
|
|
87
|
+
if (rules) {
|
|
88
|
+
plugins.push(...extendRules(rule, rules));
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
plugins.push([rule, plugin]);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return plugins;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function getLoadedRules(rules) {
|
|
99
|
+
const loadedRules = [];
|
|
100
|
+
|
|
101
|
+
for (const item of rules) {
|
|
102
|
+
const {rule} = item;
|
|
103
|
+
|
|
104
|
+
if (rule.includes('/'))
|
|
105
|
+
continue;
|
|
106
|
+
|
|
107
|
+
loadedRules.push(item);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return loadedRules;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function extendRules(rule, plugin) {
|
|
114
|
+
const result = [];
|
|
115
|
+
const entries = Object.entries(plugin);
|
|
116
|
+
|
|
117
|
+
for (const [name, plugin] of entries) {
|
|
118
|
+
result.push([`${rule}/${name}`, plugin]);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return result;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function check(options) {
|
|
125
|
+
if (!options || typeof options !== 'object')
|
|
126
|
+
throw Error('options should be an object!');
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function checkRule(rule) {
|
|
130
|
+
if (!isString(rule))
|
|
131
|
+
throw Error(`☝️ Looks like plugin name type is not 'string', but: '${typeof rule}'`);
|
|
132
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const defaultOptions = () => Object.create(null);
|
|
4
|
+
|
|
5
|
+
module.exports.mergeRules = ([rule, plugin], rules) => {
|
|
6
|
+
for (const currentRule of rules) {
|
|
7
|
+
if (currentRule.rule !== rule)
|
|
8
|
+
continue;
|
|
9
|
+
|
|
10
|
+
const {msg, options} = currentRule;
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
rule,
|
|
14
|
+
plugin,
|
|
15
|
+
msg,
|
|
16
|
+
options,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
rule,
|
|
22
|
+
plugin,
|
|
23
|
+
msg: '',
|
|
24
|
+
options: defaultOptions(),
|
|
25
|
+
};
|
|
26
|
+
};
|
package/package.json
CHANGED