1.0.20 • Published 2 years ago

exp-mgo-toolings v1.0.20

Weekly downloads
-
License
ISC
Repository
-
Last release
2 years ago

exp-mgo-toolings

Made faster query for express and mongoose

Modules

  • Query helper for MongoDB mongoose Required packages - bson
  • AWS helper easy use and include resize before upload Required packages - aws-sdk - uuid - dotenv - sharp
  • Pubnub helper a little helper made more understandable for using pubnub as realtime app Required packages - pubnub
  • Mail helper Required packages - nodemailer
  • Api Response for express made code easier to handle error and standard response
  • asyncHandler handler all error and no more try catch block every where

If you want to ignore package from other modules

  • Import directly from DIR
const asyncHandle = require("exp-mgo-toolings/src/async-handler")
const ApiResponse = require("exp-mgo-toolings/src/api-response")
const Aws = require("exp-mgo-toolings/src/aws")
const Mail = require("exp-mgo-toolings/src/mail")
const PubNub = require("exp-mgo-toolings/src/pubnub")

# Query function's description

Automatic Detect query params from query string page Perform paginate current page. Note: must follow with limit limit Perform paginate current limit. Note: must follow with page q Perform search keyword, work with setSearchField method start_date Perform filtering by date rate required with end_date end_date Perform filtering by date rate required with start_date sort Perform sorting concept column|arg ex: created_at|asc summary Get full paginate response such like: total, total_page, total_in_page, etc...

Simple usage

const { Query } = require("exp-mgo-toolings")
const mongoose = require("mongoose")

// Register somewhere for future use
const query = new Query(mongoose)

// ex1: "order" as collection's name
const execute = query.model("order") 

// ex2: Put model instance of mongoose
const ExampleModel = require("./some-mongoose-model")
const execute = query.model(ExampleModel) // ex2: "order" as collection's name

// Perform sample query
const result = await execute.exec(req) // "req" coming from express request

// ex3: Perform select and unset. Important select & unset cannot combine together
const result = await excute.
	unset("removeField1 removeField2") // or ["removeField1","removeField1"]
	.exec(req) // "req" coming from express request

const result = await excute.
	select("field1","field2") // or ["field1","field2"]
	.exec(req) // "req" coming from express request

Example usage of $lookup

// Peform sample lookup aggreagte concept
const result = await excute.
	lookup({ from: "modelName", localField: "localField", foreignField: "_id", as: "localField" })
	.exec(req) // "req" coming from express request

// Peform sample lookup aggreagte concept with select
const result = await excute.
	lookup({ from: "modelName", localField: "localField", foreignField: "_id", as: "localField", select: "field1 field2" })
	.exec(req) // "req" coming from express request

// Peform sample lookup aggreagte concept with unset
const result = await excute.
	lookup({ from: "modelName", localField: "localField", foreignField: "_id", as: "localField", unset: ["field1", "field2"] })
	.exec(req) // "req" coming from express request

// Peform sample lookup aggreagte concept with many. Default is true
const result = await excute.
	lookup({ from: "modelName", localField: "localField", foreignField: "_id", as: "localField", many: false })
	// many false return as object
	.exec(req) // "req" coming from express request

Example usage of $populate

// Peform sample populate mongoose concept with many. Default is true
// ex1: Sample usage
const result = await excute.
	populate("ref_field", "field1 field2") // 1. ref model 2.select field
	.exec(req) // "req" coming from express request

// ex2: With $select
const result = await excute.
	populate({ path: "ref_field", select: "field1 field2" })
	.exec(req) // "req" coming from express request

// ex3:With $unset
const result = await excute.
	populate({ path: "ref_field", unset: ["field1", "field2"] })
	.exec(req) // "req" coming from express request

// ex3: With $many  deafult is false
const result = await excute.
	populate({ path: "ref_field", many: true })
	.exec(req) // "req" coming from express request

// ex4: With sub populate required "modelName"
const result = await excute.
	populate({
		path: "ref_field",
		populate: {
			modelName: "ref_model", path: "ref_field"
			// Can use unset, select, many, etc...
		}
	})
	.exec(req) // "req" coming from express request

// ex5: With many sub populate required "modelName"
const result = await excute.
	populate({
		path: "ref_field",
		populate: [{
			modelName: "ref_model", path: "ref_field"
			// Can use unset, select, many, etc...
		}]
	})
	.exec(req) // "req" coming from express request

// ex6: With sub populate required "modelName"
const result = await excute.
	populate({
		path: "ref_field",
		populate: {
			modelName: "ref_model", path: "ref_field",
			// Can use unset, select, many, etc...
			populate: {
				modelName: "ref_model", path: "ref_field"
				// Can use unset, select, many, etc...
			}
		}
	})
	.exec(req) // "req" coming from express request

Example usage of $match

// ex1: simple match
const result = await excute.
	match({
		name: "bank"
	})
	.exec(req) // "req" coming from express request


// ex2: Perform match with populate
/* 
[
	{
		"name":"bank",
		"office_id":"18273817231927371892731"
	}
]
*/
const result = await excute.
	populate({
		path: "office_id",
		select: "name"
	}).
	match({
		"office_id.name": "where is my office data"
	})
	.exec(req) // "req" coming from express request

Example usage of $setSearchField work with "q" from query string

// ex1: simple match
const result = await excute.
	.setSearchField("name", "another_field")
	.exec(req) // "req" coming from express request


// ex2: Perform match with populate
/* 
[
	{
		"name":"bank",
		"office_id":"18273817231927371892731"
	}
]
*/
const result = await excute.
	populate({
		path: "office_id",
		select: "name"
	}).
	.setSearchField("office_id.name", "another_field")
	.exec(req) // "req" coming from express request

lookup Perform join document in aggregate concept

  • path Reference path
  • select Filter only given select field
  • populate Sub populate
  • many Perform default "false"
  • unset Filter out field

populate Perform join document in mongoose concept

  • path Reference path
  • select Filter only given select field
  • populate Sub populate
  • many Perform default "false"
  • unset Filter out field
  • modelName Models's name to reference to. Required only in sub populate

set(String) Set response json like $project ex: "field1 field2"

match(Object) Perform $match condition

setSearchField(...String) Perform $match condition ("field1","field2")

custom(Object) Perform custom pipeline in aggregate concept

forcePaginate(Boolean) True: required page, limit in query

select(String) Perform Select field ex: "field1 field2" or "field1","field2"

unset(...String) Perform filter out parameters in response ex: ("field1","field2")

setOption(Object)

  • performPaginateBeforeLogic Advance usage perform paginate before condition or end of condition
  • dateField Set filter field from query "start_date" and "end_date"

Final query must be called (Promise function)

exec(req) Combine all condition and Automatic detect query string and perform query

# ApiResponse with asyncHandler

API RESPONSE Usage description

  • Overview Ex: Throw new Error(StatusCode-ErrorCode::Message)
  • Ex1: Throw new Error(400::Your error message)
  • Ex2: Throw new Error(Your error message) Default 500 status
  • Ex3: Multi language: Throw new Error(400::en=English message && la=Lao message)
  • Ex4: With error CODE as ER001: Throw new Error(400-ER001::Your error message)
  • EX5: No Message use throw new Error(400-ERR001) Default message "Request failed"
  • EX6: No Message & No Error Code use throw new Error(400) Default message "Request failed" and "ERR500" for error code

Let's try in express and asyncHandle

const { asyncHandle, ApiResponse } = require("exp-mgo-toolings")

// ex1: sample use sage
app.get("/", asyncHandle(async ({ req, res }) => {
	const resp = new ApiResponse(res)

	if (checkError) throw new Error(`400::Your response message`)

	// Your code here
	return resp.response({})
}))

// ex2: sample with mongoose transaction
app.get("/",asyncHandle(async ({ body, res, opts, commit }) => {
	const resp = new ApiResponse(res)

	// Dont worry about abort 
	// If there is error automatic abort transaction

	await ExampleModel.insertOne(body, opts)

	await commit() // commit transaction

	return resp.response({})
}, mongoose))

#AWS File upload

Important ENV must specific Don't worry I wont save your credential XD

  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_KEY
  • AWS_S3_BUCKET_NAME

Methods

uploadFile()

file file as buffer ex: req.file.image

bucket (optional) default is set in ENV

fileType file's format jpg,png...

path storage path

file_name by default it will generate file name as uuid string for you if you want to generate your own file's name then use this

origin_filename use original file's name

return_only_name by default will return with path if you want to return only filename then set this to "true"

upload() and uploadMany()

file file as buffer ex: req.file.image

bucket (optional) default is set in ENV

fileType file's format jpg,png...

path storage path

resize (Optional) ex: we want to resize image to 256px then set 256 or multiple size 500,256

Example usage

// Ex1: Sample usage
const filename = await AwsFunc.upload({
	file: req.files.image,
	fileType: "jpg",
	path: "some_path/"
})

// Ex2: With resize
const filename = await AwsFunc.upload({
	file: req.files.image,
	fileType: "jpg",
	resize: [256, 800],
	path: "some_path/"
})

// Ex3: Multiple File
const filename = await AwsFunc.uploadMany({
	file: req.files.image,
	fileType: "jpg",
	path: "some_path/"
})

// Ex4: Multiple File With resize
const filename = await AwsFunc.uploadMany({
	file: req.files.image,
	fileType: "jpg",
	resize: [256, 800],
	path: "some_path/"
})

Validator Usage with express

WORK WELL with API-RESPONSE ASYN-HANDLE and mongoose

const { Validator } = require("exp-mgo-toolings")
const mongoose = require("mongoose")

// Perform as req from express
const example1 = {
    body: {
        id: "",
        uuidVs: "e09e2870-4c66-11ed-979f-00163e9b33ca",
        uuidV2: "9f0f0cd0-4c66-11ed-bdc3-0242ac120002",
        uuidV3: "078c5665-3df4-3b1c-8fd0-1c530f9a062b",
        uuidV4: null,
        uuidV5: null,
        birthDate: "2022-01-22",
        name: "sdsd",
        age: 10,
        email: null,
        gender: "male",
        isActive: true,
        ip: "128.0.0.1",
        array: ["1", "2", "3", "4", "5"],
        contact: {
            id: "1",
            name: "souksavanhm",
            age: 10,
            email: "souksavanh@gmail.com",
            gender: "male",
            isActive: true,
            ip: "128.0.0.1",
            object: {
                id: "1",
                name: "asdasd",
                age: 10,
                email: null,
                gender: "male"
            },
        },
        permission: [
            {
                id: "1",
                age: 10,
                name: "22",
                email: "souksavanh@gmail.com",
                object: {
                    id: "1",
                    age: "10",
                    name: "234",
                    email: "souksavanhgmail.com",
                    object: {
                        id: "1",
                        age: 10,
                        name: "nsame 1",
                        email: "souksavanh@gmail.com"
                    }
                }
            },
            {
                id: "2",
                name: "name 2",
                age: 10,
                email: "souksavanh@gmail.com",
                object: {
                    id: "1",
                    age: 10,
                    name: "name 1",
                    email: "souksavanh@gmail.com",
                    object: {
                        id: "1",
                        age: 10,
                        name: "name 1",
                        email: "souksavanh@gmail.com"
                    }
                }
            },
            {
                id: "1",
                name: "name 2",
                age: 10,
                email: "souksavanh@gmail.com",
                object: {
                    id: "1",
                    age: 10,
                    name: "name 1",
                    email: "souksavanh@gmail.com",
                    object: {
                        id: "1",
                        age: 10,
                        name: "name 1",
                        email: "souksavanh@gmail.com"
                    }
                }
            },
        ]
    }
}

Let's start!!!

// Ex1: with mongoose validate exist data
const rule = new Validator(example1)

// Ex2: simple use
const rule = new Validator(example1, mongoose)

SIMPLE USE

rule.body("uuidV1", "validate_uuidV1").required().uuid(1) // UUID V1
rule.body("uuidV3", "validate_uuidV3").required().uuid(3) // UUID V3
rule.body("uuidV4", "validate_uuidV4").optional(true).uuid(4) // UUID V4
rule.body("uuidV5", "validate_uuidV5").optional(true).uuid(5) // UUID V5
rule.body("birthDate", "validate_birthDate").optional(true).date()
rule.body("name", "validate_name").required().string()
rule.body("age", "validate_age").optional().int()
rule.body("email", "validate_email").optional(true).email()
rule.body("gender", "validate_gender").required().enum("male", "female")
rule.body("isActive", "validate_isActive").optional().bool()
rule.body("ip", "validate_ip").required().IP()
rule.body("id", "validate_id").optional(true).string()

Array without object item

rule.body("array", "validate_array").required().array({ maxLength: 5 })

// Find inside mongoose model by given "model's name" and "target key"
// ex: find in user's model where name === xxxx
rule.body("array.*", "validate_array").required().string().mustExistIn("user", { key: "name" })

Object items

rule.body("contact.id", "validate_contact_id").required().string()
rule.body("contact.age", "validate_age").optional().int()
rule.body("contact.email", "validate_email").optional(true).email()
rule.body("contact.gender", "validate_gender").required().enum("male", "female")

Array with item inside

Not support nested array, ONYLY WORK WITH nested OBJECT

rule.body("permission", "validate_contact_id").required().array()
rule.body("permission.*.id", "validate_permission_id").required().string()
rule.body("permission.*.name", "validate_permission_name").required().string()
rule.body("permission.*.email", "validate_permission_email").required().email()
rule.body("permission.*.object.name", "validate_permission_name").required().string()
rule.body("permission.*.object.object.name", "validate_permission_name").required().string().mustExistIn("user", { key: "name" })

Perform validate

soreContext Will store mongoose data if found in database

const isValid = await rule.validate({ 
    storeContext: true , // Store result from mongoose in req
    useError: true // Throw error if detected
})

isValid.throwError() // if useError is not set. Can use this one to trigger error
isValid.isEmpty() // Check if empty error
isValid.errors() // Get all detected error

Eample with array body

const example2 = {
    body: [
        {
            id: "1",
            name: "name 2",
            age: 10,
            email: "souksavanh@gmail.com",
            object: {
                id: "1",
                age: 10,
                name: "Dsemo",
                email: "souksavanh@gmail.com",
            }
        },
        {
            id: "2",
            name: "13",
            age: 10,
            email: "souksavanh@gmail.com",
            object: {
                id: "1",
                age: 10,
                name: "Demso",
                email: "souksavanh@gmail.com",
            }
        }
    ]
}



const _ = new Validator(example2)

_.body("*").required().array()
_.body("*.id").required().string()
_.body("*.name").required().string()
_.body("*.object").required().object(true)
_.body("*.object.id").required().string()
_.body("*.object.age").required().string()
_.body("*.object.name").optional().string().mustExistIn("user")
_.body("*.object.email").required().email()

_.validate()
1.0.20

2 years ago

1.0.19

2 years ago

1.0.18

2 years ago

1.0.17

2 years ago

1.0.16

2 years ago

1.0.15

2 years ago

1.0.13

2 years ago

1.0.12

2 years ago

1.0.11

2 years ago

1.0.10

2 years ago

1.0.9

2 years ago

1.0.8

2 years ago

1.0.7

2 years ago

1.0.6

2 years ago

1.0.5

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago