Last active
August 24, 2024 07:07
-
-
Save 0xkohe/28a50823f94a2360e3001cc519bc3c29 to your computer and use it in GitHub Desktop.
Clean Architecture with InversifyJS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { firestore } from 'firebase' | |
import { injectable, inject, Container } from 'inversify' | |
import { db } from '@/plugins/firebase' | |
import 'reflect-metadata' | |
class RestaurantDataModel { | |
constructor(init: any) { | |
this.id = init.id || this.id | |
this.clientUID = init.clientUID || this.clientUID | |
this.content = init.content || this.content | |
this.status = init.status || this.status | |
this.tags = init.tags || this.tags | |
this.name = init.name || this.name | |
} | |
readonly id: string = '' | |
readonly clientUID: string | null = null | |
readonly content: string | null = null | |
readonly status: string | null = null | |
readonly tags: string[] | null = null | |
readonly name: string | null = null | |
} | |
class RestaurantEntity { | |
constructor(init: any) { | |
this.id = init.id || this.id | |
this.clientUID = init.clientUID || this.clientUID | |
this.content = init.content || this.content | |
this.status = init.status || this.status | |
this.tags = init.tags || this.tags | |
this.name = init.name || this.name | |
} | |
readonly id: string = '' | |
readonly clientUID: string | null = null | |
readonly content: string | null = null | |
readonly status: string | null = null | |
readonly tags: string[] | null = null | |
readonly name: string | null = null | |
} | |
const TYPES = { | |
IResutaurantUseCasae: Symbol.for('IResutaurantUseCasae'), | |
IRestaurantRepository: Symbol.for('IRestaurantRepository'), | |
RestaurantController: Symbol.for('RestaurantController'), | |
} | |
interface IResutaurantUseCasae { | |
Handle(request: RestaurantGetRequest): Promise<RestaurantEntity[]> | |
} | |
class RestaurantGetRequest { | |
public tags: string[] = [] | |
public limit: number = 0 | |
constructor(tags: string[], limit: number) { | |
this.tags = tags | |
this.limit = limit | |
} | |
} interface IRestaurantRepository { | |
GetByTags(tags: string[], limit: number): Promise<RestaurantEntity[]> | |
} | |
@injectable() | |
class RestaurantRepository implements IRestaurantRepository { | |
private readonly db!: firestore.Firestore | |
private readonly collectionPath: string = 'public/v1/restaurants' | |
constructor(connection: firestore.Firestore = db) { | |
this.db = connection | |
} | |
public async GetByTags( | |
tags: string[], | |
limit: number | |
): Promise<RestaurantEntity[]> { | |
const docs = await this.db.collection(this.collectionPath).limit(limit).get() | |
const restaurants: RestaurantEntity[] = [] | |
docs.forEach((doc) => { | |
const restaurant = doc.data() | |
const dataModel = new RestaurantDataModel(restaurant) | |
restaurants.push(new RestaurantEntity(dataModel)) | |
}) | |
return restaurants | |
} | |
} | |
@injectable() | |
class RestaurantGetInteractor implements IResutaurantUseCasae { | |
private readonly restaurantRepository: IRestaurantRepository | |
constructor( | |
@inject(TYPES.IRestaurantRepository) restaurantRepository: IRestaurantRepository | |
) { | |
this.restaurantRepository = restaurantRepository | |
} | |
Handle(request: RestaurantGetRequest): Promise<RestaurantEntity[]> { | |
const tags = request.tags | |
const res = this.restaurantRepository.GetByTags(tags, 1) | |
return res | |
} | |
} | |
@injectable() | |
class RestaurantController { | |
private readonly usecase: IResutaurantUseCasae | |
constructor(@inject(TYPES.IResutaurantUseCasae) usecase: IResutaurantUseCasae) { | |
this.usecase = usecase | |
} | |
Get(tags: string[], limit: number) { | |
const request = new RestaurantGetRequest(tags, limit) | |
const res = this.usecase.Handle(request) | |
return res | |
} | |
} | |
// move inversify.config.ts | |
const myContainer = new Container() | |
myContainer | |
.bind<IResutaurantUseCasae>(TYPES.IResutaurantUseCasae) | |
.to(RestaurantGetInteractor) | |
myContainer.bind<IRestaurantRepository>(TYPES.IRestaurantRepository).to(RestaurantRepository) | |
myContainer.bind<RestaurantController>(TYPES.RestaurantController).to(RestaurantController) | |
const restaurantController = myContainer.get<RestaurantController>(TYPES.RestaurantController) | |
export { restaurantController } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment