To implement this class, you will need an create entity.
import { CoreEntityContract } from 'niro-health';
export class User extends CoreEntityContract {
username: string;
email: string;
password: string;
constructor(data: Partial<User>) {
super(data);
this.username = data?.username;
this.email = data?.email;
this.password = data?.password;
}
}
You will need an implementation for the database.
import { CoreDatabaseContract } from 'niro-health';
import type { User } from './entities';
export abstract class UserDatabaseContract extends CoreDatabaseContract<User> {
abstract findByEmail(email: string): Promise<User | null>;
}
Let's create an in-memory bank by implementing our contract.
import type { INestApplication } from '@nestjs/common';
import type { ISimilarityFilterService, SimilarityFilterType as Type } from 'niro-health';
import type { User } from './entities';
import { UserDatabaseContract } from './contracts';
import * as _ from 'lodash';
export class UserMemoryDB extends UserDatacbaseContract {
private readonly _similarityFilterService: ISimilarityFilterService;
constructor(
protected readonly app: INestApplication,
private users: User[] = [],
) {
super(app);
this._similarityFilterService = this.app.get<ISimilarityFilterService>(
'ISimilarityFilterService',
);
}
async create(data: User): Promise<User> {
this.users.push(data);
return data;
}
async findAll(limit?: number, offset?: number): Promise<User[]> {
return this.users.slice(offset || 0, limit || this.users.length);
}
async findOne(id: number | string): Promise<User | null> {
return this.users.find((user) => user.id === id);
}
async findBy(filter: Partial<User>, similarity?: Type): Promise<User[]> {
return this.users.filter((key) =>
this._similarityFilterService.execute<User>(
filter,
key as User,
similarity || 'full',
),
) as User[];
}
async findByEmail(email: string): Promise<User | null> {
const hash = this.hashText(email);
return this.users.find((user) => user.hash.email === hash);
}
async update(id: number | string, newData: User): Promise<User | null> {
this.users = this.users.map((user) =>
user.id === id ? { ...user, ..._.omitBy(newData, _.isNil) } : user,
) as User[];
return await this.findOne(id);
}
async delete(id: number | string): Promise<boolean> {
this.users = this.users.filter((user) => user.id !== id);
return true;
}
}
To implement creating, updating, and deleting users, we should create use cases to make code maintenance and organization easier.
import type { INestApplication } from '@nestjs/common';
import type { CreateUserDto } from './users/dto/create';
import { UserRepository } from './users/repositories';
import { UserDatabaseContract } from './users/contracts';
import { User } from './users/entities';
export class CreateUser {
static async execute(
user: CreateUserDto,
database: UserDatabaseContract,
app: INestApplication,
) {
const repository = new UserRepository(database, app);
const entity = new User({ id: database.generateUUID() });
entity.username = user.username;
entity.email = user.email;
entity.password = user.password;
return await repository.create(entity);
}
}
Now we can implement a factory to group our use cases with our database implementations.
import type { INestApplication } from '@nestjs/common';
import type { CreateUserDto } from './users/dto/create';
import { CreateUser } from './users/usecases/create';
import { UserMemoryDB } from './users/db/memory';
export class CreateUserFactory {
static async run(user: CreateUserDto, app: INestApplication) {
const database = new UserMemoryDB(app);
return await CreateUser.execute(user, database, app);
}
}
Our implementation is complete.