@rafaelmedrib/tronco v1.1.2
Tronco
A boilerplate generator lib to streamline the process of class creation using:
- IoC
- State Design Pattern
- Feature Flags
The objective is to simplify and standardize the state management to facilitate working with a singe main branch (like in trunk based development).
Installation
npm install -g @rafaelmedrib/tronco
The boilerplate code generated by tronco depends on the following libraries:
- tsyringe
- reflect-metadata
- change-case-all It does not install them automatically. In order to use the generated code, you must install them manually.
npm install tsyringe reflect-metadata change-case-all
Usage
To run the generator, simply run the following command in the root of your project:
tronco
The CLI will prompt you to input the name of the class you want to generate and where you want to save it. The file structure generated will be as follows:
root/
├─ src/
│ ├─ types/
│ │ ├─ business/
│ │ │ ├─ StateDependentClass.d.ts
│ │ │ ├─ index.ts
│ ├─ business/
│ │ ├─ StateDependentClass/
│ │ │ ├─ state/
│ │ │ │ ├─ DefaultState.ts
│ │ │ │ ├─ index.ts
│ │ │ ├─ StateDependentClass.ts
│ │ │ ├─ index.ts
├─ start.ts
├─ feature_toggles.json
The business
folder in the example could be anything you want, like domain
, usecase
, feature
, etc. The StateDependentClass
is the name of the class you input in the CLI.
Let's breakdown the structure:
types/**/StateDependentClass.d.ts
This is a good place from where to start. It contains the interface of the class you want to implement. As default it will contain the a single method execute
that will be implemented in the StateDependentClass.ts
file.
export namespace IStateDependentClass {
export interface Context {
execute(): void;
}
export type State = Context;
}
Note that the State
type is an alias for the Context
interface.
StateDependentClass.ts
This is the main file of the class. The class itself has no logic, it only delegates the execution to the state. The state is injected using the IoC container.
// other imports...
import './state'
const BUSINESS = 'StateDependentClass';
container.register(BUSINESS, {
useFactory: (container) => {
const config = getContainerConfig(BUSINESS)
return container.resolve(config)
}
})
@injectable()
export class StateDependentClass implements IStateDependentClass.Context {
constructor(
@inject(BUSINESS)
private state: IStateDependentClass.State
) {}
execute() {
this.state.execute()
}
}
Note the import './state'
line. This is necessary to load the state into the IoC container.
The class will be registered and will be resolved using a factory function that will return the state configured in the feature_toggles.json
file.
state/DefaultState.ts
As default, tronco will generate a DefaultState
class that implements the State
interface. It contains only one method execute
that will be called by the StateDependentClass
when the execute
method is called. Here is where you should put the logic of the class. Initially, it will throw an error.
@registry([{
token: 'DefaultState',
useClass: DefaultState
}])
export class DefaultState implements IStateDependentClass.State {
execute() {
throw new Error('Method not implemented.');
}
}
feature_toggles.json
This file contains the configuration of the class. It is a simple JSON file that maps the class name to the state that should be used.
{
"business": {
"StateDependentClass": {
"state": "DefaultState",
"metadata": [
{
"issue": "https://example.jira.issue.com/IC-1236",
"name": "DefaultState",
"description": "Implemented the DefaultState for handling the StateDependentClass requests",
"tags": ["default", "example"]
}
]
}
}
}
Note that, by default, tronco will add any new states to the metadata but will not change the state being used.
start.ts
This is the code that pre-loads the configured states as environment variables and then proceeds to initialize the application through the entrypoint at src/index.ts
.
Roadmap
v1.x
- Map the project structure;
- Create the templates
- Create the prompts;
- Add a workflow example to the README;
v2.x
- Use symbol as token to avoid name collision;