Skip to content

Commit

Permalink
feat: add plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
saisilinus committed Dec 14, 2021
1 parent 0ba5241 commit 857a465
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 0 deletions.
25 changes: 25 additions & 0 deletions src/plugins/inlineToJSON.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/* eslint-disable no-param-reassign */

/**
* A mongoose schema plugin which allows user to hide fields dynamically using a hide option
*/

const inlineToJSON = (schema: any) => {
schema.options.toJSON = {};
schema.options.toJSON.hide = '';
schema.options.toJSON.transform = function (doc: any, ret: any, options: Record<string, any>) {
if (options['hide']) {
options['hide'].split(' ').forEach(function (prop: string) {
delete ret[prop];
});
}
ret.id = ret._id.toString();
delete ret._id;
delete ret.__v;
delete ret.createdAt;
delete ret.updatedAt;
return ret;
};
};

export default inlineToJSON;
70 changes: 70 additions & 0 deletions src/plugins/paginate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* eslint-disable no-param-reassign */

const paginate = (schema: any) => {
/**
* @typedef {Object} QueryResult
* @property {Document[]} results - Results found
* @property {number} page - Current page
* @property {number} limit - Maximum number of results per page
* @property {number} totalPages - Total number of pages
* @property {number} totalResults - Total number of documents
*/
/**
* Query for documents with pagination
* @param {Object} [filter] - Mongo filter
* @param {Object} [options] - Query options
* @param {string} [options.sortBy] - Sorting criteria using the format: sortField:(desc|asc). Multiple sorting criteria should be separated by commas (,)
* @param {string} [options.populate] - Populate data fields. Hierarchy of fields should be separated by (.). Multiple populating criteria should be separated by commas (,)
* @param {number} [options.limit] - Maximum number of results per page (default = 10)
* @param {number} [options.page] - Current page (default = 1)
* @returns {Promise<QueryResult>}
*/
schema.statics.paginate = async function (filter: Record<string, any>, options: Record<string, any>) {
let sort = '';
if (options['sortBy']) {
const sortingCriteria: any = [];
options['sortBy'].split(',').forEach((sortOption: string) => {
const [key, order] = sortOption.split(':');
sortingCriteria.push((order === 'desc' ? '-' : '') + key);
});
sort = sortingCriteria.join(' ');
} else {
sort = 'createdAt';
}

const limit = options['limit'] && parseInt(options['limit'], 10) > 0 ? parseInt(options['limit'], 10) : 10;
const page = options['page'] && parseInt(options['page'], 10) > 0 ? parseInt(options['page'], 10) : 1;
const skip = (page - 1) * limit;

const countPromise = this.countDocuments(filter).exec();
let docsPromise = this.find(filter).sort(sort).skip(skip).limit(limit);

if (options['populate']) {
options['populate'].split(',').forEach((populateOption: any) => {
docsPromise = docsPromise.populate(
populateOption
.split('.')
.reverse()
.reduce((a: string, b: string) => ({ path: b, populate: a }))
);
});
}

docsPromise = docsPromise.exec();

return Promise.all([countPromise, docsPromise]).then((values) => {
const [totalResults, results] = values;
const totalPages = Math.ceil(totalResults / limit);
const result = {
results,
page,
limit,
totalPages,
totalResults,
};
return Promise.resolve(result);
});
};
};

export default paginate;
43 changes: 43 additions & 0 deletions src/plugins/toJSON.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/* eslint-disable no-param-reassign */

/**
* A mongoose schema plugin which applies the following in the toJSON transform call:
* - removes __v, createdAt, updatedAt, and any path that has private: true
* - replaces _id with id
*/

const deleteAtPath = (obj: any, path: any, index: number) => {
if (index === path.length - 1) {
delete obj[path[index]];
return;
}
deleteAtPath(obj[path[index]], path, index + 1);
};

const toJSON = (schema: any) => {
let transform: Function;
if (schema.options.toJSON && schema.options.toJSON.transform) {
transform = schema.options.toJSON.transform;
}

schema.options.toJSON = Object.assign(schema.options.toJSON || {}, {
transform(doc: any, ret: any, options: Record<string, any>) {
Object.keys(schema.paths).forEach((path) => {
if (schema.paths[path].options && schema.paths[path].options.private) {
deleteAtPath(ret, path.split('.'), 0);
}
});

ret.id = ret._id.toString();
delete ret._id;
delete ret.__v;
delete ret.createdAt;
delete ret.updatedAt;
if (transform) {
return transform(doc, ret, options);
}
},
});
};

export default toJSON;

0 comments on commit 857a465

Please sign in to comment.