UNPKG

couchbase

Version:

The official Couchbase Node.js Client Library.

728 lines (727 loc) 29.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CouchbaseSet = exports.CouchbaseQueue = exports.CouchbaseMap = exports.CouchbaseList = void 0; const errors_1 = require("./errors"); const generaltypes_1 = require("./generaltypes"); const observabilityhandler_1 = require("./observabilityhandler"); const observabilitytypes_1 = require("./observabilitytypes"); const sdspecs_1 = require("./sdspecs"); const utilities_1 = require("./utilities"); /** * CouchbaseList provides a simplified interface for storing lists * within a Couchbase document. * * @see {@link Collection.list} * @category Datastructures */ class CouchbaseList { /** * @internal */ constructor(collection, key) { this._coll = collection; this._key = key; } async _get(parentSpan) { const doc = await this._coll.get(this._key, { parentSpan: parentSpan }); if (!(doc.content instanceof Array)) { throw new errors_1.CouchbaseError('expected document of array type'); } return doc.content; } /** * Returns the entire list of items in this list. * * @param callback A node-style callback to be invoked after execution. */ async getAll(callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.ListGetAll, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { const res = await this._get(obsReqHandler.wrappedSpan); obsReqHandler.end(); return res; } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Iterates each item in the list. * * @param rowCallback A callback invoked for each item in the list. * @param callback A node-style callback to be invoked after execution. */ async forEach(rowCallback, callback) { return utilities_1.PromiseHelper.wrapAsync(async () => { const values = await this._get(); for (let i = 0; i < values.length; ++i) { rowCallback(values[i], i, this); } }, callback); } /** * Provides the ability to async-for loop this object. */ [Symbol.asyncIterator]() { const getNext = async () => this._get(); return { data: null, index: -1, async next() { if (this.index < 0) { this.data = await getNext(); this.index = 0; } const data = this.data; if (this.index < data.length) { return { done: false, value: data[this.index++] }; } return { done: true }; }, }; } /** * Retrieves the item at a specific index in the list. * * @param index The index to retrieve. * @param callback A node-style callback to be invoked after execution. */ async getAt(index, callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.ListGetAt, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { const res = await this._coll.lookupIn(this._key, [sdspecs_1.LookupInSpec.get('[' + index + ']')], { parentSpan: obsReqHandler.wrappedSpan }); const itemRes = res.content[0]; if (itemRes.error) { throw itemRes.error; } obsReqHandler.end(); return itemRes.value; } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Removes an item at a specific index from the list. * * @param index The index to remove. * @param callback A node-style callback to be invoked after execution. */ async removeAt(index, callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.ListRemoveAt, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { await this._coll.mutateIn(this._key, [sdspecs_1.MutateInSpec.remove('[' + index + ']')], { parentSpan: obsReqHandler.wrappedSpan }); obsReqHandler.end(); } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Returns the index of a specific value from the list. * * @param value The value to search for. * @param callback A node-style callback to be invoked after execution. */ async indexOf(value, callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.ListIndexOf, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { const items = await this._get(obsReqHandler.wrappedSpan); for (let i = 0; i < items.length; ++i) { if (items[i] === value) { obsReqHandler.end(); return i; } } obsReqHandler.end(); return -1; } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Returns the number of items in the list. * * @param callback A node-style callback to be invoked after execution. */ async size(callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.ListSize, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { const res = await this._coll.lookupIn(this._key, [sdspecs_1.LookupInSpec.count('')], { parentSpan: obsReqHandler.wrappedSpan }); obsReqHandler.end(); return res.content[0].value; } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Adds a new item to the end of the list. * * @param value The value to add. * @param callback A node-style callback to be invoked after execution. */ async push(value, callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.ListPush, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { await this._coll.mutateIn(this._key, [sdspecs_1.MutateInSpec.arrayAppend('', value)], { storeSemantics: generaltypes_1.StoreSemantics.Upsert, parentSpan: obsReqHandler.wrappedSpan, }); obsReqHandler.end(); } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Adds a new item to the beginning of the list. * * @param value The value to add. * @param callback A node-style callback to be invoked after execution. */ async unshift(value, callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.ListUnshift, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { await this._coll.mutateIn(this._key, [sdspecs_1.MutateInSpec.arrayPrepend('', value)], { storeSemantics: generaltypes_1.StoreSemantics.Upsert, parentSpan: obsReqHandler.wrappedSpan, }); obsReqHandler.end(); } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } } exports.CouchbaseList = CouchbaseList; /** * CouchbaseMap provides a simplified interface for storing a map * within a Couchbase document. * * @see {@link Collection.map} * @category Datastructures */ class CouchbaseMap { /** * @internal */ constructor(collection, key) { this._coll = collection; this._key = key; } async _get(parentSpan) { const doc = await this._coll.get(this._key, { parentSpan: parentSpan }); if (!(doc.content instanceof Object)) { throw new errors_1.CouchbaseError('expected document of object type'); } return doc.content; } /** * Returns an object representing all items in the map. * * @param callback A node-style callback to be invoked after execution. */ async getAll(callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.MapGetAll, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { const res = await this._get(obsReqHandler.wrappedSpan); obsReqHandler.end(); return res; } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Iterates through every item in the map. * * @param rowCallback A callback invoked for each item in the list. * @param callback A node-style callback to be invoked after execution. */ async forEach(rowCallback, callback) { return utilities_1.PromiseHelper.wrapAsync(async () => { const values = await this._get(); for (const i in values) { rowCallback(values[i], i, this); } }, callback); } /** * Provides the ability to async-for loop this object. */ [Symbol.asyncIterator]() { const getNext = async () => this._get(); return { data: null, keys: null, index: -1, async next() { if (this.index < 0) { this.data = await getNext(); this.keys = Object.keys(this.data); this.index = 0; } const keys = this.keys; const data = this.data; if (this.index < keys.length) { const key = keys[this.index++]; return { done: false, value: [data[key], key] }; } return { done: true, value: undefined }; }, }; } /** * Sets a specific to the specified value in the map. * * @param item The key in the map to set. * @param value The new value to set. * @param callback A node-style callback to be invoked after execution. */ async set(item, value, callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.MapSet, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { await this._coll.mutateIn(this._key, [sdspecs_1.MutateInSpec.upsert(item, value)], { storeSemantics: generaltypes_1.StoreSemantics.Upsert, parentSpan: obsReqHandler.wrappedSpan, }); obsReqHandler.end(); } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Fetches a specific key from the map. * * @param item The key in the map to retrieve. * @param callback A node-style callback to be invoked after execution. */ async get(item, callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.MapGet, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { const res = await this._coll.lookupIn(this._key, [sdspecs_1.LookupInSpec.get(item)], { parentSpan: obsReqHandler.wrappedSpan }); const itemRes = res.content[0]; if (itemRes.error) { throw itemRes.error; } obsReqHandler.end(); return itemRes.value; } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Removes a specific key from the map. * * @param item The key in the map to remove. * @param callback A node-style callback to be invoked after execution. */ async remove(item, callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.MapRemove, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { await this._coll.mutateIn(this._key, [sdspecs_1.MutateInSpec.remove(item)], { parentSpan: obsReqHandler.wrappedSpan, }); obsReqHandler.end(); } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Checks whether a specific key exists in the map. * * @param item The key in the map to search for. * @param callback A node-style callback to be invoked after execution. */ async exists(item, callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.MapExists, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { const res = await this._coll.lookupIn(this._key, [sdspecs_1.LookupInSpec.exists(item)], { parentSpan: obsReqHandler.wrappedSpan }); const itemRes = res.content[0]; obsReqHandler.end(); return itemRes.value; } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Returns a list of all the keys which exist in the map. * * @param callback A node-style callback to be invoked after execution. */ async keys(callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.MapKeys, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { const values = await this._get(obsReqHandler.wrappedSpan); obsReqHandler.end(); return Object.keys(values); } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Returns a list of all the values which exist in the map. * * @param callback A node-style callback to be invoked after execution. */ async values(callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.MapValues, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { const values = await this._get(obsReqHandler.wrappedSpan); obsReqHandler.end(); return Object.values(values); } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Returns the number of items that exist in the map. * * @param callback A node-style callback to be invoked after execution. */ async size(callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.MapSize, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { const res = await this._coll.lookupIn(this._key, [sdspecs_1.LookupInSpec.count('')], { parentSpan: obsReqHandler.wrappedSpan }); obsReqHandler.end(); return res.content[0].value; } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } } exports.CouchbaseMap = CouchbaseMap; /** * CouchbaseQueue provides a simplified interface for storing a queue * within a Couchbase document. * * @see {@link Collection.queue} * @category Datastructures */ class CouchbaseQueue { /** * @internal */ constructor(collection, key) { this._coll = collection; this._key = key; } async _get() { const doc = await this._coll.get(this._key); if (!(doc.content instanceof Array)) { throw new errors_1.CouchbaseError('expected document of array type'); } return doc.content; } /** * Returns the number of items in the queue. * * @param callback A node-style callback to be invoked after execution. */ async size(callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.QueueSize, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { const res = await this._coll.lookupIn(this._key, [sdspecs_1.LookupInSpec.count('')], { parentSpan: obsReqHandler.wrappedSpan }); obsReqHandler.end(); return res.content[0].value; } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Adds a new item to the back of the queue. * * @param value The value to add. * @param callback A node-style callback to be invoked after execution. */ async push(value, callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.QueuePush, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { await this._coll.mutateIn(this._key, [sdspecs_1.MutateInSpec.arrayPrepend('', value)], { storeSemantics: generaltypes_1.StoreSemantics.Upsert, parentSpan: obsReqHandler.wrappedSpan, }); obsReqHandler.end(); } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Removes an item from the front of the queue. * * @param callback A node-style callback to be invoked after execution. */ async pop(callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.QueuePop, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { for (let i = 0; i < 16; ++i) { try { const res = await this._coll.lookupIn(this._key, [sdspecs_1.LookupInSpec.get('[-1]')], { parentSpan: obsReqHandler.wrappedSpan }); const value = res.content[0].value; await this._coll.mutateIn(this._key, [sdspecs_1.MutateInSpec.remove('[-1]')], { cas: res.cas, parentSpan: obsReqHandler.wrappedSpan, }); obsReqHandler.end(); return value; } catch (e) { if (e instanceof errors_1.PathInvalidError) { throw new errors_1.CouchbaseError('no items available in list'); } // continue and retry } } throw new errors_1.CouchbaseError('no items available to pop'); } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } } exports.CouchbaseQueue = CouchbaseQueue; /** * CouchbaseSet provides a simplified interface for storing a set * within a Couchbase document. * * @see {@link Collection.set} * @category Datastructures */ class CouchbaseSet { /** * @internal */ constructor(collection, key) { this._coll = collection; this._key = key; } async _get(parentSpan) { const doc = await this._coll.get(this._key, { parentSpan: parentSpan }); if (!(doc.content instanceof Array)) { throw new errors_1.CouchbaseError('expected document of array type'); } return doc.content; } /** * Adds a new item to the set. Returning whether the item already existed * in the set or not. * * @param item The item to add. * @param callback A node-style callback to be invoked after execution. */ async add(item, callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.SetAdd, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { await this._coll.mutateIn(this._key, [sdspecs_1.MutateInSpec.arrayAddUnique('', item)], { storeSemantics: generaltypes_1.StoreSemantics.Upsert, parentSpan: obsReqHandler.wrappedSpan, }); } catch (e) { if (e instanceof errors_1.PathExistsError) { obsReqHandler.end(); return false; } obsReqHandler.endWithError(e); throw e; } obsReqHandler.end(); return true; }, callback); } /** * Returns whether a specific value already exists in the set. * * @param item The value to search for. * @param callback A node-style callback to be invoked after execution. */ async contains(item, callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.SetContains, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { const values = await this._get(obsReqHandler.wrappedSpan); for (let i = 0; i < values.length; ++i) { if (values[i] === item) { obsReqHandler.end(); return true; } } obsReqHandler.end(); return false; } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Removes a specific value from the set. * * @param item The value to remove. * @param callback A node-style callback to be invoked after execution. */ async remove(item, callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.SetRemove, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { for (let i = 0; i < 16; ++i) { try { const res = await this._coll.get(this._key, { parentSpan: obsReqHandler.wrappedSpan, }); if (!(res.content instanceof Array)) { throw new errors_1.CouchbaseError('expected document of array type'); } const itemIdx = res.content.indexOf(item); if (itemIdx === -1) { throw new Error('item was not found in set'); } await this._coll.mutateIn(this._key, [sdspecs_1.MutateInSpec.remove('[' + itemIdx + ']')], { cas: res.cas, parentSpan: obsReqHandler.wrappedSpan, }); obsReqHandler.end(); return; } catch (_e) { // continue and retry } } throw new errors_1.CouchbaseError('no items available to pop'); } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Returns a list of all values in the set. * * @param callback A node-style callback to be invoked after execution. */ async values(callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.SetValues, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { const res = await this._get(obsReqHandler.wrappedSpan); obsReqHandler.end(); return res; } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } /** * Returns the number of elements in this set. * * @param callback A node-style callback to be invoked after execution. */ async size(callback) { const obsReqHandler = new observabilityhandler_1.ObservableRequestHandler(observabilitytypes_1.DatastructureOp.SetSize, this._coll.observabilityInstruments); obsReqHandler.setRequestKeyValueAttributes(this._coll._cppDocId(this._key)); return utilities_1.PromiseHelper.wrapAsync(async () => { try { const res = await this._coll.lookupIn(this._key, [sdspecs_1.LookupInSpec.count('')], { parentSpan: obsReqHandler.wrappedSpan }); obsReqHandler.end(); return res.content[0].value; } catch (e) { obsReqHandler.endWithError(e); throw e; } }, callback); } } exports.CouchbaseSet = CouchbaseSet;