mc-helpers
v1.3.5
Published
Configure Backend to use material-crud
Downloads
36
Readme
Installation
Install mc-helpers package. -E will install the exact version
//with npm
npm i mc-helpers -E
To get started with mc-helpers is necesary to configure mongoose models and Services.
Services
- This is the basic service configuration
//services/store.ts
import { BaseServices } from "mc-helpers";
import { StoreModel, StoreProps } from "../models/Store";
export const StoreService = new BaseServices<StoreProps>(StoreModel)
- In order to override the New, Edit, Find methods, you will need to override some methods. ApiError explication is below
//services/store.ts
import {ApiError, BaseServices} from 'mc-helpers'
import {StoreErrors} from '../errors/Store.errors'
import {StoreModel, StoreProps} from '../models/Store'
interface NewProps {
name: string
}
class Service extends BaseServices<StoreProps> {
constructor() {
super(StoreModel)
}
New = async (props: NewProps) => {
const {name} = props
const check = await this.Exists({nombre: {$regex: new RegExp(name, 'i')}})
if (check) throw new ApiError(StoreErrors.Exists)
return await this.Create(props)
}
Find = (extraParams: any) => {
return this.Model.aggregate().sort({name:-1})
}
}
export const StoreService = new Service()
- You can override multiple methods from the
BaseService
class. New, Edit, Find, Paginate, Export, PrePaginate, Filter, etc.
export class BaseServices<T, K = any> {
Model: FinalModel<T>
constructor(model: FinalModel<T>) {
this.Model = model
}
Create: CreateProps<T, K> = async (item) => {
const created = await this.Model.create(item)
return this.FindById(created.id)
}
Exists: ExistsProps<T> = async (find) => {
return this.Model.findOne(find)
}
New: BaseNewProps<K> = async (item: any) => {
return this.Create(item)
}
CheckCreate: CheckCreateProps<T, K> = async (find, item) => {
const check = await this.Exists(find)
if (!check) {
return this.Create(item || (find as T))
}
return this.FindById(check.id)
}
Modify: ModifyProps<T> = async (_id, item) => {
return await this.Model.findByIdAndUpdate(_id, item)
}
Edit: EditProps<T, K> = async (_id, item) => {
const edited = await this.Modify(_id, item)
return this.FindById(edited?.id)
}
Delete: DeleteProps<T> = async (_id) => {
return this.Model.findByIdAndDelete(_id)
}
DeleteAll: DeleteAllProps = () => {
if (process.env.NODE_ENV !== 'test')
throw Error('No se puede utilizar fuera del entodo de test')
return this.Model.deleteMany({})
}
DocById: DocByIdProps<T> = async (id) => {
const document = await this.Model.findById(id)
return document
}
FindById: FindByIdProps<K> = async (id) => {
const aggregate = this.Find().match({_id: Types.ObjectId(id)})
const [full] = await aggregate
return full
}
Find: BaseFindProps<K> = () => {
const aggrete = this.Model.aggregate()
return aggrete.sort({createdAt: -1})
}
Filter: FiltersProps = (filters) => {
return prepareFilter(filters)
}
PrePaginate: PrePaginateProps<K> = (aggregate) => aggregate
Paginate: PaginateProps = async (pageConfig, extraParams) => {
const {page, filters, limit, sort} = pageConfig
const finalFilters = this.Filter(filters)
const aggregate = this.Find(extraParams).match(finalFilters)
const finalSort = prepareSort(sort)
if (sort) aggregate.sort(finalSort)
const finalAggregate = this.PrePaginate(aggregate, pageConfig, extraParams)
return this.Model.aggregatePaginate(finalAggregate, {page, limit: limit || 10})
}
Export: ExportProps = async () => {
throw new ApiError(NoExportOverride)
}
Base: BaseProps<T> = () => this.Model
}
Models
//models/store.ts
import {createModel, createSchema, FinalDoc} from 'mc-helpers'
export type StoreProps = {name: string}
const schema = createSchema<StoreProps>({name: String})
export const StoreModel = createModel<StoreProps>('store', schema)
export type StoreDocument = FinalDoc<StoreProps>
ROUTES
For each service you will to configure an use from express route, yo can set arrays middlewares for every created route, getId, post, get, put, delete, export the same for errors which must be ValidationChain[]
//routes/api.ts
const storeRoute = configureRoute({
api: StoreService,
middlewares: {
getId: [authentication],
post: [authentication],
},
errors: {post: [StoreErrors.NoName]},
})
router.use('/store', storeRoute)
Error Handlers
- In order to throw ApiError is necesary to configure the Errors per Route/Api. You can created as follow
ValidationChain its from express.validator must be set in the route configuration
ErrorMessage can be throw by
ApiError
basicaly generates an Object{name:string, code:number}
addCheck adds check for get params addBody adds checks for put/post/delete params
import {ValidationChain} from 'express-validator'
import {ErrorMessage, Errors} from 'mc-helpers'
interface ErrorResponse {
NoPage: ValidationChain
NoName: ValidationChain
Exists: ErrorMessage
}
export const StoreErrors = Errors.generateError<ErrorResponse>(400, { // Error code number 400 401 402
NoPage: Errors.addCheck('page'),
NoName: Errors.addBody('name'),
Exists: Errors.addMessage('The store already existis'),
})
Helpers
- Configure ENV vars. require dontenv. Create a file .env in root dir with the env vars required.
type ENV_TYPE = 'development' | 'production' | 'test'
type EnvProps = {PORT: number; NAME: string; NODE_ENV: ENV_TYPE}
const proccesEnv = configureEnv<EnvProps>('PORT', 'NAME', 'NODE_ENV')
Last
- Do not forget to configure mongo!
const dbFinalName = `DBNAME`
const finalConnString = `${Config.MONGODB}${dbFinalName}`
mongoose.connect(finalConnString, {
useUnifiedTopology: true,
useNewUrlParser: true,
useCreateIndex: true,
useFindAndModify: false,
})
mongoose.connection.on('connected', () => {
console.log(`Conectado a ${finalConnString}`)
})