@logzio-node-toolbox/consul
Advanced tools
Comparing version 0.0.10 to 0.0.11
@@ -9,5 +9,8 @@ interface AnyObject { | ||
baseUrl?: string; | ||
validateOptions?: ValidateOptions; | ||
watchOptions?: WatchOptions; | ||
registerRetryOptions?: RegisterRetryOptions; | ||
} | ||
export interface ValidateConnectedOptions { | ||
export interface ValidateOptions { | ||
fail?: boolean; | ||
@@ -20,26 +23,37 @@ timeout?: number; | ||
export interface WatchOptions { | ||
key?: string; | ||
export interface WatchOptionsInner { | ||
backoffFactor?: number; | ||
backoffMax?: number; | ||
maxAttempts?: number; | ||
} | ||
export interface WatchOptions { | ||
key?: string; | ||
onChange?: VoidFunction; | ||
onError?: VoidFunction; | ||
watchOptions?: WatchOptionsInner; | ||
} | ||
export interface RegisterOptions { | ||
export interface RegisterOptionsInner { | ||
factor?: number; | ||
retries?: number; | ||
onRetry?: VoidFunction; | ||
} | ||
export interface RegisterData { | ||
meta?: AnyObject; | ||
checks?: AnyObject; | ||
address?: string; | ||
hostname?: string; | ||
serviceName?: string; | ||
id?: string; | ||
name?: string; | ||
port?: number; | ||
interval?: number; | ||
} | ||
export interface RegisterOptions { | ||
data: RegisterData; | ||
validateRegisteredInterval?: number; | ||
onError?: VoidFunction; | ||
registerOptions?: RegisterOptionsInner; | ||
} | ||
export declare class Consul { | ||
public constructor(consulOptions: ConsulOptions); | ||
public validateConnected(validateConnectedOptions: ValidateConnectedOptions): void; | ||
private parseValue(Values?: { Value?: string; key?: string }): void; | ||
public validateConnected(validateOptions: ValidateOptions): void; | ||
private buildKey(key: string): { key: string; value: AnyObject }; | ||
@@ -54,7 +68,5 @@ public get(key?: string): AnyObject; | ||
} | ||
interface MultiConsulOptions extends ConsulOptions { | ||
paths: string[]; | ||
} | ||
export declare class MultiConsul extends Consul { | ||
@@ -61,0 +73,0 @@ public constructor(multiConsulOptions: MultiConsulOptions); |
@@ -5,7 +5,47 @@ import retry from 'async-retry'; | ||
const defaultValidateOptions = { | ||
fail: true, | ||
timeout: 5000, | ||
retries: 6, | ||
factor: 2, | ||
onRetry: null | ||
}; | ||
const defaultWatchOptions = { | ||
backoffFactor: 100, | ||
backoffMax: 30000, | ||
maxAttempts: 10000 | ||
}; | ||
const defaultRegisterRetryOptions = { | ||
factor: 2, | ||
retries: 6, | ||
onRetry: null | ||
}; | ||
function parseValue({ | ||
Value = null, | ||
Key = null | ||
} = {}) { | ||
if (!Key || !Value) return undefined; | ||
let value; | ||
try { | ||
value = JSON.parse(Value); | ||
} catch (err) { | ||
value = Value; | ||
} | ||
return { | ||
key: Key, | ||
value | ||
}; | ||
} | ||
class Consul { | ||
constructor({ | ||
port, | ||
port = 8500, | ||
host = 'localhost', | ||
baseUrl = null | ||
baseUrl = null, | ||
validateOptions = {}, | ||
watchOptions = {}, | ||
registerRetryOptions = {} | ||
} = {}) { | ||
@@ -24,2 +64,11 @@ if (!port) throw new Error('consul must have port'); | ||
this.openWatchersToClose = []; | ||
this.watchOptions = { ...defaultWatchOptions, | ||
...watchOptions | ||
}; | ||
this.validateOptions = { ...defaultValidateOptions, | ||
...validateOptions | ||
}; | ||
this.registerRetryOptions = { ...defaultRegisterRetryOptions, | ||
...registerRetryOptions | ||
}; | ||
this.registerParams = { | ||
@@ -32,9 +81,13 @@ id: null, | ||
async validateConnected({ | ||
fail = true, | ||
timeout = 5000, | ||
retries = 6, | ||
factor = 2, | ||
onRetry = null | ||
}) { | ||
async validateConnected(validateOptions = {}) { | ||
let { | ||
fail, | ||
timeout, | ||
retries, | ||
factor, | ||
onRetry | ||
} = { ...this.validateOptions, | ||
...validateOptions | ||
}; | ||
try { | ||
@@ -53,21 +106,2 @@ await retry(async () => this.consulInstance.agent.check.list({ | ||
parseValue({ | ||
Value = null, | ||
Key = null | ||
} = {}) { | ||
if (!Key || !Value) return undefined; | ||
let value; | ||
try { | ||
value = JSON.parse(Value); | ||
} catch (err) { | ||
value = Value; | ||
} | ||
return { | ||
key: Key, | ||
value | ||
}; | ||
} | ||
buildKey(key) { | ||
@@ -78,3 +112,3 @@ return `${this.keyPrefix}${key.replace(new RegExp(`^/*${this.keyPrefix}/*|^/*`), '')}`; | ||
async get(key) { | ||
return this.parseValue(await this.consulInstance.kv.get(this.buildKey(key))); | ||
return parseValue(await this.consulInstance.kv.get(this.buildKey(key))); | ||
} | ||
@@ -102,5 +136,3 @@ | ||
onError, | ||
backoffFactor = 100, | ||
backoffMax = 30000, | ||
maxAttempts = 10000 | ||
watchOptions = {} | ||
} = {}) { | ||
@@ -113,8 +145,7 @@ if (!key || !onChange) return; | ||
}, | ||
backoffFactor, | ||
backoffMax, | ||
maxAttempts | ||
...this.watchOptions, | ||
...watchOptions | ||
}; | ||
const watcher = this.consulInstance.watch(options); | ||
watcher.on('change', data => data && onChange(this.parseValue(data))); | ||
watcher.on('change', data => data && onChange(parseValue(data))); | ||
watcher.on('error', err => err && onError(err)); | ||
@@ -125,51 +156,41 @@ this.openWatchersToClose.push(watcher); | ||
async register({ | ||
meta, | ||
checks, | ||
address, | ||
hostname, | ||
serviceName, | ||
port, | ||
interval = null, | ||
onErorr | ||
data = {}, | ||
validateRegisteredInterval, | ||
onError, | ||
registerRetryOptions = {} | ||
} = {}) { | ||
if (!serviceName || !hostname) throw new Error('must provide serviceName and hostname to service discovery'); | ||
if (!data.name || !data.id) throw new Error('must provide name and id to register for consul service discovery'); | ||
if (this.registerParams.id) return; | ||
const options = { | ||
id: hostname, | ||
name: serviceName, | ||
port, | ||
address, | ||
meta, | ||
checks | ||
const options = { ...this.registerRetryOptions, | ||
...registerRetryOptions | ||
}; | ||
const invokeRegister = async () => { | ||
const list = await retry(async () => this.consulInstance.agent.service.list(), this.retry); | ||
const isRegistered = Object.entries(list).some(([id, { | ||
Service | ||
}]) => id === hostname && Service === serviceName); | ||
const startRegister = async () => { | ||
try { | ||
const list = await retry(async () => this.consulInstance.agent.service.list(), options); | ||
const isRegistered = Object.entries(list).some(([id, { | ||
Service | ||
}]) => id === data.id && Service === data.name); | ||
if (!isRegistered) { | ||
await retry(async () => this.consulInstance.agent.service.register(options), this.retry); | ||
this.registerParams.id = hostname; | ||
} | ||
}; | ||
if (!isRegistered) { | ||
await retry(async () => this.consulInstance.agent.service.register(data), options); | ||
this.registerParams.id = data.id; | ||
} | ||
const startRegisterInterval = async () => { | ||
try { | ||
await invokeRegister(); | ||
if (interval) this.registerParams.timeoutId = setTimeout(startRegisterInterval, interval); | ||
if (validateRegisteredInterval) this.registerParams.timeoutId = setTimeout(startRegister, validateRegisteredInterval); | ||
} catch (err) { | ||
onErorr(err); | ||
onError(err); | ||
} | ||
}; | ||
await invokeRegister(); | ||
startRegisterInterval(); | ||
await startRegister(); | ||
} | ||
async close() { | ||
async close(registerRetryOptions = {}) { | ||
if (this.registerParams.id) { | ||
if (this.registerParams.timeoutId) clearTimeout(this.registerParams.timeoutId); | ||
await retry(async () => this.consulInstance.agent.service.deregister(this.registerParams.id), this.retry); | ||
const options = { ...this.registerRetryOptions, | ||
...registerRetryOptions | ||
}; | ||
await retry(async () => this.consulInstance.agent.service.deregister(this.registerParams.id), options); | ||
} | ||
@@ -184,16 +205,7 @@ | ||
function createCommonjsModule(fn, basedir, module) { | ||
return module = { | ||
path: basedir, | ||
exports: {}, | ||
require: function (path, base) { | ||
return commonjsRequire(path, (base === undefined || base === null) ? module.path : base); | ||
} | ||
}, fn(module, module.exports), module.exports; | ||
function createCommonjsModule(fn) { | ||
var module = { exports: {} }; | ||
return fn(module, module.exports), module.exports; | ||
} | ||
function commonjsRequire () { | ||
throw new Error('Dynamic requires are not currently supported by @rollup/plugin-commonjs'); | ||
} | ||
var check = function (it) { | ||
@@ -204,3 +216,3 @@ return it && it.Math == Math && it; | ||
var global_1 = // eslint-disable-next-line no-undef | ||
var global$1 = // eslint-disable-next-line no-undef | ||
check(typeof globalThis == 'object' && globalThis) || check(typeof window == 'object' && window) || check(typeof self == 'object' && self) || check(typeof commonjsGlobal == 'object' && commonjsGlobal) || // eslint-disable-next-line no-new-func | ||
@@ -219,3 +231,3 @@ function () { | ||
// Thank's IE8 for his funny defineProperty | ||
// Detect IE8's incomplete defineProperty implementation | ||
@@ -237,3 +249,3 @@ | ||
}, 1); // `Object.prototype.propertyIsEnumerable` method implementation | ||
// https://tc39.github.io/ecma262/#sec-object.prototype.propertyisenumerable | ||
// https://tc39.es/ecma262/#sec-object.prototype.propertyisenumerable | ||
@@ -275,3 +287,3 @@ var f = NASHORN_BUG ? function propertyIsEnumerable(V) { | ||
// `RequireObjectCoercible` abstract operation | ||
// https://tc39.github.io/ecma262/#sec-requireobjectcoercible | ||
// https://tc39.es/ecma262/#sec-requireobjectcoercible | ||
var requireObjectCoercible = function (it) { | ||
@@ -296,3 +308,3 @@ if (it == undefined) throw TypeError("Can't call method on " + it); | ||
// `ToPrimitive` abstract operation | ||
// https://tc39.github.io/ecma262/#sec-toprimitive | ||
// https://tc39.es/ecma262/#sec-toprimitive | ||
// instead of the ES6 spec version, we didn't implement @@toPrimitive case | ||
@@ -317,3 +329,3 @@ // and the second argument - flag - preferred type is a string | ||
var document = global_1.document; // typeof document.createElement is 'object' in old IE | ||
var document = global$1.document; // typeof document.createElement is 'object' in old IE | ||
@@ -338,3 +350,3 @@ var EXISTS = isObject(document) && isObject(document.createElement); | ||
var nativeGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; // `Object.getOwnPropertyDescriptor` method | ||
// https://tc39.github.io/ecma262/#sec-object.getownpropertydescriptor | ||
// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor | ||
@@ -365,3 +377,3 @@ var f$1 = descriptors ? nativeGetOwnPropertyDescriptor : function getOwnPropertyDescriptor(O, P) { | ||
var nativeDefineProperty = Object.defineProperty; // `Object.defineProperty` method | ||
// https://tc39.github.io/ecma262/#sec-object.defineproperty | ||
// https://tc39.es/ecma262/#sec-object.defineproperty | ||
@@ -395,5 +407,5 @@ var f$2 = descriptors ? nativeDefineProperty : function defineProperty(O, P, Attributes) { | ||
try { | ||
createNonEnumerableProperty(global_1, key, value); | ||
createNonEnumerableProperty(global$1, key, value); | ||
} catch (error) { | ||
global_1[key] = value; | ||
global$1[key] = value; | ||
} | ||
@@ -405,3 +417,3 @@ | ||
var SHARED = '__core-js_shared__'; | ||
var store = global_1[SHARED] || setGlobal(SHARED, {}); | ||
var store = global$1[SHARED] || setGlobal(SHARED, {}); | ||
var sharedStore = store; | ||
@@ -419,3 +431,3 @@ | ||
var WeakMap$1 = global_1.WeakMap; | ||
var WeakMap$1 = global$1.WeakMap; | ||
var nativeWeakMap = typeof WeakMap$1 === 'function' && /native code/.test(inspectSource(WeakMap$1)); | ||
@@ -429,5 +441,5 @@ | ||
})('versions', []).push({ | ||
version: '3.7.0', | ||
version: '3.8.2', | ||
mode: 'global', | ||
copyright: '© 2020 Denis Pushkarev (zloirock.ru)' | ||
copyright: '© 2021 Denis Pushkarev (zloirock.ru)' | ||
}); | ||
@@ -451,3 +463,3 @@ }); | ||
var WeakMap$2 = global_1.WeakMap; | ||
var WeakMap$2 = global$1.WeakMap; | ||
var set, get, has$1; | ||
@@ -539,3 +551,3 @@ | ||
if (O === global_1) { | ||
if (O === global$1) { | ||
if (simple) O[key] = value;else setGlobal(key, value); | ||
@@ -555,3 +567,3 @@ return; | ||
var path = global_1; | ||
var path = global$1; | ||
@@ -563,3 +575,3 @@ var aFunction = function (variable) { | ||
var getBuiltIn = function (namespace, method) { | ||
return arguments.length < 2 ? aFunction(path[namespace]) || aFunction(global_1[namespace]) : path[namespace] && path[namespace][method] || global_1[namespace] && global_1[namespace][method]; | ||
return arguments.length < 2 ? aFunction(path[namespace]) || aFunction(global$1[namespace]) : path[namespace] && path[namespace][method] || global$1[namespace] && global$1[namespace][method]; | ||
}; | ||
@@ -569,3 +581,3 @@ | ||
var floor = Math.floor; // `ToInteger` abstract operation | ||
// https://tc39.github.io/ecma262/#sec-tointeger | ||
// https://tc39.es/ecma262/#sec-tointeger | ||
@@ -577,3 +589,3 @@ var toInteger = function (argument) { | ||
var min = Math.min; // `ToLength` abstract operation | ||
// https://tc39.github.io/ecma262/#sec-tolength | ||
// https://tc39.es/ecma262/#sec-tolength | ||
@@ -618,6 +630,6 @@ var toLength = function (argument) { | ||
// `Array.prototype.includes` method | ||
// https://tc39.github.io/ecma262/#sec-array.prototype.includes | ||
// https://tc39.es/ecma262/#sec-array.prototype.includes | ||
includes: createMethod(true), | ||
// `Array.prototype.indexOf` method | ||
// https://tc39.github.io/ecma262/#sec-array.prototype.indexof | ||
// https://tc39.es/ecma262/#sec-array.prototype.indexof | ||
indexOf: createMethod(false) | ||
@@ -650,3 +662,3 @@ }; | ||
var hiddenKeys$1 = enumBugKeys.concat('length', 'prototype'); // `Object.getOwnPropertyNames` method | ||
// https://tc39.github.io/ecma262/#sec-object.getownpropertynames | ||
// https://tc39.es/ecma262/#sec-object.getownpropertynames | ||
@@ -737,7 +749,7 @@ var f$3 = Object.getOwnPropertyNames || function getOwnPropertyNames(O) { | ||
if (GLOBAL) { | ||
target = global_1; | ||
target = global$1; | ||
} else if (STATIC) { | ||
target = global_1[TARGET] || setGlobal(TARGET, {}); | ||
target = global$1[TARGET] || setGlobal(TARGET, {}); | ||
} else { | ||
target = (global_1[TARGET] || {}).prototype; | ||
target = (global$1[TARGET] || {}).prototype; | ||
} | ||
@@ -823,3 +835,3 @@ | ||
var WellKnownSymbolsStore = shared('wks'); | ||
var Symbol$1 = global_1.Symbol; | ||
var Symbol$1 = global$1.Symbol; | ||
var createWellKnownSymbol = useSymbolAsUid ? Symbol$1 : Symbol$1 && Symbol$1.withoutSetter || uid; | ||
@@ -984,3 +996,3 @@ | ||
// `Promise.allSettled` method | ||
// https://github.com/tc39/proposal-promise-allSettled | ||
// https://tc39.es/ecma262/#sec-promise.allsettled | ||
@@ -987,0 +999,0 @@ |
{ | ||
"name": "@logzio-node-toolbox/consul", | ||
"version": "0.0.10", | ||
"version": "0.0.11", | ||
"description": "Consul easy use for json configs and service discovery", | ||
@@ -5,0 +5,0 @@ "main": "dist/index.cjs", |
106
README.md
@@ -13,31 +13,91 @@ <p align="center"> | ||
import { Consul } from '@logzio-node-toolbox/consul'; | ||
/* params | ||
port: number | -must- | ||
host: string | localhost | ||
connectMaxRetries: number | 5 | ||
connectTimeout: number | 5000 | ||
connectRetryBackoffFactor: number | 2 | ||
failOnFailedConnection: boolean | true | ||
watchBackoffFactor: number | 100, | ||
watchBackoffMax: number | 30000, | ||
watchMaxAttempts: number, | ||
baseUrl: string, | ||
logger: logger instance, | ||
*/ | ||
const consul = new Consul({ port: 18500 }); | ||
const consul = new Consul({ port: 18500, host: '127.0.0.1', baseUrl = 'some_base_url' }); | ||
``` | ||
initialized params: | ||
1. port - consul port to connect default 8500 (default 8500) | ||
2. host - consul host to connect default 8500 (default localhost) | ||
3. baseUrl - some default path to load configs from, will prefix the path to each get request (default '') | ||
4. validateOptions - object with defaults { fail: true, timeout: 5000, retries: 6, factor: 2, onRetry: null } | ||
can override each one of the defaults. | ||
5. defaultWatchOptions - object with defaults { backoffFactor: 100, backoffMax: 30000, maxAttempts: 10000 } | ||
can override each one of the defaults. | ||
6. defaultRegisterRetryOptions - object with defaults { factor: 2, retries: 6, onRetry: null } | ||
can override each one of the defaults. | ||
## methods | ||
validateConnected - make use connected to consul service (will retry (connectMaxRetries) of times); | ||
get(key) - will get a key from consul service | ||
set(key, value) - will set value | ||
keys(path) - list of keys in path | ||
merge(key, values) - deepmerge values with key | ||
watch(fn => ({key, onChange})) - will listen when key changed and invoke onChange | ||
onChange will received the new ({key ,vale}) | ||
### validateConnected - make use connected to consul service (will retry (connectMaxRetries) of times); | ||
receive same params as validateOptions and will merge with th one passed to the initializer | ||
``javascript | ||
await consul.validateConnected(validateOptions) | ||
``` | ||
register({ meta, checks, address, hostname, serviceName, port, registerInterval }) - will register to service discovery and with given params will interval to make sure service is still registered | ||
close() - deregister and close all watchers | ||
### get - will get a key from consul service, (if initlized with base path it will prefix it) | ||
```javascript | ||
const { key, value } = await consul.get('somepath/config.json') | ||
// if have base path will fetch 'some_base_url/somepath/config.json' | ||
``` | ||
### set - will set a value to consul, (if initlized with basebath it will prefix it) | ||
```javascript | ||
await consul.set('somepath/config.json', {key: "value"}) | ||
// if have base path will set to 'some_base_url/somepath/config.json' | ||
``` | ||
### keys - list of keys in path | ||
```javascript | ||
await consul.keys('somepath/config.json') | ||
``` | ||
### merge - deepmerge current values with new values | ||
it will fetch current values will deep merge all keys and set it | ||
```javascript | ||
await consul.merge('somepath/config.json', {newKey: "newValue" }) | ||
``` | ||
### watch - listen to key change and invoke handler | ||
receive same watchOptions object as the initializer ( will merge them together) | ||
```javascript | ||
await consul.watch({ | ||
key: 'somepath/config.json', | ||
onChange: ({key, value}) => { | ||
console.log(key) | ||
console.log(value) // new values | ||
}, | ||
onError:(err) => { | ||
console.log(err) | ||
}, | ||
watchOptions | ||
}) | ||
``` | ||
### register - will register to service discovery and with given params will interval to make sure service is still registered | ||
receive same registerRetryOptions object as the initializer ( will merge them together) | ||
```javascript | ||
interface RegisterData { | ||
meta?: AnyObject; | ||
checks?: AnyObject; | ||
address?: string; | ||
id?: string; | ||
name?: string; | ||
port?: number; | ||
} | ||
await consul.register({ | ||
data, | ||
validateRegisteredInterval: 3000, | ||
onError:(err) => { | ||
console.log(err) | ||
}, | ||
registerRetryOptions | ||
}) | ||
``` | ||
#### close - deregister and close all watchers | ||
receive same registerRetryOptions object as the initializer ( will merge them together) | ||
```javascript | ||
await consul.close(registerRetryOptions) | ||
``` | ||
# multiConsul | ||
@@ -44,0 +104,0 @@ extend consul to work on multiple keys and merged config |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
71632
1952
136
2