generate-react-cli 8.0.1 → 8.1.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 +13 -9
- package/readme.md +124 -16
- package/src/cli.js +6 -0
- package/src/commands/generateComponent.js +5 -0
- package/src/services/openAiService.js +18 -0
- package/src/utils/generateComponentUtils.js +20 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "generate-react-cli",
|
|
3
|
-
"version": "8.0
|
|
3
|
+
"version": "8.1.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",
|
|
@@ -38,28 +38,30 @@
|
|
|
38
38
|
"prepare": "husky install"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"chalk": "5.
|
|
41
|
+
"chalk": "5.2.0",
|
|
42
42
|
"commander": "9.4.1",
|
|
43
43
|
"deep-keys": "0.5.0",
|
|
44
|
-
"
|
|
44
|
+
"dotenv": "^16.0.3",
|
|
45
|
+
"fs-extra": "11.1.0",
|
|
45
46
|
"inquirer": "9.1.4",
|
|
46
47
|
"lodash": "4.17.21",
|
|
48
|
+
"openai": "^3.1.0",
|
|
47
49
|
"replace": "1.2.2"
|
|
48
50
|
},
|
|
49
51
|
"devDependencies": {
|
|
50
|
-
"@commitlint/cli": "17.
|
|
51
|
-
"@commitlint/config-conventional": "17.
|
|
52
|
+
"@commitlint/cli": "17.3.0",
|
|
53
|
+
"@commitlint/config-conventional": "17.3.0",
|
|
52
54
|
"@semantic-release/commit-analyzer": "9.0.2",
|
|
53
55
|
"@semantic-release/git": "10.0.1",
|
|
54
|
-
"@semantic-release/github": "8.0.
|
|
56
|
+
"@semantic-release/github": "8.0.7",
|
|
55
57
|
"@semantic-release/npm": "9.0.1",
|
|
56
58
|
"@semantic-release/release-notes-generator": "10.0.3",
|
|
57
|
-
"eslint": "8.
|
|
59
|
+
"eslint": "8.29.0",
|
|
58
60
|
"eslint-config-airbnb-base": "15.0.0",
|
|
59
61
|
"eslint-config-prettier": "8.5.0",
|
|
60
62
|
"eslint-plugin-prettier": "4.2.1",
|
|
61
|
-
"husky": "8.0.
|
|
62
|
-
"prettier": "2.
|
|
63
|
+
"husky": "8.0.2",
|
|
64
|
+
"prettier": "2.8.1",
|
|
63
65
|
"pretty-quick": "3.1.3",
|
|
64
66
|
"semantic-release": "19.0.5"
|
|
65
67
|
},
|
|
@@ -70,6 +72,8 @@
|
|
|
70
72
|
},
|
|
71
73
|
"release": {
|
|
72
74
|
"branches": [
|
|
75
|
+
"alpha",
|
|
76
|
+
"beta",
|
|
73
77
|
"main"
|
|
74
78
|
],
|
|
75
79
|
"plugins": [
|
package/readme.md
CHANGED
|
@@ -10,18 +10,18 @@
|
|
|
10
10
|
|
|
11
11
|
To help speed up productivity in React projects and stop copying, pasting, and renaming files each time you want to create a new component.
|
|
12
12
|
|
|
13
|
-
A short [article](https://dev.to/arminbro/generate-react-cli-1ooh)
|
|
13
|
+
A short [article](https://dev.to/arminbro/generate-react-cli-1ooh) goes deeper into why we created GRC if you have the time.
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
You can also watch an excellent [video](https://www.youtube.com/watch?v=NEvnt3MWttY) tutorial on how to use GRC by [Eric Murphy](https://www.youtube.com/channel/UC5KDiSAFxrDWhmysBcNqtMA).
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
## Table of Contents:
|
|
18
18
|
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
-
|
|
19
|
+
- [Config file](#config-file)
|
|
20
|
+
- [Generate components](#generate-components)
|
|
21
|
+
- [Custom component types](#custom-component-types)
|
|
22
|
+
- [Custom component templates](#custom-component-templates)
|
|
23
|
+
- [Custom component files](#custom-component-files)
|
|
24
|
+
- [OpenAi integration (Alpha release)](#openai-integration-alpha-release)
|
|
25
25
|
|
|
26
26
|
## You can run it using npx like this:
|
|
27
27
|
|
|
@@ -39,7 +39,7 @@ When you run GRC within your project the first time, it will ask you a series of
|
|
|
39
39
|
|
|
40
40
|
```json
|
|
41
41
|
{
|
|
42
|
-
"usesTypeScript":
|
|
42
|
+
"usesTypeScript": true,
|
|
43
43
|
"usesCssModule": true,
|
|
44
44
|
"cssPreprocessor": "scss",
|
|
45
45
|
"testLibrary": "Testing Library",
|
|
@@ -57,7 +57,7 @@ When you run GRC within your project the first time, it will ask you a series of
|
|
|
57
57
|
|
|
58
58
|
## Generate Components
|
|
59
59
|
|
|
60
|
-
```
|
|
60
|
+
```sh
|
|
61
61
|
npx generate-react-cli component Box
|
|
62
62
|
```
|
|
63
63
|
|
|
@@ -78,13 +78,13 @@ This command will create a folder with your component name within your default (
|
|
|
78
78
|
|
|
79
79
|
You can also override some of the GRC component config rules using one-off commands. So for example, let's say you have set **withTest** to be `true` in the `component.default` property. You can override it like this:
|
|
80
80
|
|
|
81
|
-
```
|
|
81
|
+
```sh
|
|
82
82
|
npx generate-react-cli component Box --withTest=false
|
|
83
83
|
```
|
|
84
84
|
|
|
85
85
|
Or vice versa, if you have set **withTest** to be `false` you can do this:
|
|
86
86
|
|
|
87
|
-
```
|
|
87
|
+
```sh
|
|
88
88
|
npx generate-react-cli component Box --withTest=true
|
|
89
89
|
```
|
|
90
90
|
|
|
@@ -166,6 +166,14 @@ Otherwise, if you don't pass any options, it will just use the default values th
|
|
|
166
166
|
<td width="20%">Boolean</td>
|
|
167
167
|
<td width="20%"><code>false<code></td>
|
|
168
168
|
</tr>
|
|
169
|
+
<tr>
|
|
170
|
+
<td width="20%"><b>--describe</b></td>
|
|
171
|
+
<td width="60%">
|
|
172
|
+
Describe the component you're trying to generate, and OpenAI will do its best to render it following your instructions.
|
|
173
|
+
</td>
|
|
174
|
+
<td width="20%">String</td>
|
|
175
|
+
<td width="20%"><code>null<code></td>
|
|
176
|
+
</tr>
|
|
169
177
|
</table>
|
|
170
178
|
|
|
171
179
|
### Custom component types:
|
|
@@ -210,11 +218,11 @@ You can do so by extending the **generate-react-cli.json** config file like this
|
|
|
210
218
|
|
|
211
219
|
Now you can generate a component with your custom component types like this:
|
|
212
220
|
|
|
213
|
-
```
|
|
221
|
+
```sh
|
|
214
222
|
npx generate-react-cli component HomePage --type=page
|
|
215
223
|
```
|
|
216
224
|
|
|
217
|
-
```
|
|
225
|
+
```sh
|
|
218
226
|
npx generate-react-cli component BoxLayout --type=layout
|
|
219
227
|
```
|
|
220
228
|
|
|
@@ -376,6 +384,106 @@ You should also see that we added `index` and `storyStyle` to our `customTemplat
|
|
|
376
384
|
|
|
377
385
|
Also, we used the `TemplateName` keyword for the `storyStyle` custom file. GRC will generate this corresponding file and replace `TemplateName` with the component name.
|
|
378
386
|
|
|
387
|
+
## OpenAI integration (Alpha release)
|
|
388
|
+
|
|
389
|
+
Well, the time has come to incorporate OpenAI with GRC.
|
|
390
|
+
|
|
391
|
+
I had a chance to experiment with OpenAI's latest GPT-3 natural language model, and I was super impressed by its capabilities. You can read more about OpenAI by visiting their site: https://openai.com/.
|
|
392
|
+
|
|
393
|
+
If you've been using GRC, you already know about its component generation capabilities using its internal templates or the custom ones you provide.
|
|
394
|
+
|
|
395
|
+
With the help of OpenAI, we can now generate our components intelligently by describing them using the new `--describe` flag, or `-d` for short.
|
|
396
|
+
|
|
397
|
+
The plan for this alpha integration will start simple, but I have a few good ideas coming in the near future (and I'm hoping to hear some of yours) on how we can use OpenAI with GRC to improve the developer experience.
|
|
398
|
+
|
|
399
|
+
Please remember that this release is still early, and you will run into bugs. So, please report any bugs or issues [here](https://github.com/arminbro/generate-react-cli/issues).
|
|
400
|
+
|
|
401
|
+
### Okay, let's get started.
|
|
402
|
+
|
|
403
|
+
1. If you don't have one, you must create an OpenAI account: https://openai.com/api/.
|
|
404
|
+
2. You'll need to obtain a secret API key from OpenAI. You can do so by visiting https://beta.openai.com/account/api-keys.
|
|
405
|
+
3. Once you have your API key, you'll need to create a `.env.local` file in your react project and store it as a variable as `OPENAI_API_KEY`. Please be sure not to share the key or push it to version control, as it is private.
|
|
406
|
+
|
|
407
|
+
GRC will pass the key to OpenAI to communicate with the API on your behalf. You will see the usage reflected on your OpenAI account here: https://beta.openai.com/account/usage.
|
|
408
|
+
|
|
409
|
+
GRC uses the DaVinci language model, so you can check out their pricing here: https://openai.com/api/pricing/.
|
|
410
|
+
|
|
411
|
+
Let's generate our first component using OpenAI:
|
|
412
|
+
|
|
413
|
+
```sh
|
|
414
|
+
npx generate-react-cli@alpha c Counter -d "Create a counter component that increments by one when I click on the increment button"
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
GRC should have created a Counter component that looks something like this 🤯:
|
|
418
|
+
|
|
419
|
+
```jsx
|
|
420
|
+
import React, { useState } from 'react';
|
|
421
|
+
import PropTypes from 'prop-types';
|
|
422
|
+
import './Counter.css';
|
|
423
|
+
|
|
424
|
+
const Counter = () => {
|
|
425
|
+
const [count, setCount] = useState(0);
|
|
426
|
+
|
|
427
|
+
return (
|
|
428
|
+
<div className="Counter" data-testid="Counter">
|
|
429
|
+
<h2> The count is: {count} </h2>
|
|
430
|
+
<button onClick={() => setCount(count + 1)}>Increment</button>
|
|
431
|
+
</div>
|
|
432
|
+
);
|
|
433
|
+
};
|
|
434
|
+
|
|
435
|
+
Counter.propTypes = {};
|
|
436
|
+
|
|
437
|
+
Counter.defaultProps = {};
|
|
438
|
+
|
|
439
|
+
export default Counter;
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
OpenAI will do its best to generate the component following the instructions provided in the `--describe` flag while using the patterns supplied from the internal or custom component templates.
|
|
443
|
+
|
|
444
|
+
Okay, let's try another one.
|
|
445
|
+
|
|
446
|
+
```sh
|
|
447
|
+
npx generate-react-cli@alpha c GlobalNav -d "Create a navbar component with 1 logo named 'GRC' and 3 links: 'Home', 'About', 'Contact'"
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
and here's the output in src/components/GlobalNav/GlobalNav.js:
|
|
451
|
+
|
|
452
|
+
```jsx
|
|
453
|
+
import React from 'react';
|
|
454
|
+
import PropTypes from 'prop-types';
|
|
455
|
+
import './GlobalNav.css';
|
|
456
|
+
|
|
457
|
+
const GlobalNav = () => (
|
|
458
|
+
<div className="GlobalNav" data-testid="GlobalNav">
|
|
459
|
+
<a href="#">GRC</a>
|
|
460
|
+
<ul>
|
|
461
|
+
<li>
|
|
462
|
+
<a href="#">Home</a>
|
|
463
|
+
</li>
|
|
464
|
+
<li>
|
|
465
|
+
<a href="#">About</a>
|
|
466
|
+
</li>
|
|
467
|
+
<li>
|
|
468
|
+
<a href="#">Contact</a>
|
|
469
|
+
</li>
|
|
470
|
+
</ul>
|
|
471
|
+
</div>
|
|
472
|
+
);
|
|
473
|
+
|
|
474
|
+
GlobalNav.propTypes = {};
|
|
475
|
+
|
|
476
|
+
GlobalNav.defaultProps = {};
|
|
477
|
+
|
|
478
|
+
export default GlobalNav;
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
That's a wrap. I hope this integration will allow us to generate React components more efficiently, and we can still go in and make the necessary adjustments.
|
|
482
|
+
|
|
483
|
+
Again, please provide any feedback if you have any, and I would love to see some of the components that you generate with GRC+OpenAI.
|
|
484
|
+
|
|
485
|
+
Please share them with me on Twitter [@arminbro](https://twitter.com/arminbro).
|
|
486
|
+
|
|
379
487
|
## License
|
|
380
488
|
|
|
381
|
-
Generate React CLI is open source software [licensed as MIT](https://github.com/arminbro/generate-react-cli/blob/master/LICENSE).
|
|
489
|
+
Generate React CLI is an open source software [licensed as MIT](https://github.com/arminbro/generate-react-cli/blob/master/LICENSE).
|
package/src/cli.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { program } from 'commander';
|
|
2
2
|
import { createRequire } from 'module';
|
|
3
|
+
import { config as dotEnvConfig } from 'dotenv';
|
|
4
|
+
import path from 'path';
|
|
3
5
|
|
|
4
6
|
import initGenerateComponentCommand from './commands/generateComponent.js';
|
|
5
7
|
import { getCLIConfigFile } from './utils/grcConfigUtils.js';
|
|
@@ -9,6 +11,10 @@ export default async function cli(args) {
|
|
|
9
11
|
const localRequire = createRequire(import.meta.url);
|
|
10
12
|
const pkg = localRequire('../package.json');
|
|
11
13
|
|
|
14
|
+
// init dotenv
|
|
15
|
+
|
|
16
|
+
dotEnvConfig({ path: path.resolve(process.cwd(), '.env.local') });
|
|
17
|
+
|
|
12
18
|
// Initialize generate component command
|
|
13
19
|
|
|
14
20
|
initGenerateComponentCommand(args, cliConfigFile, program);
|
|
@@ -19,6 +19,11 @@ export default function initGenerateComponentCommand(args, cliConfigFile, progra
|
|
|
19
19
|
'You can pass a component type that you have configured in your GRC config file.',
|
|
20
20
|
'default'
|
|
21
21
|
)
|
|
22
|
+
.option(
|
|
23
|
+
'-d, --describe <describe>',
|
|
24
|
+
'Describe the component you want GRC to generate (e.g., Create a counter component that increments by one when I click on the increment button).',
|
|
25
|
+
null
|
|
26
|
+
)
|
|
22
27
|
.option('-f, --flat', 'Generate the files in the mentioned path insted of creating new folder for it', false);
|
|
23
28
|
|
|
24
29
|
// Dynamic component command option defaults.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Configuration, OpenAIApi } from 'openai';
|
|
2
|
+
|
|
3
|
+
export async function aiComponentGenerator(componentTemplate, prompt) {
|
|
4
|
+
const configuration = new Configuration({ apiKey: process.env.OPENAI_API_KEY });
|
|
5
|
+
const openAiApi = new OpenAIApi(configuration);
|
|
6
|
+
|
|
7
|
+
const generatedComponent = await openAiApi.createCompletion({
|
|
8
|
+
model: 'text-davinci-003',
|
|
9
|
+
prompt: `Create a React component using this template "${componentTemplate}", but make the adjustments needed with these instructions as follows "${prompt}"`,
|
|
10
|
+
temperature: 0.7,
|
|
11
|
+
max_tokens: 2000,
|
|
12
|
+
top_p: 1.0,
|
|
13
|
+
frequency_penalty: 0.0,
|
|
14
|
+
presence_penalty: 1,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
return generatedComponent.data.choices[0].text;
|
|
18
|
+
}
|
|
@@ -7,6 +7,7 @@ import snakeCase from 'lodash/snakeCase.js';
|
|
|
7
7
|
import startCase from 'lodash/startCase.js';
|
|
8
8
|
import fsExtra from 'fs-extra';
|
|
9
9
|
|
|
10
|
+
import { aiComponentGenerator } from '../services/openAiService.js';
|
|
10
11
|
import componentJsTemplate from '../templates/component/componentJsTemplate.js';
|
|
11
12
|
import componentTsTemplate from '../templates/component/componentTsTemplate.js';
|
|
12
13
|
import componentCssTemplate from '../templates/component/componentCssTemplate.js';
|
|
@@ -418,6 +419,25 @@ export function generateComponent(componentName, cmd, cliConfigFile) {
|
|
|
418
419
|
});
|
|
419
420
|
}
|
|
420
421
|
|
|
422
|
+
// Generate component with openAi, if component description is provided
|
|
423
|
+
|
|
424
|
+
if (cmd.describe && componentFileType === buildInComponentFileTypes.COMPONENT) {
|
|
425
|
+
aiComponentGenerator(template, cmd.describe)
|
|
426
|
+
.then((aiGeneratedComponent) => {
|
|
427
|
+
outputFileSync(componentPath, aiGeneratedComponent.trim());
|
|
428
|
+
console.log(
|
|
429
|
+
chalk.green(`OpenAI Successfully created the ${filename} component with the provided description.`)
|
|
430
|
+
);
|
|
431
|
+
})
|
|
432
|
+
.catch((error) =>
|
|
433
|
+
console.log(
|
|
434
|
+
chalk.red(`OpenAI failed to create the ${filename} component with the provided description.`, error)
|
|
435
|
+
)
|
|
436
|
+
);
|
|
437
|
+
|
|
438
|
+
return;
|
|
439
|
+
}
|
|
440
|
+
|
|
421
441
|
console.log(chalk.green(`${filename} was successfully created at ${componentPath}`));
|
|
422
442
|
} catch (error) {
|
|
423
443
|
console.error(chalk.red(`${filename} failed and was not created.`));
|