Skip to content

Commit

Permalink
Merge pull request #44 from expressots/feature/update-doc-ifaam
Browse files Browse the repository at this point in the history
Update controller doc
  • Loading branch information
rsaz committed Feb 28, 2024
2 parents b3f59af + db48d82 commit e638370
Show file tree
Hide file tree
Showing 4 changed files with 215 additions and 233 deletions.
104 changes: 48 additions & 56 deletions docs/overview/controller.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,27 +45,22 @@ As a result, DTOs help to segregate and filter the data being sent to the client

## Controller Class

The controller class in ExpressoTS represents the endpoint that you want to create for your application. You can define the route and HTTP method for the controller by using the `@controller()` decorator from the [Inversify Express Utils package](https://github.com/inversify/inversify-express-utils).
The controller class in ExpressoTS represents the endpoint that you want to create for your application. You can define the route and HTTP method for the controller by using the `@controller()` decorator from the [Decorator section](./decorators.md).

Each controller class contains a single method called `execute()` that handles the request and sends the response. This method is annotated with the **[@httpMethods()](./decorators.md)** decorators. Additionally, you can also annotate the parameters of the `execute()` method.
Each controller class contains a single method called `execute()` that handles the request and sends the response. This method is annotated with the **[http methods](./decorators.md#http-method-decorators)** decorators. Additionally, you can also annotate the parameters of the `execute()` method.

Here is an example of a simple ExpressoTS controller class:

```typescript
@controller("/")
class AppController {

@httpGet("/")
execute(@response() res: any) {
return res.send("Hello from ExpressoTS!");
}
@Get("/")
execute(@response() res: Response) {
return res.send("Hello from ExpressoTS!");
}
}
```

:::info
In the AppController class above we are using res as any (`res:any`), but the `res:Response` type from the `express` package is also available for use. This allows you to make use of all the methods that the **[Response](https://expressjs.com/en/4x/api.html#res)** type offers.
:::

## BaseController Class

We also power a controller class with the `BaseController` class that offers in the constructor a parameter that the developer can indicate what service or domain he is currently building. This helps the log system throw errors with more information about the context of the error and where the error occurred.
Expand All @@ -84,9 +79,9 @@ The signature of the `callUseCase` method:
callUseCase(useCase: any, res: any, successStatusCode: number);
```

- `useCase`: The use case that will be called. This use case is injected in the controller constructor.
- `res`: The response object from the express request.
- `successStatusCode`: The status code that will be sent to the client if the use case is executed successfully. Please see the **[Http Status Code](./status-code.md)** type for more information.
- `useCase`: The use case that will be called. This use case is injected in the controller constructor.
- `res`: The response object from the express request.
- `successStatusCode`: The status code that will be sent to the client if the use case is executed successfully. Please see the **[Http Status Code](./status-code.md)** type for more information.

The default response:

Expand All @@ -99,17 +94,14 @@ A more complete example of a controller class inheriting from the **BaseControll
```typescript
@controller("/")
class AppController extends BaseController {
constructor(private appUseCase: AppUseCase) {
super("app-controller");
}

@httpGet("/")
execute(@response() res: any): IAppResponseDTO {
return this.callUseCase(this.appUseCase.execute(),
res,
StatusCode.OK
);
}
constructor(private appUseCase: AppUseCase) {
super("app-controller");
}

@httpGet("/")
execute(@response() res: any): IAppResponseDTO {
return this.callUseCase(this.appUseCase.execute(), res, StatusCode.OK);
}
}
```

Expand All @@ -127,7 +119,7 @@ Here is an example of usage:
```typescript
@scope(BindingScopeEnum.Singleton)
@controller("/")
class CreateUserController extends BaseController { }
class CreateUserController extends BaseController {}
```

The controller above will be scoped as `Singleton` and will be shared across all requests.
Expand Down Expand Up @@ -174,30 +166,30 @@ Here is an example of use MVC approach, which contains a single controller class
```typescript
@controller("/product")
class ProductController {
@httpPost("/")
create(@response() res: any) {
return res.status(201).json({ message: "Product created" });
}

@httpGet("/")
list(@response() res: any) {
return res.status(200).json({ message: "Product listed" });
}

@httpGet("/:id")
get(@response() res: any) {
return res.status(200).json({ message: "Product get" });
}

@httpPatch("/:id")
update(@response() res: any) {
return res.status(200).json({ message: "Product updated" });
}

@httpDelete("/:id")
delete(@response() res: any) {
return res.status(200).json({ message: "Product deleted" });
}
@httpPost("/")
create(@response() res: any) {
return res.status(201).json({ message: "Product created" });
}

@httpGet("/")
list(@response() res: any) {
return res.status(200).json({ message: "Product listed" });
}

@httpGet("/:id")
get(@response() res: any) {
return res.status(200).json({ message: "Product get" });
}

@httpPatch("/:id")
update(@response() res: any) {
return res.status(200).json({ message: "Product updated" });
}

@httpDelete("/:id")
delete(@response() res: any) {
return res.status(200).json({ message: "Product deleted" });
}
}
```

Expand All @@ -207,9 +199,9 @@ class ProductController {

ExpressoTS is an MIT-licensed open source project. It's an independent project with ongoing development made possible thanks to your support. If you'd like to help, please consider:

- Become a **[sponsor on GitHub](https://github.com/sponsors/expressots)**
- Follow the **[organization](https://github.com/expressots)** on GitHub and Star ⭐ the project
- Subscribe to the Twitch channel: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)**
- Join our **[Discord](https://discord.com/invite/PyPJfGK)**
- Contribute submitting **[issues and pull requests](https://github.com/expressots/expressots/issues/new/choose)**
- Share the project with your friends and colleagues
- Become a **[sponsor on GitHub](https://github.com/sponsors/expressots)**
- Follow the **[organization](https://github.com/expressots)** on GitHub and Star ⭐ the project
- Subscribe to the Twitch channel: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)**
- Join our **[Discord](https://discord.com/invite/PyPJfGK)**
- Contribute submitting **[issues and pull requests](https://github.com/expressots/expressots/issues/new/choose)**
- Share the project with your friends and colleagues
74 changes: 36 additions & 38 deletions docs/overview/first-steps.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ We believe in the power of strongly typed languages, and **[TypeScript](https://

## Why TypeScript?

- Improved code quality: Strong typing helps to catch errors and bugs at compile time, rather than at runtime, which helps to improve the overall quality of the code. This can lead to fewer crashes and issues with the code in production.
- Improved code quality: Strong typing helps to catch errors and bugs at compile time, rather than at runtime, which helps to improve the overall quality of the code. This can lead to fewer crashes and issues with the code in production.

- Better scalability: Strong typing can help make code more scalable by allowing for easier refactoring and maintenance. This is because strong typing ensures that changes to the code are consistent and predictable, making it easier to add new features or modify existing ones.
- Better scalability: Strong typing can help make code more scalable by allowing for easier refactoring and maintenance. This is because strong typing ensures that changes to the code are consistent and predictable, making it easier to add new features or modify existing ones.

- Increased productivity: Strong typing can increase developer productivity by providing better tooling and editor support, such as code completion, type inference, and automatic refactoring. This can help developers write code faster and with fewer errors.
- Increased productivity: Strong typing can increase developer productivity by providing better tooling and editor support, such as code completion, type inference, and automatic refactoring. This can help developers write code faster and with fewer errors.

- Improved collaboration: Strong typing can make it easier for developers to collaborate by providing a shared understanding of the types and interfaces used in the codebase. This can help reduce misunderstandings and inconsistencies and make it easier for developers to work together on the same codebase.
- Improved collaboration: Strong typing can make it easier for developers to collaborate by providing a shared understanding of the types and interfaces used in the codebase. This can help reduce misunderstandings and inconsistencies and make it easier for developers to work together on the same codebase.

- Better documentation: Strong typing can help make code more self-documenting by providing a clear and concise description of the types and interfaces used in the code. This can help reduce the need for extensive comments and documentation, making the code easier to understand and maintain.
- Better documentation: Strong typing can help make code more self-documenting by providing a clear and concise description of the types and interfaces used in the code. This can help reduce the need for extensive comments and documentation, making the code easier to understand and maintain.

## Pre-requisites

Expand Down Expand Up @@ -49,8 +49,8 @@ expressots new <project-name> -t <template-name> -p <package-manager>
:::tip
ExpressoTS offers two options for project templates:

- Non-opinionated: Want to have the liberty to build and structure your project as you wish? Non opinionated template offers a very small footprint, with only the necessary files to get you started.
- Opinionated: Opinionated template is made for more complex projects, as it provides a more layered architecture.
- Non-opinionated: Want to have the liberty to build and structure your project as you wish? Non opinionated template offers a very small footprint, with only the necessary files to get you started.
- Opinionated: Opinionated template is made for more complex projects, as it provides a more layered architecture.

:::

Expand Down Expand Up @@ -92,8 +92,6 @@ project-name/
│ ├── providers/
│ │ └── application/
│ │ └── application.provider.ts
│ │ └── db-in-memory/
│ │ └── db-in-memory.provider.ts
│ ├── repositories/
│ │ └── user/
│ │ └── user-repository.ts
Expand Down Expand Up @@ -146,9 +144,9 @@ Below you can find some extra information about **[Providers](./providers.md)**,

Contain 2 providers:

- application: This provider is a class that extend from the Application class from @expressots/core that provides the application **[Life Cycle Hooks](application.md#lifecycle-hooks)**.
- application: This provider is a class that extend from the Application class from @expressots/core that provides the application **[Life Cycle Hooks](application.md#lifecycle-hooks)**.

- db-in-memory: This is a simple in-memory database provider that allows you to store data in memory. We use this provider in the User use cases to store and retrieve user data.
- db-in-memory: This is a simple in-memory database provider that allows you to store data in memory. We use this provider in the User use cases to store and retrieve user data.

:::info
InMemoryDB provider is an example supplied to help you prototype endpoints quickly without having to worry about setting up a database. It is not intended to be used in production. You can replace it with your own database provider.
Expand All @@ -158,16 +156,16 @@ InMemoryDB provider is an example supplied to help you prototype endpoints quick

The use cases in the Opinionated template are organized in 2 modules:

- AppModule and UserModule, providing some examples of usage of the ExpressoTS resources. For more information about modules, please check the **[Modules Section](./module.md)**.
- AppModule and UserModule, providing some examples of usage of the ExpressoTS resources. For more information about modules, please check the **[Modules Section](./module.md)**.

Here are the endpoints in each module:

- [AppModule]/app.controller: returns `Hello from ExpressoTS App`
- [UserModule]/user-create.controller: creates a new user in the in-memory database
- [UserModule]/user-delete.controller: delete a user by `id` in the in-memory database
- [UserModule]/user-find.controller: return one user from the in-memory database
- [UserModule]/user-findall.controller: returns all users from the in-memory database
- [UserModule]/user-update.controller: update a user info from the in-memory database
- [AppModule]/app.controller: returns `Hello from ExpressoTS App`
- [UserModule]/user-create.controller: creates a new user in the in-memory database
- [UserModule]/user-delete.controller: delete a user by `id` in the in-memory database
- [UserModule]/user-find.controller: return one user from the in-memory database
- [UserModule]/user-findall.controller: returns all users from the in-memory database
- [UserModule]/user-update.controller: update a user info from the in-memory database

#### Main

Expand All @@ -177,8 +175,8 @@ The `main.ts` includes an async function that will bootstrap the ExpressoTS appl

```typescript
async function bootstrap() {
const app = await AppFactory.create(container, App);
await app.listen(3000, ServerEnvironment.Development);
const app = await AppFactory.create(container, App);
await app.listen(3000, ServerEnvironment.Development);
}

bootstrap();
Expand All @@ -188,8 +186,8 @@ bootstrap();

```typescript
async function bootstrap() {
const app = await AppFactory.create(container, []);
await app.listen(3000, ServerEnvironment.Development);
const app = await AppFactory.create(container, []);
await app.listen(3000, ServerEnvironment.Development);
}

bootstrap();
Expand All @@ -199,23 +197,23 @@ bootstrap();

To bootstrap an ExpressoTS application, there are two ways:

- Non-opinionated template using the AppFactory to creates an instance of the default ExpressoTS adapter which is the Express.js. User can directly pass an array of middleware to the `AppFactory.create` method, which will be responsible for creating an Expressjs application with the provided middleware. This method of creating an ExpressoTS application exposes the Expressjs application instance, which can be used to add additional middleware or to configure the Expressjs application.
- Non-opinionated template using the AppFactory to creates an instance of the default ExpressoTS adapter which is the Express.js. User can directly pass an array of middleware to the `AppFactory.create` method, which will be responsible for creating an Expressjs application with the provided middleware. This method of creating an ExpressoTS application exposes the Expressjs application instance, which can be used to add additional middleware or to configure the Expressjs application.

```typescript
async function bootstrap() {
const app = await AppFactory.create(container, [cors(), helmet()]);
await app.listen(3000, ServerEnvironment.Development);
const app = await AppFactory.create(container, [cors(), helmet()]);
await app.listen(3000, ServerEnvironment.Development);
}

bootstrap();
```

- Opinionated template using the AppFactory to create an AppExpress application. By using the App (AppExpress) class, you can take advantage of its built-in mechanisms for controlling the **[application life cycle hooks](application.md#application-lifecycle-hooks)**, such as injecting and executing services before, after, and during application shutdown.
- Opinionated template using the AppFactory to create an AppExpress application. By using the App (AppExpress) class, you can take advantage of its built-in mechanisms for controlling the **[application life cycle hooks](application.md#application-lifecycle-hooks)**, such as injecting and executing services before, after, and during application shutdown.

```typescript
async function bootstrap() {
const app = await AppFactory.create(container, App);
await app.listen(3000, ServerEnvironment.Development);
const app = await AppFactory.create(container, App);
await app.listen(3000, ServerEnvironment.Development);
}

bootstrap();
Expand All @@ -242,8 +240,8 @@ Read more about the modules in the **[Modules](module.md)** section.
const appContainer = new AppContainer();

const container: Container = appContainer.create([
// Add your modules here
AppModule,
// Add your modules here
AppModule,
]);
```

Expand All @@ -253,8 +251,8 @@ The controller layer handles incoming requests and returns appropriate responses

```typescript
const AppModule: ContainerModule = CreateModule([
// Add your controllers here
AppController,
// Add your controllers here
AppController,
]);
```

Expand Down Expand Up @@ -302,9 +300,9 @@ ExpressoTS is a versatile framework that is not bound to any specific platform o

ExpressoTS is an MIT-licensed open source project. It's an independent project with ongoing development made possible thanks to your support. If you'd like to help, please consider:

- Become a **[sponsor on GitHub](https://github.com/sponsors/expressots)**
- Follow the **[organization](https://github.com/expressots)** on GitHub and Star ⭐ the project
- Subscribe to the Twitch channel: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)**
- Join our **[Discord](https://discord.com/invite/PyPJfGK)**
- Contribute submitting **[issues and pull requests](https://github.com/expressots/expressots/issues/new/choose)**
- Share the project with your friends and colleagues
- Become a **[sponsor on GitHub](https://github.com/sponsors/expressots)**
- Follow the **[organization](https://github.com/expressots)** on GitHub and Star ⭐ the project
- Subscribe to the Twitch channel: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)**
- Join our **[Discord](https://discord.com/invite/PyPJfGK)**
- Contribute submitting **[issues and pull requests](https://github.com/expressots/expressots/issues/new/choose)**
- Share the project with your friends and colleagues
Loading

0 comments on commit e638370

Please sign in to comment.