From 9c74b58e3c1fd0ef07d73f2e18b66ae3c3b49559 Mon Sep 17 00:00:00 2001 From: Richard Zampieri Date: Tue, 5 Mar 2024 23:21:53 -0800 Subject: [PATCH] feat: add middleware section --- docs/overview/controller.md | 2 +- docs/overview/decorators.md | 14 +- docs/overview/dependencies.md | 44 ++--- docs/overview/di.md | 72 +++---- docs/overview/entities.md | 76 ++++---- docs/overview/error-handling.md | 137 ++++++------- docs/overview/middleware.md | 183 ++++++++++++++++++ docs/overview/providers.md | 61 +++--- docs/overview/render.md | 16 +- docs/overview/repositories.md | 86 ++++---- docs/overview/status-code.md | 34 ++-- docs/overview/test.md | 18 +- docs/overview/usecase.md | 45 ++--- .../current/overview/controller.md | 2 +- .../current/overview/decorators.md | 14 +- .../current/overview/dependencies.md | 44 ++--- .../current/overview/di.md | 72 +++---- .../current/overview/entities.md | 76 ++++---- .../current/overview/error-handling.md | 155 +++++++-------- .../current/overview/middleware.md | 183 ++++++++++++++++++ .../current/overview/providers.md | 63 +++--- .../current/overview/render.md | 22 +-- .../current/overview/repositories.md | 90 ++++----- .../current/overview/status-code.md | 36 ++-- .../current/overview/test.md | 18 +- .../current/overview/usecase.md | 47 ++--- 26 files changed, 965 insertions(+), 645 deletions(-) create mode 100644 docs/overview/middleware.md create mode 100644 i18n/pt/docusaurus-plugin-content-docs/current/overview/middleware.md diff --git a/docs/overview/controller.md b/docs/overview/controller.md index 0b8e22cd..385313b6 100644 --- a/docs/overview/controller.md +++ b/docs/overview/controller.md @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +sidebar_position: 6 --- # Controllers diff --git a/docs/overview/decorators.md b/docs/overview/decorators.md index 2fe31285..b16d1f28 100644 --- a/docs/overview/decorators.md +++ b/docs/overview/decorators.md @@ -1,5 +1,5 @@ --- -sidebar_position: 10 +sidebar_position: 11 --- # Decorators @@ -62,9 +62,9 @@ Here is a list of all parameter decorators available in ExpressoTS, along with t 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 diff --git a/docs/overview/dependencies.md b/docs/overview/dependencies.md index 96dc4941..864a4ef8 100644 --- a/docs/overview/dependencies.md +++ b/docs/overview/dependencies.md @@ -1,5 +1,5 @@ --- -sidebar_position: 12 +sidebar_position: 13 --- # Dependencies @@ -16,27 +16,27 @@ For now, we will keep a vigilant watch on included dependencies, using tools lik ## Utilities (Dev Dependencies) -- @commitlint/cli: Lint commit messages -- @commitLint/config-conventional: Lint commit messages -- @release-it/conventional-changelog: Generate changelog -- dotenv: Loads environment variables from .env file -- husky: Git hooks -- prettier: Code formatter -- eslint: Linting code -- ts-node-dev: Typescript runner -- tsconfig-paths: Resolve paths from tsconfig.json +- @commitlint/cli: Lint commit messages +- @commitLint/config-conventional: Lint commit messages +- @release-it/conventional-changelog: Generate changelog +- dotenv: Loads environment variables from .env file +- husky: Git hooks +- prettier: Code formatter +- eslint: Linting code +- ts-node-dev: Typescript runner +- tsconfig-paths: Resolve paths from tsconfig.json ## Core Packages -- express: Http server framework -- inversify: IoC container -- inversify-binding-decorators: Decorators for inversify -- reflect-metadata: Polyfill for metadata reflection API +- express: Http server framework +- inversify: IoC container +- inversify-binding-decorators: Decorators for inversify +- reflect-metadata: Polyfill for metadata reflection API ## Test -- vitest: Testing framework -- vite: Vitest's requirement +- vitest: Testing framework +- vite: Vitest's requirement --- @@ -44,9 +44,9 @@ For now, we will keep a vigilant watch on included dependencies, using tools lik 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 diff --git a/docs/overview/di.md b/docs/overview/di.md index 0c863c63..0bc6548e 100644 --- a/docs/overview/di.md +++ b/docs/overview/di.md @@ -1,5 +1,5 @@ --- -sidebar_position: 11 +sidebar_position: 12 --- # Dependency Injection @@ -10,19 +10,19 @@ Dependency Injection (DI) is a design pattern used in software development that Here are some of the key benefits of using Dependency Injection: -- Decoupling: DI helps to decouple the components of your application. Instead of components creating the objects they depend upon, these objects are passed in (injected) by a DI framework or container. This means components don't need to know about the inner workings of their dependencies, and dependencies can be swapped out without the component knowing or caring. +- Decoupling: DI helps to decouple the components of your application. Instead of components creating the objects they depend upon, these objects are passed in (injected) by a DI framework or container. This means components don't need to know about the inner workings of their dependencies, and dependencies can be swapped out without the component knowing or caring. -- Testability: DI makes unit testing easier. Because dependencies are injected, you can easily provide mock objects during testing. This allows each unit of code to be tested in isolation, with full control over its dependencies. +- Testability: DI makes unit testing easier. Because dependencies are injected, you can easily provide mock objects during testing. This allows each unit of code to be tested in isolation, with full control over its dependencies. -- Reusable Code: With DI, your classes are typically designed to work with interfaces rather than concrete classes. This means you can reuse the same class in different contexts, with different injected dependencies. +- Reusable Code: With DI, your classes are typically designed to work with interfaces rather than concrete classes. This means you can reuse the same class in different contexts, with different injected dependencies. -- Easier Maintenance and Increased Efficiency: By centralizing the creation of objects, and by reducing the amount of hard-coded class instantiation, maintenance becomes easier. When a class changes, you typically only need to update code in one place. +- Easier Maintenance and Increased Efficiency: By centralizing the creation of objects, and by reducing the amount of hard-coded class instantiation, maintenance becomes easier. When a class changes, you typically only need to update code in one place. -- Configurability: You can configure your application structure externally, typically through XML or similar files. This means you can modify the structure and dependencies of your components without having to modify the code itself. +- Configurability: You can configure your application structure externally, typically through XML or similar files. This means you can modify the structure and dependencies of your components without having to modify the code itself. -- Lifecycles and Scoping: manage the lifecycle of injected objects, and control their scoping (e.g., singleton scope, request scope). +- Lifecycles and Scoping: manage the lifecycle of injected objects, and control their scoping (e.g., singleton scope, request scope). -- Concurrency Management: containers can automatically handle service lifetimes in a concurrent environment, which can be a complex task to handle correctly without such a tool. +- Concurrency Management: containers can automatically handle service lifetimes in a concurrent environment, which can be a complex task to handle correctly without such a tool. In conclusion, DI is a technique that facilitates loose coupling, increased testability, and more maintainable and flexible code. @@ -36,26 +36,26 @@ Here is how ExpressoTS implements DI: Here is a breakdown of the DI components used in ExpressoTS: -| Components | Description | -| ------------ | ------------------------------------------------------------------------------------------------- | -| Container | The DI container of the ExpressoTS application. | -| Module | A container module is typically used to group related controllers and their dependencies together. | -| Controller | Primary interface between the client and server. Responsible to handle incoming requests. | -| Classes | Any other class part of the ExpressoTS ecosystem, for example, providers, entities, helpers, etc. | +| Components | Description | +| ---------- | -------------------------------------------------------------------------------------------------- | +| Container | The DI container of the ExpressoTS application. | +| Module | A container module is typically used to group related controllers and their dependencies together. | +| Controller | Primary interface between the client and server. Responsible to handle incoming requests. | +| Classes | Any other class part of the ExpressoTS ecosystem, for example, providers, entities, helpers, etc. | ### Resume -- Container have its default scope that can be override by the module. The default scope is `Request` scope. -- Defining a scope for a module forces all controllers under that module to have the same scope. -- Not defining a scope for a module allow controllers to have their own scope using `@scope()` decorator. -- All other registered classes such as providers, entities, helpers can have their specific scope based on the decorator used. -- Decorators: +- Container have its default scope that can be override by the module. The default scope is `Request` scope. +- Defining a scope for a module forces all controllers under that module to have the same scope. +- Not defining a scope for a module allow controllers to have their own scope using `@scope()` decorator. +- All other registered classes such as providers, entities, helpers can have their specific scope based on the decorator used. +- Decorators: -| Decorator | Description | -| ------------------ | ------------------------------------------------------------------------------ | -| @provide | Binds a class to a dependency injection container as RequestScope. | -| @provideSingleton | Binds a class to a dependency injection container as Singleton. | -| @provideTransient | Binds a class to a dependency injection container as Transient. | +| Decorator | Description | +| ----------------- | ------------------------------------------------------------------ | +| @provide | Binds a class to a dependency injection container as RequestScope. | +| @provideSingleton | Binds a class to a dependency injection container as Singleton. | +| @provideTransient | Binds a class to a dependency injection container as Transient. | ### Container @@ -85,30 +85,30 @@ Example of usage: ```typescript @provide(MyRequest) -class MyRequest { } +class MyRequest {} ``` #### Singleton ```typescript @provideSingleton(MySingleton) -class MySingleton { } +class MySingleton {} ``` #### Transient ```typescript @provideTransient(MyTransient) -class MyTransient { } +class MyTransient {} ``` :::tip To define scope bindings the enum BindingScopeEnum can be used. ::: -- `BindingScopeEnum.Singleton` - The dependency will be created once and will be shared across all requests. -- `BindingScopeEnum.Request` - The dependency will be created once per request. -- `BindingScopeEnum.Transient` - The dependency will be created every time it is requested. +- `BindingScopeEnum.Singleton` - The dependency will be created once and will be shared across all requests. +- `BindingScopeEnum.Request` - The dependency will be created once per request. +- `BindingScopeEnum.Transient` - The dependency will be created every time it is requested. --- @@ -116,9 +116,9 @@ To define scope bindings the enum BindingScopeEnum can be used. 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 \ No newline at end of file +- 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 diff --git a/docs/overview/entities.md b/docs/overview/entities.md index 2e823283..13e2dd4c 100644 --- a/docs/overview/entities.md +++ b/docs/overview/entities.md @@ -1,5 +1,5 @@ --- -sidebar_position: 9 +sidebar_position: 10 --- # Entities @@ -15,17 +15,17 @@ Here a simple example of an entity User and it's properties: ```typescript @provide(User) class User { - private id: string; - public name: string; - public email: string; + private id: string; + public name: string; + public email: string; - constructor() { - this.id = uuidv4(); - } + constructor() { + this.id = uuidv4(); + } - get Id(): string { - return this.id; - } + get Id(): string { + return this.id; + } } ``` @@ -51,8 +51,7 @@ If your entity has dependencies, you can inject them using the `@inject` decorat ```typescript @provide(User) class User { - - constructor(@inject("logger") private logger: Logger) {} + constructor(@inject("logger") private logger: Logger) {} } ``` @@ -63,10 +62,10 @@ Avoid marking constructors with primitive parameters as injectable. This is beca ```typescript @provide(User) class User { - name: string; - constructor(name: string) { - this.name = name; - } + name: string; + constructor(name: string) { + this.name = name; + } } ``` @@ -78,11 +77,11 @@ In many dependency injection (DI) systems, including InversifyJS, the DI contain Here are some of the reasons why constructors with primitive parameters can be problematic in DI: -- Ambiguity: If a class has a constructor that requires primitive types, the DI container won't know what values to inject. For example, if a class requires a number in its constructor, the DI container doesn't know what this number represents and what value it should have. +- Ambiguity: If a class has a constructor that requires primitive types, the DI container won't know what values to inject. For example, if a class requires a number in its constructor, the DI container doesn't know what this number represents and what value it should have. -- Inflexibility: A primitive value in the constructor implies that the value is a fixed part of the class. However, DI is often used to manage interchangeable parts of an application (e.g., different implementations of an interface). +- Inflexibility: A primitive value in the constructor implies that the value is a fixed part of the class. However, DI is often used to manage interchangeable parts of an application (e.g., different implementations of an interface). -- Non-descriptive: Primitive values are often non-descriptive and can lead to confusing code. For example, a constructor that takes two string parameters might raise questions like: What do these strings represent? Are there any specific formats or constraints on these strings? +- Non-descriptive: Primitive values are often non-descriptive and can lead to confusing code. For example, a constructor that takes two string parameters might raise questions like: What do these strings represent? Are there any specific formats or constraints on these strings? ## Entity proper injection @@ -93,31 +92,30 @@ Here is an example of a factory: ```typescript @provide(User) class User implements IEntity { - public id: string; - public name!: string; - public email!: string; + public id: string; + public name!: string; + public email!: string; - constructor() { - this.id = randomUUID(); - } + constructor() { + this.id = randomUUID(); + } } interface IUserFactory { - create(name: string, email: string): User; + create(name: string, email: string): User; } @provide(UserFactory) class UserFactory implements IUserFactory { - create(name: string, email: string): User { - const user = new User(); - user.name = name; - user.email = email; - return user; - } + create(name: string, email: string): User { + const user = new User(); + user.name = name; + user.email = email; + return user; + } } export { User, UserFactory }; - ``` Now `UserFactory` can be easily injected into other classes. @@ -130,9 +128,9 @@ As mentioned above, there are several other approaches, as long as you remain st 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 diff --git a/docs/overview/error-handling.md b/docs/overview/error-handling.md index 4fc4ec29..6a34b847 100644 --- a/docs/overview/error-handling.md +++ b/docs/overview/error-handling.md @@ -1,22 +1,22 @@ --- -sidebar_position: 14 +sidebar_position: 15 --- # Error Handling When it comes to error handling in Node.js TypeScript APIs, there are several best practices and approaches you can follow. ExpressoTS provides a simple and easy way to handle errors. -- We use HTTP status codes appropriately: HTTP **[status codes](./status-code.md)** are used to indicate the status of a response. It is important to use them appropriately in your API to indicate the success or failure of an operation. +- We use HTTP status codes appropriately: HTTP **[status codes](./status-code.md)** are used to indicate the status of a response. It is important to use them appropriately in your API to indicate the success or failure of an operation. -- We use a consistent error format: Define a consistent error format across your API so that consumers can easily understand and handle errors. +- We use a consistent error format: Define a consistent error format across your API so that consumers can easily understand and handle errors. -- We handle errors in middleware: Middleware functions are a great way to handle errors in a centralized location. +- We handle errors in middleware: Middleware functions are a great way to handle errors in a centralized location. -- We use try-catch blocks: Use try-catch blocks to handle synchronous errors in your code. If an error occurs in the try block, the catch block can handle it. Be sure to throw the error so that it can be handled by our error handling middleware. +- We use try-catch blocks: Use try-catch blocks to handle synchronous errors in your code. If an error occurs in the try block, the catch block can handle it. Be sure to throw the error so that it can be handled by our error handling middleware. -- We use async/await error handling: When using async/await, you can use try-catch blocks to handle synchronous errors in your code. However, you also need to handle any asynchronous errors that may occur. +- We use async/await error handling: When using async/await, you can use try-catch blocks to handle synchronous errors in your code. However, you also need to handle any asynchronous errors that may occur. -- We log errors: Logging errors is important for debugging and monitoring. +- We log errors: Logging errors is important for debugging and monitoring. ## Our approach @@ -67,22 +67,15 @@ This middleware function is used to handle errors that occur during request proc * @param res - The Express response object. * @param next - The Express next function for passing control to the next middleware function. */ -function defaultErrorHandler( - error: Error, - req: Request, - res: Response, - next: NextFunction -): void { - if (error instanceof AppError) { - res - .status(error.statusCode) - .json({ statusCode: error.statusCode, error: error.message }); - } else { - res.status(StatusCode.InternalServerError).json({ - statusCode: StatusCode.InternalServerError, - error: "An unexpected error occurred.", - }); - } +function defaultErrorHandler(error: Error, req: Request, res: Response, next: NextFunction): void { + if (error instanceof AppError) { + res.status(error.statusCode).json({ statusCode: error.statusCode, error: error.message }); + } else { + res.status(StatusCode.InternalServerError).json({ + statusCode: StatusCode.InternalServerError, + error: "An unexpected error occurred.", + }); + } } export default defaultErrorHandler; @@ -97,15 +90,15 @@ It logs the error, sets the status code, and sends a JSON response containing th ```typescript class FooClass { - constructor(private report: Report) {} - - execute() { - try { - // do something - } catch (error: any) { - this.report.Error(error, StatusCode.BadRequest, "your-service"); + constructor(private report: Report) {} + + execute() { + try { + // do something + } catch (error: any) { + this.report.Error(error, StatusCode.BadRequest, "your-service"); + } } - } } ``` @@ -114,43 +107,41 @@ Use case example: ```typescript @provide(CreateUserUseCase) class CreateUserUseCase { - constructor(private userRepository: UserRepository, private report: Report) {} - - execute(data: ICreateUserRequestDTO): ICreateUserResponseDTO | null { - try { - const { name, email } = data; - - const userAlreadyExists = await this.userRepository.findByEmail(email); - - if (userAlreadyExists) { - this.report.Error( - "User already exists", - StatusCode.BadRequest, - "create-user-usecase" - ); - } - - const user: User | null = this.userRepository.create( - new User(name, email) - ); - - let response: ICreateUserResponseDTO; - - if (user !== null) { - response = { - id: user.Id, - name: user.name, - email: user.email, - status: "success", - }; - return response; - } - - return null; - } catch (error: any) { - throw error; + constructor(private userRepository: UserRepository, private report: Report) {} + + execute(data: ICreateUserRequestDTO): ICreateUserResponseDTO | null { + try { + const { name, email } = data; + + const userAlreadyExists = await this.userRepository.findByEmail(email); + + if (userAlreadyExists) { + this.report.Error( + "User already exists", + StatusCode.BadRequest, + "create-user-usecase" + ); + } + + const user: User | null = this.userRepository.create(new User(name, email)); + + let response: ICreateUserResponseDTO; + + if (user !== null) { + response = { + id: user.Id, + name: user.name, + email: user.email, + status: "success", + }; + return response; + } + + return null; + } catch (error: any) { + throw error; + } } - } } ``` @@ -170,9 +161,9 @@ class CreateUserUseCase { 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 diff --git a/docs/overview/middleware.md b/docs/overview/middleware.md new file mode 100644 index 00000000..ec27a925 --- /dev/null +++ b/docs/overview/middleware.md @@ -0,0 +1,183 @@ +--- +sidebar_position: 5 +--- + +# Middleware + +Middleware is a function that has access to the request object (req), the response object (res), and the next middleware function in the application’s request-response cycle. The next middleware function is commonly denoted by a variable named next. + +Middleware can: + +- Run code. +- Modify request and response objects. +- Conclude the request-response process. +- Proceed to the next middleware in the sequence. +- Ensure to invoke next() if the middleware does not close the request-response loop to avoid stalling the request. + +:::info +ExpressoTS fully supports [Express](https://expressjs.com/) middleware. +::: + +## Adding Middleware + +ExpressoTS application supports adding middleware globally to the application as well as per route. It offers all the [middleware supported by Express Team](https://expressjs.com/en/resources/middleware.html) out-of-the-box through the use of `this.middleware` property. + +```typescript +@provide(App) +export class App extends AppExpress { + private middleware: IMiddleware; + + constructor() { + super(); + this.middleware = container.get(Middleware); + } + + protected configureServices(): void { + this.middleware.addBodyParser(); + this.middleware.addCors(); + this.middleware.addHelmet(); + } +} +``` + +:::caution +If you add a middleware that is not installed as dependency, the application will throw a warning message and continue to run. +::: + +### Global Middleware + +Middlewares can be added globally using the `App` class through the `this.middleware` property, using the out-of-the-box middleware list provided by Express Team: + +```typescript +protected configureServices(): void { + this.middleware.addBodyParser(); + this.middleware.addCors(); + this.middleware.addHelmet(); + } +``` + +For any other middleware, or a custom middleware, you can add it using the `this.middleware.addMiddleware()` method. Using the `addMiddleware` method, you can add any middleware from NPM Registry, custom Expressjs middleware or a custom ExpressoTS middleware. + +NPM Registry middleware: + +```typescript +this.middleware.addMiddleware(cors()); +``` + +Custom Expressjs middleware: + +```typescript +function myMiddleware(req: Request, res: Response, next: NextFunction) { + // Do something + next(); +} +``` + +```typescript +this.middleware.addMiddleware(myMiddleware); +``` + +Custom ExpressoTS middleware: + +```typescript +class CustomMiddleware extends ExpressoMiddleware { + use(req: Request, res: Response, next: NextFunction): void | Promise { + // Do something + next(); + } +} +``` + +```typescript +this.middleware.addMiddleware(new CustomMiddleware()); +``` + +### Route Middleware + +Middlewares can be added per route in the `App` class through the `this.middleware.addMiddleware()` method. You can add any middleware from NPM Registry, custom Expressjs middleware or a custom ExpressoTS middleware. + +```typescript +this.middleware.addMiddleware({ path: "/api", middlewares: [] }); +``` + +:::info +Each route can have multiple middlewares. +::: + +Or you add a middleware to a specific route in the `Controller` class through the `@controller()` and/Or `http Method` decorators. + +```typescript +@controller("/") +export class AppController { + @Post("", express.json()) + execute() { + return "Hello World"; + } +} +``` + +If you want to apply a middleware to all routes under a specific controller, you can add it to the `@controller()` decorator. + +```typescript +@controller("/app", express.json()) +export class AppController { + @Post("/create") + createApp() { + return "Create App"; + } + + @Patch("/update") + updateApp() { + return "Update App"; + } +} +``` + +## Creating Custom ExpressoTS Middleware + +To create a custom middleware, you need to extend the `ExpressoMiddleware` class and implement the `use` method. + +```typescript +class CustomMiddleware extends ExpressoMiddleware { + private isOn: boolean; + + constructor(isOn: boolean) { + super(); + this.isOn = isOn; + } + + use(req: Request, res: Response, next: NextFunction): void | Promise { + // Do something + if (this.isOn) { + next(); + } else { + res.status(403).send("Forbidden"); + } + } +} +``` + +Custom middleware allows you to pass parameters to the constructor and use them as options in the `use` method of your middleware. + +:::tip +Use ExpressoTS CLI to scaffold a custom middleware. +::: + +CLI command to scaffold a custom middleware: + +```bash +expressots g m <> +``` + +--- + +## Support the project + +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 diff --git a/docs/overview/providers.md b/docs/overview/providers.md index 3005ff59..80511d14 100644 --- a/docs/overview/providers.md +++ b/docs/overview/providers.md @@ -1,5 +1,5 @@ --- -sidebar_position: 7 +sidebar_position: 8 --- # Providers @@ -45,23 +45,21 @@ const enum EmailType { CreateUser, ChangePassword, Login, - RecoveryPassword + RecoveryPassword, } @provide(MailTrapProvider) class MailTrapProvider { - private transporter: Mail; constructor() { - this.transporter = nodemailer.createTransport({ host: Env.Mailtrap.HOST, port: Env.Mailtrap.PORT, auth: { user: Env.Mailtrap.USERNAME, - pass: Env.Mailtrap.PASSWORD - } + pass: Env.Mailtrap.PASSWORD, + }, }); } @@ -69,15 +67,15 @@ class MailTrapProvider { await this.transporter.sendMail({ to: { name: message.to.name, - address: message.to.email + address: message.to.email, }, from: { name: message.from.name, - address: message.from.email + address: message.from.email, }, subject: message.subject, - html: message.body - }) + html: message.body, + }); } sendEmail(emailType: EmailType): Promise { @@ -94,14 +92,14 @@ class MailTrapProvider { this.MailSender({ to: { name: "User", - email: Env.Mailtrap.INBOX_ALIAS + email: Env.Mailtrap.INBOX_ALIAS, }, from: { name: "ExpressoTS", - email: "noreply@expresso-ts.com" + email: "noreply@expresso-ts.com", }, subject: "Successfully logged in!", - body: "

Welcome to the system!

" + body: "

Welcome to the system!

", }); break; } @@ -121,21 +119,20 @@ Here is the use case implementation making use of the provider: ```typescript @provide(LoginUserUseCase) class LoginUserUseCase { + constructor(private mailTrapProvider?: MailTrapProvider) {} - constructor(private mailTrapProvider?: MailTrapProvider) { } - - execute(payload: ILoginUserRequestDTO): boolean { - const { email, password } = payload; - - if (isAuthenticated(email, password)) { - return true; - } + execute(payload: ILoginUserRequestDTO): boolean { + const { email, password } = payload; - // Implementation of the use case logic - mailTrapProvider?.sendEmail(EmailType.Login); - - return false; - } + if (isAuthenticated(email, password)) { + return true; + } + + // Implementation of the use case logic + mailTrapProvider?.sendEmail(EmailType.Login); + + return false; + } } export { LoginUserUseCase }; @@ -149,9 +146,9 @@ In the Use Case above we injected MailTrapProvider in the constructor making use 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 \ No newline at end of file +- 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 diff --git a/docs/overview/render.md b/docs/overview/render.md index 4435206a..051ad72a 100644 --- a/docs/overview/render.md +++ b/docs/overview/render.md @@ -1,5 +1,5 @@ --- -sidebar_position: 16 +sidebar_position: 17 --- # Render @@ -43,7 +43,7 @@ import { AppInstance, IHandlebars, ServerEnvironment } from "@expressots/core"; async function bootstrap() { AppInstance.create(container); - + // Setting handlebars as the view engine. AppInstance.setEngine({ extName: "hbs", @@ -83,9 +83,9 @@ npm i express-handlebars 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 \ No newline at end of file +- 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 diff --git a/docs/overview/repositories.md b/docs/overview/repositories.md index d8d71687..bda341c5 100644 --- a/docs/overview/repositories.md +++ b/docs/overview/repositories.md @@ -1,5 +1,5 @@ --- -sidebar_position: 8 +sidebar_position: 9 --- # Repositories @@ -20,13 +20,13 @@ The main goal of the repository pattern is to separate business logic from data By using the repository pattern, we can easily swap out the underlying data storage mechanism without affecting the rest of the application. For example, we can switch from using a relational database to a NoSQL database, or even a completely different storage mechanism like a web API, with minimal changes to the rest of the application code. Additionally, the repository pattern can make it easier to test the application, as we can use mock repositories to simulate data storage for testing purposes. Here are some of the benefits of using the repository pattern: -- Centralization of data access logic: all data access logic is contained within the repository, making it easier to maintain and change the data store implementation without impacting the rest of the application. +- Centralization of data access logic: all data access logic is contained within the repository, making it easier to maintain and change the data store implementation without impacting the rest of the application. -- Abstraction of data store details: the repository provides an abstraction layer that hides the details of how data is stored and accessed, allowing the application to work with data in a more abstract and consistent way. +- Abstraction of data store details: the repository provides an abstraction layer that hides the details of how data is stored and accessed, allowing the application to work with data in a more abstract and consistent way. -- Separation of concerns: the repository separates business logic from data access logic, making the code easier to read, test, and maintain. +- Separation of concerns: the repository separates business logic from data access logic, making the code easier to read, test, and maintain. -- Improved testability: the repository can be easily mocked or stubbed in unit tests, allowing for more thorough testing of the business logic without needing to connect to a real data store. +- Improved testability: the repository can be easily mocked or stubbed in unit tests, allowing for more thorough testing of the business logic without needing to connect to a real data store. Overall, the repository pattern is a powerful tool that can help developers build scalable and maintainable TypeScript applications that are more focused on business requirements and less on technical implementation details. @@ -42,15 +42,15 @@ In ExpressoTS, we implement the repository pattern in a specific folder called * ```typescript interface IEntity { - Id: string; + Id: string; } interface IBaseRepository { - create(item: T): T | null; - update(item: T): T | null; - delete(id: string): boolean; - find(id: string): T | null; - findAll(): T[]; + create(item: T): T | null; + update(item: T): T | null; + delete(id: string): boolean; + find(id: string): T | null; + findAll(): T[]; } ``` @@ -59,36 +59,36 @@ interface IBaseRepository { ```typescript @provide(BaseRepository) class BaseRepository implements IBaseRepository { - private readonly DB: T[] = []; + private readonly DB: T[] = []; - create(item: T): T | null { - this.DB.push(item); - return item; - } + create(item: T): T | null { + this.DB.push(item); + return item; + } - update(item: T) { - this.DB.push(item); - return item; - } + update(item: T) { + this.DB.push(item); + return item; + } - delete(id: string): boolean { - const index: number = this.DB.findIndex((item) => item.Id === id); + delete(id: string): boolean { + const index: number = this.DB.findIndex((item) => item.Id === id); - if (index != -1) { - this.DB.splice(index, 1); - return true; + if (index != -1) { + this.DB.splice(index, 1); + return true; + } + return false; } - return false; - } - find(id: string): T | null { - const user = this.DB.find((item) => item.Id === id); - return user || null; - } + find(id: string): T | null { + const user = this.DB.find((item) => item.Id === id); + return user || null; + } - findAll(): T[] { - return this.DB; - } + findAll(): T[] { + return this.DB; + } } ``` @@ -97,9 +97,9 @@ class BaseRepository implements IBaseRepository { ```typescript @provide(UserRepository) class UserRepository extends BaseRepository { - constructor() { - super(); - } + constructor() { + super(); + } } ``` @@ -109,9 +109,9 @@ class UserRepository extends BaseRepository { 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 diff --git a/docs/overview/status-code.md b/docs/overview/status-code.md index 8c64d8c4..f70e8fed 100644 --- a/docs/overview/status-code.md +++ b/docs/overview/status-code.md @@ -1,16 +1,16 @@ --- -sidebar_position: 13 +sidebar_position: 14 --- # Status Code Status code is a way to represent the result of a request. These HTTP responses indicate whether a specific HTTP request has been successfully completed. Responses are grouped in five classes: -- Informational responses (100-199) -- Successful responses (200-299) -- Redirection messages (300-399) -- Client error responses (400-499) -- Server error responses (500-599) +- Informational responses (100-199) +- Successful responses (200-299) +- Redirection messages (300-399) +- Client error responses (400-499) +- Server error responses (500-599) You can find more details about the status code in the **[MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)**. @@ -36,12 +36,12 @@ class CreateUserController extends BaseController { @httpPost("/") execute( @requestBody() data: ICreateUserRequestDTO, - @response() res: any, + @response() res: any ): ICreateUserResponseDTO { return this.callUseCase( this.createUserUseCase.execute(data), res, - StatusCode.Created, // Status code + StatusCode.Created // Status code ); } } @@ -60,12 +60,10 @@ class CreateUserUseCase { try { const { name, email } = data; - const user: User | null = this.userRepository.create( - new User(name, email), - ); + const user: User | null = this.userRepository.create(new User(name, email)); if (!user) { - Report.Error("User already exists", StatusCode.BadRequest,"create-user-usecase"); + Report.Error("User already exists", StatusCode.BadRequest, "create-user-usecase"); } let response: ICreateUserResponseDTO; @@ -94,9 +92,9 @@ class CreateUserUseCase { 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 \ No newline at end of file +- 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 diff --git a/docs/overview/test.md b/docs/overview/test.md index d5e325cd..814a7864 100644 --- a/docs/overview/test.md +++ b/docs/overview/test.md @@ -1,14 +1,14 @@ --- -sidebar_position: 15 +sidebar_position: 16 --- # Test Unit testing and integration testing are both important in any application development process because they serve different purposes. -- **Unit tests**: focus on testing individual units of code, such as a single function or method, in isolation from the rest of the application. They typically involve mocking dependencies and external services to ensure that the unit being tested behaves as expected in a controlled environment. Unit tests are important because they allow developers to catch bugs and errors early in the development process, when they are easier and cheaper to fix. They also help to ensure that individual units of code are functioning correctly, which can make debugging and troubleshooting easier later on. +- **Unit tests**: focus on testing individual units of code, such as a single function or method, in isolation from the rest of the application. They typically involve mocking dependencies and external services to ensure that the unit being tested behaves as expected in a controlled environment. Unit tests are important because they allow developers to catch bugs and errors early in the development process, when they are easier and cheaper to fix. They also help to ensure that individual units of code are functioning correctly, which can make debugging and troubleshooting easier later on. -- **Integration tests**: on the other hand, test the interactions between different components or modules of the application, including how they interact with external dependencies and services. Unlike unit tests, integration tests involve testing the application as a whole, rather than individual units in isolation. Integration tests are important because they help to ensure that the application is functioning correctly as a whole, and that different components are working together as expected. +- **Integration tests**: on the other hand, test the interactions between different components or modules of the application, including how they interact with external dependencies and services. Unlike unit tests, integration tests involve testing the application as a whole, rather than individual units in isolation. Integration tests are important because they help to ensure that the application is functioning correctly as a whole, and that different components are working together as expected. :::tip Combining unit tests and integration tests can be beneficial because it allows developers to test both individual units of code and the application as a whole. This helps ensure that each piece of code is working correctly on its own and in conjunction with other parts of the application. Furthermore, combining tests can provide more complete test coverage and identify problems at different levels of abstraction, from individual functions to complete system interaction with external components. @@ -53,9 +53,9 @@ We have in our Roadmap the implementation of a test library that wraps a modern 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 \ No newline at end of file +- 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 diff --git a/docs/overview/usecase.md b/docs/overview/usecase.md index 3254d38e..6112bf7e 100644 --- a/docs/overview/usecase.md +++ b/docs/overview/usecase.md @@ -1,5 +1,5 @@ --- -sidebar_position: 6 +sidebar_position: 7 --- # Use Cases @@ -35,16 +35,15 @@ Here is a simple implementation of the use case: ```typescript @provide(LoginUserUseCase) class LoginUserUseCase { + execute(payload: ILoginUserRequestDTO): boolean { + const { email, password } = payload; - execute(payload: ILoginUserRequestDTO): boolean { - const { email, password } = payload; - - if (isAuthenticated(email, password)) { - return true; + if (isAuthenticated(email, password)) { + return true; + } + + return false; } - - return false; - } } export { LoginUserUseCase }; @@ -64,16 +63,12 @@ Here is an example of a use case with constructor injection: ```typescript class ExampleUseCase { - - constructor( - private yourInjection1: Injection1, - private yourInjection2: Injection2 - ) {} - - execute() { - this.yourInjection1.foo(); - this.yourInjection2.bar(); - } + constructor(private yourInjection1: Injection1, private yourInjection2: Injection2) {} + + execute() { + this.yourInjection1.foo(); + this.yourInjection2.bar(); + } } ``` @@ -87,9 +82,9 @@ It is important to adhere to the principle of single responsibility when impleme 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 \ No newline at end of file +- 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 diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/overview/controller.md b/i18n/pt/docusaurus-plugin-content-docs/current/overview/controller.md index a3413484..45cc513a 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/overview/controller.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/overview/controller.md @@ -1,5 +1,5 @@ --- -sidebar_position: 5 +sidebar_position: 6 --- # Controladores diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/overview/decorators.md b/i18n/pt/docusaurus-plugin-content-docs/current/overview/decorators.md index 9bf4b8f9..a163a393 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/overview/decorators.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/overview/decorators.md @@ -1,5 +1,5 @@ --- -sidebar_position: 10 +sidebar_position: 11 --- # Decoradores @@ -62,9 +62,9 @@ Aqui está uma lista de todos os decoradores de parâmetros disponíveis no Expr ExpressoTS é um projeto de código aberto licenciado sob o MIT. É um projeto independente com desenvolvimento contínuo possibilitado graças ao seu suporte. Se você deseja ajudar, por favor considere: -- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** -- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto -- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** -- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** -- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** -- Compartilhe o projeto com seus amigos e colegas +- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** +- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto +- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** +- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** +- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** +- Compartilhe o projeto com seus amigos e colegas diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/overview/dependencies.md b/i18n/pt/docusaurus-plugin-content-docs/current/overview/dependencies.md index f60cb978..70110d7b 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/overview/dependencies.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/overview/dependencies.md @@ -1,5 +1,5 @@ --- -sidebar_position: 12 +sidebar_position: 13 --- # Dependências @@ -16,27 +16,27 @@ Enquanto isso, vamos continuar monitorando de perto as dependências, utilizando ## Pacotes Utilitários (Dependencias de Desenvolvimento) -- @commitlint/cli: Lint mensagens de commit -- @commitLint/config-conventional: Lint mensagens de commit -- @release-it/conventional-changelog: Gera changelog -- dotenv: Carregar variáveis de ambiente -- husky: Git hooks -- prettier: Formatador de códigos -- eslint: Linting code -- ts-node-dev: Executa arquivos de typescript -- tsconfig-paths: Resolve caminhos através do tsconfig.json +- @commitlint/cli: Lint mensagens de commit +- @commitLint/config-conventional: Lint mensagens de commit +- @release-it/conventional-changelog: Gera changelog +- dotenv: Carregar variáveis de ambiente +- husky: Git hooks +- prettier: Formatador de códigos +- eslint: Linting code +- ts-node-dev: Executa arquivos de typescript +- tsconfig-paths: Resolve caminhos através do tsconfig.json ## Pacotes Core -- express: Servidor Http -- inversify: IoC container -- inversify-binding-decorators: Decoradores do inversify -- reflect-metadata: Polyfill para metadados e reflexão +- express: Servidor Http +- inversify: IoC container +- inversify-binding-decorators: Decoradores do inversify +- reflect-metadata: Polyfill para metadados e reflexão ## Teste -- vitest: Framework de teste -- vite: Vitest's requerimento +- vitest: Framework de teste +- vite: Vitest's requerimento --- @@ -44,9 +44,9 @@ Enquanto isso, vamos continuar monitorando de perto as dependências, utilizando ExpressoTS é um projeto de código aberto licenciado sob o MIT. É um projeto independente com desenvolvimento contínuo possibilitado graças ao seu suporte. Se você deseja ajudar, por favor considere: -- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** -- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto -- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** -- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** -- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** -- Compartilhe o projeto com seus amigos e colegas +- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** +- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto +- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** +- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** +- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** +- Compartilhe o projeto com seus amigos e colegas diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/overview/di.md b/i18n/pt/docusaurus-plugin-content-docs/current/overview/di.md index b372758f..39a145ba 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/overview/di.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/overview/di.md @@ -1,5 +1,5 @@ --- -sidebar_position: 11 +sidebar_position: 12 --- # Injeção de Dependências @@ -10,19 +10,19 @@ Dependency Injection (DI) é um padrão de design usado no desenvolvimento de so Aqui estão alguns dos principais benefícios do uso da injeção de dependência: -- Desacoplamento: DI ajuda a desacoplar os componentes do seu aplicativo. Em vez de os componentes criarem os objetos dos quais dependem, esses objetos são passados (injetados) por uma estrutura ou contêiner de DI. Isso significa que os componentes não precisam saber sobre o funcionamento interno de suas dependências, e as dependências podem ser trocadas sem que o componente saiba ou se importe. +- Desacoplamento: DI ajuda a desacoplar os componentes do seu aplicativo. Em vez de os componentes criarem os objetos dos quais dependem, esses objetos são passados (injetados) por uma estrutura ou contêiner de DI. Isso significa que os componentes não precisam saber sobre o funcionamento interno de suas dependências, e as dependências podem ser trocadas sem que o componente saiba ou se importe. -- Testabilidade: DI facilita o teste de unidade. Como as dependências são injetadas, você pode facilmente fornecer objetos fictícios durante o teste. Isso permite que cada unidade de código seja testada isoladamente, com controle total sobre suas dependências. +- Testabilidade: DI facilita o teste de unidade. Como as dependências são injetadas, você pode facilmente fornecer objetos fictícios durante o teste. Isso permite que cada unidade de código seja testada isoladamente, com controle total sobre suas dependências. -- Código reutilizável: com DI, suas classes são normalmente projetadas para funcionar com interfaces em vez de classes concretas. Isso significa que você pode reutilizar a mesma classe em diferentes contextos, com diferentes dependências injetadas. +- Código reutilizável: com DI, suas classes são normalmente projetadas para funcionar com interfaces em vez de classes concretas. Isso significa que você pode reutilizar a mesma classe em diferentes contextos, com diferentes dependências injetadas. -- Manutenção mais fácil e maior eficiência: centralizando a criação de objetos e reduzindo a quantidade de instanciação de classe codificada, a manutenção se torna mais fácil. Quando uma classe muda, normalmente você só precisa atualizar o código em um lugar. +- Manutenção mais fácil e maior eficiência: centralizando a criação de objetos e reduzindo a quantidade de instanciação de classe codificada, a manutenção se torna mais fácil. Quando uma classe muda, normalmente você só precisa atualizar o código em um lugar. -- Configurabilidade: Você pode configurar sua estrutura de aplicação externamente, normalmente através de XML ou arquivos similares. Isso significa que você pode modificar a estrutura e as dependências de seus componentes sem precisar modificar o próprio código. +- Configurabilidade: Você pode configurar sua estrutura de aplicação externamente, normalmente através de XML ou arquivos similares. Isso significa que você pode modificar a estrutura e as dependências de seus componentes sem precisar modificar o próprio código. -- Ciclos de vida e escopo: gerencie o ciclo de vida de objetos injetados e controle seu escopo (por exemplo, escopo singleton, escopo de solicitação). +- Ciclos de vida e escopo: gerencie o ciclo de vida de objetos injetados e controle seu escopo (por exemplo, escopo singleton, escopo de solicitação). -- Gerenciamento de simultaneidade: os contêineres podem lidar automaticamente com tempos de vida de serviço em um ambiente simultâneo, o que pode ser uma tarefa complexa para lidar corretamente sem essa ferramenta. +- Gerenciamento de simultaneidade: os contêineres podem lidar automaticamente com tempos de vida de serviço em um ambiente simultâneo, o que pode ser uma tarefa complexa para lidar corretamente sem essa ferramenta. Em conclusão, DI é uma técnica que facilita o acoplamento fraco, maior capacidade de teste e código mais flexível e de fácil manutenção. @@ -36,26 +36,26 @@ Aqui está como o ExpressoTS implementa DI: Aqui está uma análise dos componentes DI usados no ExpressoTS: -| Componentes | Descrição | -| ------------ | ------------------------------------------------------------------------------------------------- | -| Container | O container DI do aplicativo ExpressoTS. | -| Module | Um módulo de contêiner é normalmente usado para agrupar controladores relacionados e suas dependências. | -| Controller | Interface primária entre o cliente e o servidor. Responsável por lidar com as solicitações recebidas. | -| Classes | Qualquer outra classe que faça parte do ecossistema ExpressoTS, por exemplo, fornecedores, entidades, ajudantes, etc. | +| Componentes | Descrição | +| ----------- | --------------------------------------------------------------------------------------------------------------------- | +| Container | O container DI do aplicativo ExpressoTS. | +| Module | Um módulo de contêiner é normalmente usado para agrupar controladores relacionados e suas dependências. | +| Controller | Interface primária entre o cliente e o servidor. Responsável por lidar com as solicitações recebidas. | +| Classes | Qualquer outra classe que faça parte do ecossistema ExpressoTS, por exemplo, fornecedores, entidades, ajudantes, etc. | ### Resumo -- O contêiner tem seu escopo padrão que pode ser substituído pelo módulo. O escopo padrão é o escopo `Request`. -- Definir um escopo para um módulo força todos os controladores desse módulo a terem o mesmo escopo. -- Não definir um escopo para um módulo permite que os controladores tenham seu próprio escopo usando o decorador `@scope()`. -- Todas as outras classes cadastradas como provedores, entidades, helpers podem ter seu escopo específico baseado no decorador utilizado. -- Decoradores: +- O contêiner tem seu escopo padrão que pode ser substituído pelo módulo. O escopo padrão é o escopo `Request`. +- Definir um escopo para um módulo força todos os controladores desse módulo a terem o mesmo escopo. +- Não definir um escopo para um módulo permite que os controladores tenham seu próprio escopo usando o decorador `@scope()`. +- Todas as outras classes cadastradas como provedores, entidades, helpers podem ter seu escopo específico baseado no decorador utilizado. +- Decoradores: -| Decoradores | Descrição | -| ------------------ | ------------------------------------------------------------------------------ | -| @provide | Vincula uma classe a um contêiner de injeção de dependência como RequestScope. | -| @provideSingleton | Vincula uma classe a um contêiner de injeção de dependência como Singleton. | -| @provideTransient | Vincula uma classe a um contêiner de injeção de dependência como Transient. | +| Decoradores | Descrição | +| ----------------- | ------------------------------------------------------------------------------ | +| @provide | Vincula uma classe a um contêiner de injeção de dependência como RequestScope. | +| @provideSingleton | Vincula uma classe a um contêiner de injeção de dependência como Singleton. | +| @provideTransient | Vincula uma classe a um contêiner de injeção de dependência como Transient. | ### Container @@ -85,30 +85,30 @@ Exemplo de uso: ```typescript @provide(MyRequest) -class MyRequest { } +class MyRequest {} ``` #### Singleton ```typescript @provideSingleton(MySingleton) -class MySingleton { } +class MySingleton {} ``` #### Transient ```typescript @provideTransient(MyTransient) -class MyTransient { } +class MyTransient {} ``` :::tip Para definir as ligações de escopo, o enum BindingScopeEnum pode ser usado. ::: -- `BindingScopeEnum.Singleton` - A dependência será criada uma vez e será compartilhada entre todas as solicitações. -- `BindingScopeEnum.Request` - A dependência será criada uma vez por solicitação. -- `BindingScopeEnum.Transient` - A dependência será criada toda vez que for solicitada. +- `BindingScopeEnum.Singleton` - A dependência será criada uma vez e será compartilhada entre todas as solicitações. +- `BindingScopeEnum.Request` - A dependência será criada uma vez por solicitação. +- `BindingScopeEnum.Transient` - A dependência será criada toda vez que for solicitada. --- @@ -116,9 +116,9 @@ Para definir as ligações de escopo, o enum BindingScopeEnum pode ser usado. ExpressoTS é um projeto de código aberto licenciado sob o MIT. É um projeto independente com desenvolvimento contínuo possibilitado graças ao seu suporte. Se você deseja ajudar, por favor considere: -- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** -- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto -- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** -- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** -- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** -- Compartilhe o projeto com seus amigos e colegas \ No newline at end of file +- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** +- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto +- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** +- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** +- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** +- Compartilhe o projeto com seus amigos e colegas diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/overview/entities.md b/i18n/pt/docusaurus-plugin-content-docs/current/overview/entities.md index 9470770b..be779fd8 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/overview/entities.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/overview/entities.md @@ -1,5 +1,5 @@ --- -sidebar_position: 9 +sidebar_position: 10 --- # Entidades @@ -15,17 +15,17 @@ Um exemplo simples de uma entidade User e suas propriedades: ```typescript @provide(User) class User { - private id: string; - public name: string; - public email: string; + private id: string; + public name: string; + public email: string; - constructor() { - this.id = uuidv4(); - } + constructor() { + this.id = uuidv4(); + } - get Id(): string { - return this.id; - } + get Id(): string { + return this.id; + } } ``` @@ -50,8 +50,7 @@ Se sua entidade tiver dependências, você pode injetá-las usando o decorador ` ```typescript @provide(User) class User { - - constructor(@inject("logger") private logger: Logger) {} + constructor(@inject("logger") private logger: Logger) {} } ``` @@ -62,10 +61,10 @@ Evite marcar construtores com parâmetros primitivos como injetáveis. Isso ocor ```typescript @provide(User) class User { - name: string; - constructor(name: string) { - this.name = name; - } + name: string; + constructor(name: string) { + this.name = name; + } } ``` @@ -77,11 +76,11 @@ Em muitos sistemas de injeção de dependência (DI), incluindo InversifyJS, o c Aqui estão algumas das razões pelas quais construtores com parâmetros primitivos podem ser problemáticos em DI: -- Ambigüidade: Se uma classe tiver um construtor que requer tipos primitivos, o contêiner DI não saberá quais valores injetar. Por exemplo, se uma classe requer um número em seu construtor, o container DI não sabe o que esse número representa e qual valor ele deve ter. +- Ambigüidade: Se uma classe tiver um construtor que requer tipos primitivos, o contêiner DI não saberá quais valores injetar. Por exemplo, se uma classe requer um número em seu construtor, o container DI não sabe o que esse número representa e qual valor ele deve ter. -- Inflexibilidade: Um valor primitivo no construtor implica que o valor é uma parte fixa da classe. No entanto, a DI é frequentemente usada para gerenciar partes intercambiáveis de um aplicativo (por exemplo, diferentes implementações de uma interface). +- Inflexibilidade: Um valor primitivo no construtor implica que o valor é uma parte fixa da classe. No entanto, a DI é frequentemente usada para gerenciar partes intercambiáveis de um aplicativo (por exemplo, diferentes implementações de uma interface). -- Não descritivo: valores primitivos geralmente não são descritivos e podem levar a códigos confusos. Por exemplo, um construtor que usa dois parâmetros de string pode levantar questões como: O que essas strings representam? Existem formatos ou restrições específicas nessas strings? +- Não descritivo: valores primitivos geralmente não são descritivos e podem levar a códigos confusos. Por exemplo, um construtor que usa dois parâmetros de string pode levantar questões como: O que essas strings representam? Existem formatos ou restrições específicas nessas strings? ## Injeção adequada de entidade @@ -92,31 +91,30 @@ Aqui está um exemplo de uma fábrica: ```typescript @provide(User) class User implements IEntity { - public id: string; - public name!: string; - public email!: string; + public id: string; + public name!: string; + public email!: string; - constructor() { - this.id = randomUUID(); - } + constructor() { + this.id = randomUUID(); + } } interface IUserFactory { - create(name: string, email: string): User; + create(name: string, email: string): User; } @provide(UserFactory) class UserFactory implements IUserFactory { - create(name: string, email: string): User { - const user = new User(); - user.name = name; - user.email = email; - return user; - } + create(name: string, email: string): User { + const user = new User(); + user.name = name; + user.email = email; + return user; + } } export { User, UserFactory }; - ``` Agora `UserFactory` pode ser facilmente injetado em outras classes. @@ -129,9 +127,9 @@ Como mencionado acima, existem várias outras abordagens, desde que você perman ExpressoTS é um projeto de código aberto licenciado sob o MIT. É um projeto independente com desenvolvimento contínuo possibilitado graças ao seu suporte. Se você deseja ajudar, por favor considere: -- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** -- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto -- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** -- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** -- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** -- Compartilhe o projeto com seus amigos e colegas +- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** +- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto +- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** +- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** +- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** +- Compartilhe o projeto com seus amigos e colegas diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/overview/error-handling.md b/i18n/pt/docusaurus-plugin-content-docs/current/overview/error-handling.md index 005916dc..57c73016 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/overview/error-handling.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/overview/error-handling.md @@ -1,22 +1,22 @@ --- -sidebar_position: 14 +sidebar_position: 15 --- # Gerenciamento de Error Quando se trata de tratamento de erros nas APIs TypeScript do Node.js, existem várias práticas recomendadas e abordagens que você pode seguir. O ExpressoTS fornece uma maneira simples e fácil de lidar com erros. -- Usamos códigos de status HTTP apropriadamente: HTTP **[códigos de status](./status-code.md)** são usados para indicar o status de uma resposta. É importante utilizá-los adequadamente em sua API para indicar o sucesso ou falha de uma operação. +- Usamos códigos de status HTTP apropriadamente: HTTP **[códigos de status](./status-code.md)** são usados para indicar o status de uma resposta. É importante utilizá-los adequadamente em sua API para indicar o sucesso ou falha de uma operação. -- Usamos um formato de erro consistente: defina um formato de erro consistente em sua API para que os consumidores possam entender e lidar facilmente com os erros. +- Usamos um formato de erro consistente: defina um formato de erro consistente em sua API para que os consumidores possam entender e lidar facilmente com os erros. -- Lidamos com erros em middleware: as funções de middleware são uma ótima maneira de lidar com erros em um local centralizado. +- Lidamos com erros em middleware: as funções de middleware são uma ótima maneira de lidar com erros em um local centralizado. -- Usamos blocos try-catch: Use blocos try-catch para lidar com erros síncronos em seu código. Se ocorrer um erro no bloco try, o bloco catch pode lidar com isso. Certifique-se de lançar o erro para que ele possa ser tratado por nosso middleware de tratamento de erros. +- Usamos blocos try-catch: Use blocos try-catch para lidar com erros síncronos em seu código. Se ocorrer um erro no bloco try, o bloco catch pode lidar com isso. Certifique-se de lançar o erro para que ele possa ser tratado por nosso middleware de tratamento de erros. -- Usamos tratamento de erro async/await: ao usar async/await, você pode usar blocos try-catch para lidar com erros síncronos em seu código. No entanto, você também precisa lidar com quaisquer erros assíncronos que possam ocorrer. +- Usamos tratamento de erro async/await: ao usar async/await, você pode usar blocos try-catch para lidar com erros síncronos em seu código. No entanto, você também precisa lidar com quaisquer erros assíncronos que possam ocorrer. -- Registramos erros: o registro de erros é importante para depuração e monitoramento. +- Registramos erros: o registro de erros é importante para depuração e monitoramento. ## Nossa Abordagem @@ -32,17 +32,13 @@ A classe Report é uma classe de utilitário para gerenciar e lançar erros espe ```typescript class Report { - /** - * O método Error pega uma instância de Error e a lança. - * @param error - Uma instância de Error ou uma string que representa a mensagem de erro. - * @param statusCode - O código de status HTTP do erro. - * @param service - O serviço onde ocorreu o erro. - */ - public static Error( - error: Error | string, - statusCode?: number, - service?: string - ): void {} + /** + * O método Error pega uma instância de Error e a lança. + * @param error - Uma instância de Error ou uma string que representa a mensagem de erro. + * @param statusCode - O código de status HTTP do erro. + * @param service - O serviço onde ocorreu o erro. + */ + public static Error(error: Error | string, statusCode?: number, service?: string): void {} } ``` @@ -61,22 +57,15 @@ Essa função de middleware é usada para manipular erros que ocorrem durante o * @param res - O objeto de resposta do Express. * @param next - A função next do Express para passar o controle para a próxima função de middleware. */ -function defaultErrorHandler( - error: Error, - req: Request, - res: Response, - next: NextFunction -): void { - if (error instanceof AppError) { - res - .status(error.statusCode) - .json({ statusCode: error.statusCode, error: error.message }); - } else { - res.status(StatusCode.InternalServerError).json({ - statusCode: StatusCode.InternalServerError, - error: "Ocorreu um erro inesperado.", - }); - } +function defaultErrorHandler(error: Error, req: Request, res: Response, next: NextFunction): void { + if (error instanceof AppError) { + res.status(error.statusCode).json({ statusCode: error.statusCode, error: error.message }); + } else { + res.status(StatusCode.InternalServerError).json({ + statusCode: StatusCode.InternalServerError, + error: "Ocorreu um erro inesperado.", + }); + } } export default defaultErrorHandler; @@ -91,15 +80,15 @@ Ela registra o erro, define o código de status e envia uma resposta JSON conten ```typescript class FooClass { - constructor(private report: Report) {} - - execute() { - try { - // fazer algo - } catch (error: any) { - this.report.Error(error, StatusCode.BadRequest, "seu-servico"); + constructor(private report: Report) {} + + execute() { + try { + // fazer algo + } catch (error: any) { + this.report.Error(error, StatusCode.BadRequest, "seu-servico"); + } } - } } ``` @@ -108,43 +97,41 @@ Use case example: ```typescript @provide(CreateUserUseCase) class CreateUserUseCase { - constructor(private userRepository: UserRepository, private report: Report) {} - - execute(data: ICreateUserRequestDTO): ICreateUserResponseDTO | null { - try { - const { name, email } = data; - - const userAlreadyExists = await this.userRepository.findByEmail(email); - - if (userAlreadyExists) { - this.report.Error( - "User already exists", - StatusCode.BadRequest, - "create-user-usecase" - ); - } - - const user: User | null = this.userRepository.create( - new User(name, email) - ); - - let response: ICreateUserResponseDTO; - - if (user !== null) { - response = { - id: user.Id, - name: user.name, - email: user.email, - status: "success", - }; - return response; - } - - return null; - } catch (error: any) { - throw error; + constructor(private userRepository: UserRepository, private report: Report) {} + + execute(data: ICreateUserRequestDTO): ICreateUserResponseDTO | null { + try { + const { name, email } = data; + + const userAlreadyExists = await this.userRepository.findByEmail(email); + + if (userAlreadyExists) { + this.report.Error( + "User already exists", + StatusCode.BadRequest, + "create-user-usecase" + ); + } + + const user: User | null = this.userRepository.create(new User(name, email)); + + let response: ICreateUserResponseDTO; + + if (user !== null) { + response = { + id: user.Id, + name: user.name, + email: user.email, + status: "success", + }; + return response; + } + + return null; + } catch (error: any) { + throw error; + } } - } } ``` @@ -164,9 +151,9 @@ class CreateUserUseCase { ExpressoTS é um projeto de código aberto licenciado sob o MIT. É um projeto independente com desenvolvimento contínuo possibilitado graças ao seu suporte. Se você deseja ajudar, por favor considere: -- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** -- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto -- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** -- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** -- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** -- Compartilhe o projeto com seus amigos e colegas +- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** +- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto +- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** +- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** +- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** +- Compartilhe o projeto com seus amigos e colegas diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/overview/middleware.md b/i18n/pt/docusaurus-plugin-content-docs/current/overview/middleware.md new file mode 100644 index 00000000..68052b36 --- /dev/null +++ b/i18n/pt/docusaurus-plugin-content-docs/current/overview/middleware.md @@ -0,0 +1,183 @@ +--- +sidebar_position: 5 +--- + +# Middleware + +Middleware é uma função que tem acesso ao objeto de requisição (req), ao objeto de resposta (res) e à próxima função de middleware no ciclo de requisição-resposta da aplicação. A próxima função de middleware é comumente indicada por uma variável chamada next. + +Middleware pode: + +- Executar código. +- Modificar os objetos de requisição e resposta. +- Concluir o processo de requisição-resposta. +- Prosseguir para o próximo middleware na sequência. +- Assegurar a invocação de next() se o middleware não finalizar o ciclo de requisição-resposta para evitar que a requisição fique parada. + +:::info +ExpressoTS oferece suporte total ao middleware do [Express](https://expressjs.com/). +::: + +## Adicionando Middleware + +A aplicação ExpressoTS suporta a adição de middleware de forma global à aplicação, bem como por rota. Ela oferece todo o [middleware suportado pela Equipe do Express](https://expressjs.com/en/resources/middleware.html) através do uso da propriedade `this.middleware`. + +```typescript +@provide(App) +export class App extends AppExpress { + private middleware: IMiddleware; + + constructor() { + super(); + this.middleware = container.get(Middleware); + } + + protected configureServices(): void { + this.middleware.addBodyParser(); + this.middleware.addCors(); + this.middleware.addHelmet(); + } +} +``` + +:::caution +Se você adicionar um middleware que não está instalado como dependência, a aplicação emitirá uma mensagem de aviso e continuará a funcionar. +::: + +### Middleware Global + +Middlewares podem ser adicionados globalmente usando a classe `App` através da propriedade `this.middleware`, utilizando a lista de middleware disponibilizada pela Equipe do Express: + +```typescript +protected configureServices(): void { + this.middleware.addBodyParser(); + this.middleware.addCors(); + this.middleware.addHelmet(); + } +``` + +Para qualquer outro middleware, ou um middleware personalizado, você pode adicioná-lo usando o método `this.middleware.addMiddleware()`. Com o método `addMiddleware`, você pode adicionar qualquer middleware do Registro NPM, middleware personalizado do Expressjs ou um middleware personalizado do ExpressoTS. + +Middleware do Registro NPM: + +```typescript +this.middleware.addMiddleware(cors()); +``` + +Middleware personalizado do Expressjs: + +```typescript +function myMiddleware(req: Request, res: Response, next: NextFunction) { + // Do something + next(); +} +``` + +```typescript +this.middleware.addMiddleware(myMiddleware); +``` + +Middleware personalizado do ExpressoTS: + +```typescript +class CustomMiddleware extends ExpressoMiddleware { + use(req: Request, res: Response, next: NextFunction): void | Promise { + // Do something + next(); + } +} +``` + +```typescript +this.middleware.addMiddleware(new CustomMiddleware()); +``` + +## Middleware por Rota + +Middlewares podem ser adicionados por rota na classe `App` através do método `this.middleware.addMiddleware()`. Você pode adicionar qualquer middleware do Registro NPM, middleware personalizado do Expressjs ou um middleware personalizado do ExpressoTS. + +```typescript +this.middleware.addMiddleware({ path: "/api", middlewares: [] }); +``` + +:::info +Cada rota pode ter múltiplos middlewares. +::: + +Ou você pode adicionar um middleware a uma rota específica na classe `Controller` através dos decoradores `@controller()` e/ou `http Method`. + +```typescript +@controller("/") +export class AppController { + @Post("", express.json()) + execute() { + return "Hello World"; + } +} +``` + +Se você quiser aplicar um middleware a todas as rotas sob um controlador específico, você pode adicioná-lo ao decorador `@controller()`. + +```typescript +@controller("/app", express.json()) +export class AppController { + @Post("/create") + createApp() { + return "Create App"; + } + + @Patch("/update") + updateApp() { + return "Update App"; + } +} +``` + +## Criando Middleware Personalizado do ExpressoTS + +Para criar um middleware personalizado, você precisa estender a classe `ExpressoMiddleware` e implementar o método `use`. + +```typescript +class CustomMiddleware extends ExpressoMiddleware { + private isOn: boolean; + + constructor(isOn: boolean) { + super(); + this.isOn = isOn; + } + + use(req: Request, res: Response, next: NextFunction): void | Promise { + // Do something + if (this.isOn) { + next(); + } else { + res.status(403).send("Forbidden"); + } + } +} +``` + +Middleware personalizado permite que você passe parâmetros para o construtor e os use como opções no método use do seu middleware. + +:::tip +Use o CLI do ExpressoTS para criar um scaffold de um middleware personalizado. +::: + +Comando CLI para criar um scaffold de um middleware personalizado: + +```bash +expressots g m <> +``` + +--- + +## Apoie o projeto + +ExpressoTS é um projeto de código aberto licenciado sob o MIT. É um projeto independente com desenvolvimento contínuo possibilitado graças ao seu suporte. Se você deseja ajudar, por favor considere: + +- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** +- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto +- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** +- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** +- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** +- Compartilhe o projeto com seus amigos e colegas diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/overview/providers.md b/i18n/pt/docusaurus-plugin-content-docs/current/overview/providers.md index 6baa581d..26622fd9 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/overview/providers.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/overview/providers.md @@ -1,5 +1,5 @@ --- -sidebar_position: 7 +sidebar_position: 8 --- # Provedores @@ -45,23 +45,21 @@ const enum EmailType { CreateUser, ChangePassword, Login, - RecoveryPassword + RecoveryPassword, } @provide(MailTrapProvider) class MailTrapProvider { - private transporter: Mail; constructor() { - this.transporter = nodemailer.createTransport({ host: Env.Mailtrap.HOST, port: Env.Mailtrap.PORT, auth: { user: Env.Mailtrap.USERNAME, - pass: Env.Mailtrap.PASSWORD - } + pass: Env.Mailtrap.PASSWORD, + }, }); } @@ -69,15 +67,15 @@ class MailTrapProvider { await this.transporter.sendMail({ to: { name: message.to.name, - address: message.to.email + address: message.to.email, }, from: { name: message.from.name, - address: message.from.email + address: message.from.email, }, subject: message.subject, - html: message.body - }) + html: message.body, + }); } sendEmail(emailType: EmailType): Promise { @@ -94,14 +92,14 @@ class MailTrapProvider { this.MailSender({ to: { name: "User", - email: Env.Mailtrap.INBOX_ALIAS + email: Env.Mailtrap.INBOX_ALIAS, }, from: { name: "ExpressoTS", - email: "noreply@expresso-ts.com" + email: "noreply@expresso-ts.com", }, subject: "Successfully logged in!", - body: "

Welcome to the system!

" + body: "

Welcome to the system!

", }); break; } @@ -111,7 +109,7 @@ class MailTrapProvider { export { MailTrapProvider, EmailType }; ``` -Nessa implementação, há uma função auxiliar privada e uma única interface pública chamada `sendEmail()` que será usada no caso de uso. O provedor é injetado no construtor para ser usado pelo caso de uso. +Nessa implementação, há uma função auxiliar privada e uma única interface pública chamada `sendEmail()` que será usada no caso de uso. O provedor é injetado no construtor para ser usado pelo caso de uso. ### Consumindo o provedor no caso de uso @@ -120,21 +118,20 @@ Aqui está a implementação do caso de uso fazendo uso do provedor: ```typescript @provide(LoginUserUseCase) class LoginUserUseCase { + constructor(private mailTrapProvider?: MailTrapProvider) {} - constructor(private mailTrapProvider?: MailTrapProvider) { } - - execute(payload: ILoginUserRequestDTO): boolean { - const { email, password } = payload; - - if (isAuthenticated(email, password)) { - return true; - } + execute(payload: ILoginUserRequestDTO): boolean { + const { email, password } = payload; - // Implementação da lógica do caso de uso - mailTrapProvider?.sendEmail(EmailType.Login); - - return false; - } + if (isAuthenticated(email, password)) { + return true; + } + + // Implementação da lógica do caso de uso + mailTrapProvider?.sendEmail(EmailType.Login); + + return false; + } } export { LoginUserUseCase }; @@ -148,9 +145,9 @@ No caso de uso acima, injetamos o `MailTrapProvider` no construtor fazendo uso d ExpressoTS é um projeto de código aberto licenciado sob o MIT. É um projeto independente com desenvolvimento contínuo possibilitado graças ao seu suporte. Se você deseja ajudar, por favor considere: -- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** -- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto -- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** -- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** -- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** -- Compartilhe o projeto com seus amigos e colegas \ No newline at end of file +- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** +- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto +- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** +- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** +- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** +- Compartilhe o projeto com seus amigos e colegas diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/overview/render.md b/i18n/pt/docusaurus-plugin-content-docs/current/overview/render.md index 9704d167..eac2ad18 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/overview/render.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/overview/render.md @@ -1,5 +1,5 @@ --- -sidebar_position: 16 +sidebar_position: 17 --- # Renderizacão @@ -19,17 +19,17 @@ Atualmente, oferecemos suporte a um número muito limitado de opções para o Ha interface IHandlebars { /** * Especifica o nome da extensão para os templates do Handlebars. - */ + */ extName: string; /** * Especifica o caminho para o diretório que contém os templates do Handlebars. - */ + */ viewPath: string; /** * Especifica a função para renderizar os templates do Handlebars. - */ + */ engine: Engine; } @@ -43,7 +43,7 @@ import { AppInstance, IHandlebars, ServerEnvironment } from "@expressots/core"; async function bootstrap() { AppInstance.create(container); - + // Configurando handlebars como motor de renderização. AppInstance.setEngine({ extName: "hbs", @@ -83,9 +83,9 @@ npm i express-handlebars ExpressoTS é um projeto de código aberto licenciado sob o MIT. É um projeto independente com desenvolvimento contínuo possibilitado graças ao seu suporte. Se você deseja ajudar, por favor considere: -- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** -- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto -- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** -- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** -- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** -- Compartilhe o projeto com seus amigos e colegas \ No newline at end of file +- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** +- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto +- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** +- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** +- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** +- Compartilhe o projeto com seus amigos e colegas diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/overview/repositories.md b/i18n/pt/docusaurus-plugin-content-docs/current/overview/repositories.md index ed53436f..eaa6b919 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/overview/repositories.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/overview/repositories.md @@ -1,5 +1,5 @@ --- -sidebar_position: 8 +sidebar_position: 9 --- # Repositórios @@ -20,37 +20,37 @@ O objetivo principal do padrão repository é separar a lógica de negócio da l Ao usar o padrão de repositório, podemos trocar facilmente o mecanismo de armazenamento de dados subjacente sem afetar o restante do aplicativo. Por exemplo, podemos mudar de um banco de dados relacional para um banco de dados NoSQL ou até mesmo um mecanismo de armazenamento completamente diferente, como uma API da Web, com alterações mínimas no restante do código do aplicativo. Além disso, o padrão de repositório pode facilitar o teste do aplicativo, pois podemos usar repositórios fictícios para simular o armazenamento de dados para fins de teste. Aqui estão alguns dos benefícios de usar o padrão de repositório: -- Centralização da lógica de acesso a dados: toda a lógica de acesso a dados é contida dentro do repositório, tornando mais fácil manter e alterar a implementação do armazenamento de dados sem afetar o resto da aplicação. +- Centralização da lógica de acesso a dados: toda a lógica de acesso a dados é contida dentro do repositório, tornando mais fácil manter e alterar a implementação do armazenamento de dados sem afetar o resto da aplicação. -- Abstração dos detalhes do armazenamento de dados: o repositório fornece uma camada de abstração que oculta os detalhes de como os dados são armazenados e acessados, permitindo que a aplicação trabalhe com dados de uma forma mais abstrata e consistente. +- Abstração dos detalhes do armazenamento de dados: o repositório fornece uma camada de abstração que oculta os detalhes de como os dados são armazenados e acessados, permitindo que a aplicação trabalhe com dados de uma forma mais abstrata e consistente. -- Separação de preocupações: o repositório separa a lógica de negócios da lógica de acesso a dados, tornando o código mais fácil de ler, testar e manter. +- Separação de preocupações: o repositório separa a lógica de negócios da lógica de acesso a dados, tornando o código mais fácil de ler, testar e manter. -- Melhoria na testabilidade: o repositório pode ser facilmente simulado ou substituído em testes de unidade, permitindo testar com mais profundidade a lógica de negócios sem precisar se conectar a um armazenamento de dados real. +- Melhoria na testabilidade: o repositório pode ser facilmente simulado ou substituído em testes de unidade, permitindo testar com mais profundidade a lógica de negócios sem precisar se conectar a um armazenamento de dados real. -- Em geral, o padrão repository é uma ferramenta poderosa que pode ajudar os desenvolvedores a construir aplicativos TypeScript escaláveis e fáceis de manter que estão mais focados nos requisitos de negócios e menos nos detalhes de implementação técnica. +- Em geral, o padrão repository é uma ferramenta poderosa que pode ajudar os desenvolvedores a construir aplicativos TypeScript escaláveis e fáceis de manter que estão mais focados nos requisitos de negócios e menos nos detalhes de implementação técnica. ## Exemplo Oferecemos um exemplo de implementação do padrão Repository no template opinativo do ExpressoTS. :::info -No ExpressoTS, implementamos o padrão repository em uma pasta específica chamada **"repositories"**, que é separada da pasta **"provider"** intencionalmente, embora possa ser considerada como um tipo de provider. Fizemos isso para dar mais ênfase ao padrão repository e deixar claro para os desenvolvedores que ele é um desacoplamento importante que o desenvolvimento da aplicação pode se beneficiar. +No ExpressoTS, implementamos o padrão repository em uma pasta específica chamada **"repositories"**, que é separada da pasta **"provider"** intencionalmente, embora possa ser considerada como um tipo de provider. Fizemos isso para dar mais ênfase ao padrão repository e deixar claro para os desenvolvedores que ele é um desacoplamento importante que o desenvolvimento da aplicação pode se beneficiar. ::: ### Interface do base repositório ```typescript interface IEntity { - Id: string; + Id: string; } interface IBaseRepository { - create(item: T): T | null; - update(item: T): T | null; - delete(id: string): boolean; - find(id: string): T | null; - findAll(): T[]; + create(item: T): T | null; + update(item: T): T | null; + delete(id: string): boolean; + find(id: string): T | null; + findAll(): T[]; } ``` @@ -59,36 +59,36 @@ interface IBaseRepository { ```typescript @provide(BaseRepository) class BaseRepository implements IBaseRepository { - private readonly USERDB: T[] = []; + private readonly USERDB: T[] = []; - create(item: T): T | null { - this.DB.push(item); - return item; - } + create(item: T): T | null { + this.DB.push(item); + return item; + } - update(item: T) { - this.DB.push(item); - return item; - } + update(item: T) { + this.DB.push(item); + return item; + } - delete(id: string): boolean { - const index: number = this.DB.findIndex((item) => item.Id === id); + delete(id: string): boolean { + const index: number = this.DB.findIndex((item) => item.Id === id); - if (index != -1) { - this.DB.splice(index, 1); - return true; + if (index != -1) { + this.DB.splice(index, 1); + return true; + } + return false; } - return false; - } - find(id: string): T | null { - const user = this.DB.find((item) => item.Id === id); - return user || null; - } + find(id: string): T | null { + const user = this.DB.find((item) => item.Id === id); + return user || null; + } - findAll(): T[] { - return this.DB; - } + findAll(): T[] { + return this.DB; + } } ``` @@ -97,9 +97,9 @@ class BaseRepository implements IBaseRepository { ```typescript @provide(UserRepository) class UserRepository extends BaseRepository { - constructor() { - super(); - } + constructor() { + super(); + } } ``` @@ -109,9 +109,9 @@ class UserRepository extends BaseRepository { ExpressoTS é um projeto de código aberto licenciado sob o MIT. É um projeto independente com desenvolvimento contínuo possibilitado graças ao seu suporte. Se você deseja ajudar, por favor considere: -- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** -- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto -- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** -- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** -- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** -- Compartilhe o projeto com seus amigos e colegas \ No newline at end of file +- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** +- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto +- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** +- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** +- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** +- Compartilhe o projeto com seus amigos e colegas diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/overview/status-code.md b/i18n/pt/docusaurus-plugin-content-docs/current/overview/status-code.md index 72d74a18..2984f4ca 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/overview/status-code.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/overview/status-code.md @@ -1,16 +1,16 @@ --- -sidebar_position: 13 +sidebar_position: 14 --- # Código de Status O código de status é uma forma de representar o resultado de uma requisição. Essas respostas HTTP indicam se uma solicitação HTTP específica foi concluída com êxito. As respostas são agrupadas em cinco classes: -- Respostas informativas (100-199) -- Respostas bem-sucedidas (200-299) -- Mensagens de redirecionamento (300-399) -- Respostas de erro do cliente (400-499) -- Respostas de erro do servidor (500-599) +- Respostas informativas (100-199) +- Respostas bem-sucedidas (200-299) +- Mensagens de redirecionamento (300-399) +- Respostas de erro do cliente (400-499) +- Respostas de erro do servidor (500-599) Você encontra aqui mais detalhes sobre os códigos de status **[MDN Web Docs](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status)**. @@ -36,12 +36,12 @@ class CreateUserController extends BaseController { @httpPost("/") execute( @requestBody() data: ICreateUserRequestDTO, - @response() res: any, + @response() res: any ): ICreateUserResponseDTO { return this.callUseCase( this.createUserUseCase.execute(data), res, - StatusCode.Created, // Status code + StatusCode.Created // Status code ); } } @@ -60,17 +60,15 @@ class CreateUserUseCase { try { const { name, email } = data; - const user: User | null = this.userRepository.create( - new User(name, email), - ); + const user: User | null = this.userRepository.create(new User(name, email)); if (!user) { Report.Error( new AppError( StatusCode.BadRequest, // Status code "User already exists", - "create-user-usecase", - ), + "create-user-usecase" + ) ); } @@ -100,9 +98,9 @@ class CreateUserUseCase { ExpressoTS é um projeto de código aberto licenciado sob o MIT. É um projeto independente com desenvolvimento contínuo possibilitado graças ao seu suporte. Se você deseja ajudar, por favor considere: -- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** -- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto -- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** -- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** -- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** -- Compartilhe o projeto com seus amigos e colegas \ No newline at end of file +- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** +- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto +- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** +- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** +- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** +- Compartilhe o projeto com seus amigos e colegas diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/overview/test.md b/i18n/pt/docusaurus-plugin-content-docs/current/overview/test.md index 9804ef6e..e3cc9cd3 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/overview/test.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/overview/test.md @@ -1,14 +1,14 @@ --- -sidebar_position: 15 +sidebar_position: 16 --- # Teste Os testes de unidade e os testes de integração são importantes em qualquer processo de desenvolvimento de aplicativos porque servem a propósitos diferentes. -- **Testes de unidade**: focam na realização de testes em unidades individuais de código, como uma única função ou método, isoladamente do restante do aplicativo. Eles normalmente envolvem simulação de dependências e serviços externos para garantir que a unidade sendo testada se comporte como esperado em um ambiente controlado. Os testes de unidade são importantes porque permitem que os desenvolvedores identifiquem bugs e erros precocemente no processo de desenvolvimento, quando são mais fáceis e baratos de corrigir. Eles também ajudam a garantir que unidades individuais de código estejam funcionando corretamente, o que pode facilitar a depuração e solução de problemas mais tarde. +- **Testes de unidade**: focam na realização de testes em unidades individuais de código, como uma única função ou método, isoladamente do restante do aplicativo. Eles normalmente envolvem simulação de dependências e serviços externos para garantir que a unidade sendo testada se comporte como esperado em um ambiente controlado. Os testes de unidade são importantes porque permitem que os desenvolvedores identifiquem bugs e erros precocemente no processo de desenvolvimento, quando são mais fáceis e baratos de corrigir. Eles também ajudam a garantir que unidades individuais de código estejam funcionando corretamente, o que pode facilitar a depuração e solução de problemas mais tarde. -- **Testes de integração**: por outro lado, testam as interações entre diferentes componentes ou módulos do aplicativo, incluindo como eles interagem com dependências e serviços externos. Ao contrário dos testes de unidade, os testes de integração envolvem testar o aplicativo como um todo, em vez de unidades individuais de forma isolada. Os testes de integração são importantes porque ajudam a garantir que o aplicativo esteja funcionando corretamente como um todo e que os diferentes componentes estejam trabalhando juntos conforme o esperado. +- **Testes de integração**: por outro lado, testam as interações entre diferentes componentes ou módulos do aplicativo, incluindo como eles interagem com dependências e serviços externos. Ao contrário dos testes de unidade, os testes de integração envolvem testar o aplicativo como um todo, em vez de unidades individuais de forma isolada. Os testes de integração são importantes porque ajudam a garantir que o aplicativo esteja funcionando corretamente como um todo e que os diferentes componentes estejam trabalhando juntos conforme o esperado. :::tip Combinar testes unitários e testes de integração pode ser benéfico porque permite que os desenvolvedores testem tanto unidades individuais de código quanto o aplicativo como um todo. Isso ajuda a garantir que cada parte do código esteja funcionando corretamente por si só e em conjunto com outras partes do aplicativo. Além disso, a combinação de testes pode fornecer uma cobertura de teste mais completa e identificar problemas em diferentes níveis de abstração, desde funções individuais até a interação completa do sistema com componentes externos. @@ -53,9 +53,9 @@ Temos em nosso Roadmap a implementação de uma biblioteca de testes que envolve ExpressoTS é um projeto de código aberto licenciado sob o MIT. É um projeto independente com desenvolvimento contínuo possibilitado graças ao seu suporte. Se você deseja ajudar, por favor considere: -- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** -- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto -- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** -- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** -- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** -- Compartilhe o projeto com seus amigos e colegas \ No newline at end of file +- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** +- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto +- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** +- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** +- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** +- Compartilhe o projeto com seus amigos e colegas diff --git a/i18n/pt/docusaurus-plugin-content-docs/current/overview/usecase.md b/i18n/pt/docusaurus-plugin-content-docs/current/overview/usecase.md index ee369dbb..7ef898e2 100644 --- a/i18n/pt/docusaurus-plugin-content-docs/current/overview/usecase.md +++ b/i18n/pt/docusaurus-plugin-content-docs/current/overview/usecase.md @@ -1,10 +1,10 @@ --- -sidebar_position: 6 +sidebar_position: 7 --- # Casos de Uso -Do ponto de vista da UML, os casos de uso fornecem uma maneira de modelar as interações entre usuários, outros sistemas e um aplicativo de software. Um caso de uso descreve um cenário específico ou fluxo de eventos entre os atores e o sistema, levando a um determinado resultado. +Do ponto de vista da UML, os casos de uso fornecem uma maneira de modelar as interações entre usuários, outros sistemas e um aplicativo de software. Um caso de uso descreve um cenário específico ou fluxo de eventos entre os atores e o sistema, levando a um determinado resultado. No contexto do ExpressoTS, os casos de uso servem para representar a lógica de negócios da aplicação, permitindo uma clara separação entre o controlador e a execução da solicitação. @@ -35,16 +35,15 @@ Aqui está nossa implementação simples do caso de uso no ExpressoTS: ```typescript @provide(LoginUserUseCase) class LoginUserUseCase { + execute(payload: ILoginUserRequestDTO): boolean { + const { email, password } = payload; - execute(payload: ILoginUserRequestDTO): boolean { - const { email, password } = payload; - - if (isAuthenticated(email, password)) { - return true; + if (isAuthenticated(email, password)) { + return true; + } + + return false; } - - return false; - } } export { LoginUserUseCase }; @@ -64,16 +63,12 @@ Aqui está um exemplo de um caso de uso com injeção de construtor: ```typescript class ExampleUseCase { - - constructor( - private yourInjection1: Injection1, - private yourInjection2: Injection2 - ) {} - - execute() { - this.yourInjection1.foo(); - this.yourInjection2.bar(); - } + constructor(private yourInjection1: Injection1, private yourInjection2: Injection2) {} + + execute() { + this.yourInjection1.foo(); + this.yourInjection2.bar(); + } } ``` @@ -87,9 +82,9 @@ class ExampleUseCase { ExpressoTS é um projeto de código aberto licenciado sob o MIT. É um projeto independente com desenvolvimento contínuo possibilitado graças ao seu suporte. Se você deseja ajudar, por favor considere: -- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** -- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto -- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** -- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** -- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** -- Compartilhe o projeto com seus amigos e colegas \ No newline at end of file +- Se tornar um **[Sponsor no GitHub](https://github.com/sponsors/expressots)** +- Siga a **[organização](https://github.com/expressots)** no GitHub e de um Star ⭐ no projeto +- Subscreva no nosso canal na Twitch: **[Richard Zampieri](https://www.twitch.tv/richardzampieri)** +- Entre no nosso **[Discord](https://discord.com/invite/PyPJfGK)** +- Contribua submetendo **[issues e pull requests](https://github.com/expressots/expressots/issues/new/choose)** +- Compartilhe o projeto com seus amigos e colegas