generate-react-cli 9.0.1 → 10.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/package.json +20 -45
- package/readme.md +1 -0
- package/src/cli.js +1 -7
- package/src/utils/deepKeysUtils.js +23 -0
- package/src/utils/generateComponentUtils.js +10 -0
- package/src/utils/grcConfigUtils.js +83 -44
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "generate-react-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "10.0.0",
|
|
4
4
|
"description": "A simple React CLI to generate components instantly and more.",
|
|
5
5
|
"repository": "https://github.com/arminbro/generate-react-cli",
|
|
6
6
|
"bugs": "https://github.com/arminbro/generate-react-cli/issues",
|
|
@@ -28,46 +28,41 @@
|
|
|
28
28
|
"generate-react-cli"
|
|
29
29
|
],
|
|
30
30
|
"engines": {
|
|
31
|
-
"node": ">=
|
|
32
|
-
"npm": ">=
|
|
31
|
+
"node": ">=22",
|
|
32
|
+
"npm": ">=10"
|
|
33
33
|
},
|
|
34
34
|
"browserslist": [
|
|
35
35
|
"maintained node versions"
|
|
36
36
|
],
|
|
37
37
|
"scripts": {
|
|
38
|
-
"prepare": "husky install"
|
|
38
|
+
"prepare": "husky install",
|
|
39
|
+
"lint": "eslint .",
|
|
40
|
+
"lint:fix": "eslint . --fix"
|
|
39
41
|
},
|
|
40
42
|
"dependencies": {
|
|
41
43
|
"chalk": "5.6.2",
|
|
42
|
-
"commander": "14.0.
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"fs-extra": "11.2.0",
|
|
46
|
-
"inquirer": "12.9.4",
|
|
44
|
+
"commander": "14.0.2",
|
|
45
|
+
"fs-extra": "11.3.3",
|
|
46
|
+
"inquirer": "13.2.0",
|
|
47
47
|
"lodash": "4.17.21",
|
|
48
48
|
"replace": "1.2.2"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
|
-
"@
|
|
52
|
-
"@commitlint/
|
|
51
|
+
"@antfu/eslint-config": "4.12.0",
|
|
52
|
+
"@commitlint/cli": "20.3.1",
|
|
53
|
+
"@commitlint/config-conventional": "20.3.1",
|
|
53
54
|
"@semantic-release/commit-analyzer": "13.0.1",
|
|
54
55
|
"@semantic-release/git": "10.0.1",
|
|
55
|
-
"@semantic-release/github": "
|
|
56
|
-
"@semantic-release/npm": "
|
|
57
|
-
"@semantic-release/release-notes-generator": "14.0
|
|
58
|
-
"eslint": "
|
|
59
|
-
"eslint-config-airbnb-base": "15.0.0",
|
|
60
|
-
"eslint-config-prettier": "9.1.0",
|
|
61
|
-
"eslint-plugin-prettier": "5.5.4",
|
|
56
|
+
"@semantic-release/github": "12.0.2",
|
|
57
|
+
"@semantic-release/npm": "13.1.3",
|
|
58
|
+
"@semantic-release/release-notes-generator": "14.1.0",
|
|
59
|
+
"eslint": "9.39.2",
|
|
62
60
|
"husky": "9.1.7",
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
"semantic-release": "24.2.7"
|
|
61
|
+
"lint-staged": "16.1.0",
|
|
62
|
+
"semantic-release": "25.0.2"
|
|
66
63
|
},
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"trailingComma": "es5",
|
|
70
|
-
"printWidth": 120
|
|
64
|
+
"lint-staged": {
|
|
65
|
+
"*.js": "eslint --fix"
|
|
71
66
|
},
|
|
72
67
|
"release": {
|
|
73
68
|
"plugins": [
|
|
@@ -97,25 +92,5 @@
|
|
|
97
92
|
200
|
|
98
93
|
]
|
|
99
94
|
}
|
|
100
|
-
},
|
|
101
|
-
"eslintConfig": {
|
|
102
|
-
"extends": [
|
|
103
|
-
"airbnb-base",
|
|
104
|
-
"plugin:prettier/recommended"
|
|
105
|
-
],
|
|
106
|
-
"env": {
|
|
107
|
-
"commonjs": false,
|
|
108
|
-
"node": true
|
|
109
|
-
},
|
|
110
|
-
"parserOptions": {
|
|
111
|
-
"ecmaVersion": "latest"
|
|
112
|
-
},
|
|
113
|
-
"rules": {
|
|
114
|
-
"import/extensions": [
|
|
115
|
-
{
|
|
116
|
-
"js": "always"
|
|
117
|
-
}
|
|
118
|
-
]
|
|
119
|
-
}
|
|
120
95
|
}
|
|
121
96
|
}
|
package/readme.md
CHANGED
|
@@ -317,6 +317,7 @@ export default TemplateName;
|
|
|
317
317
|
| `template-name` | component name in kebab-case |
|
|
318
318
|
| `template_name` | component name in snake_case |
|
|
319
319
|
| `TEMPLATE_NAME` | component name in uppercase SNAKE_CASE |
|
|
320
|
+
| `TEMPLATENAME` | component name in full UPPERCASE |
|
|
320
321
|
|
|
321
322
|
#### Example of a custom test template file:
|
|
322
323
|
|
package/src/cli.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
1
2
|
import { program } from 'commander';
|
|
2
|
-
import { createRequire } from 'module';
|
|
3
|
-
import { config as dotEnvConfig } from 'dotenv';
|
|
4
|
-
import path from 'path';
|
|
5
3
|
|
|
6
4
|
import initGenerateComponentCommand from './commands/generateComponent.js';
|
|
7
5
|
import { getCLIConfigFile } from './utils/grcConfigUtils.js';
|
|
@@ -11,10 +9,6 @@ export default async function cli(args) {
|
|
|
11
9
|
const localRequire = createRequire(import.meta.url);
|
|
12
10
|
const pkg = localRequire('../package.json');
|
|
13
11
|
|
|
14
|
-
// init dotenv
|
|
15
|
-
|
|
16
|
-
dotEnvConfig({ path: path.resolve(process.cwd(), '.env.local') });
|
|
17
|
-
|
|
18
12
|
// Initialize generate component command
|
|
19
13
|
|
|
20
14
|
initGenerateComponentCommand(args, cliConfigFile, program);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Recursively extracts all keys from a nested object as dot-notation paths.
|
|
3
|
+
*
|
|
4
|
+
* @param {object} obj - The object to extract keys from
|
|
5
|
+
* @param {string} [prefix] - Internal prefix for recursion
|
|
6
|
+
* @returns {string[]} Array of dot-notation key paths
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* deepKeys({ a: 1, b: { c: 2 } })
|
|
10
|
+
* // Returns: ['a', 'b.c']
|
|
11
|
+
*/
|
|
12
|
+
export default function deepKeys(obj, prefix = '') {
|
|
13
|
+
return Object.keys(obj).reduce((keys, key) => {
|
|
14
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
15
|
+
const value = obj[key];
|
|
16
|
+
|
|
17
|
+
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
18
|
+
return [...keys, ...deepKeys(value, path)];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return [...keys, path];
|
|
22
|
+
}, []);
|
|
23
|
+
}
|
|
@@ -418,6 +418,7 @@ export function generateComponent(componentName, cmd, cliConfigFile) {
|
|
|
418
418
|
'template-name': kebabCase(componentName),
|
|
419
419
|
template_name: snakeCase(componentName),
|
|
420
420
|
TEMPLATE_NAME: snakeCase(componentName).toUpperCase(),
|
|
421
|
+
TEMPLATENAME: componentName.toUpperCase(),
|
|
421
422
|
};
|
|
422
423
|
|
|
423
424
|
const { componentPath, filename, template } = generateTemplate({
|
|
@@ -490,6 +491,15 @@ export function generateComponent(componentName, cmd, cliConfigFile) {
|
|
|
490
491
|
recursive: false,
|
|
491
492
|
silent: true,
|
|
492
493
|
});
|
|
494
|
+
|
|
495
|
+
// Will replace the TEMPLATENAME in uppercase SNAKE_CASE
|
|
496
|
+
replace({
|
|
497
|
+
regex: 'TEMPLATENAME',
|
|
498
|
+
replacement: convertors['TEMPLATENAME'],
|
|
499
|
+
paths: [componentPath],
|
|
500
|
+
recursive: false,
|
|
501
|
+
silent: true,
|
|
502
|
+
});
|
|
493
503
|
}
|
|
494
504
|
|
|
495
505
|
console.log(chalk.green(`${filename} was successfully created at ${componentPath}`));
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import chalk from 'chalk';
|
|
2
|
-
|
|
3
|
-
import deepKeys from 'deep-keys';
|
|
2
|
+
import fsExtra from 'fs-extra';
|
|
4
3
|
import inquirer from 'inquirer';
|
|
4
|
+
|
|
5
5
|
import merge from 'lodash/merge.js';
|
|
6
|
-
import
|
|
6
|
+
import deepKeys from './deepKeysUtils.js';
|
|
7
7
|
|
|
8
8
|
const { accessSync, constants, outputFileSync, readFileSync } = fsExtra;
|
|
9
9
|
const { prompt } = inquirer;
|
|
@@ -25,19 +25,19 @@ const projectLevelQuestions = [
|
|
|
25
25
|
},
|
|
26
26
|
{
|
|
27
27
|
type: 'confirm',
|
|
28
|
-
when:
|
|
28
|
+
when: answers => !answers.usesStyledComponents,
|
|
29
29
|
name: 'usesCssModule',
|
|
30
30
|
message: 'Does this project use CSS modules?',
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
|
-
type: '
|
|
33
|
+
type: 'select',
|
|
34
34
|
name: 'cssPreprocessor',
|
|
35
|
-
when:
|
|
35
|
+
when: answers => !answers.usesStyledComponents,
|
|
36
36
|
message: 'Does this project use a CSS Preprocessor?',
|
|
37
37
|
choices: ['css', 'scss', 'less', 'styl'],
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
|
-
type: '
|
|
40
|
+
type: 'select',
|
|
41
41
|
name: 'testLibrary',
|
|
42
42
|
message: 'What testing library does your project use?',
|
|
43
43
|
choices: ['Testing Library', 'Enzyme', 'None'],
|
|
@@ -50,23 +50,27 @@ export const componentLevelQuestions = [
|
|
|
50
50
|
{
|
|
51
51
|
type: 'input',
|
|
52
52
|
name: 'component.default.path',
|
|
53
|
-
message:
|
|
53
|
+
message:
|
|
54
|
+
'Set the default path directory to where your components will be generated in?',
|
|
54
55
|
default: () => 'src/components',
|
|
55
56
|
},
|
|
56
57
|
{
|
|
57
58
|
type: 'confirm',
|
|
58
59
|
name: 'component.default.withStyle',
|
|
59
|
-
message:
|
|
60
|
+
message:
|
|
61
|
+
'Would you like to create a corresponding stylesheet file with each component you generate?',
|
|
60
62
|
},
|
|
61
63
|
{
|
|
62
64
|
type: 'confirm',
|
|
63
65
|
name: 'component.default.withTest',
|
|
64
|
-
message:
|
|
66
|
+
message:
|
|
67
|
+
'Would you like to create a corresponding test file with each component you generate?',
|
|
65
68
|
},
|
|
66
69
|
{
|
|
67
70
|
type: 'confirm',
|
|
68
71
|
name: 'component.default.withStory',
|
|
69
|
-
message:
|
|
72
|
+
message:
|
|
73
|
+
'Would you like to create a corresponding story with each component you generate?',
|
|
70
74
|
},
|
|
71
75
|
{
|
|
72
76
|
type: 'confirm',
|
|
@@ -78,29 +82,34 @@ export const componentLevelQuestions = [
|
|
|
78
82
|
|
|
79
83
|
// --- merge all questions together.
|
|
80
84
|
|
|
81
|
-
const grcConfigQuestions = [
|
|
85
|
+
const grcConfigQuestions = [
|
|
86
|
+
...projectLevelQuestions,
|
|
87
|
+
...componentLevelQuestions,
|
|
88
|
+
];
|
|
82
89
|
|
|
83
90
|
async function createCLIConfigFile() {
|
|
84
91
|
try {
|
|
85
92
|
console.log();
|
|
86
93
|
console.log(
|
|
87
94
|
chalk.cyan(
|
|
88
|
-
'--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------'
|
|
89
|
-
)
|
|
95
|
+
'--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------',
|
|
96
|
+
),
|
|
90
97
|
);
|
|
91
98
|
console.log(
|
|
92
|
-
chalk.cyan(
|
|
99
|
+
chalk.cyan(
|
|
100
|
+
'It looks like this is the first time that you\'re running generate-react-cli within this project.',
|
|
101
|
+
),
|
|
93
102
|
);
|
|
94
103
|
console.log();
|
|
95
104
|
console.log(
|
|
96
105
|
chalk.cyan(
|
|
97
|
-
'Answer a few questions to customize generate-react-cli for your project needs (this will create a "generate-react-cli.json" config file on the root level of this project).'
|
|
98
|
-
)
|
|
106
|
+
'Answer a few questions to customize generate-react-cli for your project needs (this will create a "generate-react-cli.json" config file on the root level of this project).',
|
|
107
|
+
),
|
|
99
108
|
);
|
|
100
109
|
console.log(
|
|
101
110
|
chalk.cyan(
|
|
102
|
-
'--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------'
|
|
103
|
-
)
|
|
111
|
+
'--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------',
|
|
112
|
+
),
|
|
104
113
|
);
|
|
105
114
|
console.log();
|
|
106
115
|
|
|
@@ -111,8 +120,8 @@ async function createCLIConfigFile() {
|
|
|
111
120
|
console.log();
|
|
112
121
|
console.log(
|
|
113
122
|
chalk.cyan(
|
|
114
|
-
'The "generate-react-cli.json" config file has been successfully created on the root level of your project.'
|
|
115
|
-
)
|
|
123
|
+
'The "generate-react-cli.json" config file has been successfully created on the root level of your project.',
|
|
124
|
+
),
|
|
116
125
|
);
|
|
117
126
|
|
|
118
127
|
console.log('');
|
|
@@ -123,8 +132,13 @@ async function createCLIConfigFile() {
|
|
|
123
132
|
console.log('');
|
|
124
133
|
|
|
125
134
|
return answers;
|
|
126
|
-
}
|
|
127
|
-
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
console.error(
|
|
138
|
+
chalk.red.bold(
|
|
139
|
+
'ERROR: Could not create a "generate-react-cli.json" config file.',
|
|
140
|
+
),
|
|
141
|
+
);
|
|
128
142
|
return e;
|
|
129
143
|
}
|
|
130
144
|
}
|
|
@@ -134,41 +148,59 @@ async function updateCLIConfigFile(missingConfigQuestions, currentConfigFile) {
|
|
|
134
148
|
console.log('');
|
|
135
149
|
console.log(
|
|
136
150
|
chalk.cyan(
|
|
137
|
-
'------------------------------------------------------------------------------------------------------------------------------'
|
|
138
|
-
)
|
|
151
|
+
'------------------------------------------------------------------------------------------------------------------------------',
|
|
152
|
+
),
|
|
139
153
|
);
|
|
140
154
|
console.log(
|
|
141
155
|
chalk.cyan(
|
|
142
|
-
'Generate React CLI has been updated and has a few new features from the last time you ran it within this project.'
|
|
143
|
-
)
|
|
156
|
+
'Generate React CLI has been updated and has a few new features from the last time you ran it within this project.',
|
|
157
|
+
),
|
|
144
158
|
);
|
|
145
159
|
console.log('');
|
|
146
|
-
console.log(chalk.cyan('Please answer a few questions to update the "generate-react-cli.json" config file.'));
|
|
147
160
|
console.log(
|
|
148
161
|
chalk.cyan(
|
|
149
|
-
'
|
|
150
|
-
)
|
|
162
|
+
'Please answer a few questions to update the "generate-react-cli.json" config file.',
|
|
163
|
+
),
|
|
164
|
+
);
|
|
165
|
+
console.log(
|
|
166
|
+
chalk.cyan(
|
|
167
|
+
'------------------------------------------------------------------------------------------------------------------------------',
|
|
168
|
+
),
|
|
151
169
|
);
|
|
152
170
|
console.log('');
|
|
153
171
|
|
|
154
172
|
const answers = await prompt(missingConfigQuestions);
|
|
155
173
|
const updatedAnswers = merge({}, currentConfigFile, answers);
|
|
156
174
|
|
|
157
|
-
outputFileSync(
|
|
175
|
+
outputFileSync(
|
|
176
|
+
'generate-react-cli.json',
|
|
177
|
+
JSON.stringify(updatedAnswers, null, 2),
|
|
178
|
+
);
|
|
158
179
|
|
|
159
180
|
console.log();
|
|
160
|
-
console.log(
|
|
181
|
+
console.log(
|
|
182
|
+
chalk.cyan(
|
|
183
|
+
'The ("generate-react-cli.json") has successfully updated for this project.',
|
|
184
|
+
),
|
|
185
|
+
);
|
|
161
186
|
|
|
162
187
|
console.log();
|
|
163
|
-
console.log(
|
|
188
|
+
console.log(
|
|
189
|
+
chalk.cyan('You can always go back and manually update it as needed.'),
|
|
190
|
+
);
|
|
164
191
|
console.log();
|
|
165
192
|
console.log(chalk.cyan('Happy Hacking!'));
|
|
166
193
|
console.log();
|
|
167
194
|
console.log();
|
|
168
195
|
|
|
169
196
|
return updatedAnswers;
|
|
170
|
-
}
|
|
171
|
-
|
|
197
|
+
}
|
|
198
|
+
catch (e) {
|
|
199
|
+
console.error(
|
|
200
|
+
chalk.red.bold(
|
|
201
|
+
'ERROR: Could not update the "generate-react-cli.json" config file.',
|
|
202
|
+
),
|
|
203
|
+
);
|
|
172
204
|
return e;
|
|
173
205
|
}
|
|
174
206
|
}
|
|
@@ -183,7 +215,9 @@ export async function getCLIConfigFile() {
|
|
|
183
215
|
|
|
184
216
|
try {
|
|
185
217
|
accessSync('./generate-react-cli.json', constants.R_OK);
|
|
186
|
-
const currentConfigFile = JSON.parse(
|
|
218
|
+
const currentConfigFile = JSON.parse(
|
|
219
|
+
readFileSync('./generate-react-cli.json'),
|
|
220
|
+
);
|
|
187
221
|
|
|
188
222
|
/**
|
|
189
223
|
* Check to see if there's a difference between grcConfigQuestions and the currentConfigFile.
|
|
@@ -191,24 +225,29 @@ export async function getCLIConfigFile() {
|
|
|
191
225
|
*/
|
|
192
226
|
|
|
193
227
|
const missingConfigQuestions = grcConfigQuestions.filter(
|
|
194
|
-
|
|
195
|
-
!deepKeys(currentConfigFile).includes(question.name)
|
|
196
|
-
(question.when ? question.when(currentConfigFile) : true)
|
|
228
|
+
question =>
|
|
229
|
+
!deepKeys(currentConfigFile).includes(question.name)
|
|
230
|
+
&& (question.when ? question.when(currentConfigFile) : true),
|
|
197
231
|
);
|
|
198
232
|
|
|
199
233
|
if (missingConfigQuestions.length) {
|
|
200
|
-
return await updateCLIConfigFile(
|
|
234
|
+
return await updateCLIConfigFile(
|
|
235
|
+
missingConfigQuestions,
|
|
236
|
+
currentConfigFile,
|
|
237
|
+
);
|
|
201
238
|
}
|
|
202
239
|
|
|
203
240
|
return currentConfigFile;
|
|
204
|
-
}
|
|
241
|
+
}
|
|
242
|
+
catch {
|
|
205
243
|
return await createCLIConfigFile();
|
|
206
244
|
}
|
|
207
|
-
}
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
208
247
|
console.error(
|
|
209
248
|
chalk.red.bold(
|
|
210
|
-
|
|
211
|
-
)
|
|
249
|
+
'ERROR: Please make sure that you\'re running the generate-react-cli commands from the root level of your React project',
|
|
250
|
+
),
|
|
212
251
|
);
|
|
213
252
|
return process.exit(1);
|
|
214
253
|
}
|