create-alistt69-kit 0.1.9 → 0.1.12

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.
Files changed (45) hide show
  1. package/LICENSE +20 -20
  2. package/README.md +123 -122
  3. package/bin/index.js +24 -24
  4. package/package.json +44 -44
  5. package/src/core/apply-features.js +14 -14
  6. package/src/core/collect-project-info.js +170 -194
  7. package/src/core/copy-base-template.js +11 -11
  8. package/src/core/create-project.js +99 -98
  9. package/src/core/install-dependencies.js +27 -27
  10. package/src/core/parse-cli-args.js +122 -122
  11. package/src/core/prepare-target-directory.js +69 -69
  12. package/src/core/render-project-readme.js +188 -75
  13. package/src/core/replace-tokens.js +45 -45
  14. package/src/core/restore-special-files.js +18 -18
  15. package/src/features/autoprefixer/files/postcss.config.cjs +4 -4
  16. package/src/features/autoprefixer/index.js +19 -23
  17. package/src/features/define-feature.js +33 -0
  18. package/src/features/eslint/files/eslint.config.mjs +133 -133
  19. package/src/features/eslint/index.js +30 -35
  20. package/src/features/index.js +25 -15
  21. package/src/features/react-router/files/src/app/App.tsx +20 -20
  22. package/src/features/react-router/files/src/app/layouts/app/index.tsx +36 -36
  23. package/src/features/react-router/files/src/app/providers/router/config/router.tsx +13 -13
  24. package/src/features/react-router/files/src/pages/error/index.ts +1 -1
  25. package/src/features/react-router/files/src/pages/error/lazy.ts +3 -3
  26. package/src/features/react-router/files/src/pages/error/page.tsx +7 -7
  27. package/src/features/react-router/files/src/pages/main/index.ts +1 -1
  28. package/src/features/react-router/files/src/pages/main/lazy.ts +3 -3
  29. package/src/features/react-router/files/src/pages/main/page.tsx +7 -7
  30. package/src/features/react-router/index.js +19 -23
  31. package/src/features/stylelint/files/stylelint.config.mjs +13 -13
  32. package/src/features/stylelint/index.js +24 -29
  33. package/src/templates/base/.editorconfig +11 -11
  34. package/src/templates/base/README.md +2 -2
  35. package/src/templates/base/babel.config.json +12 -12
  36. package/src/templates/base/gitignore +27 -27
  37. package/src/templates/base/package.json +48 -48
  38. package/src/templates/base/public/index.html +12 -12
  39. package/src/templates/base/src/app/App.tsx +17 -17
  40. package/src/templates/base/src/index.tsx +16 -16
  41. package/src/templates/base/src/styles/index.scss +13 -13
  42. package/src/templates/base/tsconfig.json +25 -25
  43. package/src/utils/console-format.js +11 -11
  44. package/src/utils/package-json.js +96 -72
  45. package/src/utils/package-manager.js +22 -22
@@ -1,195 +1,171 @@
1
- import {
2
- cancel,
3
- confirm,
4
- intro,
5
- isCancel,
6
- multiselect,
7
- note,
8
- select,
9
- text,
10
- } from '@clack/prompts';
11
- import process from 'node:process';
12
- import { format } from '../utils/console-format.js';
13
- import { allowedPackageManagers } from '../utils/package-manager.js';
14
-
15
- const availableFeatures = [
16
- {
17
- value: 'eslint',
18
- label: 'ESLint + Stylistic',
19
- hint: 'JS/TS/React linting',
20
- },
21
- {
22
- value: 'stylelint',
23
- label: 'Stylelint',
24
- hint: 'SCSS/CSS linting',
25
- },
26
- {
27
- value: 'autoprefixer',
28
- label: 'Autoprefixer',
29
- hint: 'PostCSS vendor prefixes',
30
- },
31
- {
32
- value: 'react-router',
33
- label: 'React Router DOM',
34
- hint: 'Routing + FSD-like app/pages/shared',
35
- },
36
- ];
37
-
38
- const defaultFeatureIds = availableFeatures.map((feature) => feature.value);
39
- const defaultPackageManager = 'npm';
40
- const availableFeatureIdSet = new Set(defaultFeatureIds);
41
-
42
- function handleCancel(value) {
43
- if (!isCancel(value)) {
44
- return value;
45
- }
46
-
47
- cancel('Operation cancelled.');
48
- process.exit(0);
49
- }
50
-
51
- function validateProjectName(value) {
52
- const projectName = value.trim();
53
-
54
- if (!projectName) {
55
- return 'Project name is required';
56
- }
57
-
58
- if (projectName.length > 214) {
59
- return 'Project name is too long';
60
- }
61
-
62
- if (!/^[a-z0-9._-]+$/i.test(projectName)) {
63
- return 'Use only letters, numbers, dots, underscores and hyphens';
64
- }
65
-
66
- if (projectName.startsWith('.')) {
67
- return 'Project name cannot start with a dot';
68
- }
69
-
70
- return;
71
- }
72
-
73
- function normalizeFeatureIds(featureIds) {
74
- const normalizedFeatureIds = [...new Set(featureIds.map((featureId) => featureId.toLowerCase()))];
75
-
76
- if (normalizedFeatureIds.includes('all')) {
77
- return defaultFeatureIds;
78
- }
79
-
80
- const unknownFeatureIds = normalizedFeatureIds.filter((featureId) => !availableFeatureIdSet.has(featureId));
81
-
82
- if (unknownFeatureIds.length > 0) {
83
- throw new Error(`Unknown features: ${unknownFeatureIds.join(', ')}`);
84
- }
85
-
86
- return defaultFeatureIds.filter((featureId) => normalizedFeatureIds.includes(featureId));
87
- }
88
-
89
- export async function collectProjectInfo(cliArgs = {}) {
90
- intro('create-alistt69-kit');
91
-
92
- let projectName = cliArgs.projectName;
93
- let selectedFeatureIds = cliArgs.selectedFeatureIds;
94
- let shouldInstallDependencies = cliArgs.shouldInstallDependencies;
95
- let packageManager = cliArgs.packageManager;
96
-
97
- if (cliArgs.defaults && !projectName) {
98
- throw new Error('Project name is required when using --defaults');
99
- }
100
-
101
- if (!projectName) {
102
- projectName = handleCancel(await text({
103
- message: 'Project name',
104
- placeholder: 'my-awesome-app',
105
- validate: validateProjectName,
106
- }));
107
- } else {
108
- const validationError = validateProjectName(projectName);
109
-
110
- if (validationError) {
111
- throw new Error(validationError);
112
- }
113
- }
114
-
115
- if (selectedFeatureIds === undefined) {
116
- if (cliArgs.defaults) {
117
- selectedFeatureIds = defaultFeatureIds;
118
- } else {
119
- note(
120
- [
121
- 'All features are selected by default.',
122
- 'Remove anything you do not need.',
123
- '',
124
- '↑/↓ — move',
125
- 'Space toggle feature',
126
- 'Enter — confirm selection',
127
- ].join('\n'),
128
- format.sectionTitle('Feature selection help'),
129
- );
130
-
131
- selectedFeatureIds = handleCancel(await multiselect({
132
- message: 'Remove unnecessary features',
133
- options: availableFeatures,
134
- initialValues: defaultFeatureIds,
135
- required: false,
136
- }));
137
- }
138
- }
139
-
140
- selectedFeatureIds = normalizeFeatureIds(selectedFeatureIds);
141
-
142
- if (!packageManager) {
143
- if (cliArgs.defaults) {
144
- packageManager = defaultPackageManager;
145
- } else {
146
- packageManager = handleCancel(await select({
147
- message: 'Package manager',
148
- initialValue: defaultPackageManager,
149
- options: allowedPackageManagers.map((value) => ({
150
- value,
151
- label: value,
152
- })),
153
- }));
154
- }
155
- }
156
-
157
- if (shouldInstallDependencies === undefined) {
158
- if (cliArgs.defaults) {
159
- shouldInstallDependencies = true;
160
- } else {
161
- shouldInstallDependencies = handleCancel(await confirm({
162
- message: 'Install dependencies?',
163
- initialValue: true,
164
- }));
165
- }
166
- }
167
-
168
- const summaryLines = [
169
- `${format.label('Project')} ${projectName}`,
170
- `${format.label('Features')} ${selectedFeatureIds.length ? selectedFeatureIds.join(', ') : 'none'}`,
171
- `${format.label('PM')} ${packageManager}`,
172
- `${format.label('Install')} ${shouldInstallDependencies ? 'yes' : 'no'}`,
173
- ];
174
-
175
- note(summaryLines.join('\n'), format.sectionTitle('Summary'));
176
-
177
- if (!cliArgs.defaults) {
178
- const shouldContinue = handleCancel(await confirm({
179
- message: 'Continue?',
180
- initialValue: true,
181
- }));
182
-
183
- if (!shouldContinue) {
184
- cancel('Operation cancelled.');
185
- process.exit(0);
186
- }
187
- }
188
-
189
- return {
190
- projectName: projectName.trim(),
191
- selectedFeatureIds,
192
- shouldInstallDependencies,
193
- packageManager,
194
- };
1
+ import {
2
+ cancel,
3
+ confirm,
4
+ intro,
5
+ isCancel,
6
+ multiselect,
7
+ note,
8
+ select,
9
+ text,
10
+ } from '@clack/prompts';
11
+ import process from 'node:process';
12
+ import { defaultFeatureIds, featurePromptOptions, availableFeatureIdSet } from '../features/index.js';
13
+ import { format } from '../utils/console-format.js';
14
+ import { allowedPackageManagers } from '../utils/package-manager.js';
15
+
16
+ const defaultPackageManager = 'npm';
17
+
18
+ function handleCancel(value) {
19
+ if (!isCancel(value)) {
20
+ return value;
21
+ }
22
+
23
+ cancel('Operation cancelled.');
24
+ process.exit(0);
25
+ }
26
+
27
+ function validateProjectName(value) {
28
+ const projectName = value.trim();
29
+
30
+ if (!projectName) {
31
+ return 'Project name is required';
32
+ }
33
+
34
+ if (projectName.length > 214) {
35
+ return 'Project name is too long';
36
+ }
37
+
38
+ if (!/^[a-z0-9._-]+$/i.test(projectName)) {
39
+ return 'Use only letters, numbers, dots, underscores and hyphens';
40
+ }
41
+
42
+ if (projectName.startsWith('.')) {
43
+ return 'Project name cannot start with a dot';
44
+ }
45
+
46
+ return;
47
+ }
48
+
49
+ function normalizeFeatureIds(featureIds) {
50
+ const normalizedFeatureIds = [...new Set(featureIds.map((featureId) => featureId.toLowerCase()))];
51
+
52
+ if (normalizedFeatureIds.includes('all')) {
53
+ return defaultFeatureIds;
54
+ }
55
+
56
+ const unknownFeatureIds = normalizedFeatureIds.filter((featureId) => !availableFeatureIdSet.has(featureId));
57
+
58
+ if (unknownFeatureIds.length > 0) {
59
+ throw new Error(`Unknown features: ${unknownFeatureIds.join(', ')}`);
60
+ }
61
+
62
+ return defaultFeatureIds.filter((featureId) => normalizedFeatureIds.includes(featureId));
63
+ }
64
+
65
+ export async function collectProjectInfo(cliArgs = {}) {
66
+ intro('create-alistt69-kit');
67
+
68
+ let projectName = cliArgs.projectName;
69
+ let selectedFeatureIds = cliArgs.selectedFeatureIds;
70
+ let shouldInstallDependencies = cliArgs.shouldInstallDependencies;
71
+ let packageManager = cliArgs.packageManager;
72
+
73
+ if (cliArgs.defaults && !projectName) {
74
+ throw new Error('Project name is required when using --defaults');
75
+ }
76
+
77
+ if (!projectName) {
78
+ projectName = handleCancel(await text({
79
+ message: 'Project name',
80
+ placeholder: 'my-awesome-app',
81
+ validate: validateProjectName,
82
+ }));
83
+ } else {
84
+ const validationError = validateProjectName(projectName);
85
+
86
+ if (validationError) {
87
+ throw new Error(validationError);
88
+ }
89
+ }
90
+
91
+ if (selectedFeatureIds === undefined) {
92
+ if (cliArgs.defaults) {
93
+ selectedFeatureIds = defaultFeatureIds;
94
+ } else {
95
+ note(
96
+ [
97
+ 'All features are selected by default.',
98
+ 'Remove anything you do not need.',
99
+ '',
100
+ '↑/↓ — move',
101
+ 'Space toggle feature',
102
+ 'Enter confirm selection',
103
+ ].join('\n'),
104
+ format.sectionTitle('Feature selection help'),
105
+ );
106
+
107
+ selectedFeatureIds = handleCancel(await multiselect({
108
+ message: 'Remove unnecessary features',
109
+ options: featurePromptOptions,
110
+ initialValues: defaultFeatureIds,
111
+ required: false,
112
+ }));
113
+ }
114
+ }
115
+
116
+ selectedFeatureIds = normalizeFeatureIds(selectedFeatureIds);
117
+
118
+ if (!packageManager) {
119
+ if (cliArgs.defaults) {
120
+ packageManager = defaultPackageManager;
121
+ } else {
122
+ packageManager = handleCancel(await select({
123
+ message: 'Package manager',
124
+ initialValue: defaultPackageManager,
125
+ options: allowedPackageManagers.map((value) => ({
126
+ value,
127
+ label: value,
128
+ })),
129
+ }));
130
+ }
131
+ }
132
+
133
+ if (shouldInstallDependencies === undefined) {
134
+ if (cliArgs.defaults) {
135
+ shouldInstallDependencies = true;
136
+ } else {
137
+ shouldInstallDependencies = handleCancel(await confirm({
138
+ message: 'Install dependencies?',
139
+ initialValue: true,
140
+ }));
141
+ }
142
+ }
143
+
144
+ const summaryLines = [
145
+ `${format.label('Project')} ${projectName}`,
146
+ `${format.label('Features')} ${selectedFeatureIds.length ? selectedFeatureIds.join(', ') : 'none'}`,
147
+ `${format.label('PM')} ${packageManager}`,
148
+ `${format.label('Install')} ${shouldInstallDependencies ? 'yes' : 'no'}`,
149
+ ];
150
+
151
+ note(summaryLines.join('\n'), format.sectionTitle('Summary'));
152
+
153
+ if (!cliArgs.defaults) {
154
+ const shouldContinue = handleCancel(await confirm({
155
+ message: 'Continue?',
156
+ initialValue: true,
157
+ }));
158
+
159
+ if (!shouldContinue) {
160
+ cancel('Operation cancelled.');
161
+ process.exit(0);
162
+ }
163
+ }
164
+
165
+ return {
166
+ projectName: projectName.trim(),
167
+ selectedFeatureIds,
168
+ shouldInstallDependencies,
169
+ packageManager,
170
+ };
195
171
  }
@@ -1,12 +1,12 @@
1
- import { cp } from 'node:fs/promises';
2
- import { dirname, resolve } from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
-
5
- const currentFilePath = fileURLToPath(import.meta.url);
6
- const currentDirPath = dirname(currentFilePath);
7
-
8
- export async function copyBaseTemplate(targetDirPath) {
9
- const templateDirPath = resolve(currentDirPath, '../templates/base');
10
-
11
- await cp(templateDirPath, targetDirPath, { recursive: true });
1
+ import { cp } from 'node:fs/promises';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ const currentFilePath = fileURLToPath(import.meta.url);
6
+ const currentDirPath = dirname(currentFilePath);
7
+
8
+ export async function copyBaseTemplate(targetDirPath) {
9
+ const templateDirPath = resolve(currentDirPath, '../templates/base');
10
+
11
+ await cp(templateDirPath, targetDirPath, { recursive: true });
12
12
  }
@@ -1,99 +1,100 @@
1
- import { outro, spinner } from '@clack/prompts';
2
- import { format } from '../utils/console-format.js';
3
- import { getRunScriptCommand } from '../utils/package-manager.js';
4
- import { applyFeatures } from './apply-features.js';
5
- import { collectProjectInfo } from './collect-project-info.js';
6
- import { copyBaseTemplate } from './copy-base-template.js';
7
- import { installDependencies } from './install-dependencies.js';
8
- import { prepareTargetDirectory } from './prepare-target-directory.js';
9
- import { replaceTokens } from './replace-tokens.js';
10
- import { restoreSpecialFiles } from './restore-special-files.js';
11
- import { renderProjectReadme } from './render-project-readme.js';
12
-
13
- export async function createProject(cliArgs = {}) {
14
- const {
15
- projectName,
16
- selectedFeatureIds,
17
- shouldInstallDependencies,
18
- packageManager,
19
- } = await collectProjectInfo(cliArgs);
20
-
21
- const { targetDirPath } = await prepareTargetDirectory({
22
- projectName,
23
- overwrite: cliArgs.overwrite,
24
- defaults: cliArgs.defaults,
25
- });
26
-
27
- const progress = spinner();
28
-
29
- try {
30
- progress.start('Copying base template...');
31
- await copyBaseTemplate(targetDirPath);
32
- progress.stop('Base template copied');
33
-
34
- progress.start('Restoring special files...');
35
- await restoreSpecialFiles(targetDirPath);
36
- progress.stop('Special files restored');
37
-
38
- progress.start('Replacing template tokens...');
39
- await replaceTokens(targetDirPath, {
40
- '__PROJECT_NAME__': projectName,
41
- });
42
- progress.stop('Template tokens replaced');
43
-
44
- if (selectedFeatureIds.length > 0) {
45
- progress.start(`Applying features: ${selectedFeatureIds.join(', ')}`);
46
- await applyFeatures({
47
- projectPath: targetDirPath,
48
- selectedFeatureIds,
49
- });
50
- progress.stop('Features applied');
51
- }
52
-
53
- progress.start('Generating README...');
54
- await renderProjectReadme({
55
- projectPath: targetDirPath,
56
- projectName,
57
- selectedFeatureIds,
58
- packageManager,
59
- });
60
- progress.stop('README generated');
61
-
62
- if (shouldInstallDependencies) {
63
- progress.start(`Installing dependencies with ${packageManager}...`);
64
- await installDependencies(targetDirPath, packageManager);
65
- progress.stop('Dependencies installed');
66
- }
67
- } catch (error) {
68
- progress.stop('Operation failed');
69
- throw error;
70
- }
71
-
72
- const featuresLine = selectedFeatureIds.length
73
- ? selectedFeatureIds.join(', ')
74
- : 'none';
75
-
76
- const nextSteps = shouldInstallDependencies
77
- ? [
78
- `cd ${projectName}`,
79
- getRunScriptCommand(packageManager, 'start'),
80
- ]
81
- : [
82
- `cd ${projectName}`,
83
- packageManager === 'yarn' ? 'yarn' : `${packageManager} install`,
84
- getRunScriptCommand(packageManager, 'start'),
85
- ];
86
-
87
- outro([
88
- `${format.green('✔ Project created successfully')}`,
89
- '',
90
- format.sectionTitle('Project info'),
91
- `${format.label('Project')} ${projectName}`,
92
- `${format.label('Path')} ${targetDirPath}`,
93
- `${format.label('Features')} ${featuresLine}`,
94
- `${format.label('PM')} ${packageManager}`,
95
- '',
96
- format.sectionTitle('Next steps'),
97
- ...nextSteps.map((step) => ` ${step}`),
98
- ].join('\n'));
1
+ import { outro, spinner } from '@clack/prompts';
2
+ import { format } from '../utils/console-format.js';
3
+ import { getRunScriptCommand } from '../utils/package-manager.js';
4
+ import { applyFeatures } from './apply-features.js';
5
+ import { collectProjectInfo } from './collect-project-info.js';
6
+ import { copyBaseTemplate } from './copy-base-template.js';
7
+ import { installDependencies } from './install-dependencies.js';
8
+ import { prepareTargetDirectory } from './prepare-target-directory.js';
9
+ import { replaceTokens } from './replace-tokens.js';
10
+ import { restoreSpecialFiles } from './restore-special-files.js';
11
+ import { renderProjectReadme } from './render-project-readme.js';
12
+
13
+ export async function createProject(cliArgs = {}) {
14
+ const {
15
+ projectName,
16
+ selectedFeatureIds,
17
+ shouldInstallDependencies,
18
+ packageManager,
19
+ } = await collectProjectInfo(cliArgs);
20
+
21
+ const { targetDirPath } = await prepareTargetDirectory({
22
+ projectName,
23
+ overwrite: cliArgs.overwrite,
24
+ defaults: cliArgs.defaults,
25
+ });
26
+
27
+ const progress = spinner();
28
+
29
+ try {
30
+ progress.start('Copying base template...');
31
+ await copyBaseTemplate(targetDirPath);
32
+ progress.stop('Base template copied');
33
+
34
+ progress.start('Restoring special files...');
35
+ await restoreSpecialFiles(targetDirPath);
36
+ progress.stop('Special files restored');
37
+
38
+ progress.start('Replacing template tokens...');
39
+ await replaceTokens(targetDirPath, {
40
+ '__PROJECT_NAME__': projectName,
41
+ });
42
+ progress.stop('Template tokens replaced');
43
+
44
+ if (selectedFeatureIds.length > 0) {
45
+ progress.start(`Applying features: ${selectedFeatureIds.join(', ')}`);
46
+ await applyFeatures({
47
+ projectPath: targetDirPath,
48
+ selectedFeatureIds,
49
+ });
50
+ progress.stop('Features applied');
51
+ }
52
+
53
+ progress.start('Generating README...');
54
+ await renderProjectReadme({
55
+ projectPath: targetDirPath,
56
+ projectName,
57
+ selectedFeatureIds,
58
+ packageManager,
59
+ shouldInstallDependencies,
60
+ });
61
+ progress.stop('README generated');
62
+
63
+ if (shouldInstallDependencies) {
64
+ progress.start(`Installing dependencies with ${packageManager}...`);
65
+ await installDependencies(targetDirPath, packageManager);
66
+ progress.stop('Dependencies installed');
67
+ }
68
+ } catch (error) {
69
+ progress.stop('Operation failed');
70
+ throw error;
71
+ }
72
+
73
+ const featuresLine = selectedFeatureIds.length
74
+ ? selectedFeatureIds.join(', ')
75
+ : 'none';
76
+
77
+ const nextSteps = shouldInstallDependencies
78
+ ? [
79
+ `cd ${projectName}`,
80
+ getRunScriptCommand(packageManager, 'start'),
81
+ ]
82
+ : [
83
+ `cd ${projectName}`,
84
+ packageManager === 'yarn' ? 'yarn' : `${packageManager} install`,
85
+ getRunScriptCommand(packageManager, 'start'),
86
+ ];
87
+
88
+ outro([
89
+ `${format.green('✔ Project created successfully')}`,
90
+ '',
91
+ format.sectionTitle('Project info'),
92
+ `${format.label('Project')} ${projectName}`,
93
+ `${format.label('Path')} ${targetDirPath}`,
94
+ `${format.label('Features')} ${featuresLine}`,
95
+ `${format.label('PM')} ${packageManager}`,
96
+ '',
97
+ format.sectionTitle('Next steps'),
98
+ ...nextSteps.map((step) => ` ${step}`),
99
+ ].join('\n'));
99
100
  }
@@ -1,28 +1,28 @@
1
- import { spawn } from 'node:child_process';
2
- import process from 'node:process';
3
- import { getInstallCommand } from '../utils/package-manager.js';
4
-
5
- export function installDependencies(targetDirPath, packageManager) {
6
- const { command, args } = getInstallCommand(packageManager);
7
-
8
- return new Promise((resolvePromise, rejectPromise) => {
9
- const childProcess = spawn(command, args, {
10
- cwd: targetDirPath,
11
- stdio: 'inherit',
12
- shell: process.platform === 'win32',
13
- });
14
-
15
- childProcess.on('error', (error) => {
16
- rejectPromise(error);
17
- });
18
-
19
- childProcess.on('close', (code) => {
20
- if (code === 0) {
21
- resolvePromise();
22
- return;
23
- }
24
-
25
- rejectPromise(new Error(`${command} ${args.join(' ')} failed with exit code ${code}`.trim()));
26
- });
27
- });
1
+ import { spawn } from 'node:child_process';
2
+ import process from 'node:process';
3
+ import { getInstallCommand } from '../utils/package-manager.js';
4
+
5
+ export function installDependencies(targetDirPath, packageManager) {
6
+ const { command, args } = getInstallCommand(packageManager);
7
+
8
+ return new Promise((resolvePromise, rejectPromise) => {
9
+ const childProcess = spawn(command, args, {
10
+ cwd: targetDirPath,
11
+ stdio: 'inherit',
12
+ shell: process.platform === 'win32',
13
+ });
14
+
15
+ childProcess.on('error', (error) => {
16
+ rejectPromise(error);
17
+ });
18
+
19
+ childProcess.on('close', (code) => {
20
+ if (code === 0) {
21
+ resolvePromise();
22
+ return;
23
+ }
24
+
25
+ rejectPromise(new Error(`${command} ${args.join(' ')} failed with exit code ${code}`.trim()));
26
+ });
27
+ });
28
28
  }