UNPKG

@waline/vercel

Version:

vercel server for waline comment system

223 lines (180 loc) 5.4 kB
const cloudbase = require('@cloudbase/node-sdk'); const Base = require('./base.js'); const { TCB_ENV, TCB_ID, TCB_KEY } = process.env; const app = cloudbase.init({ env: TCB_ENV, secretId: TCB_ID, secretKey: TCB_KEY, }); const db = app.database(); const _ = db.command; const $ = db.command.aggregate; const collections = {}; module.exports = class extends Base { async collection(tableName) { if (collections[tableName]) { return db.collection(tableName); } try { const instance = db.collection(tableName); await instance.count(); collections[tableName] = true; return db.collection(tableName); } catch (e) { if (e.code === 'DATABASE_COLLECTION_NOT_EXIST') { await db.createCollection(tableName); collections[tableName] = true; return db.collection(tableName); } throw e; } } 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(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': filter[parseKey(k)] = _.in(where[k][1]); break; case 'NOT IN': filter[parseKey(k)] = _.nin(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)); } filter[parseKey(k)] = reg; break; } case '!=': { filter[parseKey(k)] = _.neq(where[k][1]); break; } case '>': { filter[parseKey(k)] = _.gt(where[k][1]); break; } } } } } return filter; } where(instance, where, method = 'where') { const filter = this.parseWhere(where); if (!where._complex) { return instance[method](filter); } const filters = []; for (const k in where._complex) { if (k === '_logic') { continue; } filters.push({ ...this.parseWhere({ [k]: where._complex[k] }), ...filter, }); } return instance[method](_[where._complex._logic](...filters)); } async _select(where, { desc, limit, offset, field } = {}) { let instance = await this.collection(this.tableName); instance = this.where(instance, where); if (desc) { instance = instance.orderBy(desc, 'desc'); } if (limit) { instance = instance.limit(limit); } if (offset) { instance = instance.skip(offset); } if (field) { const filedObj = {}; field.forEach((f) => (filedObj[f] = true)); instance = instance.field(filedObj); } const { data } = await instance.get(); return data.map(({ _id, ...cmt }) => ({ ...cmt, objectId: _id.toString(), })); } async select(where, options = {}) { let data = []; let ret = []; let offset = options.offset || 0; do { options.offset = offset + data.length; ret = await this._select(where, options); data = data.concat(ret); } while (ret.length === 100); return data; } async count(where = {}, { group } = {}) { let instance = await this.collection(this.tableName); if (!group) { instance = this.where(instance, where); const { total } = await instance.count(); return total; } const _id = {}; group.forEach((f) => { _id[f] = `$${f}`; }); instance = instance.aggregate(); this.where(instance, where, 'match'); instance = instance.group({ _id, count: $.sum(1) }); const { data } = await instance.end(); return data.map(({ _id, count }) => ({ ..._id, count })); } async add(data) { if (data.objectId) { data._id = data.objectId; delete data.objectId; } const instance = await this.collection(this.tableName); const { id } = await instance.add(data); return { ...data, objectId: id }; } async update(data, where) { const instance = await this.collection(this.tableName); const { data: list } = await this.where(instance, where).get(); return Promise.all( list.map(async (item) => { const updateData = typeof data === 'function' ? data(item) : data; const instance = await this.collection(this.tableName); await instance.doc(item._id).update(updateData); return { ...item, ...updateData }; }), ); } async delete(where) { const instance = await this.collection(this.tableName); return this.where(instance, where).remove(); } };