@mutable/meta
Advanced tools
+37
-19
| 'use strict' | ||
| let http = require('http') | ||
| let Promise = require('promise') | ||
| let { EventEmitter } = require('events') | ||
| const http = require('http') | ||
| const Promise = require('promise') | ||
| const { EventEmitter } = require('events') | ||
| class Meta extends EventEmitter { | ||
@@ -9,5 +9,5 @@ constructor(){ | ||
| this._service = new Map() | ||
| this._config | ||
| this._config | ||
| this._configIndex = 0 | ||
| this._services | ||
| this._services | ||
| this._servicesIndex = 0 | ||
@@ -21,2 +21,19 @@ } | ||
| config () { | ||
| if (process.env.USE_SECRETS) { | ||
| this._config = {} | ||
| try { | ||
| if (process.env.CONFIG) this._config = JSON.parse(process.env.CONFIG) | ||
| } catch {} | ||
| Object.keys(process.env).forEach(key => { | ||
| if (key.includes("SECRET_")) { | ||
| try { | ||
| this._config[key.replace("SECRET_", "").toLowerCase()] = JSON.parse(process.env[key]) | ||
| } catch { | ||
| this._config[key.replace("SECRET_", "").toLowerCase()] = process.env[key] | ||
| } | ||
| } | ||
| }) | ||
| return Promise.resolve(this._config) | ||
| } | ||
| return this._config ? Promise.resolve(this._config) : this._watchConfig() | ||
@@ -30,2 +47,3 @@ } | ||
| service (name) { | ||
| if (process.env.DNS) return Promise.resolve([name + (process.env.DNS_POSTFIX ? process.env.DNS_POSTFIX : "")]) | ||
| if (this._service.has(name) && this._service.get(name).nodes && this._service.get(name).nodes.length > 0) | ||
@@ -36,3 +54,3 @@ return Promise.resolve(this._service.get(name).nodes) | ||
| return Promise.reject(new Error("Service " + name + " has no healthy instances")) | ||
| return this._watchService(name) | ||
@@ -45,3 +63,3 @@ } | ||
| } | ||
| _watchConfig() { | ||
@@ -57,3 +75,3 @@ return this._call(`/v1/config?index=${this._configIndex}`,null,true) | ||
| if(index < this._configIndex && JSON.stringify(config) != JSON.stringify(this._config) ) | ||
| this.emit('configChange',this._config) | ||
| this.emit('configChange',this._config) | ||
@@ -77,3 +95,3 @@ return this._config | ||
| if(index < this._servicesIndex && JSON.stringify(services) != JSON.stringify(this._services)) | ||
| this.emit('servicesChange',this._services) | ||
| this.emit('servicesChange',this._services) | ||
@@ -99,3 +117,3 @@ return this._services | ||
| this.emit('serviceChange',name) | ||
| if (Array.isArray(res.body) && res.body.length == 0) | ||
@@ -114,3 +132,3 @@ throw new Error("Service " + name + " has no health instances") | ||
| let _options = { | ||
| path, | ||
| path, | ||
| socketPath : process.env.META_SOCKET, | ||
@@ -122,3 +140,3 @@ method:'GET' | ||
| opts.data = JSON.stringify(data) | ||
| } | ||
| } | ||
@@ -132,12 +150,12 @@ | ||
| _options.headers = _options.headers ? _options.headers : {} | ||
| if (options.json) _options.headers['Content-Type'] = 'application/json' | ||
| let req = http.request(_options, onRes) | ||
| req.on('error', reject) | ||
| if (options.data) req.write(options.data) | ||
| req.end() | ||
| function onRes(_res) { | ||
@@ -158,3 +176,3 @@ if (options.encoding) | ||
| .on('data', data => res.body += data) | ||
| .on('end', ()=> { | ||
| .on('end', ()=> { | ||
| if(options.json) | ||
@@ -165,3 +183,3 @@ try{ | ||
| cb(options.full ? res : res.body) | ||
| cb(options.full ? res : res.body) | ||
| }) | ||
@@ -168,0 +186,0 @@ .resume() |
+2
-2
| { | ||
| "name": "@mutable/meta", | ||
| "version": "1.3.0", | ||
| "version": "1.5.0", | ||
| "description": "Meta client for node", | ||
@@ -10,3 +10,3 @@ "main": "index.js", | ||
| "keywords": [ | ||
| "lsq", | ||
| "mutable", | ||
| "meta" | ||
@@ -13,0 +13,0 @@ ], |
+141
-1
@@ -1,1 +0,141 @@ | ||
| # meta-node | ||
| Mutable Meta client for node | ||
| === | ||
| Service Discovery and Config manager | ||
| === | ||
| This package is a wrapper to the background service `Mutable Meta`. Mutable Meta is responsible for service discovery and service configuration. | ||
| ## API | ||
| ```js | ||
| const Meta = require('@mutable/meta') | ||
| ``` | ||
| All methods are asynchronous, and take a node-style error-first callback as last argument. | ||
| If no callback is supplied, a promise is returned instead. | ||
| Service Discovery | ||
| --- | ||
| ### Meta.services() -> Array<String> | ||
| Returns all the currently known service names. | ||
| Example: | ||
| ```js | ||
| Meta.services() | ||
| .then((_services) => { | ||
| // returns an object {} | ||
| }) | ||
| ``` | ||
| ### Meta.service(service: String) -> Service | ||
| Returns a particular service. | ||
| Example: | ||
| ```js | ||
| Meta.service("email") | ||
| .then((service) => { | ||
| request.post(`http://${service}/api/v1/demo/email`, | ||
| {json:req.body}, | ||
| (error, response, body) => { | ||
| if(error){ | ||
| console.error('can not reach email service') | ||
| return res.send(500,{error:error,result:'can not reach email service'}) | ||
| } | ||
| res.send({result:"email sent"}) | ||
| }) | ||
| }) | ||
| ``` | ||
| or | ||
| ```js | ||
| Meta.service("email", (config) => { | ||
| // returns a object | ||
| // {"hostname":"127.0.0.1", "port":3001, toString(): "127.0.0.1:3001" } | ||
| // in a string it prints concat host and port | ||
| request.post(`http://${service}/api/v1/demo/email`, | ||
| {json:req.body}, | ||
| (error, response, body) => { | ||
| if(error){ | ||
| console.error('can not reach email service') | ||
| return res.send(500,{error:error,result:'can not reach email service'}) | ||
| } | ||
| res.send({result:"email sent"}) | ||
| }) | ||
| }) | ||
| ``` | ||
| Config | ||
| --- | ||
| ### Meta.config() -> JSON | ||
| Fetches the JSON configuration for the current service. | ||
| Example: | ||
| ```js | ||
| Meta.config() | ||
| .then((_config) => { | ||
| // returns an object {} | ||
| }) | ||
| ``` | ||
| For non-mutable deployments set `USE_SECRETS=true` environment variable to set secrets in the config. | ||
| Use `CONFIG` environment variable to store configs when using secrets. | ||
| Use `SECRET_` prefix to set secrets as object in the config. | ||
| Example: | ||
| ``` | ||
| USE_SECRETS=true CONFIG={"key":"value"} SECRET_SENDGRID_KEY='your_key' SECRET_REDIS='{"db":00}' node app.js | ||
| ``` | ||
| Resulting in this config object: | ||
| ``` | ||
| { | ||
| "key": "value", | ||
| sendgrid_key: "your_key", | ||
| redis: { | ||
| "db": 00 | ||
| } | ||
| } | ||
| ``` | ||
| `SECRET_` prefix gets removed when setting the key in the config object. | ||
| ### DNS | ||
| For non-mutable deployments set `DNS` environment variable to true and use `DNS_POSTFIX` variable to modify the service url | ||
| Example: | ||
| ``` | ||
| DNS=true DNS_POSTFIX='.default.csv.cluster.local' node app.js | ||
| ``` | ||
| Result target: `http://your-web-service.default.scv.cluster.local/` | ||
| Resources | ||
| --- | ||
| - [Service Discovery and Config](https://github.com/mutable) | ||
| - [Mutable.io Docs](https://github.com/mutable/docs) | ||
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 6 instances in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
8629
67.07%149
12.88%142
7000%10
900%2
100%