UNPKG

@hapiness/etcd3

Version:
250 lines 8.95 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const etcd3_1 = require("etcd3"); const rxjs_1 = require("rxjs"); const interfaces_1 = require("../interfaces"); class Etcd3Manager { constructor(config) { this._config = config; this._basePath = (this._config.basePath || '').trim().length ? this._config.basePath : '/'; if (!config.is_mocking) { this._etcd3client = new etcd3_1.Etcd3(config.client); this._client = this._etcd3client.namespace(this._basePath); } } get client() { return this._etcd3client; } get namespace() { return this._client; } get config() { return this._config; } _fixKey(key) { if (!key || !key.trim().length || key === '/') { return '/'; } return `${this._basePath.endsWith('/') ? '' : '/'}${key.split('/').filter(_ => _.trim().length).join('/')}`; } /** * * @returns {string} The value of the base path * */ get basePath() { return this._basePath; } /****************************************************************************************** * * KV operations * ******************************************************************************************/ /** * * Get the value stored at path `key`. * * @param {string} key The key you want to retrieve the value * @param {ResponseFormat} format The format you want for the result (default is string) * * @returns {string | object | number | Buffer | null | Error} The value of the object stored * */ get(_key, format = interfaces_1.ResponseFormat.String) { const key = this._fixKey(_key); const promise = this.namespace.get(key); switch (format) { case interfaces_1.ResponseFormat.String: return rxjs_1.Observable.fromPromise(promise.string()); case interfaces_1.ResponseFormat.Number: return rxjs_1.Observable.fromPromise(promise.number()); case interfaces_1.ResponseFormat.Json: return rxjs_1.Observable.fromPromise(promise.json()); case interfaces_1.ResponseFormat.Buffer: return rxjs_1.Observable.fromPromise(promise.buffer()); default: return rxjs_1.Observable.throw(new Error('Format not supported')); } } /** * * Get all keys and values stored under the given `prefix`. * * @param {string} prefix The prefix under which you want to start looking * * @returns { { [key: string]: string } } An object having all path as keys and all values stored under them * */ getWithPrefix(_prefix) { const prefix = this._fixKey(_prefix); return rxjs_1.Observable.fromPromise(this.namespace.getAll().prefix(prefix)); } /** * * Delete the key `key`. * * @param {string} key The key you want to delete * * @returns {IDeleteRangeResponse} The result of the operation * */ delete(_key) { const key = this._fixKey(_key); return rxjs_1.Observable.fromPromise(this.namespace.delete().key(key)); } /** * * Delete all registered keys for the etcd3 client. * * @returns {IDeleteRangeResponse} The result of the operation * */ deleteAll() { return rxjs_1.Observable.fromPromise(this.namespace.delete().all()); } /** * * Append the value `value` at path `key`. * * @param {string} key The key you want to retrieve the value * @param {string | Buffer | number} value The format you want for the result (default is string) * @param {boolean} returnResult If you want to retrieve the value that was put * * @returns {IPutResponse} The result of the operation * */ put(_key, value, returnResult = true) { const key = this._fixKey(_key); if (!value) { return rxjs_1.Observable.throw(new Error('"value" should not be null nor undefined')); } const _types = { string: () => interfaces_1.ResponseFormat.String, number: () => interfaces_1.ResponseFormat.Number, object: () => { const _obj = JSON.parse(JSON.stringify(value)); if (_obj.type !== 'Buffer') { return interfaces_1.ResponseFormat.Json; } else { return interfaces_1.ResponseFormat.Buffer; } } }; let _value; if (typeof value === 'object') { const tmp = JSON.parse(JSON.stringify(value)); if (tmp.type !== 'Buffer') { _value = JSON.stringify(value); } else { _value = value; } } else { _value = value; } const returnResult$ = rxjs_1.Observable .of(returnResult) .switchMap(_ => rxjs_1.Observable .fromPromise(this.namespace.put(key).value(_value).exec()) .map(__ => ({ put_result: __, return_result: _ }))) .share(); return rxjs_1.Observable.merge(returnResult$.filter(_ => !_.return_result) .map(_ => _.put_result), returnResult$.filter(_ => !!_.return_result) .map(_ => _types[typeof value]()) .switchMap(_ => this.get(key, _))); } /****************************************************************************************** * * Watch operations * ******************************************************************************************/ /** * * Create a watcher for a specific key. * * @param {string} key The key you want to watch * @param {string} prefix The prefix you want to watch * * @returns {Watcher} The watcher instance created * */ createWatcher(_key, prefix = false) { const key = this._fixKey(_key); const prefix$ = rxjs_1.Observable.of(prefix).share(); return rxjs_1.Observable.merge(prefix$.filter(_ => !!_) .map(_ => this.namespace.watch().prefix(key)), prefix$.filter(_ => !_) .map(_ => this.namespace.watch().key(key))) .flatMap(_ => rxjs_1.Observable.fromPromise(_.create())); } /****************************************************************************************** * * Lock operations * ******************************************************************************************/ /** * * Create and acquire a lock for a key `key` specifying a ttl. * It will automatically contact etcd to keep the connection live. * When the connection is broken (end of process or lock released), * the TTL is the time after when the lock will be released. * * @param {string} key The key * @param {number} ttl The TTL value in seconds. Default value is 1 * * @returns {Lock} The lock instance created * */ acquireLock(_key, ttl = 1) { const key = this._fixKey(_key); return rxjs_1.Observable.fromPromise(this.namespace.lock(key).ttl(ttl || 1).acquire()); } /****************************************************************************************** * * Lease Operations * ******************************************************************************************/ /** * * Create a lease object with a ttl. * The lease is automatically keeping alive until it is close. * * @param {number} ttl The TTL value in seconds. Default value is 1 * * @returns {Lease} The lease instance created * */ createLease(ttl = 1) { return rxjs_1.Observable.of(this.namespace.lease(ttl || 1)); } /** * * Create a lease object with a ttl and attach directly a key-value to it. * The lease is automatically keeping alive until it is close. * * NOTE: Once the lease is closed, the key-value will be destroyed by etcd. * * @param {string} key The key where to store the value * @param {string | Buffer | number} value The value that will be stored at `key` path * @param {number} ttl The TTL value in seconds. Default value is 1 * * @returns {Lease} The lease instance created * */ createLeaseWithValue(_key, value, ttl = 1) { const key = this._fixKey(_key); const lease = this.namespace.lease(ttl || 1); return rxjs_1.Observable.fromPromise(lease.put(key).value(value).exec().then(_ => lease)); } /** * * Frees resources associated with the client. * */ close() { this._etcd3client.close(); } } exports.Etcd3Manager = Etcd3Manager; //# sourceMappingURL=etcd3.manager.js.map