@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 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": "1.0.1",
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-init": "./scripts/init.js",
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
- "scripts"
28
+ "cli.js"
31
29
  ],
32
30
  "dependencies": {
33
- "@kitschpatrol/cspell-config": "1.0.1",
34
- "@kitschpatrol/markdownlint-config": "1.0.1",
35
- "@kitschpatrol/eslint-config": "1.0.1",
36
- "@kitschpatrol/stylelint-config": "1.0.1",
37
- "@kitschpatrol/npm-config": "1.0.1",
38
- "@kitschpatrol/vscode-config": "1.0.1",
39
- "@kitschpatrol/prettier-config": "1.0.1"
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-init
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-fix",
49
- "lint": "shared-config-lint",
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
@@ -1,5 +0,0 @@
1
- // Uses all tools to fix the project
2
-
3
- import { runAllCommands } from './run-helper.js';
4
-
5
- runAllCommands(true);
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
@@ -1,5 +0,0 @@
1
- // Uses all tools to check / lint the project
2
-
3
- import { runAllCommands } from './run-helper.js';
4
-
5
- runAllCommands(false);
@@ -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
- }