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.
- package/LICENSE +20 -20
- package/README.md +123 -122
- package/bin/index.js +24 -24
- package/package.json +44 -44
- package/src/core/apply-features.js +14 -14
- package/src/core/collect-project-info.js +170 -194
- package/src/core/copy-base-template.js +11 -11
- package/src/core/create-project.js +99 -98
- package/src/core/install-dependencies.js +27 -27
- package/src/core/parse-cli-args.js +122 -122
- package/src/core/prepare-target-directory.js +69 -69
- package/src/core/render-project-readme.js +188 -75
- package/src/core/replace-tokens.js +45 -45
- package/src/core/restore-special-files.js +18 -18
- package/src/features/autoprefixer/files/postcss.config.cjs +4 -4
- package/src/features/autoprefixer/index.js +19 -23
- package/src/features/define-feature.js +33 -0
- package/src/features/eslint/files/eslint.config.mjs +133 -133
- package/src/features/eslint/index.js +30 -35
- package/src/features/index.js +25 -15
- package/src/features/react-router/files/src/app/App.tsx +20 -20
- package/src/features/react-router/files/src/app/layouts/app/index.tsx +36 -36
- package/src/features/react-router/files/src/app/providers/router/config/router.tsx +13 -13
- package/src/features/react-router/files/src/pages/error/index.ts +1 -1
- package/src/features/react-router/files/src/pages/error/lazy.ts +3 -3
- package/src/features/react-router/files/src/pages/error/page.tsx +7 -7
- package/src/features/react-router/files/src/pages/main/index.ts +1 -1
- package/src/features/react-router/files/src/pages/main/lazy.ts +3 -3
- package/src/features/react-router/files/src/pages/main/page.tsx +7 -7
- package/src/features/react-router/index.js +19 -23
- package/src/features/stylelint/files/stylelint.config.mjs +13 -13
- package/src/features/stylelint/index.js +24 -29
- package/src/templates/base/.editorconfig +11 -11
- package/src/templates/base/README.md +2 -2
- package/src/templates/base/babel.config.json +12 -12
- package/src/templates/base/gitignore +27 -27
- package/src/templates/base/package.json +48 -48
- package/src/templates/base/public/index.html +12 -12
- package/src/templates/base/src/app/App.tsx +17 -17
- package/src/templates/base/src/index.tsx +16 -16
- package/src/templates/base/src/styles/index.scss +13 -13
- package/src/templates/base/tsconfig.json +25 -25
- package/src/utils/console-format.js +11 -11
- package/src/utils/package-json.js +96 -72
- 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 {
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
);
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
''
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
`${format.label('
|
|
93
|
-
`${format.label('
|
|
94
|
-
`${format.label('
|
|
95
|
-
''
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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
|
}
|