@waline/vercel
Version:
vercel server for waline comment system
181 lines (148 loc) • 4.42 kB
JavaScript
const { ObjectID: ObjectId } = require('think-mongo/lib/model');
const Base = require('./base.js');
module.exports = class extends Base {
parseWhere(where) {
if (think.isEmpty(where)) {
return {};
}
const filter = {};
const parseKey = (k) => (k === 'objectId' ? '_id' : k);
for (let k in where) {
if (k === '_complex') {
continue;
}
if (think.isString(where[k])) {
filter[parseKey(k)] = {
$eq: k === 'objectId' ? ObjectId(where[k]) : where[k],
};
continue;
}
if (where[k] === undefined) {
filter[parseKey(k)] = { $eq: null };
}
if (Array.isArray(where[k])) {
if (where[k][0]) {
const handler = where[k][0].toUpperCase();
switch (handler) {
case 'IN':
if (k === 'objectId') {
filter[parseKey(k)] = { $in: where[k][1].map(ObjectId) };
} else {
filter[parseKey(k)] = {
$regex: new RegExp(`^(${where[k][1].join('|')})$`),
};
}
break;
case 'NOT IN':
filter[parseKey(k)] = {
$nin:
k === 'objectId' ? where[k][1].map(ObjectId) : where[k][1],
};
break;
case 'LIKE': {
const first = where[k][1][0];
const last = where[k][1].slice(-1);
let reg;
if (first === '%' && last === '%') {
reg = new RegExp(where[k][1].slice(1, -1));
} else if (first === '%') {
reg = new RegExp(where[k][1].slice(1) + '$');
} else if (last === '%') {
reg = new RegExp('^' + where[k][1].slice(0, -1));
}
if (reg) {
filter[parseKey(k)] = { $regex: reg };
}
break;
}
case '!=':
filter[parseKey(k)] = { $ne: where[k][1] };
break;
case '>':
filter[parseKey(k)] = { $gt: where[k][1] };
break;
}
}
}
}
return filter;
}
where(instance, where) {
const filter = this.parseWhere(where);
if (!where._complex) {
return instance.where(filter);
}
const filters = [];
for (const k in where._complex) {
if (k === '_logic') {
continue;
}
filters.push({
...this.parseWhere({ [k]: where._complex[k] }),
...filter,
});
}
return instance.where({
// $or, $and, $not, $nor
[`$${where._complex._logic}`]: filters,
});
}
async select(where, { desc, limit, offset, field } = {}) {
const instance = this.mongo(this.tableName);
this.where(instance, where);
if (desc) {
instance.order(`${desc} DESC`);
}
if (limit || offset) {
instance.limit(offset || 0, limit);
}
if (field) {
instance.field(field);
}
const data = await instance.select();
return data.map(({ _id, ...cmt }) => ({
...cmt,
objectId: _id.toString(),
}));
}
async count(where = {}, { group } = {}) {
const instance = this.mongo(this.tableName);
this.where(instance, where);
if (group) {
instance.group(group);
}
const data = await instance.count({ raw: group });
if (!Array.isArray(data)) {
return data;
}
return data.map(({ _id, total: count }) => ({ ..._id, count }));
}
async add(data) {
if (data.objectId) {
data._id = data.objectId;
delete data.objectId;
}
const instance = this.mongo(this.tableName);
const id = await instance.add(data);
return { ...data, objectId: id.toString() };
}
async update(data, where) {
const instance = this.mongo(this.tableName);
this.where(instance, where);
const list = await instance.select();
return Promise.all(
list.map(async (item) => {
const updateData = typeof data === 'function' ? data(item) : data;
const instance = this.mongo(this.tableName);
this.where(instance, where);
await instance.update(updateData);
return { ...item, ...updateData };
}),
);
}
async delete(where) {
const instance = this.mongo(this.tableName);
this.where(instance, where);
return instance.delete();
}
};