In memory DB
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.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.
DB inspector
The InMemoryDB
class have the ability to print tables to the console. This feature is particularly useful for debugging and testing purposes. It can also be used to quickly inspect the contents of a table.
The table content will be printed to the console every time the repository is used by any endpoint that have operations that read or write to the database.
Here is an image showing the output in the console of the InMemoryDB
when we create a new user:
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.
Register InMemoryDB
To use the InMemoryDB
class, you need to import it from the @expressots/core
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:
import { InMemoryDB } from "@expressots/core";
export class App extends AppExpress {
private middleware: IMiddleware;
private provider: ProviderManager;
constructor() {
super();
this.middleware = container.get<IMiddleware>(Middleware);
this.provider = container.get(ProviderManager);
}
protected configureServices(): void {
this.provider.register(InMemoryDB, "Singleton");
}
}
When registering the InMemoryDB
class, you can specify the scope as string
or using the BindingScopeEnum
.
Create an entity
Create an entity to represent the data that will be stored in the database. The entity class should have properties that represent the fields of the data that will be stored in the database.
@provide(UserEntity)
export class UserEntity {
id: string;
name: string;
email: string;
constructor() {
this.id = randomUUID();
}
}
Repository pattern
The repository pattern is a design pattern that abstracts the data access logic from the rest of the application. It provides a way to access and manipulate data in the database without exposing the details of the database to the rest of the application.
Read more about the repository pattern in here: Repositories.
Create a repository
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.
@provide(UserRepository)
export class UserRepository extends BaseRepository<UserEntity> {
constructor() {
super("users");
}
}
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, as well as the entity class UserEntity
.
By extending the BaseRepository
class, the UserRepository
class inherits all the CRUD methods for managing entities in the database.
Define custom methods
You can also define custom methods for the user repository.
@provide(UserRepository)
class UserRepository extends BaseRepository<UserEntity> {
constructor() {
super("users");
}
findByEmail(email: string): User | null {
const user = this.table.find((item) => item.email === email);
return user || null;
}
}
Usage in a use case
You can inject the repository in the constructor or via property injection. Example:
@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,
};
}
}
@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,
};
}
}
Once a request is made to the UserCreateUseCase
:
- The
UserEntity
is populated with the request data. - The entity is created in the database using the
UserRepository
. - The response data is then returned to the client.
- The
InMemoryDB
will print the table to the console, showing the newly created entity.
Support us ❤️
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 read our support guide.