如何创建自定义蓝图?

Fab*_*ano 3 blueprint yeoman jhipster

我正在尝试为我的组织创建定制的 JHipster 蓝图。

我开始了我的旅程:

  1. 安装了 Yeoman v4.3.0
  2. 安装Jhipster v7.9.3
  3. 为我未来的蓝图创建了一个目录mkdir mygenerator && cd mygenerator
  4. 执行命令来创建新的蓝图:jhipster generate-blueprint
    • 仅选择子生成器服务器
    • 添加 cli:Y
    • 服务器生成器是并排蓝图吗:是
    • 服务器生成器是cli 命令吗:N
    • 选择任务:初始化、提示和配置

从这时起,我用 VS Code 打开了生成的蓝图项目,并注意到第一个问题,一些 jhipster 包无法解决:

  • 无法解析模块“generator-jhipster/esm/generators/server”的路径
  • 无法解析模块“generator-jhipster/esm/priorities”的路径

我还注意到为我创建的生成器与 JHipster Github 中现有的生成器有一点小小的区别,例如jhipster-dotnetcore生成器-jhipster-quarkus生成器-jhipster-nodejs:返回的函数async在引用的存储库中是常规函数(同步):

get [INITIALIZING_PRIORITY]() {
        return {
            async initializingTemplateTask() {},
        };
    }
Run Code Online (Sandbox Code Playgroud)

它在这个 Jhipster 版本中有什么区别吗?或者如果我以与jhipster-dotnetcore相同的方式返回就没有问题:

get initializing() {
        return {
            ...super._initializing(),
            setupServerConsts() {
                this.packagejs = packagejs;
            ...
Run Code Online (Sandbox Code Playgroud)

我假设这个细节并不重要,然后是异步函数并编写我的prompting函数以从用户/开发人员那里获取一些输入,以便替换模板文件中的值:

get [PROMPTING_PRIORITY]() {
        return {
            ...super._prompting(),
            async promptingTemplateTask() {
                const choices = [
                    {
                        name: 'OAuth 2.0 Protocol',
                        value: 'oauth2',
                    },
                    {
                        name: 'CAS Protocol',
                        value: 'cas',
                    },
                ];

                const PROMPTS = {
                    type: 'list',
                    name: 'authenticationProtocol',
                    message: 'Which authentication protocol do you want to use?',
                    choices,
                    default: 'oauth2',
                };

                const done = this.async();

                if (choices.length > 0) {
                    this.prompt(PROMPTS).then(prompt => {
                        this.authenticationProtocol = this.jhipsterConfig.authenticationProtocol = prompt.authenticationProtocol;
                        done();
                    });
                } else {
                    done();
                }
            },
        };
    }

Run Code Online (Sandbox Code Playgroud)
<%_ if (authenticationProtocol == 'oauth2') { _%>
    security:
        enable-csrf: true
        oauth2:
            client:
                clientId: ${this.baseName}
                clientSecret: Z3ByZXBmdGVy
                accessTokenUri: http://localhost:8443/oauth2.0/accessToken
                userAuthorizationUri: http://localhost:8443/oauth2.0/authorize
                tokenName: oauth_token
                authenticationScheme: query
                clientAuthenticationScheme: form
                logoutUri: http://localhost:8443/logout
                clientSuccessUri: http://localhost:4200/#/login-success
            resource:
                userInfoUri: http://localhost:8443/oauth2.0/profile
<%_ } _%>
    thymeleaf:
        mode: HTML
Run Code Online (Sandbox Code Playgroud)

模板/src/test/java/resources/config/application.yml.ejs

完成这一切后,我遵循了以下步骤:

  1. npm link在蓝图目录中运行。
  2. 为应用程序示例创建了一个新目录:mkdir appmygenerator && cd appmygenerator
  3. 使用我的蓝图启动了一个新的示例应用程序:jhipster --blueprint mygenerator --skip-git --skip-install --skip-user-management --skip-client回答所有问题。

在这里我有一些惊喜:

  1. 回答后What is the base name of your application?我收到此警告:[DEP0148] DeprecationWarning: Use of deprecated folder mapping "./lib/util/" in the "exports" field module resolution of the package at /...<my-generator-path>/node_modules/yeoman-environment/package.json. Update this package.json to use a subpath pattern like "./lib/util/*"
  2. 我的提示功能不知何故使一些问题重复出现,从问题Do you want to make it reactive with Spring WebFlux?直到Which other technologies would you like to use?
  3. 当我的提示最终显示时,最后一个选项前面有一条消息:CAS Protocol Run-async wrapped function (sync) returned a promise but async() callback must be executed to resolve

super._prompting()我对我的提示函数做了一些更改:删除了希望解决第2项的调用,并删除了async希望解决第3项的调用。

嗯……显然已经解决了。但是当 JHipster (或 Yeoman)尝试处理模板时,我收到一个新错误:

 An error occured while running jhipster:server#writeFiles
ERROR! /home/fabianorodrigo/Downloads/my-blueprint/generators/server/templates/src/test/resources/config/application.yml.ejs:47
    45|         favicon:
    46|             enabled: false
 >> 47| <%_ if (authenticationProtocol == 'oauth2') { _%>
    48|     security:
    49|         enable-csrf: true
    50|         oauth2:

authenticationProtocol is not defined
Run Code Online (Sandbox Code Playgroud)

为什么没有定义authenticationProtocol?我被困在这里了。我注意到的是,在我上面引用的所有 Jhipster 生成器中,提示函数设置的属性如“this.[property] = [value]”和“this.jhipsterConfig.[property] = [value]” ”并且在模板中引用了它们(只是属性的名称)并且它可以工作。

我缺少什么?为什么即使我在提示的函数中设置了属性“this.authenticationProtocol”,但在模板中却看不到?

msh*_*ima 6

  • Yeoman (yo/yeoman-generator/yeoman-environment) 不是必需的,也不应该成为依赖项,以避免依赖项树中的重复,除非您知道自己在做什么。JHipster 自定义它们,yeoman-test是测试需要的。
  • Unable to resolve path to moduleeslint-plugin-import 的一个错误
  • I also noticed that the generator created for me has a small difference from the existing generators in the JHipster Github, such as jhipster-dotnetcore, generator-jhipster-quarkus, generator-jhipster-nodejs.这些蓝图相当旧(v8/esm 的蓝图支持变化非常快)并且是完整的服务器/后端替代品,似乎您正在尝试添加cas支持。用例完全不同。
  • Does it make any difference in this Jhipster version or there is no problem if I return the same way as jhipster-dotnetcore?是的,get [INITIALIZING_PRIORITY]()是新的符号,并且INITIALIZING_PRIORITY可以>initializing代替initializing。解释就在这里。JHipster v8 将不支持旧的表示法。
  • ...super._prompting(),用于询问原始提示,由于这是一个并排蓝图,提示将被重复。
  • [DEP0148] DeprecationWarning: Use of deprecated folder mapping "./lib/util/"是 yeoman 环境中的一个错误,应该在下一版本中修复。
  • CAS Protocol Run-async wrapped function (sync) returned a promise but async() callback must be executed to resolve显示是因为您正在const done = this.async(); done();一起使用异步函数。 this.async()在 Promises 成为 js 默认值之前,它通过回调支持异步。

有一些使用新符号的蓝图可以用作灵感:nativeionicjooqentity-audit

我没有看到任何有关写入优先级的信息,因此看起来您正在覆盖现有模板,并且原始生成器将写入它。因此,您应该将配置注入到原始生成器中。

最终结果应该是这样的:

    get [INITIALIZING_PRIORITY]() {
        return {
            async initializingTemplateTask() {
                this.info('this blueprint adds support to cas authentication protocol');
            },
        };
    }

    get [PROMPTING_PRIORITY]() {
        return {
            async promptingTemplateTask() {
                await this.prompt({
                    type: 'list',
                    name: 'authenticationProtocol',
                    message: 'Which authentication protocol do you want to use?',
                    choices: [
                        {
                            name: 'OAuth 2.0 Protocol',
                            value: 'oauth2',
                        },
                        {
                            name: 'CAS Protocol',
                            value: 'cas',
                        },
                    ],
                    default: 'oauth2',
                }, this.blueprintStorage); // <- `this.blueprintStorage` tells the prompt function to store the configuration inside `.yo-rc.json` at the blueprint namespace.
            },
        };
    }

    get [CONFIGURING_PRIORITY]() {
        return {
            configuringTemplateTask() {
                // Store the default configuration
                this.blueprintConfig.authenticationProtocol = this.blueprintConfig.authenticationProtocol || 'oauth2';
            },
        };
    }

    get [LOADING_PRIORITY]() {
        return {
            loadingTemplateTask() {
                // Load the stored configuration, the prompt can be skipped so this needs to be in another priority.
                this.authenticationProtocol = this.blueprintConfig.authenticationProtocol;

                // Inject the configuration into the original generator. If you are writing the template by yourself, this may be not necessary.
                this.options.jhipsterContext.authenticationProtocol = this.blueprintConfig.authenticationProtocol;
            },
        };
    }
Run Code Online (Sandbox Code Playgroud)

  • 顺序是https://github.com/jhipster/generator-jhipster/blob/b3f304e3c9a7e0c520df1ded921c692770d5a851/lib/constants/priorities.cjs#L217-L243。优先目的位于jsdoc https://github.com/jhipster/generator-jhipster/blob/b3f304e3c9a7e0c520df1ded921c692770d5a851/generators/generator-base-blueprint.js#L186中。但由于有很多遗留方法,jsdoc 尚未发布。 (2认同)
  • _postConstruct 的实现是因为构造函数不支持异步方法,并且可能永远不会支持。这很重要,因为它在任务排队之前执行,因此它可以决定是否应忽略任务(例如:sbs或普通蓝图)以及组合生成器是否应在其之前排队。 (2认同)