@kitschpatrol/shared-config 1.0.1 → 2.0.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/cli.js +174 -0
- package/package.json +12 -12
- package/readme.md +4 -4
- package/scripts/fix.js +0 -5
- package/scripts/init.js +0 -39
- package/scripts/lint.js +0 -5
- package/scripts/run-helper.js +0 -128
package/cli.js
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env zx
|
|
2
|
+
/* eslint-disable unicorn/prefer-module */
|
|
3
|
+
import minimist from 'minimist';
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
import { once } from 'node:events';
|
|
6
|
+
import { $ } from 'zx';
|
|
7
|
+
|
|
8
|
+
const options = ['fix', 'init', 'check'];
|
|
9
|
+
async function main() {
|
|
10
|
+
const args = minimist(process.argv.slice(2), {
|
|
11
|
+
boolean: options,
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
const argumentCount = options.reduce((count, argument) => count + (args[argument] ? 1 : 0), 0);
|
|
15
|
+
if (argumentCount !== 1) {
|
|
16
|
+
console.error(`[SharedConfig] Please provide exactly one of ${options.map((opt) => `--${opt}`).join(' or ')}`);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const commands = [
|
|
21
|
+
'cspell-config',
|
|
22
|
+
'eslint-config',
|
|
23
|
+
'markdownlint-config',
|
|
24
|
+
'npm-config',
|
|
25
|
+
'prettier-config',
|
|
26
|
+
'stylelint-config',
|
|
27
|
+
'vscode-config',
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
const capabilities = await getCapabilities(commands);
|
|
31
|
+
|
|
32
|
+
process.env.FORCE_COLOR = '1';
|
|
33
|
+
if (args.init) {
|
|
34
|
+
const capabilitiesWithInit = stylePrefixes(capabilities.filter((capability) => capability.init));
|
|
35
|
+
|
|
36
|
+
for (const capability of capabilitiesWithInit) {
|
|
37
|
+
console.log(`${capability.name} Running command: ${capability.command} --init`);
|
|
38
|
+
await $`${capability.command} --init`;
|
|
39
|
+
}
|
|
40
|
+
console.log('Initialization complete.');
|
|
41
|
+
} else if (args.fix) {
|
|
42
|
+
runAllCommands(capabilities, 'fix');
|
|
43
|
+
} else if (args.check) {
|
|
44
|
+
runAllCommands(capabilities, 'check');
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
await main();
|
|
49
|
+
|
|
50
|
+
// helpers
|
|
51
|
+
async function runCommand(command, prefix) {
|
|
52
|
+
// console.log(`${prefix} Running command: ${command}`);
|
|
53
|
+
|
|
54
|
+
const subprocess = spawn(command, {
|
|
55
|
+
env: { ...process.env, FORCE_COLOR: true },
|
|
56
|
+
shell: true,
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
subprocess.stdout.on('data', (data) => {
|
|
60
|
+
const lines = data.toString().split(/\r?\n/);
|
|
61
|
+
const prefixedLines = lines
|
|
62
|
+
.filter((line) => line.trim() !== '') // Filter out empty lines
|
|
63
|
+
.map((line) => `${prefix} ${line}`)
|
|
64
|
+
.join('\n');
|
|
65
|
+
if (prefixedLines) {
|
|
66
|
+
process.stdout.write(prefixedLines); // Add a newline at the end if there's output
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
subprocess.stderr.on('data', (data) => {
|
|
71
|
+
const lines = data.toString().split(/\r?\n/);
|
|
72
|
+
const prefixedLines = lines
|
|
73
|
+
.filter((line) => line.trim() !== '') // Filter out empty lines
|
|
74
|
+
.map((line) => `${prefix} ${line}`)
|
|
75
|
+
.join('\n');
|
|
76
|
+
if (prefixedLines) {
|
|
77
|
+
console.error(prefixedLines); // Add a newline at the end if there's output
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
// Wait for the 'close' event
|
|
82
|
+
const [code] = await once(subprocess, 'close');
|
|
83
|
+
if (code !== 0) {
|
|
84
|
+
throw new Error(`${prefix} Command failed with exit code ${code}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function stylePrefixes(capabilities) {
|
|
89
|
+
// ANSI color codes (excluding red and ANSI 256-colors)
|
|
90
|
+
const colors = [
|
|
91
|
+
'\u001B[32m', // Green
|
|
92
|
+
'\u001B[34m', // Blue
|
|
93
|
+
'\u001B[33m', // Yellow
|
|
94
|
+
'\u001B[35m', // Magenta
|
|
95
|
+
'\u001B[36m', // Cyan
|
|
96
|
+
'\u001B[94m', // Bright Blue
|
|
97
|
+
'\u001B[92m', // Bright Green
|
|
98
|
+
'\u001B[93m', // Bright Yellow
|
|
99
|
+
'\u001B[95m', // Bright Magenta
|
|
100
|
+
];
|
|
101
|
+
const boldCode = '\u001B[1m';
|
|
102
|
+
const resetCode = '\u001B[0m';
|
|
103
|
+
|
|
104
|
+
// Find the length of the longest prefix
|
|
105
|
+
const longestPrefixLength = capabilities.reduce((max, capability) => Math.max(max, capability.name.length), 0);
|
|
106
|
+
|
|
107
|
+
// Pad each prefix with spaces to match the length of the longest prefix
|
|
108
|
+
return capabilities.map((cmd, index) => {
|
|
109
|
+
const colorCode = boldCode + colors[index % colors.length];
|
|
110
|
+
const paddedLength = longestPrefixLength;
|
|
111
|
+
const paddingLength = paddedLength - cmd.name.length;
|
|
112
|
+
const paddedPrefix = colorCode + '[' + cmd.name + ' '.repeat(paddingLength) + ']' + resetCode;
|
|
113
|
+
return { ...cmd, name: paddedPrefix };
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export async function runAllCommands(capabilities, option) {
|
|
118
|
+
const capabilitiesWithCommand = stylePrefixes(capabilities.filter((commandInfo) => commandInfo[option]));
|
|
119
|
+
|
|
120
|
+
let errors = [];
|
|
121
|
+
for (const cmd of capabilitiesWithCommand) {
|
|
122
|
+
try {
|
|
123
|
+
await runCommand(`${cmd.command} --${option}`, cmd.name);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
errors.push(error.message);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (errors.length > 0) {
|
|
130
|
+
console.error(`${errors.length} task(s) failed:`);
|
|
131
|
+
for (const error of errors) console.error(error);
|
|
132
|
+
process.exit(1);
|
|
133
|
+
} else {
|
|
134
|
+
console.log('All tasks completed successfully.');
|
|
135
|
+
process.exit(0);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function getCapabilities(commands) {
|
|
140
|
+
$.verbose = false;
|
|
141
|
+
const capabilities = await Promise.all(
|
|
142
|
+
commands.map(async (command) => {
|
|
143
|
+
try {
|
|
144
|
+
await $`${command}`;
|
|
145
|
+
// console.log('Command completed successfully.');
|
|
146
|
+
} catch (error) {
|
|
147
|
+
return {
|
|
148
|
+
command,
|
|
149
|
+
...parseCapabilities(error.stderr.trim()),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
console.error(`[SharedConfig] ${command} did not return any capabilities.`);
|
|
154
|
+
return '';
|
|
155
|
+
}),
|
|
156
|
+
);
|
|
157
|
+
$.verbose = true;
|
|
158
|
+
return capabilities;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function parseCapabilities(output) {
|
|
162
|
+
const parts = output.match(/\[(.*?)] Please provide exactly one of (.*)/);
|
|
163
|
+
if (!parts) return;
|
|
164
|
+
|
|
165
|
+
const name = parts[1];
|
|
166
|
+
const options = new Set(parts[2].split(' or ').map((opt) => opt.trim().replace('--', '')));
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
check: options.has('check'),
|
|
170
|
+
fix: options.has('fix'),
|
|
171
|
+
init: options.has('init'),
|
|
172
|
+
name,
|
|
173
|
+
};
|
|
174
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kitschpatrol/shared-config",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Linting and formatting for web projects.",
|
|
6
6
|
"repository": {
|
|
@@ -22,21 +22,21 @@
|
|
|
22
22
|
"pnpm": ">=8.0.0"
|
|
23
23
|
},
|
|
24
24
|
"bin": {
|
|
25
|
-
"shared-config
|
|
26
|
-
"shared-config-fix": "./scripts/fix.js",
|
|
27
|
-
"shared-config-lint": "./scripts/lint.js"
|
|
25
|
+
"shared-config": "./cli.js"
|
|
28
26
|
},
|
|
29
27
|
"files": [
|
|
30
|
-
"
|
|
28
|
+
"cli.js"
|
|
31
29
|
],
|
|
32
30
|
"dependencies": {
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"@kitschpatrol/
|
|
36
|
-
"@kitschpatrol/
|
|
37
|
-
"@kitschpatrol/npm-config": "
|
|
38
|
-
"@kitschpatrol/
|
|
39
|
-
"@kitschpatrol/
|
|
31
|
+
"minimist": "^1.2.8",
|
|
32
|
+
"zx": "^7.2.3",
|
|
33
|
+
"@kitschpatrol/markdownlint-config": "2.0.0",
|
|
34
|
+
"@kitschpatrol/cspell-config": "2.0.0",
|
|
35
|
+
"@kitschpatrol/npm-config": "2.0.0",
|
|
36
|
+
"@kitschpatrol/stylelint-config": "2.0.0",
|
|
37
|
+
"@kitschpatrol/vscode-config": "2.0.0",
|
|
38
|
+
"@kitschpatrol/prettier-config": "2.0.0",
|
|
39
|
+
"@kitschpatrol/eslint-config": "2.0.0"
|
|
40
40
|
},
|
|
41
41
|
"publishConfig": {
|
|
42
42
|
"access": "public"
|
package/readme.md
CHANGED
|
@@ -35,7 +35,7 @@ It's only been tested with `pnpm`.
|
|
|
35
35
|
3. Add default config files for all the tools to your project root:
|
|
36
36
|
|
|
37
37
|
```sh
|
|
38
|
-
pnpm shared-config
|
|
38
|
+
pnpm shared-config --init
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
4. Add helper scripts to your `package.json`:
|
|
@@ -45,8 +45,8 @@ It's only been tested with `pnpm`.
|
|
|
45
45
|
```json
|
|
46
46
|
...
|
|
47
47
|
"scripts": {
|
|
48
|
-
"format": "shared-config
|
|
49
|
-
"lint": "shared-config
|
|
48
|
+
"format": "shared-config --fix",
|
|
49
|
+
"lint": "shared-config --lint",
|
|
50
50
|
}
|
|
51
51
|
...
|
|
52
52
|
```
|
|
@@ -57,7 +57,7 @@ It's only been tested with `pnpm`.
|
|
|
57
57
|
|
|
58
58
|
Various VSCode plugins should "just work".
|
|
59
59
|
|
|
60
|
-
To lint your entire project:
|
|
60
|
+
To lint your entire project, after configuring the `package.json` as shown above:
|
|
61
61
|
|
|
62
62
|
```sh
|
|
63
63
|
pnpm run lint
|
package/scripts/fix.js
DELETED
package/scripts/init.js
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
// Copies configuration files for all tools to the root of the project
|
|
2
|
-
// It does not overwrite existing files
|
|
3
|
-
|
|
4
|
-
import { exec as execCallback } from 'node:child_process';
|
|
5
|
-
import console from 'node:console';
|
|
6
|
-
import { promisify } from 'node:util';
|
|
7
|
-
|
|
8
|
-
const exec = promisify(execCallback);
|
|
9
|
-
|
|
10
|
-
async function execCommand(command) {
|
|
11
|
-
try {
|
|
12
|
-
const { stderr, stdout } = await exec(command);
|
|
13
|
-
if (stderr) {
|
|
14
|
-
console.error(`stderr: ${stderr}`);
|
|
15
|
-
}
|
|
16
|
-
console.log(stdout);
|
|
17
|
-
return stdout;
|
|
18
|
-
} catch (error) {
|
|
19
|
-
console.error(`Error: ${error}`);
|
|
20
|
-
throw error; // Rethrow the error for further handling
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async function runCommands() {
|
|
25
|
-
try {
|
|
26
|
-
await execCommand('pnpm exec eslint-config-init');
|
|
27
|
-
await execCommand('pnpm exec prettier-config-init');
|
|
28
|
-
await execCommand('pnpm exec stylelint-config-init');
|
|
29
|
-
await execCommand('pnpm exec npm-config-init');
|
|
30
|
-
await execCommand('pnpm exec markdownlint-config-init');
|
|
31
|
-
await execCommand('pnpm exec cspell-config-init');
|
|
32
|
-
await execCommand('pnpm exec vscode-config-init');
|
|
33
|
-
console.log('All configurations have been initialized successfully.');
|
|
34
|
-
} catch (error) {
|
|
35
|
-
console.error('An error occurred while initializing configurations:', error);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
await runCommands();
|
package/scripts/lint.js
DELETED
package/scripts/run-helper.js
DELETED
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
/* eslint-disable unicorn/no-process-exit */
|
|
2
|
-
// Helper to run multiple commands
|
|
3
|
-
import { spawn } from 'node:child_process';
|
|
4
|
-
import console from 'node:console';
|
|
5
|
-
import { once } from 'node:events';
|
|
6
|
-
import process from 'node:process';
|
|
7
|
-
|
|
8
|
-
const commands = stylePrefixes([
|
|
9
|
-
{
|
|
10
|
-
command: 'eslint .',
|
|
11
|
-
fixArgument: '--fix',
|
|
12
|
-
lintArgument: '',
|
|
13
|
-
prefix: 'ESLint',
|
|
14
|
-
},
|
|
15
|
-
// Other commands...
|
|
16
|
-
{
|
|
17
|
-
command: 'stylelint --ignore-path .gitignore --allow-empty-input "**/*.{css,scss,sass,svelte,html,astro}"',
|
|
18
|
-
fixArgument: '--fix',
|
|
19
|
-
lintArgument: '',
|
|
20
|
-
prefix: 'Stylelint',
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
command:
|
|
24
|
-
'prettier --plugin=@prettier/plugin-php --plugin=@prettier/plugin-ruby --plugin=@prettier/plugin-xml --plugin=prettier-plugin-astro --plugin=prettier-plugin-pkg --plugin=prettier-plugin-sh --plugin=prettier-plugin-sql --plugin=prettier-plugin-svelte --plugin=prettier-plugin-tailwindcss --plugin=prettier-plugin-toml .',
|
|
25
|
-
fixArgument: '--write',
|
|
26
|
-
lintArgument: '--check',
|
|
27
|
-
prefix: 'Prettier',
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
command: 'markdownlint "**/*.{md,mdx}" --ignore-path .gitignore',
|
|
31
|
-
fixArgument: '--fix',
|
|
32
|
-
lintArgument: '',
|
|
33
|
-
prefix: 'markdownlint',
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
command: 'cspell --quiet .',
|
|
37
|
-
fixArgument: '',
|
|
38
|
-
lintArgument: '',
|
|
39
|
-
prefix: 'CSpell',
|
|
40
|
-
},
|
|
41
|
-
]);
|
|
42
|
-
|
|
43
|
-
function stylePrefixes(commands) {
|
|
44
|
-
// ANSI color codes (excluding red and ANSI 256-colors)
|
|
45
|
-
const colors = [
|
|
46
|
-
'\u001B[32m', // Green
|
|
47
|
-
'\u001B[34m', // Blue
|
|
48
|
-
'\u001B[33m', // Yellow
|
|
49
|
-
'\u001B[35m', // Magenta
|
|
50
|
-
'\u001B[36m', // Cyan
|
|
51
|
-
'\u001B[94m', // Bright Blue
|
|
52
|
-
'\u001B[92m', // Bright Green
|
|
53
|
-
'\u001B[93m', // Bright Yellow
|
|
54
|
-
'\u001B[95m', // Bright Magenta
|
|
55
|
-
];
|
|
56
|
-
const boldCode = '\u001B[1m';
|
|
57
|
-
const resetCode = '\u001B[0m';
|
|
58
|
-
|
|
59
|
-
// Find the length of the longest prefix
|
|
60
|
-
const longestPrefixLength = commands.reduce((max, cmd) => Math.max(max, cmd.prefix.length), 0);
|
|
61
|
-
|
|
62
|
-
// Pad each prefix with spaces to match the length of the longest prefix
|
|
63
|
-
return commands.map((cmd, index) => {
|
|
64
|
-
const colorCode = boldCode + colors[index % colors.length];
|
|
65
|
-
const paddedLength = longestPrefixLength;
|
|
66
|
-
const paddingLength = paddedLength - cmd.prefix.length;
|
|
67
|
-
const paddedPrefix = colorCode + '[' + cmd.prefix + ' '.repeat(paddingLength) + ']' + resetCode;
|
|
68
|
-
return { ...cmd, prefix: paddedPrefix };
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
async function runCommand({ command, fixArgument, lintArgument, prefix }, fix = false) {
|
|
73
|
-
const fullCommand = `${command} ${fix ? fixArgument : lintArgument}`;
|
|
74
|
-
console.log(`${prefix} Running command: ${fullCommand}`);
|
|
75
|
-
|
|
76
|
-
const subprocess = spawn(fullCommand, {
|
|
77
|
-
env: { ...process.env, FORCE_COLOR: true },
|
|
78
|
-
shell: true,
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
subprocess.stdout.on('data', (data) => {
|
|
82
|
-
const lines = data.toString().split(/\r?\n/);
|
|
83
|
-
const prefixedLines = lines
|
|
84
|
-
.filter((line) => line.trim() !== '') // Filter out empty lines
|
|
85
|
-
.map((line) => `${prefix} ${line}`)
|
|
86
|
-
.join('\n');
|
|
87
|
-
if (prefixedLines) {
|
|
88
|
-
process.stdout.write(prefixedLines + '\n'); // Add a newline at the end if there's output
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
subprocess.stderr.on('data', (data) => {
|
|
93
|
-
const lines = data.toString().split(/\r?\n/);
|
|
94
|
-
const prefixedLines = lines
|
|
95
|
-
.filter((line) => line.trim() !== '') // Filter out empty lines
|
|
96
|
-
.map((line) => `${prefix} ${line}`)
|
|
97
|
-
.join('\n');
|
|
98
|
-
if (prefixedLines) {
|
|
99
|
-
console.error(prefixedLines + '\n'); // Add a newline at the end if there's output
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
// Wait for the 'close' event
|
|
104
|
-
const [code] = await once(subprocess, 'close');
|
|
105
|
-
if (code !== 0) {
|
|
106
|
-
throw new Error(`${prefix} Command failed with exit code ${code}`);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export async function runAllCommands(fix = false) {
|
|
111
|
-
let errors = [];
|
|
112
|
-
for (const cmd of commands) {
|
|
113
|
-
try {
|
|
114
|
-
await runCommand(cmd, fix);
|
|
115
|
-
} catch (error) {
|
|
116
|
-
errors.push(error.message);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (errors.length > 0) {
|
|
121
|
-
console.error(`${errors.length} task(s) failed:`);
|
|
122
|
-
for (const error of errors) console.error(error);
|
|
123
|
-
process.exit(1);
|
|
124
|
-
} else {
|
|
125
|
-
console.log('All tasks completed successfully.');
|
|
126
|
-
process.exit(0);
|
|
127
|
-
}
|
|
128
|
-
}
|