redlint 3.1.2 β 3.2.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/ChangeLog +6 -0
- package/README.md +3 -3
- package/bin/redlint.js +121 -103
- package/lib/choose.js +2 -1
- package/lib/debug.js +14 -0
- package/lib/help.js +3 -1
- package/lib/pack/master.js +136 -0
- package/lib/pack/pack.js +39 -0
- package/lib/pack/slave.js +25 -0
- package/lib/slave.js +1 -1
- package/package.json +2 -1
package/ChangeLog
CHANGED
package/README.md
CHANGED
|
@@ -13,13 +13,13 @@
|
|
|
13
13
|
>
|
|
14
14
|
> **(c) The Book of Kon, PoKon and ZaKon**
|
|
15
15
|
|
|
16
|
-

|
|
17
17
|
|
|
18
18
|
What if **Filesystem** was a simple **JSON** file [`.filesystem.json`](https://github.com/putoutjs/redlint/blob/master/.filesystem.json). What if you can transform **JSON** file with π[**Putout**](https://github.com/coderaiser/putout) code transformer and this changes modify **Filesystem**?
|
|
19
19
|
|
|
20
20
|
What if I tell you it is possible? π± Checkout in π[**Putout Editor**](https://putout.cloudcmd.io/#/gist/0614c2da35a1864b59ac284f18656328/695a9960c401d4e8f6744f58eac591d8f9185235).
|
|
21
21
|
|
|
22
|
-
First time ever! Linter for
|
|
22
|
+
First time ever! Linter for your **Filesystem** ππΎ.
|
|
23
23
|
|
|
24
24
|
## Install
|
|
25
25
|
|
|
@@ -31,7 +31,7 @@ npm i redlint -g
|
|
|
31
31
|
|
|
32
32
|
You can choose interactively when run `redlint`:
|
|
33
33
|
|
|
34
|
-

|
|
35
35
|
|
|
36
36
|
## Scan
|
|
37
37
|
|
package/bin/redlint.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import {join} from 'node:path';
|
|
4
4
|
import process from 'node:process';
|
|
5
5
|
import {
|
|
6
6
|
readFile,
|
|
7
7
|
writeFile,
|
|
8
8
|
} from 'node:fs/promises';
|
|
9
|
+
import {lintJSON} from 'putout/lint/json';
|
|
9
10
|
import stripAnsi from 'strip-ansi';
|
|
10
11
|
import formatterCodeFrame from '@putout/formatter-codeframe';
|
|
11
12
|
import formatterDump from '@putout/formatter-dump';
|
|
@@ -15,127 +16,144 @@ import {choose} from '../lib/choose.js';
|
|
|
15
16
|
import {buildTree} from '../lib/redlint.js';
|
|
16
17
|
import {convertToSimple} from '../lib/simple.js';
|
|
17
18
|
import {masterLint} from '../lib/master.js';
|
|
19
|
+
import {masterPack} from '../lib/pack/master.js';
|
|
18
20
|
import {lint} from '../lib/lint.js';
|
|
19
|
-
import {
|
|
21
|
+
import {pack} from '../lib/pack/pack.js';
|
|
22
|
+
import {debug} from '../lib/debug.js';
|
|
20
23
|
|
|
21
24
|
const {stringify, parse} = JSON;
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
const [arg] = process.argv.slice(2);
|
|
24
27
|
let header = true;
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
await uiLoop(arg);
|
|
30
|
+
|
|
31
|
+
async function uiLoop(arg) {
|
|
32
|
+
if (!arg) {
|
|
33
|
+
const cmd = await choose();
|
|
34
|
+
|
|
35
|
+
if (!cmd)
|
|
36
|
+
process.exit(1);
|
|
37
|
+
|
|
38
|
+
[arg] = stripAnsi(cmd).split(' ');
|
|
39
|
+
header = false;
|
|
40
|
+
}
|
|
28
41
|
|
|
29
|
-
if (
|
|
30
|
-
|
|
42
|
+
if (arg === 'debug') {
|
|
43
|
+
arg = await debug();
|
|
44
|
+
|
|
45
|
+
if (arg === 'back')
|
|
46
|
+
return await uiLoop();
|
|
47
|
+
}
|
|
31
48
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
if (arg === 'exit')
|
|
37
|
-
process.exit();
|
|
38
|
-
|
|
39
|
-
if (arg === 'version') {
|
|
40
|
-
const packagePath = new URL('../package.json', import.meta.url);
|
|
41
|
-
const packageData = await readFile(packagePath);
|
|
42
|
-
const {version} = parse(packageData);
|
|
49
|
+
if (arg === 'exit')
|
|
50
|
+
process.exit();
|
|
43
51
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
process.exit();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
console.log('Running:');
|
|
56
|
-
const spinner = ora('index filesystem').start();
|
|
57
|
-
const result = await buildTree(process.cwd());
|
|
58
|
-
|
|
59
|
-
spinner.succeed();
|
|
60
|
-
|
|
61
|
-
if (arg === 'generate:simple') {
|
|
62
|
-
await writeFile('.filesystem.json', lintJSON(stringify(convertToSimple(result))));
|
|
63
|
-
process.exit(0);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const filesystem = lintJSON(stringify(result));
|
|
67
|
-
|
|
68
|
-
if (arg === 'scan') {
|
|
69
|
-
const places = await masterLint(filesystem, {
|
|
70
|
-
fix: false,
|
|
71
|
-
});
|
|
52
|
+
if (arg === 'version') {
|
|
53
|
+
const packagePath = new URL('../package.json', import.meta.url);
|
|
54
|
+
const packageData = await readFile(packagePath);
|
|
55
|
+
const {version} = parse(packageData);
|
|
56
|
+
|
|
57
|
+
console.log(`v${version}`);
|
|
58
|
+
process.exit();
|
|
59
|
+
}
|
|
72
60
|
|
|
73
|
-
if (
|
|
61
|
+
if (arg === 'help') {
|
|
62
|
+
help({
|
|
63
|
+
header,
|
|
64
|
+
});
|
|
74
65
|
process.exit();
|
|
66
|
+
}
|
|
75
67
|
|
|
76
|
-
console.log('');
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
places,
|
|
81
|
-
index: 0,
|
|
82
|
-
count: places.length,
|
|
83
|
-
filesCount: 1,
|
|
84
|
-
errorsCount: places.length,
|
|
85
|
-
});
|
|
68
|
+
console.log('Running:');
|
|
69
|
+
const spinner = ora('index filesystem').start();
|
|
70
|
+
const CWD = process.cwd();
|
|
71
|
+
const result = await buildTree(CWD);
|
|
86
72
|
|
|
87
|
-
|
|
73
|
+
spinner.succeed();
|
|
88
74
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const places = await masterLint(filesystem, {
|
|
94
|
-
fix: true,
|
|
95
|
-
});
|
|
75
|
+
if (arg === 'generate:simple') {
|
|
76
|
+
await writeFile('.filesystem.json', lintJSON(stringify(convertToSimple(result))));
|
|
77
|
+
process.exit(0);
|
|
78
|
+
}
|
|
96
79
|
|
|
97
|
-
const
|
|
98
|
-
name: '.filesystem.json',
|
|
99
|
-
source: filesystem,
|
|
100
|
-
places,
|
|
101
|
-
index: 0,
|
|
102
|
-
count: places.length,
|
|
103
|
-
filesCount: 1,
|
|
104
|
-
errorsCount: places.length,
|
|
105
|
-
});
|
|
80
|
+
const filesystem = lintJSON(stringify(result));
|
|
106
81
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
82
|
+
if (arg === 'scan') {
|
|
83
|
+
const places = await masterLint(filesystem, {
|
|
84
|
+
fix: false,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (!places.length)
|
|
88
|
+
process.exit();
|
|
89
|
+
|
|
90
|
+
console.log('');
|
|
91
|
+
const dump = await formatterDump({
|
|
92
|
+
name: '.filesystem.json',
|
|
93
|
+
source: filesystem,
|
|
94
|
+
places,
|
|
95
|
+
index: 0,
|
|
96
|
+
count: places.length,
|
|
97
|
+
filesCount: 1,
|
|
98
|
+
errorsCount: places.length,
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
process.stderr.write(dump);
|
|
102
|
+
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
115
105
|
|
|
116
|
-
|
|
106
|
+
if (arg === 'pack') {
|
|
107
|
+
const result = await masterPack(CWD, filesystem);
|
|
108
|
+
await writeFile(join(CWD, 'filesystem.red'), result);
|
|
109
|
+
const spinner = ora(`pack 'filesystem.red'`).start();
|
|
110
|
+
|
|
111
|
+
spinner.succeed();
|
|
112
|
+
process.exit();
|
|
113
|
+
}
|
|
117
114
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
errorsCount: places.length,
|
|
126
|
-
});
|
|
115
|
+
if (arg === 'pack:debug') {
|
|
116
|
+
const result = pack(CWD, filesystem);
|
|
117
|
+
await writeFile(join(CWD, 'filesystem.red'), result);
|
|
118
|
+
|
|
119
|
+
done(`pack 'filesystem.red'`);
|
|
120
|
+
process.exit();
|
|
121
|
+
}
|
|
127
122
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
123
|
+
if (arg === 'scan:debug') {
|
|
124
|
+
const places = lint(filesystem, {
|
|
125
|
+
fix: true,
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const result = await formatterCodeFrame({
|
|
129
|
+
name: '.filesystem.json',
|
|
130
|
+
source: filesystem,
|
|
131
|
+
places,
|
|
132
|
+
index: 0,
|
|
133
|
+
count: places.length,
|
|
134
|
+
filesCount: 1,
|
|
135
|
+
errorsCount: places.length,
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
process.stderr.write(result);
|
|
139
|
+
process.exit(1);
|
|
140
|
+
}
|
|
136
141
|
|
|
137
|
-
|
|
142
|
+
if (arg === 'fix') {
|
|
143
|
+
await masterLint(filesystem, {
|
|
144
|
+
fix: true,
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
process.exit();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (arg === 'generate')
|
|
151
|
+
await writeFile('.filesystem.json', filesystem);
|
|
152
|
+
|
|
153
|
+
done(`generate '.filesystem.json'`);
|
|
138
154
|
}
|
|
139
155
|
|
|
140
|
-
|
|
141
|
-
|
|
156
|
+
function done(message) {
|
|
157
|
+
const spinner = ora(message).start();
|
|
158
|
+
spinner.succeed();
|
|
159
|
+
}
|
package/lib/choose.js
CHANGED
package/lib/debug.js
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import {choose as chooseDialog} from '@putout/cli-choose';
|
|
2
|
+
|
|
3
|
+
export const debug = async () => {
|
|
4
|
+
const command = await chooseDialog('Debug:', [
|
|
5
|
+
'scan:debug',
|
|
6
|
+
'pack:debug',
|
|
7
|
+
'back',
|
|
8
|
+
'exit',
|
|
9
|
+
]);
|
|
10
|
+
|
|
11
|
+
console.log('');
|
|
12
|
+
|
|
13
|
+
return command;
|
|
14
|
+
};
|
package/lib/help.js
CHANGED
|
@@ -12,10 +12,12 @@ export const help = ({header = true}) => {
|
|
|
12
12
|
|
|
13
13
|
console.log(`Commands:
|
|
14
14
|
scan - scan files according to πPutout rules
|
|
15
|
-
scan:frame - scan files, show results in code frame
|
|
16
15
|
fix - fix files according to πPutout rules
|
|
16
|
+
pack - pack 'filesystem.red' with directory contents
|
|
17
17
|
help - show help screen and exit
|
|
18
18
|
generate - generate .filesystem.json file and exit
|
|
19
19
|
generate:simple - generate simple .filesystem.json file and exit
|
|
20
|
+
version - show version and exit
|
|
21
|
+
debug = run commands without workers
|
|
20
22
|
`);
|
|
21
23
|
};
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import {Worker} from 'node:worker_threads';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import fullstore from 'fullstore';
|
|
5
|
+
|
|
6
|
+
export function masterPack(cwd, filesystem, {
|
|
7
|
+
start = setStart,
|
|
8
|
+
end = setEnd,
|
|
9
|
+
push = setPush,
|
|
10
|
+
fail = setFail,
|
|
11
|
+
success = setSuccess,
|
|
12
|
+
} = {}) {
|
|
13
|
+
return run(cwd, filesystem, {
|
|
14
|
+
start,
|
|
15
|
+
end,
|
|
16
|
+
push,
|
|
17
|
+
fail,
|
|
18
|
+
success,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function setStart(rule, store) {
|
|
23
|
+
const spinner = ora(rule).start();
|
|
24
|
+
|
|
25
|
+
spinner.suffixText = '';
|
|
26
|
+
|
|
27
|
+
store({
|
|
28
|
+
rule,
|
|
29
|
+
count: 0,
|
|
30
|
+
spinner,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function setPush(store) {
|
|
35
|
+
const {
|
|
36
|
+
rule,
|
|
37
|
+
count,
|
|
38
|
+
spinner,
|
|
39
|
+
} = store();
|
|
40
|
+
|
|
41
|
+
store({
|
|
42
|
+
rule,
|
|
43
|
+
count: count + 1,
|
|
44
|
+
spinner,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function setFail(store) {
|
|
49
|
+
const {
|
|
50
|
+
rule,
|
|
51
|
+
count,
|
|
52
|
+
spinner,
|
|
53
|
+
} = store();
|
|
54
|
+
|
|
55
|
+
spinner.suffixText = chalk.red(count);
|
|
56
|
+
spinner.fail();
|
|
57
|
+
|
|
58
|
+
store({
|
|
59
|
+
rule,
|
|
60
|
+
count,
|
|
61
|
+
spinner,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function setSuccess(store) {
|
|
66
|
+
const {spinner} = store();
|
|
67
|
+
|
|
68
|
+
spinner.succeed();
|
|
69
|
+
spinner.suffixText = '';
|
|
70
|
+
|
|
71
|
+
store({
|
|
72
|
+
...store(),
|
|
73
|
+
spinner: null,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function setEnd(data, resolve) {
|
|
78
|
+
resolve(data);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function run(cwd, filesystem, {start, end, fail, success}) {
|
|
82
|
+
return new Promise((resolve, reject) => {
|
|
83
|
+
const worker = new Worker(new URL('./slave.js', import.meta.url), {
|
|
84
|
+
workerData: {
|
|
85
|
+
cwd,
|
|
86
|
+
filesystem,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const store = fullstore({});
|
|
91
|
+
|
|
92
|
+
worker.on('message', ([event, data]) => {
|
|
93
|
+
if (event === 'end') {
|
|
94
|
+
end(data, resolve);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (event === 'rule:start') {
|
|
99
|
+
start(data, store);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const {
|
|
104
|
+
rule,
|
|
105
|
+
count,
|
|
106
|
+
spinner,
|
|
107
|
+
} = store();
|
|
108
|
+
|
|
109
|
+
if (!spinner)
|
|
110
|
+
return;
|
|
111
|
+
|
|
112
|
+
store({
|
|
113
|
+
rule,
|
|
114
|
+
count,
|
|
115
|
+
spinner,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
const endFail = count && event === 'rule:end';
|
|
119
|
+
const endSuccess = !count && event === 'rule:end';
|
|
120
|
+
|
|
121
|
+
if (endFail) {
|
|
122
|
+
fail(store);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (endSuccess) {
|
|
127
|
+
success(store);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
worker.on('error', reject);
|
|
132
|
+
worker.on('exit', (code) => {
|
|
133
|
+
reject(Error(`Worker stopped with exit code ${code}`));
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
package/lib/pack/pack.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parse,
|
|
3
|
+
transform,
|
|
4
|
+
print,
|
|
5
|
+
} from 'putout';
|
|
6
|
+
import {createProgress} from '@putout/engine-runner/progress';
|
|
7
|
+
import * as pluginFilesystem from '@putout/plugin-filesystem';
|
|
8
|
+
import {
|
|
9
|
+
branch,
|
|
10
|
+
merge,
|
|
11
|
+
} from '@putout/processor-filesystem';
|
|
12
|
+
|
|
13
|
+
const [, readAllFiles] = pluginFilesystem.rules['read-all-files'];
|
|
14
|
+
const [, replaceCwd] = pluginFilesystem.rules['replace-cwd'];
|
|
15
|
+
|
|
16
|
+
export const pack = (from, filesystem, {progress = createProgress()} = {}) => {
|
|
17
|
+
const [{source}] = branch(filesystem);
|
|
18
|
+
const ast = parse(source);
|
|
19
|
+
|
|
20
|
+
transform(ast, filesystem, {
|
|
21
|
+
fix: true,
|
|
22
|
+
fixCount: 1,
|
|
23
|
+
progress,
|
|
24
|
+
rules: {
|
|
25
|
+
'replace-cwd': ['on', {
|
|
26
|
+
from,
|
|
27
|
+
to: '/',
|
|
28
|
+
}],
|
|
29
|
+
},
|
|
30
|
+
plugins: [
|
|
31
|
+
['read-all-files', readAllFiles],
|
|
32
|
+
['replace-cwd', replaceCwd],
|
|
33
|
+
],
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const code = print(ast);
|
|
37
|
+
|
|
38
|
+
return merge(filesystem, [code]);
|
|
39
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import {
|
|
2
|
+
parentPort,
|
|
3
|
+
workerData,
|
|
4
|
+
} from 'node:worker_threads';
|
|
5
|
+
import {pack} from './pack.js';
|
|
6
|
+
import {createProgress} from '@putout/engine-runner/progress';
|
|
7
|
+
|
|
8
|
+
const {filesystem, cwd} = workerData;
|
|
9
|
+
const progress = createProgress();
|
|
10
|
+
|
|
11
|
+
progress.on('start', ({rule}) => {
|
|
12
|
+
parentPort.postMessage(['rule:start', rule]);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
progress.on('push', ({rule}) => {
|
|
16
|
+
parentPort.postMessage(['rule:push', rule]);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
progress.on('end', ({rule}) => {
|
|
20
|
+
parentPort.postMessage(['rule:end', rule]);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
parentPort.postMessage(['end', pack(cwd, filesystem, {
|
|
24
|
+
progress,
|
|
25
|
+
})]);
|
package/lib/slave.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "redlint",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"author": "coderaiser <mnemonic.enemy@gmail.com> (https://github.com/coderaiser)",
|
|
6
6
|
"description": "Lint Filesystem with πPutout",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
"@putout/engine-runner": "^20.1.0",
|
|
35
35
|
"@putout/formatter-codeframe": "^6.0.0",
|
|
36
36
|
"@putout/formatter-dump": "^4.0.1",
|
|
37
|
+
"@putout/plugin-filesystem": "^3.6.0",
|
|
37
38
|
"@putout/processor-filesystem": "^3.0.0",
|
|
38
39
|
"chalk": "^5.3.0",
|
|
39
40
|
"fullstore": "^3.0.0",
|