From 9ee52c595cfd3f4a6bf5f9150c5a0831e160a4ba Mon Sep 17 00:00:00 2001 From: Richard Zampieri Date: Thu, 4 Jul 2024 18:22:16 -0700 Subject: [PATCH] feat: update in memory db doc --- docs/providers/in-memory-db.md | 173 +++++++++++++++++++-------------- 1 file changed, 102 insertions(+), 71 deletions(-) diff --git a/docs/providers/in-memory-db.md b/docs/providers/in-memory-db.md index e965c72f..28b8673c 100644 --- a/docs/providers/in-memory-db.md +++ b/docs/providers/in-memory-db.md @@ -4,9 +4,11 @@ sidebar_position: 3 # In Memory DB -In Memory DB is a provider that uses a simple in memory database to store data. It is a class injected in the ExpressoTS dependency injection system as a singleton. +In Memory DB is a provider that uses a simple in memory database to store data. It is a class that can be registered in the ExpressoTS dependency injection system as a singleton. -This class manages tables, represented by key-value pairs, where the key is the table name and the value is an array of entities. +```ts +this.provider.register(InMemoryDB, "Singleton"); +``` The InMemoryDB class provides a simple and efficient way to simulate a database entirely in-memory, which can be particularly useful for testing and rapid development where a full-fledged database might be overkill. @@ -24,114 +26,143 @@ Here is an image showing the output in the console of the InMemoryDB when we cre The DB inspector is enabled by default. As soon as you create a new entity and extend the BaseRepository class, the InMemoryDB will print the table to the console. ::: -## Class Definition +## How to Use InMemoryDB + +To use the InMemoryDB class, you need to import it from the `expressots` package and register it as a singleton in the dependency injection system. Here is an example of how to do this in a service class: -Detail explanation of InMemoryDB class definition. +### Register InMemoryDB ```typescript -@provideSingleton(InMemoryDB) -class InMemoryDB { - private tables: Record = {}; - // Method definitions ... -} -``` +export class App extends AppExpress { + private middleware: IMiddleware; + private provider: ProviderManager; -This decorator indicates that the InMemoryDB class is a Singleton within the dependency injection system. + constructor() { + super(); + this.middleware = container.get(Middleware); + this.provider = container.get(ProviderManager); + } -```typescript -@provideSingleton(InMemoryDB) -``` + protected configureServices(): void { + this.provider.register(InMemoryDB, "Singleton"); + } -Class Properties tables is a private property that holds the in-memory tables. Each table is a key-value pair where the key is the table name, and the value is an array of entities (IEntity[]). + protected postServerInitialization(): void {} -```typescript -private tables: Record = {}; + protected serverShutdown(): void {} +} ``` -## Class Methods - -InMemoryDB class provides the following methods: +When registering the InMemoryDB class, you can specify the scope as `string` or using the `BindingScopeEnum`. -### Get Table Method +### Define your Entity ```typescript -getTable(tableName: string): IEntity[] +@provide(UserEntity) +export class UserEntity { + id: string; + name: string; + email: string; + + constructor() { + this.id = randomUUID(); + } +} ``` -Parameters - -- tableName (string): The name of the table to retrieve. -- Returns: IEntity[]: An array of entities stored in the specified table. -- Description: Retrieves a table by its name from the in-memory database. If the table doesn't exist, it initializes an empty table. +### Create a Repository -### Show Tables Method +The repository is a class that extends the BaseRepository class and is used to manage entities of a specific type. The repository class is part of the dependency injection system and is marked by the @provide decorator. ```typescript -showTables(): void +@provide(UserRepository) +export class UserRepository extends BaseRepository { + constructor() { + super("users"); + } +} ``` -Description: Prints a list of all existing tables in the in-memory database to the standard output. If no tables exist, it outputs "No tables exist." +In the class above, we are creating a repository for the `UserEntity` class. The repository is initialized with the table name `users` in the constructor. -### Print Table Method +You can also define custom methods for the user repository. ```typescript -printTable(tableName: string): void +@provide(UserRepository) +class UserRepository extends BaseRepository { + constructor() { + super("users"); + } + + // Custom method implemented for the UserRepository only + findByEmail(email: string): User | null { + const user = this.table.find((item) => item.email === email); + return user || null; + } +} ``` -Parameters - -- tableName (string): The name of the table whose records should be printed. -- Description: Prints all records in a specific table to the console using console.table. If the table doesn't exist or is empty, it notifies the user through standard output. - -:::info -In the opinionated template the InMemoryDB is already implemented in the BaseRepository class. You don't need to use it directly. -::: +### Use the Repository -## How to Extend BaseRepository +You can inject the repository in the constructor or via property injection. -Here is a code snippet that shows how to extend the BaseRepository class to implement a custom repository. +Property Injection: ```typescript -@provide(UserRepository) -class UserRepository extends BaseRepository { - constructor() { - super("users"); - } +@provide(UserCreateUseCase) +export class UserCreateUseCase { + @inject(UserRepository) + private userRepo: UserRepository; + + @inject(UserEntity) + private userEntity: UserEntity; + + execute(payload: IUserCreateRequestDTO): IUserCreateResponseDTO { + this.userEntity.name = payload.name; + this.userEntity.email = payload.email; + + this.userRepo.create(this.userEntity); + + return { + id: this.userEntity.id, + name: this.userEntity.name, + email: this.userEntity.email, + }; + } } ``` -The UserRepository class is a specialized repository tailored for managing User entities. It extends the generic BaseRepository class and sets its table name to "users" upon construction. This class is part of the dependency injection system and is marked by the @provide decorator. - -Any custom methods can be added to the UserRepository class. For example, the following code snippet shows how to implement a findByEmail method that searches for a user by email. +Constructor Injection: ```typescript -@provide(UserRepository) -class UserRepository extends BaseRepository { - constructor() { - super("users"); - } - - // Custom method implemented for the UserRepository only - findByEmail(email: string): User | null { - const user = this.table.find((item) => item.email === email); - return user || null; - } +@provide(UserCreateUseCase) +export class UserCreateUseCase { + constructor(private userEntity: UserEntity, private userRepo: UserRepository) {} + + execute(payload: IUserCreateRequestDTO): IUserCreateResponseDTO { + this.userEntity.name = payload.name; + this.userEntity.email = payload.email; + + this.userRepo.create(this.userEntity); + + return { + id: this.userEntity.id, + name: this.userEntity.name, + email: this.userEntity.email, + }; + } } ``` -:::caution SPOILER ALERT -In the future, we plan to extend the repository pattern to support various databases, all easily scaffoldable through our CLI -::: - --- ## 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 +- 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