Slush Vert.x Structure

Francesco Guardiani edited this page Aug 18, 2017 · 6 revisions

Table of Contents

Main components of slush-vertx

Generators

Generators are the most important scripts of slush-vertx. They:

  • Ask user info about its project
  • Generate metadata for template rendering
  • Load templates
  • Renders templates
  • Write files

Most of this features are provided with the help of built-in functions of slush-vertx

Generator structure

You can find generators source code inside src/generators. For every generator, there is a file called main.js that exports an object like the following:

module.exports = {
    name: "Generator name",
    description: "Generator description",
    generate: generationFunction,
    render: renderFunction,
    metadata: metadataFunction,
    hidden: false
};

When slush-vertx runs, It searches and loads main.js files inside src/generators subdirectories. Then It loads into the main menu the generators that exports an object with at least name and generate field.

After the user has choosen the generator, slush-vertx runs the generate function

Generation function

The generation function is the entry point for the generator. It's required to run the generator. To simplify the generation process usually It's splitted in a generation function and a rendering function.

It requests to the user all informations needed for generation, in particular the language and the build tool. To provide that functionality, a generation function use the Utils.processLanguage(languagesMetadata, project_info) function. This function elaborates an array of languages metadata and puts the results inside project_info object. Give a look at Project info and languages metadata to understand the role of this two objects

Then it runs the rendering function and write its results with Utils.writeFilesArraySync()

To simplify the creation of the generation function, there is a method called Utils.generateGenerationFunction(languagesMetadata, renderingFunction) that makes all the work

Project info and languages metadata

project_info is the main metadata object used for code generation. It's builded by slush-vertx before generator's generate function is called.

The languages metadata describes all variables of generator, but splitted for every language. Every single language metadata has this schema:

{
    name: "kotlin",
    build_tools: [
        metadata.build_tools.maven
    ],
    templates: {
        src: ["MainVerticle.kt", path.join("users", "UsersRouter.kt"), path.join("products", "ProductsRouter.kt")],
        test: ["BaseTest.kt", "ProductsTest.kt", "UsersTest.kt"]
    },
    resources_dir: metadata.resources_dir,
    dependencies: _.concat(
        metadata.dependencies.kotlin_dependencies,
        metadata.dependencies.kotlin_test_dependencies,
        metadata.dependencies.vertx_test_dependencies,
        [
            {
                group: "io.vertx",
                artifact: "vertx-web",
                version: constants.VERTX_VERSION
            },
            {
                group: "io.vertx",
                artifact: "vertx-web-client",
                version: constants.VERTX_VERSION,
                test: true
            }
        ]
    ),
    questions: [
        metadata.questions.package
    ],
    var_templates: {
        package: metadata.var_templates.package,
        main: metadata.var_templates.main_class,
        src_dir: metadata.var_templates.src_dir,
        test_dir: metadata.var_templates.test_dir
    }
}

For every language metadata, there are fields allowed and fields optional:

  • name (Required): Name of the language
  • build_tools (Required): Array of build tools allowed
  • templates (Required): [Array|Object] that provides informations about templates. It strongly depends on rendering function used
  • dependencies (Required): Array of dependencies definition. Every dependency object contains:
    • group, artifact and version of the dependency (Required)
    • test boolean that defines if dependency is for test scope or not
  • questions: List of inquirer's questions objects. Every questions answer is appended to project_info object.
  • var_templates: Object with description of Variables templates. After the processing, this variables are appended to project_info object.

Variables templates

var_templates object describes variables that needs additional processing after all questions. For example the Java source directory depends on package name, so It can be defined only after the user inputs the package name. It can also used to clean user input, for example removing unallowed characters.

The keys of var_templates are the variables names, while the values can be:

  • a sync lambda function with project_info as parameter and string as return value
  • a string template. To the rendering function all project_info object is passed

Utils.processLanguage(languagesMetadata, project_info)

This function gives life to all metadatas described before. It:

  • Asks what language you want
  • Asks what build tool you want
  • Asks other questions defined in questions field
  • Process variables templates
  • Builds project_info object

When It builds project_info object, It places inside:

  • project_name
  • All fields from choosen language metadata
  • build_tool that contains all metadata from choosen build tool
  • All answers to questions declared in questions
  • All processed variables templates

Now project_info is ready to be used from templates.

Rendering function

The sync rendering function provides additional metadata elaboration (sometimes via Metadata function) and renders templates. To use the rendering function in combination with Utils.writeFilesArraySync() (called by Generation function), this function returns an objects array:

[{
    "path": "/src/fileA.java",
    "content": "Content of fileA"
},{
    "path": "/src/fileB.md",
    "content": "Content of fileB"
}]

Inside Utils, you can find two functions to create a rendering function:

  • generateRenderingFunction(generator_directory_name): It wants templates as an array containing directories of templates and requires a src_dir field inside project_info. It renders templates passing to template engine the project_info object and prepend at all templates paths the src_dir. You can find an example of this function's usage inside Vert.x Starter Generator
  • generateComplexRenderingFunction(generator_directory_name): It permits to create groups of templates. It wants templates as an object with group names as keys and arrays of templates directories as values. It requires, for every group name, a [group_name]_dir field inside project_info. You can find an example of this function's usage inside Vert.x Web Server Starter

In both cases generator_directory_name is the name of directory where slush-vertx can find templates and templates directories are name of relative directories of templates. For example with this directory structure:

├── project_templates
│   └── starter_generator
│       ├── groovy
│       │   └── MainVerticle.groovy
│       ├── java
│       │   └── MainVerticle.java
│       ├── javascript
│       │   └── main.js
│       ├── kotlin
│       │   └── MainVerticle.kt
│       └── ruby
│           └── main.rb
└── src
    └── generators
        └── starter_generator
            └── main.js

generator_directory_name is starter_generator, and templates are searched inside project_templates/starter_generator/[language_choosen]/. So templates directory of MainVerticle.java is MainVerticle.java. Every subdirectory declared inside templates are preserved.

Templates

The generator's templates are inside project_templates directory. slush-vertx uses Handlebars.js together with Handlebars helpers as template engine.

Build tools

Templates for build tools are included inside slush-vertx. This table describes supported build tools/language combinations:

Build tool Java Kotlin Javascript Groovy Ruby
Maven :heavy_check_mark: :heavy_check_mark: :x: :heavy_check_mark: :heavy_check_mark:
Gradle :heavy_check_mark: :x: :x: :heavy_check_mark: :heavy_check_mark:
NPM :x: :x: :heavy_check_mark: :x: :x:
NPM with Jar packaging :x: :x: :heavy_check_mark: :x: :x:
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.