Skip to content

Commit

Permalink
init module category
Browse files Browse the repository at this point in the history
  • Loading branch information
ayocodingit committed Sep 16, 2024
1 parent 3f15d46 commit abe7716
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 2 deletions.
21 changes: 21 additions & 0 deletions src/database/mongo/schemas/category.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Schema } from 'mongoose'
import Mongo from '../mongo'

const schema = new Schema(
{
name: {
type: String,
index: true,
required: true,
},
},
{
timestamps: {
createdAt: 'created_at',
updatedAt: 'updated_at',
},
versionKey: false,
}
)

export default Mongo.Model('categories', schema)
2 changes: 2 additions & 0 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import config from './config/config'
import Mongo from './database/mongo/mongo'
import Category from './modules/category/category'
import Images from './modules/images/images'
import Logger from './pkg/logger'
import Http from './transport/http/http'
Expand All @@ -11,6 +12,7 @@ const main = async () => {

// Start Load Modules
new Images(logger, http, config)
new Category(logger).loadHttp(http)
// End Load Modules

http.Run(config.app.port.http)
Expand Down
32 changes: 32 additions & 0 deletions src/modules/category/category.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import Http from '../../transport/http/http'
import Logger from '../../pkg/logger'
import Usecase from './usecase/usecase'
import Handler from './delivery/http/handler'
import Repository from './repository/mongo/repository'

class Category {
private usecase: Usecase
constructor(
private logger: Logger,
) {
const repository = new Repository(logger)
const usecase = new Usecase(logger, repository)
this.usecase = usecase
}

public loadHttp(http: Http) {
const handler = new Handler(this.logger, http, this.usecase)
this.httpPrivate(http, handler)
}

private httpPrivate(http: Http, handler: Handler) {
const Router = http.Router()

Router.post('/', handler.Store())
Router.get('/', handler.Fetch())

http.SetRouter('/v1/categories', Router)
}
}

export default Category
58 changes: 58 additions & 0 deletions src/modules/category/delivery/http/handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import Http from '../../../../transport/http/http'
import Logger from '../../../../pkg/logger'
import Usecase from '../../usecase/usecase'
import { NextFunction, Request, Response } from 'express'
import statusCode from '../../../../pkg/statusCode'
import { GetMeta, GetRequestParams } from '../../../../helpers/requestParams'
import { ValidateFormRequest } from '../../../../helpers/validate'
import { Store } from '../../entity/schema'

class Handler {
constructor(
private logger: Logger,
private http: Http,
private usecase: Usecase
) {}

public Fetch() {
return async (req: Request, res: Response, next: NextFunction) => {
try {
const request = GetRequestParams(req.query)
const { data, count } = await this.usecase.Fetch(request)
this.logger.Info(statusCode[statusCode.OK], {
additional_info: this.http.AdditionalInfo(
req,
statusCode.OK
),
})

return res.json({ data, meta: GetMeta(request, count) })
} catch (error) {
return next(error)
}
}
}

public Store() {
return async (req: any, res: Response, next: NextFunction) => {
try {
const value = ValidateFormRequest(Store, req.body)
const result = await this.usecase.Store(value)
this.logger.Info(statusCode[statusCode.CREATED], {
additional_info: this.http.AdditionalInfo(
req,
statusCode.CREATED
),
})

return res
.status(statusCode.CREATED)
.json({ data: result, message: 'CREATED' })
} catch (error) {
return next(error)
}
}
}
}

export default Handler
3 changes: 3 additions & 0 deletions src/modules/category/entity/interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface Store {
name: string
}
6 changes: 6 additions & 0 deletions src/modules/category/entity/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Joi from 'joi'
import { RegexSubdomain } from '../../../helpers/regex'

export const Store = Joi.object({
name: Joi.string().regex(RegexSubdomain).required(),
})
60 changes: 60 additions & 0 deletions src/modules/category/repository/mongo/repository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import Logger from '../../../../pkg/logger'
import { RequestParams } from '../../../../helpers/requestParams'
import categorySchema from '../../../../database/mongo/schemas/category.schema'
import { Store } from '../../entity/interface'

class Repository {
constructor(private logger: Logger) {}

public async Fetch({
offset,
limit,
keyword,
sort_order,
sort_by,
}: RequestParams) {
const filter = {}
const sort = {}

if (keyword)
Object.assign(filter, {
name: {
$regex: new RegExp(keyword, 'i'),
},
})

if (['created_at', 'name'].includes(sort_by)) {
Object.assign(sort, {
[sort_by]: sort_order,
})
}

const data = await categorySchema
.find(filter)
.sort(sort)
.skip(offset)
.limit(limit)
const count = await categorySchema.find(filter).count()

return {
data,
count,
}
}

public async Store(body: Store) {
const schemaNew = new categorySchema(body)

return schemaNew.save()
}

public async FindUnique(name: string) {
const result = await categorySchema.findOne({
name,
})

return result
}
}

export default Repository
25 changes: 25 additions & 0 deletions src/modules/category/usecase/usecase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { RequestParams } from '../../../helpers/requestParams'
import error from '../../../pkg/error'
import Logger from '../../../pkg/logger'
import statusCode from '../../../pkg/statusCode'
import { Store } from '../entity/interface'
import Repository from '../repository/mongo/repository'

class Usecase {
constructor(private logger: Logger, private repository: Repository) {}

public async Fetch(request: RequestParams) {
return this.repository.Fetch(request)
}

public async Store(body: Store) {
const item = await this.repository.FindUnique(body.name)
if (item)
throw new error(statusCode.BAD_REQUEST, 'Category Already Exist')
const result = await this.repository.Store(body)

return result
}
}

export default Usecase
2 changes: 0 additions & 2 deletions src/modules/images/usecase/usecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ import {
RegexExtensionImage,
} from '../../../helpers/regex'
import FileGenerator from '../../../external/fileGenerator'
import statusCode from '../../../pkg/statusCode'
import error from '../../../pkg/error'

class Usecase {
constructor(
Expand Down

0 comments on commit abe7716

Please sign in to comment.