component-creator-cli

Define and generate automatically your own custom component from CLI (like the angular CLI)


Keywords
component, creator, generator, architecture, cli, domain-driven-design
License
MIT
Install
npm install component-creator-cli@5.0.0

Documentation

Installation

Run CLI command from eveywhere

Install component-creator-cli as global dependency

  npm i -g component-creator-cli      
  • For run any command use : $ ccc keyword

Run CLI command from your project

Install component-creator-cli as dev-dependency

  npm i -D component-creator-cli      
  • For run any command use : $ ngx ccc keyword

Component creator CLI

NPM Version
NPM Downloads
Install Size
Issues Licence

Are you interested in the architecture of your project?
Do you do Domain Driven Design (DDD), Clean Architecture, React or simply MVC?
If YES, then you will probably generate a project with repeating components that will have the same file structure.
And you will reuse these paterns throughout the construction of your project architecture. (And even after) !

Therefore, in order to save time on the creation of your architecture and improve your workflow, you can use "Component creator CLI" to generate your personalized component in 1 second! (via the command line)

1- Create your custom generic template
2- And run the CLI generate command to generate your component at the chosen locations.
(It's like the Angular CLI, with your own custom components !)

I- CLI Features

# Meaning
#0a192f Implemented
#f8f8f8 Not yet Implemented
  • green Create your custom template
    • green Define the files created by the template
    • green Define the files content
    • green Place the generic replacement keyword
    • greenChoose the formatting convention for your generic keyword
    • green Configure component work directory target
    • green Configure component work directory extension
  • green Generate your own custom component
    • green Automatically Replace generic keyword
    • green Automatically Formate generic keyword
    • green Automatically Handle import path
  • red Delete created component
  • green List all template available
  • green Generate an example template

II- CLI Demo

Gif incomming
Demo animation cli

A- Create component

These 3 commands are the same :

   $ ccc generate extravagant order      
   $ ccc g extravagant user      
   $ ngx ccc generate smartphone      

These commands will generate three components based on a custom "extravagant" template.
The creation location is configured upstream (in the template config file ).
Here are the generated components :

FancifulEntities/      
β”œβ”€ my-extravagant-order/      
β”‚  β”œβ”€ interfce-order.ts                
β”‚  β”œβ”€ show-order-formated.html      
β”‚  β”œβ”€ order-beauty.css      
β”‚  β”œβ”€ test-my-order-please.test.ts      
β”‚  └─ order.js      
β”‚        
β”œβ”€ my-extravagant-user/      
β”‚  β”œβ”€ interfce-user.ts                
β”‚  β”œβ”€ show-user-formated.html      
β”‚  β”œβ”€ user-beauty.css      
β”‚  β”œβ”€ test-my-user-please.test.ts      
β”‚  └─ user.js      
β”‚        
β”œβ”€ my-extravagant-smartphone/      
β”‚  β”œβ”€ interfce-smartphone.ts                
β”‚  β”œβ”€ show-smartphone-formated.html      
β”‚  β”œβ”€ smartphone-beauty.css      
β”‚  β”œβ”€ test-my-smartphone-please.test.ts      
β”‚  └─ smartphone.js      
      

See more examples there

III- CLI Reference

Definitions:

  • Template : A template is a way of writing an entity with some information β€œleft generic”, for the CLI to fill in later, when we actually use it.
  • Component : A component is built version of a template

A- Init CLI

  $ ccc init      

This command initializes the CLI :

  • If this is the first use : it create config dir and an example template.
  • Otherwise, it checks the validity of existing templates and updates the cache.

B- Create component

  $ ccc generate <template-name> <replacement-value> [options]      
  $ ccc generate <template-name> <replacement-value> [options]      

This command will generate component based on template.

Arguments : generate

Argument Type Description
<template-name> string Required. Name of template to use.
<replacement-value> string Required. Replacement value used to replace the generic keyword in brackets

Options : generate

Option Short Type Description Default Value
--subdomain -s string Optional. Path of subdomain. It should be relative to componentWorkDir or rootWorkDir. The subdomain will be placed between the componentWorkDir and rootWorkDir none

C- List all templates

  $ ccc list      

This command lists all available templates

D- Display help interface

  $ ccc --help      

This command displays a command line help interface

IV- Generics keywords

The genereric keywords are recognized by the CLI and replaced by the reclacement value provided.

The value contained in generic keyword defines formatting result of replacement value argument :

Keyword Formatting Exemple
$none$ Don't apply formatting none
$camelCase$ Capitalized word except first one. exempleCase
$pascalCase$ Capitalized word. ExempleCase
$snakeCase$ Lower case string with underscores between words. exemple_case
$paramCase$ Lower cased string with dashes between words. exemple-case
$constantCase$ Upper case string with an underscore between words. EXEMPLE_CASE
$sentenceCase$ Lower cased string with spaces between words. exemple case

V- Template structure

A- Template directory structure

Global structure .ccc-templates/

my-project-directory/      
β”œβ”€ .ccc-templates/                   ---> CLI config directory      
β”‚  β”‚                
β”‚  β”œβ”€ my-extravagant-$none$/         ---> A custom template      
β”‚  β”‚  β”œβ”€ template-config.json        ---> Component config file      
β”‚  β”‚  β”œβ”€ interfce-$none$.ts        
β”‚  β”‚  β”œβ”€ show-$none$-formated.html        
β”‚  β”‚  β”œβ”€ $none$-beauty.css        
β”‚  β”‚  β”œβ”€ test-my-$none$-please.test.ts        
β”‚  β”‚  └─ $none$.js      
β”‚  β”‚       
β”‚  β”œβ”€ other$camelCase$Entity/         ---> Another template      
β”‚  β”‚  └─ ...      
β”‚  β”‚       
└─ ...      

The .ccc-templates/CLI configuration directory is mandatory and it must be created at the root of your project.
In this directory you will stored all your templates like my-extravagant-$none$ and other$camelCase$Entity/.

  • The keywords "[none]" and "[camelCase]" belongs to a family of generics keywords .
  • On running generate command : Every generic keywords will be replaced by the replacement value

Give template directory ID

B- Template config file properties

When you need to create multiple templates that share the same directory name, you can provide IDs to the directories to differentiate between them. Note :

  • IDs will not be used for component creation
  • ID is an optional feature

To define an id you must use a @ AFTER the root of your template : ./template_dir_name@TEMPLATE_DIR_ID

Examples :

.ccc-templates/      
β”‚  
β”œβ”€ $camelCase$@entity    
β”‚                
β”œβ”€ $camelCase$@entity-v2 
β”‚                
β”œβ”€ $camelCase$@aggregate                         
β”‚    
└─ ...      

./template-config.json

This configuration file is mandatory.

Field Type Description
template string Required & Unique. Template name.
componentWorkDirectory string | object Required. Used to set the component working directory. Should be relative to project directory

"componentWorkDirectory": string | object

As string :

Field Type Description
componentWorkDir string Required. Component working directory.

As object :

Field Type Description
componentWorkDir.rootWorkDir string Required. Component working directory. Should be relative to project directory
componentWorkDir .extensionWorkDir string Optional. Exention of component working directory. Should be relative to rootWorkDir

Use the "componentWorkDir" property as object when working with subdomains and want to create your components in different subdomains like example 3 with "--subdomain" option.

Examples

  • In all the examples we will create a component from this 'repository' template
  • All examples will use the same template
  • All the examples will use the same template and same files contoent
  • But all the examples will have different :
    • template configuration file
    • project tree directory

Same 'repository' template directory my-$paramCase$-repository/

./.ccc-templates/      
β”œβ”€ my-$paramCase$-repository/       
β”‚  β”œβ”€ template-config.json         
β”‚  β”œβ”€ interface-$paramCase$-repository.ts               
β”‚  β”œβ”€ implementation-$paramCase$-repository.ts      
β”‚  β”œβ”€ $paramCase$-repository.test.ts      
└─ ...     

Same 'repository' template file content : ./interface-$paramCase$-repository.ts

interface I$pascalCase$Repo {      
  anyProperty : string      
  hello : number      
  getAll$pascalCase$ () : Object[]      
  getOne$pascalCase$ () : Object      
}    

Example 1 : "Classic usage"

- project tree directory /my-project-1

my-project-1/      
β”œβ”€ .ccc-templates/       
β”œβ”€ src/                
β”‚  β”œβ”€ repos/      
β”œβ”€ node_modules/      
β”œβ”€ package.json    
└─ ...       

- 'repository' template config file ./template-config.json

  • define at /my-project-1/.ccc-templates/my-$paramCase$-repository/template-config.json
{      
  "template" : "repository",      
  "componentWorkDir" :"src/repos"      
}    

- command generate

ccc generate repository 'car'  

- component directory my-car-repository/ generated at /my-project-1/src/repos/my-car-repository

./my-car-repository/  
β”œβ”€ interface-car-repository.ts/    
β”œβ”€ implementation-car-repository.ts/    
└─ car-repository.test.ts/    

- component file content ./interface-car-repository.ts

interface ICarRepo {      
  anyProperty : string      
  hello : number      
  getAllCar () : Object[]      
  getOneCar () : Object      
}    

Example 2 : "Set directory extension in generate command"

- project tree directory /my-project-2

my-project-2/      
β”œβ”€ .ccc-templates/       
β”œβ”€ src/  
β”‚  β”œβ”€ domain/   
β”‚  β”œβ”€ infra/      
β”‚  β”‚  β”œβ”€ repos/   
β”‚  β”‚  β”œβ”€ mappers/     
β”‚  β”‚  β”œβ”€ .../    
β”œβ”€ node_modules/      
β”œβ”€ package.json    
└─ ...       

- 'repository' template config file ./template-config.json define at /my-project-2/.ccc-templates/my-$paramCase$-repository/template-config.json

{      
  "template" : "repository",      
  "componentWorkDir" :"src"      
}    

- command generate

ccc generate repository 'bus' -s ./infra/repos  

- component directory my-bus-repository/
generated at /my-project-2/src/infra/repos/my-bus-repository

./my-bus-repository/  
β”œβ”€ interface-bus-repository.ts/    
β”œβ”€ implementation-bus-repository.ts/    
└─ bus-repository.test.ts/    

- component file content ./interface-bus-repository.ts

interface IBusRepo {      
  anyProperty : string      
  hello : number      
  getAllBus () : Object[]      
  getOneBus () : Object      
}    

Example 3 : "Use 'componentWorkDir' config property as object"

- project tree directory /my-project-3

my-project-3/      
β”œβ”€ .ccc-templates/       
β”œβ”€ src/  
β”‚  β”œβ”€ boundedCtx1/   
β”‚  β”œβ”€ boundedCtx2/   
β”‚  β”œβ”€ boundedCtx3/   
β”‚  β”‚  β”œβ”€ domain/   
β”‚  β”‚  β”œβ”€ infra/   
β”‚  β”‚  β”‚  β”œβ”€ repos/     
β”‚  β”‚  β”‚  β”œβ”€ mappers/     
β”‚  β”‚  β”‚  β”œβ”€ .../    
β”œβ”€ node_modules/      
β”œβ”€ package.json    
└─ ...       

- 'repository' template config file ./template-config.json
define at /my-project-3/.ccc-templates/my-$paramCase$-repository/template-config.json

{      
"template" : "repository",      
"componentWorkDir" :{  
   "rootWorkDir" : "src",  
   "extensionWorkDir" : "infra/repos",  
 }     
}    

- command generate

ccc generate repository 'taxi' -s ./boundedCtx3  

- component directory my-taxi-repository/
generated at /my-project-3/src/boundedCtx3/infra/repos/my-taxi-repository

./my-taxi-repository/  
β”œβ”€ interface-taxi-repository.ts/    
β”œβ”€ implementation-taxi-repository.ts/    
└─ taxi-repository.test.ts/  

As we can see, the "--subdomain" command option allows to place a subdomain between the rootWorkDirand "extensionWorkDir" paths

- component file content ./interface-taxi-repository.ts

interface ITaxiRepo {      
anyProperty : string      
hello : number      
getAllTaxi () : Object[]      
getOneTaxi () : Object      
}    

License & Author

Lience : MIT
Author : @enzo-cora