I've yeoman generator which generate a simple sproject successfully.
I want that after the project generation, in latter time that the use will have the ability to generate a new file deployment.yaml
under the app
folder, however it needs to read some data from the main generator
for example appName
as the sub-generator needs to generate a new file
inside the generated application.
e.g. yo tdk
This command generates a new project
And when I run yo tdk:event
(or something similar) it will generate a new file inside the project app
folder
For illustration I've created this very simple generator
const Generator = require("yeoman-generator");
module.exports = class extends Generator {
prompting() {
this.props = {
appName: "my-app",
srvName: "my-service"
};
const prompts = [
{
name: "appName",
message: "Project name: ",
type: "input",
default: this.props.appName
},
{
name: "srvName",
message: "Service name: ",
type: "input",
default: this.props.srvName
}
];
return this.prompt(prompts).then(props => {
this.props = props;
});
}
writing() {
this.fs.copyTpl(
this.templatePath("app"),
this.destinationPath(this.props.appName),
this.props
);
}
};
This generator have two simple question
And it will generate a project like
myapp /root
-app /folder
- service.yaml /single file at the project generation
The generated service.yaml
looks like following:
apiVersion: v1
kind: Service
metadata:
name: <%= appName %>
spec:
selector:
app: <%= srvName %>
ports:
- protocol: TCP
port: 80
Now after the generation of the project with this service.yaml
file
I want in latter time (after the project generation)to add new file deployment.yaml
under the app folder
deployment.yaml
apiVersion: v1
kind: Deployment
metadata:
name: <%= appName %> //this is the appname from the project generation
spec:
replicas: <%= replica %>
selector:
app: <%= srvName %>
The appName
& srvName
are coming from the main generator,
(I saw that there is option to share data between sub generator
https://yeoman.io/authoring/storage.html , not sure how to share this between generators )
and the replica
should come from the new/sub generator
This is the project structure after the generation
myapp /root
-app /folder
- service.yaml /single file at the project generation
- deployment.yaml / new file added to the project under app folder
Like user start another generator/sub
and have a new question e.g. how much replicas do you want?
and then generates the file.
How can I do it ?
update This is my project strucutre
myapp
- node_modules
- package.json //here I declare the main-generator command -> tdk
- generators
-- app
---index.ts
--deployment
---index.ts
---package.json //here I declare the sub-generator command -> deploy
- node_modules
- package.json
-.yo-rc.json //here I see the data that I keep via config.set api
Update
When I call to the sub generator via program like
const yeoman = require('yeoman-environment'); const env = yeoman.createEnv();
env.lookup(function () {
env.run("tdk:deploy", {
replicas: 100
}, (err) => {
console.log("done", err);
});
});
I got error:
out from config undefined : undefined //the undefind is from the console in the sub-generator
done TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined
at validateString (internal/validators.js:125:11)
at Object.join (path.js:1037:7)
I put a console.log in the subgenerator code like
initializing() {
this.srvName = this.config.get("srvName");
this.appName = this.config.get("appName");
console.log("out from config", this.srvName, ":", this.appName);
}
And when I run the subgenerator I got empty config ( from the .yo-rc.json
)
while checking the .yo-rc.json . I was able to see the entry from the main generator, the data was stored but when I run it from the program it doesnt find it...any idea ?
This is the link for both project (very basic yeoman generator which demonstrate the point) just need to run npm install
for both projects
and for the generator run also npm link
.
At the end: a project should be generated with two files
1. service.yaml // generated from the main generator
2. deployment.yaml - // generated from sub generator with the properties from the main & sub generator
currently, the deployment.yaml
file is not generated
https://drive.google.com/drive/folders/1kBnZxpVcRR9qhGZagVtod7W4wFmt73C6
1 . generator-tdk - Generator and sub-generator
2. yeomanEnv - The code which is running the sub-generator to create the file inside the generated project
What am I doing wrong ? :(
if there is a way from the sub-generator to read the .yo-rc.json
, it can help
The . yo-rc. json file is a JSON file where configuration objects from multiple generators are stored. Each generator configuration is namespaced to ensure no naming conflicts occur between generators. This also means each generator configuration is sandboxed and can only be shared between sub-generators.
The Yeoman workflow comprises three types of tools for improving your productivity and satisfaction when building a web app: the scaffolding tool (yo), the build tool (Gulp, Grunt etc) and the package manager (like npm and Bower).
A generator is, at its core, a Node.js module. First, create a folder within which you’ll write your generator. This folder must be named generator-name (where name is the name of your generator). This is important, as Yeoman relies on the file system to find available generators.
Most importantly, Yeoman searches the directory tree for a .yo-rc.json file. If found, it considers the location of the file as the root of the project. Behind the scenes, Yeoman will change the current directory to the .yo-rc.json file location and run the requested generator there.
The generator system allows you to apply custom filters on every file writes. Automatically beautifying files, normalizing whitespace, etc, is totally possible. Once per Yeoman process, we will write every modified file to disk. This process is passed through a vinyl object stream (just like gulp ).
Run the yo generator command at the folder where you want to generate the generator project. You will be prompted to input the generator name and other details. The directory tree of the generator project will look like this: The generators\app\index.js file is the main entry of the generator.
You can set the values to config inside configuring
of the main generator like this:
configuring() {
this.config.set('appName', this.props.appName);
this.config.set('srvName', this.props.srvName);
}
and read the values inside the sub-generators:
initializing() {
this.srvName = this.config.get("srvName");
this.appName = this.config.get("appName");
}
So you'll have access to these values via this.srvName
and this.appName
upon writing.
Example code:
app/index.js:
const Generator = require("yeoman-generator");
module.exports = class extends Generator {
prompting() {
this.props = {
appName: "my-app",
srvName: "my-service",
};
const prompts = [
{
name: "appName",
message: "Project name: ",
type: "input",
default: this.props.appName,
},
{
name: "srvName",
message: "Service name: ",
type: "input",
default: this.props.srvName,
},
];
return this.prompt(prompts).then((props) => {
this.props = props;
});
}
configuring() {
this.config.set('appName', this.props.appName);
this.config.set('srvName', this.props.srvName);
}
writing() {
this.fs.copyTpl(
this.templatePath("app"),
this.destinationPath(this.props.appName),
this.props
);
}
};
deploy/index.js:
const Generator = require("yeoman-generator");
module.exports = class extends Generator {
initializing() {
this.srvName = this.config.get("srvName");
this.appName = this.config.get("appName");
}
prompting() {
this.props = {
replicas: 0,
};
const prompts = [
{
name: "replica",
message: "how much replicas do you want?",
type: "input",
default: this.props.replicas,
},
];
return this.prompt(prompts).then((props) => {
this.props = props;
});
}
writing() {
this.fs.copyTpl(
this.templatePath("deploy"),
this.destinationPath(this.appName),
{
srvName: this.srvName,
appName: this.appName,
...this.props,
}
);
}
};
and commands:
yo <name
for the main project generation
yo <name>:deploy
to ask for replicas and create deployment.yaml
To execute the sub-generator without the use of yo
:
var yeoman = require("yeoman-environment");
var env = yeoman.createEnv();
env.lookup(function () {
env.run("<name>:deploy", {
replicas: 100
}, (err) => {
console.log("done", err);
});
});
and a sample sub-generator that skips question if values are passed via options (deploy/index.js
):
const Generator = require("yeoman-generator");
module.exports = class extends Generator {
initializing() {
this.srvName = this.config.get("srvName");
this.appName = this.config.get("appName");
}
prompting() {
this.props = {
replicas: 0,
};
const prompts = [
{
name: "replicas",
message: "which app to generate?",
type: "input",
default: this.props.replicas,
when: !this.options.replicas, // disable the question if it's found in options
},
];
return this.prompt(prompts).then((props) => {
this.props = props;
// set values from options (if found)
this.props.replicas = this.options.replicas || this.props.replicas;
});
}
writing() {
this.fs.copyTpl(
this.templatePath("deploy"),
this.destinationPath(this.appName),
{
srvName: this.srvName,
appName: this.appName,
...this.props,
}
);
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With