Yeoman 生成器添加新文件生成现有项目

Yeoman generator add a new file generated exsiting project

我有 yeoman 生成器,它成功生成了一个简单的项目。

我希望 项目生成之后,稍后使用将能够在 app 下生成新文件 deployment.yaml文件夹,但是它需要从主生成器读取一些数据 例如 appName 因为子生成器需要生成一个新文件 在生成的应用程序中。

例如yo tdk

此命令生成一个新项目

当我 运行 yo tdk:event (或类似的东西)时,它会在项目 app 文件夹

中生成一个新文件

为了说明,我创建了这个非常简单的生成器

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
    );
  }
};

这个生成器有两个简单的问题

  1. 应用名称
  2. 服务名称

并且它会生成一个类似

的项目
myapp   /root
 -app   /folder
  - service.yaml   /single file at the project generation

生成的 service.yaml 如下所示:

apiVersion: v1
kind: Service
metadata:
  name: <%= appName %>
spec:
  selector:
    app: <%= srvName %>
  ports:
    - protocol: TCP
      port: 80

现在用这个 service.yaml 文件生成项目后 我想在稍后(项目生成后)在应用程序文件夹

下添加新文件deployment.yaml

deployment.yaml

apiVersion: v1
kind: Deployment
metadata:
  name: <%= appName %>  //this is the appname from the project generation

spec:
  replicas: <%= replica %>
  selector:
    app: <%= srvName %>

appNamesrvName 来自 主生成器, (我看到有选项可以在子生成器之间共享数据 https://yeoman.io/authoring/storage.html,不确定如何在生成器之间共享它) replica 应该来自 new/sub 生成器

这是生成后的项目结构

myapp   /root
 -app   /folder
  - service.yaml      /single file at the project generation
  - deployment.yaml   / new file added to the project under app folder

喜欢的用户开始另一个 generator/sub 并有一个新问题,例如how much replicas do you want?然后生成文件。

我该怎么做?

更新 这是我的项目结构

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

更新

当我通过像

这样的程序调用子生成器时

const yeoman = require('yeoman-environment'); const env = yeoman.createEnv();

env.lookup(function () {
    env.run("tdk:deploy", {
        replicas: 100
    }, (err) => {
        console.log("done", err);
    });
});

我收到错误:

out from config undefined : undefined //undefind来自子生成器的控制台

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)

我在子生成器代码中放了一个console.log,比如

  initializing() {
    this.srvName = this.config.get("srvName");
    this.appName = this.config.get("appName");
    console.log("out from config", this.srvName, ":", this.appName);
  }

当我 运行 子生成器时,我得到了空配置(来自 .yo-rc.json) 在检查 .yo-rc.json 时。我能够看到来自主生成器的条目,数据已存储,但是当我从程序中 运行 它时,它找不到它......有什么想法吗?

这是两个项目的 link(非常基本的 yeoman 生成器,证明了这一点)只需要 运行 npm install 两个项目 对于生成器 运行 也 npm link.

最后:生成一个工程,其中包含两个文件

1. service.yaml   // generated from the main generator
2. deployment.yaml - // generated from sub generator with the properties from the main & sub generator

目前,deployment.yaml 文件未生成

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

我做错了什么? :(

如果有办法从子生成器读取 .yo-rc.json ,它可以帮助

您可以像这样在主生成器的 configuring 中设置要配置的值:

configuring() {
  this.config.set('appName', this.props.appName);
  this.config.set('srvName', this.props.srvName);
}

并读取子生成器中的值:

initializing() {
  this.srvName = this.config.get("srvName");
  this.appName = this.config.get("appName");
}

因此您可以在写入时通过 this.srvNamethis.appName 访问这些值。

示例代码:

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,
      }
    );
  }
};

和命令:

yo <name主项目生成

yo <name>:deploy 请求副本并创建 deployment.yaml


不使用yo执行子生成器:

var yeoman = require("yeoman-environment");
var env = yeoman.createEnv();

env.lookup(function () {
  env.run("<name>:deploy", {
      replicas: 100
  }, (err) => {
    console.log("done", err);
  });
});

和一个示例子生成器,如果值是通过选项传递的,则跳过问题 (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,
      }
    );
  }
};