¿Qué es Plop?

Plop es un file generator tool system que te permite definir un script para generar todos los archivos boilerplate para ti. De forma similar a cómo funciona Angular schematics, puedes definir un grupo de acciones que generará el código pre-definido de forma automática o respondiendo a algunos CLI prompts.

Para empezar necesitarás definir un plopfile.js que contendrá una función que recibirá un objeto plop con acceso a todos los métodos para generar el código.

module.exports = function (plop) {
    plop.setGenerator('components', {
        description: 'This will generate the components folder',
        prompts: [{
            type: 'input',
            name: 'name',
            message: 'type the name for your components folder'
        }],
        actions: [{
            type: 'add',
            path: 'src/components/{{name}}.component.js',
            templateFile: 'plop-templates/components.hbs'
        }]
    });
};
  • Antes de nada usaremos la función .setGenerator con 'components' como nombre del generador, y si queremos disparar este generador usaremos plop components.
  • Después, en el array prompts definiremos un array de InquirerQuestion, más adelante podríamos usar los valores de entrada para esta pregunta cómo parámetros en nuestros templates.
  • Por último, actions, que acepta un array de ActionConfig, estas acciones actuarán sobre los archivos que crearemos y los adaptará a nuestras necesidades.

También deberemos añadir una nueva carpeta donde almacenar nuestro template. La llamaré plop-templates y le añadiré un nuevo archivo components.hbs.

<br />{{name}}

Tendremos la siguiente estructura:

initial folder structure

Ahora si vamos a la console, dentro de nuestra carpeta donde tenemos el archivo plopfile y escribimos plop components se nos preguntará 'type the name for your components folder' que es el mensaje que hemos definido en la clave message para el objeto prompts array. Tras responderlo, se generará una carpeta con la respuesta proporcionada; en mi caso era test-components.

Después de este paso, tendremos la siguiente estructura:

folder structure

Y si abrimos el archivo generado test-components.js comprobaremos que la variable {{name}} ha sido modificada con el nombre proporcionado en consola:

test-components

Cuando usar Plop

Ahora que hemos visto un ejemplo de qué es Plop y cómo funciona, podemos empezar a crear templates más complejos para automatizar nuestras tareas. Por ejemplo, vamos a crear un nuevo generador que nos creará todo nuestro Redux boilerplate.

main.hbs

import { Action } from '@ngrx/store';

// constants

// actions

export type {{pascalCase fileName }}Actions =
;

constants.hbs

export const {{constantCase actionName}} = '[Talents] {{actionName}}';
export const {{constantCase actionName}}_FAIL = '[Talents] {{actionName}} Fail';
export const {{constantCase actionName}}_SUCCESS = '[Talents] {{actionName}} Success';

actions.hbs

export class {{pascalCase actionName}} implements Action {
public readonly type = {{constantCase actionName}};
constructor(public payload) {}
}

export class {{pascalCase actionName}}Fail implements Action {
public readonly type = {{constantCase actionName}}_FAIL;
constructor(public payload) {}
}

export class {{pascalCase actionName}}Success implements Action {
public readonly type = {{constantCase actionName}}_SUCCESS;
constructor(public payload) {}
}

typeExport.hbs

| {{pascalCase actionName}}
| {{pascalCase actionName}}Success
| {{pascalCase actionName}}Fail

ploplfile.js

module.exports = function (plop) {
    plop.setGenerator('actions', {
        description: 'This will generate the actions file',
        prompts: [
            {
                type: 'input',
                name: 'fileName',
                message: 'type the name for your file'
            },
            {
                type: 'input',
                name: 'actionName',
                message: 'type the name for your action'
            }
        ],
        actions: [
            {
                type: 'add',
                path: '{{pascalCase fileName}}.actions.ts',
                templateFile: 'plop-templates/actions/main.hbs',
                skipIfExists: true
            },
            {
                type: 'append',
                path: '{{pascalCase fileName}}.actions.ts',
                pattern: /(\/\/ constants)/g,
                templateFile: 'plop-templates/actions/constants.hbs',
            },
            {
                type: 'append',
                path: '{{pascalCase fileName}}.actions.ts',
                pattern: /(\/\/ actions)/g,
                templateFile: 'plop-templates/actions/actions.hbs',
            },
            {
                type: 'append',
                path: '{{pascalCase fileName}}.actions.ts',
                pattern: /(export\s+type\s[\w]+\s=)/g,
                templateFile: 'plop-templates/actions/typeExport.hbs',
            }
        ]
    });
};

Link to the repo