UNPKG

@corbinu/couchbase

Version:

The unofficial Couchbase Node.js Client Library.

569 lines (492 loc) 11.8 kB
'use strict'; const PromiseHelper = require('./promisehelper'); const MutateInSpec = require('./mutateinspec'); const LookupInSpec = require('./lookupinspec'); const errors = require('./errors'); /** * CouchbaseList provides a simplified interface * for storing lists within a Couchbase document. * * @category Datastructures */ class CouchbaseList { /** * @hideconstructor */ constructor(collection, key) { this._coll = collection; this._key = key; } async _get() { var doc = await this._coll.get(this._key); if (!(doc.value instanceof Array)) { throw new errors.CouchbaseError('expected document of array type'); } return doc.value; } /** * * @param {function} callback */ async getAll(callback) { return PromiseHelper.wrapAsync(async () => { return await this._get(); }, callback); } async forEach(rowCallback, callback) { return PromiseHelper.wrapAsync(async () => { var values = await this._get(); for (var i = 0; i < values.length; ++i) { rowCallback(values[i], i, this); } return true; }, callback); } [Symbol.asyncIterator]() { var _this = this; return { data: null, index: -1, async next() { if (this.index < 0) { this.data = await _this._get(); this.index = 0; } if (this.index < this.data.length) { return { done: false, value: this.data[this.index++] }; } return { done: true }; }, }; } /** * * @param {*} index * @param {function} callback */ async getAt(index, callback) { return PromiseHelper.wrapAsync(async () => { var res = await this._coll.lookupIn(this._key, [ LookupInSpec.get('[' + index + ']'), ]); var itemRes = res.results[0]; if (itemRes.error) { throw itemRes.error; } return itemRes.value; }, callback); } /** * * @param {*} index * @param {function} callback */ async removeAt(index, callback) { return PromiseHelper.wrapAsync(async () => { await this._coll.mutateIn(this._key, [ MutateInSpec.remove('[' + index + ']'), ]); return true; }, callback); } /** * * @param {*} value * @param {function} callback */ async indexOf(value, callback) { return PromiseHelper.wrapAsync(async () => { var items = await this._get(); for (var i = 0; i < items.length; ++i) { if (items[i] === value) { return i; } } return -1; }, callback); } /** * * @param {function} callback */ async size(callback) { return PromiseHelper.wrapAsync(async () => { var res = await this._coll.lookupIn(this._key, [LookupInSpec.count('')]); return res.results[0].value; }, callback); } /** * * @param {*} value * @param {function} callback */ async push(value, callback) { return PromiseHelper.wrapAsync(async () => { await this._coll.mutateIn( this._key, [MutateInSpec.arrayAppend('', value)], { upsertDocument: true, } ); return true; }, callback); } /** * * @param {*} value * @param {function} callback */ async unshift(value, callback) { return PromiseHelper.wrapAsync(async () => { await this._coll.mutateIn( this._key, [MutateInSpec.arrayPrepend('', value)], { upsertDocument: true, } ); return true; }, callback); } } exports.List = CouchbaseList; /** * CouchbaseMap provides a simplified interface * for storing a map within a Couchbase document. * * @category Datastructures */ class CouchbaseMap { /** * @hideconstructor */ constructor(collection, key) { this._coll = collection; this._key = key; } async _get() { var doc = await this._coll.get(this._key); if (!(doc.value instanceof Object)) { throw new errors.CouchbaseError('expected document of object type'); } return doc.value; } /** * * @param {function} callback */ async getAll(callback) { return PromiseHelper.wrapAsync(async () => { return await this._get(); }, callback); } /** * * @param {function} rowCallback * @param {function} callback */ async forEach(rowCallback, callback) { return PromiseHelper.wrapAsync(async () => { var values = await this._get(); for (var i in values) { if (Object.prototype.hasOwnProperty.call(values, i)) { rowCallback(values[i], i, this); } } return true; }, callback); } [Symbol.asyncIterator]() { var _this = this; return { data: null, keys: null, index: -1, async next() { if (this.index < 0) { this.data = await _this._get(); this.keys = Object.keys(this.data); this.index = 0; } if (this.index < this.keys.length) { var key = this.keys[this.index++]; return { done: false, value: [this.data[key], key] }; } return { done: true }; }, }; } /** * * @param {*} item * @param {*} value * @param {function} callback */ async set(item, value, callback) { return PromiseHelper.wrapAsync(async () => { await this._coll.mutateIn(this._key, [MutateInSpec.upsert(item, value)], { upsertDocument: true, }); return true; }, callback); } /** * * @param {*} item * @param {function} callback */ async get(item, callback) { return PromiseHelper.wrapAsync(async () => { var res = await this._coll.lookupIn(this._key, [LookupInSpec.get(item)]); var itemRes = res.results[0]; if (itemRes.error) { throw itemRes.error; } return itemRes.value; }, callback); } /** * * @param {*} item * @param {function} callback */ async remove(item, callback) { return PromiseHelper.wrapAsync(async () => { await this._coll.mutateIn(this._key, [MutateInSpec.remove(item)]); return true; }, callback); } /** * * @param {*} item * @param {function} callback */ async exists(item, callback) { return PromiseHelper.wrapAsync(async () => { var res = await this._coll.lookupIn(this._key, [ LookupInSpec.exists(item), ]); var itemRes = res.results[0]; return itemRes.value; }, callback); } /** * * @param {function} callback */ async keys(callback) { return PromiseHelper.wrapAsync(async () => { var values = await this._get(); return Object.keys(values); }, callback); } /** * * @param {function} callback */ async values(callback) { return PromiseHelper.wrapAsync(async () => { var values = await this._get(); return Object.values(values); }, callback); } /** * * @param {function} callback */ async size(callback) { return PromiseHelper.wrapAsync(async () => { var res = await this._coll.lookupIn(this._key, [LookupInSpec.count('')]); return res.results[0].value; }, callback); } } exports.Map = CouchbaseMap; /** * CouchbaseQueue provides a simplified interface * for storing a queue within a Couchbase document. * * @category Datastructures */ class CouchbaseQueue { /** * @hideconstructor */ constructor(collection, key) { this._coll = collection; this._key = key; } async _get() { var doc = await this._coll.get(this._key); if (!(doc.value instanceof Array)) { throw new errors.CouchbaseError('expected document of array type'); } return doc.value; } /** * * @param {function} callback */ async size(callback) { return PromiseHelper.wrapAsync(async () => { var res = await this._coll.lookupIn(this._key, [LookupInSpec.count('')]); return res.results[0].value; }, callback); } /** * * @param {*} value * @param {function} callback */ async push(value, callback) { return PromiseHelper.wrapAsync(async () => { await this._coll.mutateIn( this._key, [MutateInSpec.arrayPrepend('', value)], { upsertDocument: true, } ); return true; }, callback); } /** * * @param {function} callback */ async pop(callback) { return PromiseHelper.wrapAsync(async () => { for (var i = 0; i < 16; ++i) { try { var res = await this._coll.lookupIn(this._key, [ LookupInSpec.get('[-1]'), ]); var value = res.results[0].value; await this._coll.mutateIn(this._key, [MutateInSpec.remove('[-1]')], { cas: res.cas, }); return value; } catch (e) { if (e instanceof errors.PathInvalidError) { throw new errors.CouchbaseError('no items available in list'); } // continue and retry } } throw new errors.CouchbaseError('no items available to pop'); }, callback); } } exports.Queue = CouchbaseQueue; /** * CouchbaseSet provides a simplified interface * for storing a set within a Couchbase document. * * @category Datastructures */ class CouchbaseSet { /** * @hideconstructor */ constructor(collection, key) { this._coll = collection; this._key = key; } async _get() { var doc = await this._coll.get(this._key); if (!(doc.value instanceof Array)) { throw new errors.CouchbaseError('expected document of array type'); } return doc.value; } /** * * @param {*} item * @param {function} callback */ async add(item, callback) { return PromiseHelper.wrapAsync(async () => { try { await this._coll.mutateIn( this._key, [MutateInSpec.arrayAddUnique('', item)], { upsertDocument: true, } ); } catch (e) { if (e instanceof errors.PathExistsError) { return false; } throw e; } return true; }, callback); } /** * * @param {*} item * @param {function} callback */ async contains(item, callback) { return PromiseHelper.wrapAsync(async () => { var values = await this._get(); for (var i = 0; i < values.length; ++i) { if (values[i] === item) { return true; } } return false; }, callback); } /** * * @param {*} item * @param {function} callback */ async remove(item, callback) { return PromiseHelper.wrapAsync(async () => { for (var i = 0; i < 16; ++i) { try { var res = await this._get(); var itemIdx = res.indexOf(item); if (itemIdx === -1) { throw new Error('item was not found in set'); } await this._coll.mutateIn( this._key, [MutateInSpec.remove('[' + itemIdx + ']')], { cas: res.cas, } ); return true; } catch (e) { // continue and retry } } throw new errors.CouchbaseError('no items available to pop'); }, callback); } /** * * @param {function} callback */ async values(callback) { return PromiseHelper.wrapAsync(async () => { return await this._get(); }, callback); } /** * * @param {function} callback */ async size(callback) { return PromiseHelper.wrapAsync(async () => { var res = await this._coll.lookupIn(this._key, [LookupInSpec.count('')]); return res.results[0].value; }, callback); } } exports.Set = CouchbaseSet;