Skip to content
This repository was archived by the owner on Mar 30, 2021. It is now read-only.

Commit 1eae221

Browse files
Merge pull request #36 from Nikhil-Vats/dev_docs
Added dev docs
2 parents 96ea5da + 477fa6d commit 1eae221

File tree

3 files changed

+175
-1
lines changed

3 files changed

+175
-1
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ Contains all the code for generator.
113113

114114
3. app/validator.js - Contains the validator functions for the prompts which checks user inputs and also performs other functions like copying the build file, installing the component as npm package, downloading the build file from npm package and validating npm package's version.
115115

116+
To understand the code in `2. app/index.js` and `3. app/validator.js`, read the [developer docs](DEV_DOCS.md).
116117
All the other files are self explanatory.
117118

118119
### To-do / roadmap.

DEV_DOCS.md

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
# generator/app/index.js
2+
3+
```
4+
this.argument("projectDirectory", {
5+
type: String,
6+
required: false,
7+
default: "web-component",
8+
desc: `${chalk.blue(
9+
"path of the project directory, if you enter the path of a directory which does not exist, the generator will make one for you, otherwise it will use the existing one."
10+
)} Default directory: ${chalk.cyan("web-component")}`
11+
});
12+
```
13+
14+
This defines the project directory argument which is entered when the generator is run. The string value stored in the `desc` above is shown when user runs the command `yo @biojs/biojs-webcomponents --help`. Each argument should have a desc field so that yeoman can provide help when user asks.
15+
16+
The methods listed after the `constructor` are default methods provided by yeoman which are executed in the order they are written which is -
17+
### 1. initializing()
18+
19+
Contains initialization methods
20+
21+
```
22+
initializing() {
23+
this.composeWith(require.resolve("generator-license"), {
24+
defaultLicense: "MIT" // (optional) Select a default license
25+
});
26+
}
27+
```
28+
29+
This embeds the [generator-license](https://github.com/jozefizso/generator-license) in our generator. The prompts of the `generator-license` will be asked after the prompts in `prompting()` method.
30+
31+
### 2. prompting()
32+
33+
Contains the question asked allowing with the validation, type of input, etc. for each question.
34+
35+
Note: For validating user inputs, validators are used which are in a separate file [validator.js](generator/app/validator.js), to make the code reusable and easy to understand.
36+
37+
The prompts are divided in multiple groups and are asked in a particular order which is give below -
38+
39+
40+
If user chooses to make a new web component then firstly, `initialPrompts` are asked followed by `commonPrompts` and lastly the prompts for `generator-license` are asked.
41+
42+
If user chooses to upgrade an existing component to a web component, then -
43+
1. `initialPrompts` are asked.
44+
2. `upgradeComponentPrompts` are asked.
45+
46+
Based on which option user chooses out of the following, different prompts are asked -
47+
```
48+
#1. Install component from npm package. (Recommended - fastest way)
49+
#2. Tell us the path of the build file on your local machine and I will import it in the project.
50+
#3. Tell us the npm package name, version, build file URL and I will download the build file.
51+
```
52+
53+
3a. If user chooses #1 then `installNpmPackagePrompts` are asked.
54+
3b. If user chooses #2 then `localPrompts` are asked.
55+
3c. Is user chooses #3 then `npmPrompts` are asked.
56+
57+
4. Lastly, `commonPrompts` are asked followed by the prompts for `generator-license`.
58+
59+
This order of the prompts is ensured by `recursivePromptExecution` which is a recursive function because while upgrading components user may want to change the method of importing component for which there are prompts in each workflow of importing, if user wishes to change the method of importing, then this function will be executed again.
60+
61+
### 3. writing()
62+
63+
Generates the project files using the templates and inputs provided by user.
64+
65+
```
66+
this.destinationRoot(`./${this.options.projectDirectory}`);
67+
```
68+
69+
Changes the destination directory so that files are created in the directory whose path is entered in arguments.
70+
71+
### 4. install()
72+
73+
Installs the dependencies in project directory listed in templates/package.json.
74+
75+
The `toCamelCase` function converts the human name of the project into camel case.
76+
77+
# generator/app/validator.js
78+
79+
The validators not only validate the user inputs but also perform other functions like inporting build file, installing npm packages, making project directory etc.
80+
81+
### 1. storeArg
82+
83+
Makes the project directory whose path is entered in arguments while running the generator. If the generator fails to create a directory it will check if directory already exists before throwing an error to user. In case, this also fails, the generator will throw an error.
84+
85+
Note: We can access the user input of the current question in the `props` parameter, there is no need to explicitly send this while calling validator function.
86+
87+
```
88+
async function(props) {
89+
projectDirectory = props;
90+
if (projectDirectory.trim() === ".") {
91+
return true;
92+
}
93+
94+
let res = await executeCommand("mkdir " + projectDirectory)
95+
.then(() => true)
96+
.catch(async () => {
97+
let tryAgain = await executeCommand(
98+
"ls " + projectDirectory,
99+
"checkDirExistence"
100+
)
101+
.then(() => true)
102+
.catch(err => {
103+
return chalk.red(
104+
`Oops! We encountered an error. Please see below for the more details - \n${chalk.yellow(
105+
err
106+
)}\n.Try this - cd into that directory and run ${chalk.cyan(
107+
"`yo @biojs/biojs-webcomponents .`"
108+
)}.`
109+
);
110+
});
111+
return tryAgain;
112+
});
113+
return res;
114+
};
115+
```
116+
117+
Used in `initialPrompts`.
118+
119+
### 2. packageName
120+
121+
Checks whether a package exists and shows it description if it does otherwise throws an error, uses the `npm view <package-name>` command provided by npm to do this.
122+
123+
Used in `installNpmPackagePrompts` (to install component as npm package) as well as `npmPrompts` (to import the build file from npm).
124+
125+
### 3. version
126+
127+
Checks whether a version is valid or not using the `npm view <package-name>@<version>` command.
128+
129+
```
130+
async function(props, answers) {
131+
.....
132+
.....
133+
..
134+
};
135+
```
136+
137+
The second parameter contains the `answer hash` (all the answers by user upto the previous question), like `props` there is no need to send it explicitly while calling the validator function.
138+
139+
Used in `npmPrompts` (to import the build file from npm).
140+
141+
### 4. checkVersionAndInstallComponent
142+
143+
Validates the version and installs the component from npm if version is valid, throws an error otherwise.
144+
145+
### 5. directoryName
146+
147+
The build file is imported in a separate directory whose default name is `component-dist`, otherwise user can enter any name of their choice. If the directory with the same name already exists it shows an error and provides the following options -
148+
149+
1. Overwrite the contents the of the existing directory.
150+
2. Make a new directory with a new name.
151+
152+
### 6. importBuildFileFromNPM
153+
154+
After user enters the package name and version and they are validated, the user is shown a URL (using JSDelivr - https://www.jsdelivr.com/package/npm/<package-npm>?version=<version>) and asked to go to that URL which contains the directory of that package, find the build file and paste its URL, the validator `importBuildFileFromNPM` downloads that file.
155+
156+
### 7. importBuildFileLocally
157+
158+
Copies and pastes the build file whose path is entered in the prompt.
159+
160+
### 8. toolNameComputer
161+
162+
Checks whether the toolNameComputer is formatted correctly using a regular expression.
163+
164+
### 9. toolNameHuman
165+
166+
Checks whether the toolNameHuman is formatted correctly using a regular expression.
167+
168+
Note - The function `executeCommand` uses the `exec` command to execute the asynchronous tasks like importing build file, installing component, etc. The parameter `type` is used to stop unnecessary output from logging and show the output to user only when its necessary.
169+
170+
One more reason the validators are in a separate file is because to test the generator, we need to test if the validators are working correctly and if they are defined like `validate: function promptValidator() {...}`, it makes it impossible to test them.
171+
172+
`ora` is used to show the loader whenever an asynchronous task is performed and `chalk` is used to highlight the messages, output and errors using colors.
173+

generators/app/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ module.exports = class extends Generator {
3434
)
3535
);
3636

37-
// First prompt
37+
// Primary prompts
3838
const initialPrompts = [
3939
{
4040
type: "input",

0 commit comments

Comments
 (0)