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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "generate-react-cli",
3
- "version": "9.0.1",
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": ">=10.x",
32
- "npm": ">= 6.x"
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.0",
43
- "deep-keys": "0.5.0",
44
- "dotenv": "16.6.1",
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
- "@commitlint/cli": "19.8.1",
52
- "@commitlint/config-conventional": "19.8.1",
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": "11.0.5",
56
- "@semantic-release/npm": "12.0.2",
57
- "@semantic-release/release-notes-generator": "14.0.3",
58
- "eslint": "8.57.1",
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
- "prettier": "3.6.2",
64
- "pretty-quick": "4.2.2",
65
- "semantic-release": "24.2.7"
61
+ "lint-staged": "16.1.0",
62
+ "semantic-release": "25.0.2"
66
63
  },
67
- "prettier": {
68
- "singleQuote": true,
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 fsExtra from 'fs-extra';
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: (answers) => !answers['usesStyledComponents'],
28
+ when: answers => !answers.usesStyledComponents,
29
29
  name: 'usesCssModule',
30
30
  message: 'Does this project use CSS modules?',
31
31
  },
32
32
  {
33
- type: 'list',
33
+ type: 'select',
34
34
  name: 'cssPreprocessor',
35
- when: (answers) => !answers['usesStyledComponents'],
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: 'list',
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: 'Set the default path directory to where your components will be generated in?',
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: 'Would you like to create a corresponding stylesheet file with each component you generate?',
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: 'Would you like to create a corresponding test file with each component you generate?',
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: 'Would you like to create a corresponding story with each component you generate?',
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 = [...projectLevelQuestions, ...componentLevelQuestions];
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("It looks like this is the first time that you're running generate-react-cli within this project.")
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
- } catch (e) {
127
- console.error(chalk.red.bold('ERROR: Could not create a "generate-react-cli.json" config file.'));
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('generate-react-cli.json', JSON.stringify(updatedAnswers, null, 2));
175
+ outputFileSync(
176
+ 'generate-react-cli.json',
177
+ JSON.stringify(updatedAnswers, null, 2),
178
+ );
158
179
 
159
180
  console.log();
160
- console.log(chalk.cyan('The ("generate-react-cli.json") has successfully updated for this project.'));
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(chalk.cyan('You can always go back and manually update it as needed.'));
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
- } catch (e) {
171
- console.error(chalk.red.bold('ERROR: Could not update the "generate-react-cli.json" config file.'));
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(readFileSync('./generate-react-cli.json'));
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
- (question) =>
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(missingConfigQuestions, currentConfigFile);
234
+ return await updateCLIConfigFile(
235
+ missingConfigQuestions,
236
+ currentConfigFile,
237
+ );
201
238
  }
202
239
 
203
240
  return currentConfigFile;
204
- } catch (e) {
241
+ }
242
+ catch {
205
243
  return await createCLIConfigFile();
206
244
  }
207
- } catch (error) {
245
+ }
246
+ catch {
208
247
  console.error(
209
248
  chalk.red.bold(
210
- "ERROR: Please make sure that you're running the generate-react-cli commands from the root level of your React project"
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
  }