@kitschpatrol/shared-config 1.0.2 → 2.0.1

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,175 @@
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
+ console.log('\n');
40
+ }
41
+ console.log('Initialization complete.');
42
+ } else if (args.fix) {
43
+ runAllCommands(capabilities, 'fix');
44
+ } else if (args.check) {
45
+ runAllCommands(capabilities, 'check');
46
+ }
47
+ }
48
+
49
+ await main();
50
+
51
+ // helpers
52
+ async function runCommand(command, prefix) {
53
+ // console.log(`${prefix} Running command: ${command}`);
54
+
55
+ const subprocess = spawn(command, {
56
+ env: { ...process.env, FORCE_COLOR: true },
57
+ shell: true,
58
+ });
59
+
60
+ subprocess.stdout.on('data', (data) => {
61
+ const lines = data.toString().split(/\r?\n/);
62
+ const prefixedLines = lines
63
+ .filter((line) => line.trim() !== '') // Filter out empty lines
64
+ .map((line) => `${prefix} ${line}`)
65
+ .join('\n');
66
+ if (prefixedLines) {
67
+ process.stdout.write(prefixedLines); // Add a newline at the end if there's output
68
+ }
69
+ });
70
+
71
+ subprocess.stderr.on('data', (data) => {
72
+ const lines = data.toString().split(/\r?\n/);
73
+ const prefixedLines = lines
74
+ .filter((line) => line.trim() !== '') // Filter out empty lines
75
+ .map((line) => `${prefix} ${line}`)
76
+ .join('\n');
77
+ if (prefixedLines) {
78
+ console.error(prefixedLines); // Add a newline at the end if there's output
79
+ }
80
+ });
81
+
82
+ // Wait for the 'close' event
83
+ const [code] = await once(subprocess, 'close');
84
+ if (code !== 0) {
85
+ throw new Error(`${prefix} Command failed with exit code ${code}`);
86
+ }
87
+ }
88
+
89
+ function stylePrefixes(capabilities) {
90
+ // ANSI color codes (excluding red and ANSI 256-colors)
91
+ const colors = [
92
+ '\u001B[32m', // Green
93
+ '\u001B[34m', // Blue
94
+ '\u001B[33m', // Yellow
95
+ '\u001B[35m', // Magenta
96
+ '\u001B[36m', // Cyan
97
+ '\u001B[94m', // Bright Blue
98
+ '\u001B[92m', // Bright Green
99
+ '\u001B[93m', // Bright Yellow
100
+ '\u001B[95m', // Bright Magenta
101
+ ];
102
+ const boldCode = '\u001B[1m';
103
+ const resetCode = '\u001B[0m';
104
+
105
+ // Find the length of the longest prefix
106
+ const longestPrefixLength = capabilities.reduce((max, capability) => Math.max(max, capability.name.length), 0);
107
+
108
+ // Pad each prefix with spaces to match the length of the longest prefix
109
+ return capabilities.map((cmd, index) => {
110
+ const colorCode = boldCode + colors[index % colors.length];
111
+ const paddedLength = longestPrefixLength;
112
+ const paddingLength = paddedLength - cmd.name.length;
113
+ const paddedPrefix = colorCode + '[' + cmd.name + ' '.repeat(paddingLength) + ']' + resetCode;
114
+ return { ...cmd, name: paddedPrefix };
115
+ });
116
+ }
117
+
118
+ export async function runAllCommands(capabilities, option) {
119
+ const capabilitiesWithCommand = stylePrefixes(capabilities.filter((commandInfo) => commandInfo[option]));
120
+
121
+ let errors = [];
122
+ for (const cmd of capabilitiesWithCommand) {
123
+ try {
124
+ await runCommand(`${cmd.command} --${option}`, cmd.name);
125
+ } catch (error) {
126
+ errors.push(error.message);
127
+ }
128
+ }
129
+
130
+ if (errors.length > 0) {
131
+ console.error(`${errors.length} task(s) failed:`);
132
+ for (const error of errors) console.error(error);
133
+ process.exit(1);
134
+ } else {
135
+ console.log('All tasks completed successfully.');
136
+ process.exit(0);
137
+ }
138
+ }
139
+
140
+ async function getCapabilities(commands) {
141
+ $.verbose = false;
142
+ const capabilities = await Promise.all(
143
+ commands.map(async (command) => {
144
+ try {
145
+ await $`${command}`;
146
+ // console.log('Command completed successfully.');
147
+ } catch (error) {
148
+ return {
149
+ command,
150
+ ...parseCapabilities(error.stderr.trim()),
151
+ };
152
+ }
153
+
154
+ console.error(`[SharedConfig] ${command} did not return any capabilities.`);
155
+ return '';
156
+ }),
157
+ );
158
+ $.verbose = true;
159
+ return capabilities;
160
+ }
161
+
162
+ function parseCapabilities(output) {
163
+ const parts = output.match(/\[(.*?)] Please provide exactly one of (.*)/);
164
+ if (!parts) return;
165
+
166
+ const name = parts[1];
167
+ const options = new Set(parts[2].split(' or ').map((opt) => opt.trim().replace('--', '')));
168
+
169
+ return {
170
+ check: options.has('check'),
171
+ fix: options.has('fix'),
172
+ init: options.has('init'),
173
+ name,
174
+ };
175
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitschpatrol/shared-config",
3
- "version": "1.0.2",
3
+ "version": "2.0.1",
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/npm-config": "1.0.1",
35
- "@kitschpatrol/eslint-config": "1.0.1",
36
- "@kitschpatrol/markdownlint-config": "1.0.1",
37
- "@kitschpatrol/prettier-config": "1.0.1",
38
- "@kitschpatrol/vscode-config": "1.0.1",
39
- "@kitschpatrol/stylelint-config": "1.0.1"
31
+ "minimist": "^1.2.8",
32
+ "zx": "^7.2.3",
33
+ "@kitschpatrol/cspell-config": "2.0.0",
34
+ "@kitschpatrol/eslint-config": "2.0.0",
35
+ "@kitschpatrol/markdownlint-config": "2.0.0",
36
+ "@kitschpatrol/npm-config": "2.0.0",
37
+ "@kitschpatrol/stylelint-config": "2.0.0",
38
+ "@kitschpatrol/vscode-config": "2.0.0",
39
+ "@kitschpatrol/prettier-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,133 +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 lintOrFix = [
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 --log-level warn --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
-
37
- const lintOnly = [
38
- {
39
- command: 'cspell --quiet .',
40
- fixArgument: '',
41
- lintArgument: '',
42
- prefix: 'CSpell',
43
- },
44
- ];
45
-
46
- function stylePrefixes(commands) {
47
- // ANSI color codes (excluding red and ANSI 256-colors)
48
- const colors = [
49
- '\u001B[32m', // Green
50
- '\u001B[34m', // Blue
51
- '\u001B[33m', // Yellow
52
- '\u001B[35m', // Magenta
53
- '\u001B[36m', // Cyan
54
- '\u001B[94m', // Bright Blue
55
- '\u001B[92m', // Bright Green
56
- '\u001B[93m', // Bright Yellow
57
- '\u001B[95m', // Bright Magenta
58
- ];
59
- const boldCode = '\u001B[1m';
60
- const resetCode = '\u001B[0m';
61
-
62
- // Find the length of the longest prefix
63
- const longestPrefixLength = commands.reduce((max, cmd) => Math.max(max, cmd.prefix.length), 0);
64
-
65
- // Pad each prefix with spaces to match the length of the longest prefix
66
- return commands.map((cmd, index) => {
67
- const colorCode = boldCode + colors[index % colors.length];
68
- const paddedLength = longestPrefixLength;
69
- const paddingLength = paddedLength - cmd.prefix.length;
70
- const paddedPrefix = colorCode + '[' + cmd.prefix + ' '.repeat(paddingLength) + ']' + resetCode;
71
- return { ...cmd, prefix: paddedPrefix };
72
- });
73
- }
74
-
75
- async function runCommand({ command, fixArgument, lintArgument, prefix }, fix = false) {
76
- const fullCommand = `${command} ${fix ? fixArgument : lintArgument}`;
77
- console.log(`${prefix} Running command: ${fullCommand}`);
78
-
79
- const subprocess = spawn(fullCommand, {
80
- env: { ...process.env, FORCE_COLOR: true },
81
- shell: true,
82
- });
83
-
84
- subprocess.stdout.on('data', (data) => {
85
- const lines = data.toString().split(/\r?\n/);
86
- const prefixedLines = lines
87
- .filter((line) => line.trim() !== '') // Filter out empty lines
88
- .map((line) => `${prefix} ${line}`)
89
- .join('\n');
90
- if (prefixedLines) {
91
- process.stdout.write(prefixedLines + '\n'); // Add a newline at the end if there's output
92
- }
93
- });
94
-
95
- subprocess.stderr.on('data', (data) => {
96
- const lines = data.toString().split(/\r?\n/);
97
- const prefixedLines = lines
98
- .filter((line) => line.trim() !== '') // Filter out empty lines
99
- .map((line) => `${prefix} ${line}`)
100
- .join('\n');
101
- if (prefixedLines) {
102
- console.error(prefixedLines + '\n'); // Add a newline at the end if there's output
103
- }
104
- });
105
-
106
- // Wait for the 'close' event
107
- const [code] = await once(subprocess, 'close');
108
- if (code !== 0) {
109
- throw new Error(`${prefix} Command failed with exit code ${code}`);
110
- }
111
- }
112
-
113
- export async function runAllCommands(fix = false) {
114
- const commands = stylePrefixes(fix ? [...lintOrFix] : [...lintOrFix, ...lintOnly]);
115
-
116
- let errors = [];
117
- for (const cmd of commands) {
118
- try {
119
- await runCommand(cmd, fix);
120
- } catch (error) {
121
- errors.push(error.message);
122
- }
123
- }
124
-
125
- if (errors.length > 0) {
126
- console.error(`${errors.length} task(s) failed:`);
127
- for (const error of errors) console.error(error);
128
- process.exit(1);
129
- } else {
130
- console.log('All tasks completed successfully.');
131
- process.exit(0);
132
- }
133
- }