From d18cf16f5b0f5c47b8fdf39bbe8078eb69081ee9 Mon Sep 17 00:00:00 2001 From: Peter Elger Date: Fri, 10 Oct 2014 15:57:08 +0100 Subject: [PATCH 001/117] added dockerfile --- Dockerfile | 10 ++++++++++ build.sh | 3 +++ 2 files changed, 13 insertions(+) create mode 100644 Dockerfile create mode 100644 build.sh diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..52efb86 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,10 @@ +FROM ubuntu +RUN echo "deb http://archive.ubuntu.com/ubuntu precise universe" >> /etc/apt/sources.list +RUN apt-get update +RUN apt-get install -y software-properties-common +RUN apt-get install -y python-software-properties python g++ make +RUN add-apt-repository -y ppa:chris-lea/node.js +RUN apt-get update +RUN apt-get install -y nodejs +ADD . / + diff --git a/build.sh b/build.sh new file mode 100644 index 0000000..1ccc34d --- /dev/null +++ b/build.sh @@ -0,0 +1,3 @@ +#!/bin/sh +npm install +echo TARGET:. From 22042161965fe8cb010c61736f354f0cdbd32471 Mon Sep 17 00:00:00 2001 From: Peter Elger Date: Sun, 9 Nov 2014 23:43:57 +0000 Subject: [PATCH 002/117] added prod --- srvs/github-prod.js | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/srvs/github-prod.js b/srvs/github-prod.js index 316807c..d2be9be 100644 --- a/srvs/github-prod.js +++ b/srvs/github-prod.js @@ -1,3 +1,4 @@ +'use strict'; var seneca = require('seneca')() @@ -6,18 +7,17 @@ var seneca = require('seneca')() .use('../github.js') .add('role:info,req:part',function(args,done){ - done() + done(); this.act( 'role:github,cmd:get', {name:args.name}, function(err,mod){ - if( err ) return; + if (err) return; - if( mod ) { - this.act('role:info,res:part,part:github', - {name:args.name,data:mod.data$()}) + if (mod) { + this.act('role:info,res:part,part:github', {name:args.name,data:mod.data$()}); } else { this.act( @@ -45,10 +45,8 @@ var seneca = require('seneca')() } }) }) + .listen({host: '192.168.59.103', type:'redis',pin:'role:info,req:part'}) + .client({host: '192.168.59.103', type:'redis',pin:'role:info,res:part'}) + .client({host: '192.168.59.103', port:9001,pin:'role:npm'}) + .listen(); - .listen({type:'redis',pin:'role:info,req:part'}) - .client({type:'redis',pin:'role:info,res:part'}) - - .client({port:9001,pin:'role:npm'}) - - .listen() From a0923f8505d8eb1e86d5987d51a0c9dc6528a2ac Mon Sep 17 00:00:00 2001 From: Peter Elger Date: Tue, 13 Jan 2015 10:31:01 +0000 Subject: [PATCH 003/117] moved production to beanstalk --- package.json | 1 + srvs/github-prod.js | 82 ++++++++++++++++++--------------------------- 2 files changed, 34 insertions(+), 49 deletions(-) diff --git a/package.json b/package.json index 13cdaad..2a79aed 100644 --- a/package.json +++ b/package.json @@ -17,6 +17,7 @@ "dependencies": { "github": "^0.2.2", "mocha": "^1.21.4", + "seneca-beanstalk-transport": "^0.1.1", "seneca-redis-transport": "^0.1.1" }, "devDependencies": { diff --git a/srvs/github-prod.js b/srvs/github-prod.js index d2be9be..741a136 100644 --- a/srvs/github-prod.js +++ b/srvs/github-prod.js @@ -1,52 +1,36 @@ 'use strict'; -var seneca = require('seneca')() - - .use('redis-transport') - .use('jsonfile-store',{folder:__dirname+'/../data'}) - .use('../github.js') - - .add('role:info,req:part',function(args,done){ - done(); - - this.act( - 'role:github,cmd:get', - {name:args.name}, - - function(err,mod){ - if (err) return; - - if (mod) { - this.act('role:info,res:part,part:github', {name:args.name,data:mod.data$()}); - } - else { - this.act( - 'role:npm,cmd:get', - {name:args.name}, - - function(err,mod){ - if( err ) return; - - if( mod ) { - this.act( - 'role:github,cmd:get', - {name:args.name,giturl:mod.giturl}, - - function( err, mod ){ - if( err ) return; - - if( mod ) { - this.act('role:info,res:part,part:github', - {name:args.name,data:mod.data$()}) - } - }) - } - }) - } - }) - }) - .listen({host: '192.168.59.103', type:'redis',pin:'role:info,req:part'}) - .client({host: '192.168.59.103', type:'redis',pin:'role:info,res:part'}) - .client({host: '192.168.59.103', port:9001,pin:'role:npm'}) - .listen(); +require('seneca')() + .use('redis-transport') + .use('jsonfile-store',{folder:__dirname+'/../data'}) + .use('beanstalk-transport') + .use('../github.js') + .add('role:info,req:part',function(args,done){ + done(); + this.act('role:github,cmd:get', {name:args.name}, function(err,mod){ + if (err) { return; } + + if (mod) { + this.act('role:info,res:part,part:github', {name:args.name,data:mod.data$()}); + } + else { + this.act('role:npm,cmd:get', {name:args.name}, function(err,mod){ + if( err ) { return; } + + if( mod ) { + this.act('role:github,cmd:get', {name:args.name,giturl:mod.giturl}, function( err, mod ){ + if (err) { return; } + if (mod) { + this.act('role:info,res:part,part:github', {name:args.name,data:mod.data$()}); + } + }); + } + }); + } + }); + }) + .listen({host: process.env.REDIS_IP, type:'redis',pin:'role:info,req:part'}) + .client({host: process.env.REDIS_IP, type:'redis',pin:'role:info,res:part'}) + .client({host: process.env.BEANSTALK_IP, port: 1130, type: 'beanstalk', pin: 'role:npm,cmd:*'}) + .listen({host: process.env.BEANSTALK_IP, port: 1130, type: 'beanstalk', pin: 'role:github,cmd:*'}); From 0f429710c010133dd490d5d225138cd6b452ba00 Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Wed, 9 Dec 2015 21:04:19 +0000 Subject: [PATCH 004/117] mesh --- package.json | 2 +- srv/github-dev.js | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 77067be..52c7ec9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nodezoo-github", - "version": "4.0.0", + "version": "5.0.0", "description": "nodezoo.com micro-service handling github meta data", "main": "github.js", "keywords": [ diff --git a/srv/github-dev.js b/srv/github-dev.js index 1a2629d..b3abce1 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -1,6 +1,5 @@ var HOST = process.env.HOST || 'localhost' -var REDIS = process.env.REDIS || 'localhost' var TOKEN = process.env.TOKEN || 'NO_TOKEN' require('seneca')() @@ -48,11 +47,6 @@ require('seneca')() }) }) + .use( 'mesh', {auto:true, pins:['role:info,req:part','role:github']} ) - .listen({ host:REDIS, type:'redis', pin:'role:info,req:part' }) - .client({ host:REDIS, type:'redis', pin:'role:info,res:part' }) - - .client({ host:HOST, port:44003, pin:'role:npm' }) - - .listen(44004) - .repl(43004) + .repl(33004) From 704c1c769f3dd8ccd6c68958542da38729987ae0 Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Wed, 16 Dec 2015 12:02:52 +0000 Subject: [PATCH 005/117] package.json --- package.json | 7 +++++-- srv/github-dev.js | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 52c7ec9..fc5324b 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,11 @@ "license": "MIT", "dependencies": { "github": "^0.2.2", - "seneca": "^0.7.1", "seneca-redis-transport": "^0.3.0", - "seneca-level-store": "^0.2.3" + "seneca-level-store": "^0.2.3", + "seneca": "https://github.com/senecajs/seneca", + "seneca-msgstats": "https://github.com/rjrodger/seneca-msgstats", + "seneca-mesh": "https://github.com/rjrodger/seneca-mesh", + "seneca-balance-client": "https://github.com/rjrodger/seneca-balance-client" } } diff --git a/srv/github-dev.js b/srv/github-dev.js index b3abce1..fe02102 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -47,6 +47,7 @@ require('seneca')() }) }) - .use( 'mesh', {auto:true, pins:['role:info,req:part','role:github']} ) + .use( 'mesh', + {auto:true, pins:['role:github','role:info,req:part'], model:'publish'} ) .repl(33004) From 6978d9450234c788c4f8ff6a34db3acfaaa73b9a Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Tue, 19 Jan 2016 16:01:02 +0000 Subject: [PATCH 006/117] Making live branch --- github.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github.js b/github.js index c61103d..94e8826 100644 --- a/github.js +++ b/github.js @@ -15,7 +15,7 @@ module.exports = function github( options ){ var seneca = this options = seneca.util.deepextend({ - token: 'GITHUB_TOKEN' + token: 'YOUR_TOKEN_HERE' },options) From ef963da6121406bc25762c121c37459438eb3908 Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 1 Feb 2016 10:42:54 +0000 Subject: [PATCH 007/117] edited readme --- README.md | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ee53da3..70a8805 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,12 @@ -nodezoo-github -============== +![Nodezoo](https://raw.githubusercontent.com/rjrodger/nodezoo-web/to-redux/client/assets/img/logo-nodezoo.png) + +# nodezoo-github +Nodezoo.com micro-service handling github meta data. Please see the [main repo]() for more details + +- __Sponsor:__ [nearForm][] + + -nodezoo.com micro-service handling github meta data. # Running @@ -10,3 +15,15 @@ nodezoo.com micro-service handling github meta data. $ node srvs/github-dev.js --seneca.options.github.token=GITHUB-PERSONAL-ACCESS-TOKEN --seneca.log.all ``` +## Contributing +The [NodeZoo][] org encourages open participation. If you feel you can help in any way, be it with documentation, examples, extra testing, or new features please get in touch. + +## License +Copyright (c) 2015, Richard Rodgers and other contributors. +Licensed under [MIT][]. + + +[MIT]: ./LICENSE +[Code of Conduct]: https://github.com/nearform/vidi-contrib/docs/code_of_conduct.md +[nearForm]: http://www.nearform.com/ +[NodeZoo]: http://www.nodezoo.com/ From fb5aa60856f8856b8e43c8574ddca64246ad0e64 Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 1 Feb 2016 11:06:56 +0000 Subject: [PATCH 008/117] fixed hyperlink --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 70a8805..7126392 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ ![Nodezoo](https://raw.githubusercontent.com/rjrodger/nodezoo-web/to-redux/client/assets/img/logo-nodezoo.png) # nodezoo-github -Nodezoo.com micro-service handling github meta data. Please see the [main repo]() for more details +Nodezoo.com micro-service handling github meta data. Please see the [main repo][] for more details - __Sponsor:__ [nearForm][] @@ -22,7 +22,7 @@ The [NodeZoo][] org encourages open participation. If you feel you can help in a Copyright (c) 2015, Richard Rodgers and other contributors. Licensed under [MIT][]. - +[main repo]: https://github.com/rjrodger/nodezoo [MIT]: ./LICENSE [Code of Conduct]: https://github.com/nearform/vidi-contrib/docs/code_of_conduct.md [nearForm]: http://www.nearform.com/ From c156ab98e3ad3d36fbefcd6510f6da4263736b54 Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 1 Feb 2016 11:22:44 +0000 Subject: [PATCH 009/117] added travis file --- .travis.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..b47846b --- /dev/null +++ b/.travis.yml @@ -0,0 +1,10 @@ +language: node_js +sudo: false + +node_js: + - "5" + - "4" + +cache: + directories: + - node_modules From 369b8da5e821adc6b071269644b2fb3f708a47e5 Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 1 Feb 2016 12:02:11 +0000 Subject: [PATCH 010/117] added messages list --- README.md | 10 ++++++++++ package.json | 3 +++ 2 files changed, 13 insertions(+) diff --git a/README.md b/README.md index 7126392..6385367 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,16 @@ Nodezoo.com micro-service handling github meta data. Please see the [main repo][ $ node srvs/github-dev.js --seneca.options.github.token=GITHUB-PERSONAL-ACCESS-TOKEN --seneca.log.all ``` +## Messages + +This micro-service recognizes the following messages: + + * _role:github,cmd:get_ + * _role:github,cmd:query_ + * _role:github,cmd:parse_ + + + ## Contributing The [NodeZoo][] org encourages open participation. If you feel you can help in any way, be it with documentation, examples, extra testing, or new features please get in touch. diff --git a/package.json b/package.json index fc5324b..26f76e1 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,9 @@ "microservice" ], "author": "Richard Rodger (richard.rodger@nearform.com)", + "contributors": [ + "Isaac Mahon (github.com/CodeWriterWriter)" + ], "license": "MIT", "dependencies": { "github": "^0.2.2", From 64980efe7032aff497afe50eabdce8c91fa747cd Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 1 Feb 2016 12:17:50 +0000 Subject: [PATCH 011/117] Added instructions on how to obtain personal access token --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6385367..59e52d1 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,15 @@ Nodezoo.com micro-service handling github meta data. Please see the [main repo][ ```sh $ node srvs/github-dev.js --seneca.options.github.token=GITHUB-PERSONAL-ACCESS-TOKEN --seneca.log.all ``` +## Creating a GitHub Personal Access Token + + - In the top right corner of any page, click your profile photo, then click Settings. + - In the user settings sidebar, click Personal access tokens. + - Click Generate new token + - Give your token a descriptive name. + - Select the scopes you wish to grant to this token. The default scopes allow you to interact with public and private repositories, user data, and gists + - Click Generate token. + - Copy the token to your clipboard. For security reasons, after you navigate off this page, no one will be able to see the token again. ## Messages @@ -21,7 +30,7 @@ This micro-service recognizes the following messages: * _role:github,cmd:get_ * _role:github,cmd:query_ - * _role:github,cmd:parse_ + * _role:github,cmd:parse_ From 20203d9df3e2ee34304c23f6643f022bf633df97 Mon Sep 17 00:00:00 2001 From: Glen Keane Date: Mon, 1 Feb 2016 12:40:22 +0000 Subject: [PATCH 012/117] add linting, tests, coverage and pre-commit hooks --- github.js | 105 +++++++++++++++++++++------------------------- package.json | 25 ++++++++--- srv/github-dev.js | 47 +++++++++++---------- 3 files changed, 93 insertions(+), 84 deletions(-) diff --git a/github.js b/github.js index 94e8826..d407fa8 100644 --- a/github.js +++ b/github.js @@ -1,72 +1,63 @@ /* Copyright (c) 2014-2015 Richard Rodger, MIT License */ -/* jshint node:true, asi:true, eqnull:true */ -"use strict"; +'use strict' +const GitHubAPI = require('github') -var GitHubAPI = require('github') - -var gitapi = new GitHubAPI({ - version: "3.0.0" +var gitapi = new GitHubAPI({ + version: '3.0.0' }) - - -module.exports = function github( options ){ +module.exports = function github (options) { var seneca = this options = seneca.util.deepextend({ token: 'YOUR_TOKEN_HERE' - },options) - - - - seneca.add( 'role:github,cmd:get', cmd_get ) - seneca.add( 'role:github,cmd:query', cmd_query ) - seneca.add( 'role:github,cmd:parse', cmd_parse ) + }, options) + seneca.add('role:github,cmd:get', cmd_get) + seneca.add('role:github,cmd:query', cmd_query) + seneca.add('role:github,cmd:parse', cmd_parse) - - function cmd_get( args, done ) { - var seneca = this - var github_ent = seneca.make$('github') + function cmd_get (args, done) { + var seneca = this + var github_ent = seneca.make$('github') var github_name = args.name - github_ent.load$( github_name, function(err,github_mod){ - if( err ) return done(err); + github_ent.load$(github_name, function (err, github_mod) { + if (err) return done(err) - if( github_mod ) { - return done(null,github_mod); + if (github_mod) { + return done(null, github_mod) } - else if( args.giturl ) { + else if (args.giturl) { seneca.act( 'role:github,cmd:parse', - {name:github_name,giturl:args.giturl}, - - function(err,out){ - if( err ) return done(err); + { name: github_name, giturl: args.giturl }, + function (err, out) { + if (err) return done(err) seneca.act( 'role:github,cmd:query', - {name:github_name,user:out.user,repo:out.repo}, + { name: github_name, user: out.user, repo: out.repo }, done) }) } - else return done(); + else return done() }) } - function cmd_query( args, done ) { - var seneca = this - var github_ent = seneca.make$('github') + function cmd_query (args, done) { + var seneca = this + var github_ent = seneca.make$('github') var github_name = args.name - var user = args.user - var repo = args.repo + var user = args.user + var repo = args.repo gitapi.authenticate({ - type: "basic", + type: 'basic', username: options.token, password: 'x-oauth-basic' }) @@ -76,48 +67,46 @@ module.exports = function github( options ){ user: user, repo: repo }, - function(err,repo){ - if( err ) return done(err); + function (err, repo) { + if (err) return done(err) var data - if( repo ) { + if (repo) { data = { - user: args.user, - repo: args.repo, - stars: repo.stargazers_count, + user: args.user, + repo: args.repo, + stars: repo.stargazers_count, watches: repo.subscribers_count, - forks: repo.forks_count, - last: repo.pushed_at + forks: repo.forks_count, + last: repo.pushed_at } - github_ent.load$(github_name, function(err,github_mod){ - if( err ) return done(err); + github_ent.load$(github_name, function (err, github_mod) { + if (err) return done(err) - if( github_mod ) { - return github_mod.data$(data).save$(done); + if (github_mod) { + return github_mod.data$(data).save$(done) } else { data.id$ = github_name - github_ent.make$(data).save$(done); + github_ent.make$(data).save$(done) } }) } else return done() - } ) } - function cmd_parse( args, done ) { - var seneca = this + function cmd_parse (args, done) { + // commented out unused var... + // var seneca = this var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) - if( m ) { - return done( null, { user:m[1], repo:m[2] }) + if (m) { + return done(null, { user: m[1], repo: m[2] }) } - else return done(); + else return done() } - - } diff --git a/package.json b/package.json index 26f76e1..b358ea2 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,12 @@ "name": "nodezoo-github", "version": "5.0.0", "description": "nodezoo.com micro-service handling github meta data", + "scripts": { + "test": "lab -v ./test/*.test.js -m 4000", + "coverage": "lab ./test/*test.js -r lcov -o coverage/lcov.info -r html -o coverage/index.html", + "publish-coverage": "coveralls < coverage/lcov.info", + "lint": "lab -dL" + }, "main": "github.js", "keywords": [ "nodezoo", @@ -15,12 +21,21 @@ ], "license": "MIT", "dependencies": { + "eslint-config-seneca": "^1.1.2", + "eslint-plugin-hapi": "^4.0.0", + "eslint-plugin-standard": "^1.3.1", "github": "^0.2.2", - "seneca-redis-transport": "^0.3.0", - "seneca-level-store": "^0.2.3", + "lab": "^8.2.0", + "pre-commit": "^1.1.2", "seneca": "https://github.com/senecajs/seneca", - "seneca-msgstats": "https://github.com/rjrodger/seneca-msgstats", + "seneca-balance-client": "https://github.com/rjrodger/seneca-balance-client", + "seneca-level-store": "^0.2.3", "seneca-mesh": "https://github.com/rjrodger/seneca-mesh", - "seneca-balance-client": "https://github.com/rjrodger/seneca-balance-client" - } + "seneca-msgstats": "https://github.com/rjrodger/seneca-msgstats", + "seneca-redis-transport": "^0.3.0" + }, + "pre-commit": [ + "test", + "lint" + ] } diff --git a/srv/github-dev.js b/srv/github-dev.js index fe02102..d2801bb 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -1,45 +1,47 @@ +'use strict' -var HOST = process.env.HOST || 'localhost' -var TOKEN = process.env.TOKEN || 'NO_TOKEN' +// HOST is commented out because it is unusued +// const HOST = process.env.HOST || 'localhost' +const TOKEN = process.env.TOKEN || 'NO_TOKEN' require('seneca')() .use('redis-transport') .use('level-store') - .use('../github.js',{token:TOKEN}) + .use('../github.js', { token: TOKEN }) - .add('role:info,req:part',function(args,done){ + .add('role:info,req:part', function (args, done) { done() this.act( 'role:github,cmd:get', - {name:args.name}, + { name: args.name }, - function(err,mod){ - if( err ) return; + function (err, mod) { + if (err) return - if( mod ) { + if (mod) { return this.act( 'role:info,res:part,part:github', - {name:args.name,data:mod.data$()}) + { name: args.name, data: mod.data$() }) } - this.act( - 'role:npm,cmd:get', {name:args.name}, - function(err,mod){ - if( err ) return; + this.act( + 'role:npm,cmd:get', { name: args.name }, + function (err, mod) { + if (err) return - if( mod ) { + if (mod) { this.act( 'role:github,cmd:get', - {name:args.name,giturl:mod.giturl}, - function( err, mod ){ - if( err ) return; + { name: args.name, giturl: mod.giturl }, + function (err, mod) { + if (err) return - if( mod ) { + if (mod) { this.act('role:info,res:part,part:github', - {name:args.name,data:mod.data$()}) + { name: args.name, data: mod.data$() }) } }) } @@ -47,7 +49,10 @@ require('seneca')() }) }) - .use( 'mesh', - {auto:true, pins:['role:github','role:info,req:part'], model:'publish'} ) + .use('mesh', { + auto: true, + pins: ['role:github', 'role:info,req:part'], + model: 'publish' + }) .repl(33004) From 153802d2138c884454539e2105fa4e5a4ad34a40 Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 1 Feb 2016 12:44:49 +0000 Subject: [PATCH 013/117] added npm run start script field --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index 26f76e1..9c44b45 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,9 @@ "contributors": [ "Isaac Mahon (github.com/CodeWriterWriter)" ], + "scripts":{ + "start": "node ./github.js" + }, "license": "MIT", "dependencies": { "github": "^0.2.2", From 58cbfa163f3038e9cdbbba967df186c76081457a Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 1 Feb 2016 13:45:58 +0000 Subject: [PATCH 014/117] added start script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 9c44b45..069bfd8 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,8 @@ "Isaac Mahon (github.com/CodeWriterWriter)" ], "scripts":{ - "start": "node ./github.js" + "start": "node srv/github-dev.js", + "start-dev": "node srv/github-dev.js" }, "license": "MIT", "dependencies": { From e1090f24afb209b0092c1c01e638f60bc80fa2c3 Mon Sep 17 00:00:00 2001 From: Glen Keane Date: Mon, 1 Feb 2016 14:21:19 +0000 Subject: [PATCH 015/117] added tests --- .travis.yml | 5 +++++ github.js | 3 ++- package.json | 4 +++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b47846b..0414ee6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,3 +8,8 @@ node_js: cache: directories: - node_modules + +after_script: + - npm run lint + - npm run coverage + - npm run publish-coverage diff --git a/github.js b/github.js index d407fa8..fc0dcac 100644 --- a/github.js +++ b/github.js @@ -2,6 +2,7 @@ 'use strict' const GitHubAPI = require('github') +const Err = require('eraro')({ package: 'nodezoo-github' }) var gitapi = new GitHubAPI({ version: '3.0.0' @@ -107,6 +108,6 @@ module.exports = function github (options) { if (m) { return done(null, { user: m[1], repo: m[2] }) } - else return done() + else return done(null, { ok: false, err: Err('parsing input failed') }) } } diff --git a/package.json b/package.json index b358ea2..d1ea2b2 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "test": "lab -v ./test/*.test.js -m 4000", "coverage": "lab ./test/*test.js -r lcov -o coverage/lcov.info -r html -o coverage/index.html", - "publish-coverage": "coveralls < coverage/lcov.info", + "publish-coverage": "coveralls < coverage/lcov.info", "lint": "lab -dL" }, "main": "github.js", @@ -21,6 +21,8 @@ ], "license": "MIT", "dependencies": { + "code": "^2.1.0", + "eraro": "^0.4.1", "eslint-config-seneca": "^1.1.2", "eslint-plugin-hapi": "^4.0.0", "eslint-plugin-standard": "^1.3.1", From 0994ded787426cbb9d82aff7d0f087352b92f621 Mon Sep 17 00:00:00 2001 From: Glen Keane Date: Mon, 1 Feb 2016 14:31:40 +0000 Subject: [PATCH 016/117] change sudo:false to true in travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0414ee6..79346a8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ language: node_js -sudo: false +sudo: true node_js: - "5" From 743798f6ba89ba4bc6cbc0f6233094ac2aa0d895 Mon Sep 17 00:00:00 2001 From: Glen Keane Date: Mon, 1 Feb 2016 14:38:58 +0000 Subject: [PATCH 017/117] update gcc version in travis for native modules --- .travis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.travis.yml b/.travis.yml index 79346a8..acb6bb9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,6 +5,15 @@ node_js: - "5" - "4" +env: + - CXX=g++-4.8 +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.8 + cache: directories: - node_modules From 746d0be8e064352c3848a324661a243e86a5f725 Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 1 Feb 2016 14:54:54 +0000 Subject: [PATCH 018/117] added info on using curl --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 59e52d1..d750602 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,12 @@ This micro-service recognizes the following messages: * _role:github,cmd:query_ * _role:github,cmd:parse_ +## Running with Curl +Any of the messages above can be run using curl in the following format +``` +curl -d '{"role":"github","cmd":"get"}' http://localhost:52472/act +``` ## Contributing The [NodeZoo][] org encourages open participation. If you feel you can help in any way, be it with documentation, examples, extra testing, or new features please get in touch. From 69609598862e769e29e1472a2c90f89466b6bef0 Mon Sep 17 00:00:00 2001 From: Glen Keane Date: Mon, 1 Feb 2016 15:27:35 +0000 Subject: [PATCH 019/117] fix nits, add some general comments --- github.js | 59 +++++++++++++++++++++++++++++++++++++++-------- package.json | 3 ++- srv/github-dev.js | 2 -- 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/github.js b/github.js index fc0dcac..355cb68 100644 --- a/github.js +++ b/github.js @@ -1,4 +1,3 @@ -/* Copyright (c) 2014-2015 Richard Rodger, MIT License */ 'use strict' const GitHubAPI = require('github') @@ -12,13 +11,27 @@ module.exports = function github (options) { var seneca = this options = seneca.util.deepextend({ - token: 'YOUR_TOKEN_HERE' + token: '' }, options) seneca.add('role:github,cmd:get', cmd_get) seneca.add('role:github,cmd:query', cmd_query) seneca.add('role:github,cmd:parse', cmd_parse) + /* + * function cmd_get(args, done) + * Param: args. The args received by the seneeca act + * Param: done. The callback + * + * Tries to get data on a github repo from a seneca entity in some connected store. + * If none is found, this founction tries to fallback to a giturl argument + * to fetch the data from github. + * + * Expected input: args.name. The id of the seneca entity to be found/created. + * Expected input: args.giturl. the repo location, used if no entity is found. + * Callback returns (error, output). + * Output is a dynamic object which contains data on a github repo. + */ function cmd_get (args, done) { var seneca = this var github_ent = seneca.make$('github') @@ -48,7 +61,19 @@ module.exports = function github (options) { }) } - + /* + * function cmd_query(args, done) + * Param: args. The args received by the seneeca act + * Param: done. The callback + * + * Gets data on some github repo given the owner and repo name + * + * Expected input: args.name. The id of the seneca entity to be created. + * Expected input: args.user. The user who owns some github repo. + * Expected input: args.repo. the repo they own. + * Callback returns (error, output). + * Output is a dynamic object which contains data on a github repo. + */ function cmd_query (args, done) { var seneca = this var github_ent = seneca.make$('github') @@ -99,14 +124,28 @@ module.exports = function github (options) { ) } - + /* + * function cmd_parse(args, done) + * Param: args. The args received by the seneeca act + * Param: done. The callback + * + * Parses a github repo url to its owner and repo name + * + * Expected input: args.giturl. The url of a git repo. + * Callback returns (error, output). + * Output is a dynamic object which contains a `user` and `repo` property + * on a valid `args.giturl`, or it contains an `ok: false` property. + */ function cmd_parse (args, done) { - // commented out unused var... - // var seneca = this - - var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) - if (m) { - return done(null, { user: m[1], repo: m[2] }) + // The regex below tries to parse the owner and repo name from a valid + // github url, in the formats: + // git@github.com:owner/repo + // git@github.com:owner/repo.git + // https://github.com/owner/repo.git + // Etc... + var match = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) + if (match) { + return done(null, { user: match[1], repo: match[2] }) } else return done(null, { ok: false, err: Err('parsing input failed') }) } diff --git a/package.json b/package.json index d1ea2b2..b07dd7a 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ ], "author": "Richard Rodger (richard.rodger@nearform.com)", "contributors": [ - "Isaac Mahon (github.com/CodeWriterWriter)" + "Isaac Mahon (github.com/CodeWriterWriter)", + "Glen Keane (glenkeane.me)" ], "license": "MIT", "dependencies": { diff --git a/srv/github-dev.js b/srv/github-dev.js index d2801bb..7482864 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -1,7 +1,5 @@ 'use strict' -// HOST is commented out because it is unusued -// const HOST = process.env.HOST || 'localhost' const TOKEN = process.env.TOKEN || 'NO_TOKEN' require('seneca')() From 0653f635bd5d008544aeef0e024d51d988f5849d Mon Sep 17 00:00:00 2001 From: Glen Keane Date: Mon, 1 Feb 2016 15:28:33 +0000 Subject: [PATCH 020/117] cleanup work --- .eslintrc | 3 ++ test/github.test.js | 67 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 .eslintrc create mode 100644 test/github.test.js diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..dfc6b32 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,3 @@ +{ + "extends": "seneca" +} diff --git a/test/github.test.js b/test/github.test.js new file mode 100644 index 0000000..6a296a0 --- /dev/null +++ b/test/github.test.js @@ -0,0 +1,67 @@ +'use strict' + +var Lab = require('lab') +var Code = require('code') +var Seneca = require('seneca') + +var lab = exports.lab = Lab.script() + +var describe = lab.describe +var it = lab.it +var expect = Code.expect + +var Github = require('..') + +/* + * Notice: For travis/CI, tests have been configured with a token provided by + * https://github.com/thekemkid. However, This is a read only token which will + * only be able to read from public repos. You can create a similar token in + * your github settings > personal access tokens > generate new token. You do + * not have to enable any special permissions for this token. + */ + +describe('nodezoo-github', function () { + it('Fired the get pattern', function (done) { + var seneca = Seneca({ log: 'silent' }) + seneca.use(Github, { token: process.env.GITHUB_TOKEN }) + + seneca.ready(function () { + seneca.act({ role: 'github', cmd: 'get', name: 'nodejs/node.git', giturl: 'git@github.com:nodejs/node.git' }, function (err, res) { + expect(err).to.not.exist() + expect(res.user).to.equal('nodejs') + expect(res.repo).to.equal('node') + expect(res.id).to.equal('nodejs/node.git') + done() + }) + }) + }) + + it('Fired the query pattern', function (done) { + var seneca = Seneca({ log: 'silent' }) + seneca.use(Github, { token: process.env.GITHUB_TOKEN }) + + seneca.ready(function () { + seneca.act({ role: 'github', cmd: 'query', name: 'nodejs/node.git', user: 'nodejs', repo: 'node' }, function (err, res) { + expect(err).to.not.exist() + expect(res.user).to.equal('nodejs') + expect(res.repo).to.equal('node') + expect(res.id).to.equal('nodejs/node.git') + done() + }) + }) + }) + + it('Fired the parse pattern', function (done) { + var seneca = Seneca({ log: 'silent' }) + seneca.use(Github, { token: process.env.GITHUB_TOKEN }) + + seneca.ready(function () { + seneca.act({ role: 'github', cmd: 'parse', giturl: 'git@github.com:nodejs/node.git' }, function (err, res) { + expect(err).to.not.exist() + expect(res.user).to.equal('nodejs') + expect(res.repo).to.equal('node') + done() + }) + }) + }) +}) From c3ff615346592e604cc5cb9f1ce5e4ce65dbba1f Mon Sep 17 00:00:00 2001 From: Glen Keane Date: Mon, 1 Feb 2016 16:20:30 +0000 Subject: [PATCH 021/117] updated comments --- github.js | 47 +++++++++++++++++++++++++++++++++++++++++++---- srv/github-dev.js | 8 +++++--- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/github.js b/github.js index 355cb68..b17842b 100644 --- a/github.js +++ b/github.js @@ -1,21 +1,37 @@ 'use strict' +// the github api for node const GitHubAPI = require('github') + +// eraro is a seneca module for error tracking const Err = require('eraro')({ package: 'nodezoo-github' }) +// instatiate our api with a specific version var gitapi = new GitHubAPI({ - version: '3.0.0' + version: '3.0.0' // api version }) +// export our module, to be used as a seneca plugin module.exports = function github (options) { var seneca = this + // merge options with the defaults + // token is the github api access token, + // you can pass in your own in the plugin options. options = seneca.util.deepextend({ token: '' }, options) + // handle get requests, looking for info on some seneca entity + // see: function comment seneca.add('role:github,cmd:get', cmd_get) + + // handle queries for some github repo, eg get it stars, num watchers, etc + // see: function comment seneca.add('role:github,cmd:query', cmd_query) + + // parse some github repo url into a format usable by the query command + // see: function comment seneca.add('role:github,cmd:parse', cmd_parse) /* @@ -34,29 +50,41 @@ module.exports = function github (options) { */ function cmd_get (args, done) { var seneca = this + + // make a github seneca entity, which can then be acted on var github_ent = seneca.make$('github') + // the name(id) of the seneca entity (for some repo) var github_name = args.name + // load the entity based on the name github_ent.load$(github_name, function (err, github_mod) { if (err) return done(err) + // if there is/was an entity stored, send it to the callback if (github_mod) { return done(null, github_mod) } + // else if there is no entity stored that matches, try lookup the github + // repo if the url is provided else if (args.giturl) { + // first we should parse the github repo url seneca.act( 'role:github,cmd:parse', { name: github_name, giturl: args.giturl }, function (err, out) { if (err) return done(err) + // now we can query the api with the info that the parse sent us. + // to query the api, we call our query command seneca.act( 'role:github,cmd:query', { name: github_name, user: out.user, repo: out.repo }, done) }) } + // else, we want to do nothing as not enough info was passed to this + // function else return done() }) } @@ -76,28 +104,36 @@ module.exports = function github (options) { */ function cmd_query (args, done) { var seneca = this + + // again, make a git seneca entity which we can act against later var github_ent = seneca.make$('github') + // the name of that entity var github_name = args.name + // the user who owns the github repo to be queried var user = args.user + // the repo to be queried var repo = args.repo + // setup the githubapi authentication with oauth gitapi.authenticate({ type: 'basic', - username: options.token, + username: options.token, // heres where our token is useful password: 'x-oauth-basic' }) + // get some repo data from github, based on some user and their repo names gitapi.repos.get( { - user: user, - repo: repo + user: user, // the github user + repo: repo // the github repo }, function (err, repo) { if (err) return done(err) var data if (repo) { + // build some repo data to be passed back to the querier data = { user: args.user, repo: args.repo, @@ -107,6 +143,9 @@ module.exports = function github (options) { last: repo.pushed_at } + // attempt to load some entity related to the repo + // and then save it with the updated data, or, create a new entity + // and save it with the data github_ent.load$(github_name, function (err, github_mod) { if (err) return done(err) diff --git a/srv/github-dev.js b/srv/github-dev.js index 7482864..0b3124d 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -1,12 +1,14 @@ 'use strict' +// your github token can be stored in an env variable named token, +// and will be picked up here const TOKEN = process.env.TOKEN || 'NO_TOKEN' require('seneca')() .use('redis-transport') .use('level-store') - + // initialise our github plugin with our token .use('../github.js', { token: TOKEN }) .add('role:info,req:part', function (args, done) { @@ -46,11 +48,11 @@ require('seneca')() }) }) }) - + // tell our service to use seneca-mesh to find service peers and connect to .use('mesh', { auto: true, pins: ['role:github', 'role:info,req:part'], model: 'publish' }) - + // open a seneeca repl port for debugging .repl(33004) From 6523c08d106dc4708258e727ce8ab563b38f3307 Mon Sep 17 00:00:00 2001 From: Isaac Date: Tue, 2 Feb 2016 10:00:21 +0000 Subject: [PATCH 022/117] included coc and updated readme --- CODE_OF_CONDUCT.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++ README.md | 17 +++++++++------ srv/github-dev.js | 6 +++++- 3 files changed, 69 insertions(+), 8 deletions(-) create mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..eac78ac --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,54 @@ +# Contributor Code of Conduct + +As contributors and maintainers of this project, and in the interest of +fostering an open and welcoming community, we pledge to respect all people who +contribute through reporting issues, posting feature requests, updating +documentation, submitting pull requests or patches, and other activities. + +We are committed to making participation in this project a harassment-free +experience for everyone, regardless of level of experience, gender, gender +identity and expression, sexual orientation, disability, personal appearance, +body size, race, ethnicity, age, religion, or nationality. We will +prioritize marginalized people's safety over privileged people's comfort. + +Examples of unacceptable behavior by participants include: + +* The use of sexualized language or imagery +* Personal attacks +* Trolling or insulting/derogatory comments +* Public or private harassment +* Publishing other's private information, such as physical or electronic + addresses, without explicit permission +* Other unethical or unprofessional conduct + +Project maintainers have the right _and responsibility_ to remove, edit, or +reject comments, commits, code, wiki edits, issues, and other contributions +that are not aligned to this Code of Conduct, or to ban temporarily or +permanently any contributor for other behaviors that they deem inappropriate, +threatening, offensive, or harmful. + +By adopting this Code of Conduct, project maintainers commit themselves to +fairly and consistently applying these principles to every aspect of managing +this project. Project maintainers who do not follow or enforce the Code of +Conduct may be permanently removed from the project team. + +This Code of Conduct applies both within project spaces and in public spaces +when an individual is representing the project or its community. + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported by contacting us at [hello@nearform.com][email]. All +complaints will be reviewed and investigated and will result in a response that +is deemed necessary and appropriate to the circumstances. Maintainers are +obligated to maintain confidentiality with regard to the reporter of an +incident. + +This Code of Conduct is adapted from the [Contributor Covenant][homepage] version 1.3.0 +and [Open Code of Conduct][opencoc]. + +Copied verbatim from the [Chakra Core][] project, with thanks. + +[email]: mailto:hello@nearform.com +[homepage]: http://contributor-covenant.org +[version]: http://contributor-covenant.org/version/1/3/0/ +[opencoc]: http://todogroup.org/opencodeofconduct/ +[Chakra Core]: https://github.com/Microsoft/ChakraCore diff --git a/README.md b/README.md index d750602..a51a022 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ ![Nodezoo](https://raw.githubusercontent.com/rjrodger/nodezoo-web/to-redux/client/assets/img/logo-nodezoo.png) -# nodezoo-github +## nodezoo-github Nodezoo.com micro-service handling github meta data. Please see the [main repo][] for more details - __Sponsor:__ [nearForm][] +## Install +1. clone this repo into a root _/nodezoo_ folder. +2. run `npm install` - - - -# Running +## Starting ```sh $ node srvs/github-dev.js --seneca.options.github.token=GITHUB-PERSONAL-ACCESS-TOKEN --seneca.log.all @@ -34,13 +34,15 @@ This micro-service recognizes the following messages: ## Running with Curl -Any of the messages above can be run using curl in the following format +Any of the messages above can be run using curl in the following format in the command line ``` curl -d '{"role":"github","cmd":"get"}' http://localhost:52472/act ``` ## Contributing -The [NodeZoo][] org encourages open participation. If you feel you can help in any way, be it with documentation, examples, extra testing, or new features please get in touch. +The [NodeZoo org][] encourages __open__ and __safe__ participation. If you feel you can help in any way, be it with documentation, examples, extra testing, or new features please get in touch. + +- Before contributing please review our __[Code of Conduct][CoC]__ ## License Copyright (c) 2015, Richard Rodgers and other contributors. @@ -51,3 +53,4 @@ Licensed under [MIT][]. [Code of Conduct]: https://github.com/nearform/vidi-contrib/docs/code_of_conduct.md [nearForm]: http://www.nearform.com/ [NodeZoo]: http://www.nodezoo.com/ +[CoC]: ./CoC.md diff --git a/srv/github-dev.js b/srv/github-dev.js index fe02102..9411932 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -2,7 +2,7 @@ var HOST = process.env.HOST || 'localhost' var TOKEN = process.env.TOKEN || 'NO_TOKEN' -require('seneca')() +var seneca = require('seneca')() .use('redis-transport') .use('level-store') @@ -51,3 +51,7 @@ require('seneca')() {auto:true, pins:['role:github','role:info,req:part'], model:'publish'} ) .repl(33004) + + + +console.log(seneca.options()) From 565b7e40d035593f3b11e7252202577416c2bff5 Mon Sep 17 00:00:00 2001 From: Isaac Date: Tue, 2 Feb 2016 10:01:37 +0000 Subject: [PATCH 023/117] removed print line from github-dev --- srv/github-dev.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/srv/github-dev.js b/srv/github-dev.js index 9411932..443600a 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -2,7 +2,7 @@ var HOST = process.env.HOST || 'localhost' var TOKEN = process.env.TOKEN || 'NO_TOKEN' -var seneca = require('seneca')() +require('seneca')() .use('redis-transport') .use('level-store') @@ -25,7 +25,7 @@ var seneca = require('seneca')() {name:args.name,data:mod.data$()}) } - this.act( + this.act( 'role:npm,cmd:get', {name:args.name}, function(err,mod){ if( err ) return; @@ -47,11 +47,7 @@ var seneca = require('seneca')() }) }) - .use( 'mesh', + .use( 'mesh', {auto:true, pins:['role:github','role:info,req:part'], model:'publish'} ) .repl(33004) - - - -console.log(seneca.options()) From df1781e6e2bfbe6b97cb06a31ce21a37df6b7dbb Mon Sep 17 00:00:00 2001 From: Isaac Date: Tue, 2 Feb 2016 10:03:38 +0000 Subject: [PATCH 024/117] fixed hyperlink in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a51a022..e5b8328 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ curl -d '{"role":"github","cmd":"get"}' http://localhost:52472/act ``` ## Contributing -The [NodeZoo org][] encourages __open__ and __safe__ participation. If you feel you can help in any way, be it with documentation, examples, extra testing, or new features please get in touch. +The [NodeZoo][] org encourages __open__ and __safe__ participation. If you feel you can help in any way, be it with documentation, examples, extra testing, or new features please get in touch. - Before contributing please review our __[Code of Conduct][CoC]__ From dfa0c91b77bd4f83b349522933cefb167649d78d Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Wed, 17 Feb 2016 16:55:23 +0000 Subject: [PATCH 025/117] Updated license and readme. Added .toolbagrc.js toolbagrc did not commit Updates to repo --- .toolbagrc.js | 41 +++++++++++++++++++++++++++++++++++++++++ LICENSE | 2 +- README.md | 2 +- package.json | 31 +++++++++++++------------------ 4 files changed, 56 insertions(+), 20 deletions(-) create mode 100644 .toolbagrc.js diff --git a/.toolbagrc.js b/.toolbagrc.js new file mode 100644 index 0000000..9f9f6a0 --- /dev/null +++ b/.toolbagrc.js @@ -0,0 +1,41 @@ +'use strict' + +const StatsCollector = require('toolbag/lib/plugins/stats_collector') +const UdpReporter = require('toolbag/lib/plugins/udp_reporter') + +module.exports = function (defaults, callback) { + callback(null, { + plugins: [ + { + plugin: UdpReporter, + options: { + id: 'udp reporter', + socketType: 'udp4', + port: 5001, + host: 'localhost' + } + }, + { + plugin: StatsCollector, + options: { + enabled: true, + period: 1000, + eventLoopLimit: 30, + features: { + process: true, + system: true, + cpu: true, + memory: true, + gc: true, + handles: true, + requests: true, + eventLoop: true, + meta: { + tags: ['nodezoo-github'] + } + } + } + } + ] + }) +} diff --git a/LICENSE b/LICENSE index 3dbe85a..12abeb9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Richard Rodger +Copyright (c) 2014-2016 Richard Rodger Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index e5b8328..8c7278c 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ The [NodeZoo][] org encourages __open__ and __safe__ participation. If you feel - Before contributing please review our __[Code of Conduct][CoC]__ ## License -Copyright (c) 2015, Richard Rodgers and other contributors. +Copyright (c) 2014-2016, Richard Rodger and other contributors. Licensed under [MIT][]. [main repo]: https://github.com/rjrodger/nodezoo diff --git a/package.json b/package.json index 9e2f49a..8d218e5 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,8 @@ "version": "5.0.0", "description": "nodezoo.com micro-service handling github meta data", "scripts": { - "test": "lab -v ./test/*.test.js -m 4000", - "coverage": "lab ./test/*test.js -r lcov -o coverage/lcov.info -r html -o coverage/index.html", - "publish-coverage": "coveralls < coverage/lcov.info", - "lint": "lab -dL" + "start": "node srv/github-dev.js", + "start-dev": "node srv/github-dev.js" }, "main": "github.js", "keywords": [ @@ -20,26 +18,23 @@ "Isaac Mahon (github.com/CodeWriterWriter)", "Glen Keane (glenkeane.me)" ], - "scripts":{ - "start": "node srv/github-dev.js", - "start-dev": "node srv/github-dev.js" - }, "license": "MIT", "dependencies": { - "code": "^2.1.0", - "eraro": "^0.4.1", - "eslint-config-seneca": "^1.1.2", - "eslint-plugin-hapi": "^4.0.0", - "eslint-plugin-standard": "^1.3.1", - "github": "^0.2.2", - "lab": "^8.2.0", - "pre-commit": "^1.1.2", + "code": "2.1.0", + "eraro": "0.4.1", + "eslint-config-seneca": "1.1.2", + "eslint-plugin-hapi": "4.0.0", + "eslint-plugin-standard": "1.3.1", + "github": "0.2.2", + "lab": "8.2.0", + "pre-commit": "1.1.2", "seneca": "https://github.com/senecajs/seneca", "seneca-balance-client": "https://github.com/rjrodger/seneca-balance-client", - "seneca-level-store": "^0.2.3", + "seneca-level-store": "0.2.3", "seneca-mesh": "https://github.com/rjrodger/seneca-mesh", "seneca-msgstats": "https://github.com/rjrodger/seneca-msgstats", - "seneca-redis-transport": "^0.3.0" + "seneca-redis-transport": "0.3.0", + "toolbag": "0.9.0" }, "pre-commit": [ "test", From 73c3b0e1fb27d98d73de7e01ce8933946dcf0567 Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Thu, 18 Feb 2016 12:54:10 +0000 Subject: [PATCH 026/117] Removed CoC, changed link to CoC in readme Fixed CoC and image link Update readme to fix link Removed unused link Update --- CODE_OF_CONDUCT.md | 54 ---------------------------------------------- README.md | 7 +++--- 2 files changed, 3 insertions(+), 58 deletions(-) delete mode 100644 CODE_OF_CONDUCT.md diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md deleted file mode 100644 index eac78ac..0000000 --- a/CODE_OF_CONDUCT.md +++ /dev/null @@ -1,54 +0,0 @@ -# Contributor Code of Conduct - -As contributors and maintainers of this project, and in the interest of -fostering an open and welcoming community, we pledge to respect all people who -contribute through reporting issues, posting feature requests, updating -documentation, submitting pull requests or patches, and other activities. - -We are committed to making participation in this project a harassment-free -experience for everyone, regardless of level of experience, gender, gender -identity and expression, sexual orientation, disability, personal appearance, -body size, race, ethnicity, age, religion, or nationality. We will -prioritize marginalized people's safety over privileged people's comfort. - -Examples of unacceptable behavior by participants include: - -* The use of sexualized language or imagery -* Personal attacks -* Trolling or insulting/derogatory comments -* Public or private harassment -* Publishing other's private information, such as physical or electronic - addresses, without explicit permission -* Other unethical or unprofessional conduct - -Project maintainers have the right _and responsibility_ to remove, edit, or -reject comments, commits, code, wiki edits, issues, and other contributions -that are not aligned to this Code of Conduct, or to ban temporarily or -permanently any contributor for other behaviors that they deem inappropriate, -threatening, offensive, or harmful. - -By adopting this Code of Conduct, project maintainers commit themselves to -fairly and consistently applying these principles to every aspect of managing -this project. Project maintainers who do not follow or enforce the Code of -Conduct may be permanently removed from the project team. - -This Code of Conduct applies both within project spaces and in public spaces -when an individual is representing the project or its community. - -Instances of abusive, harassing, or otherwise unacceptable behavior may be -reported by contacting us at [hello@nearform.com][email]. All -complaints will be reviewed and investigated and will result in a response that -is deemed necessary and appropriate to the circumstances. Maintainers are -obligated to maintain confidentiality with regard to the reporter of an -incident. - -This Code of Conduct is adapted from the [Contributor Covenant][homepage] version 1.3.0 -and [Open Code of Conduct][opencoc]. - -Copied verbatim from the [Chakra Core][] project, with thanks. - -[email]: mailto:hello@nearform.com -[homepage]: http://contributor-covenant.org -[version]: http://contributor-covenant.org/version/1/3/0/ -[opencoc]: http://todogroup.org/opencodeofconduct/ -[Chakra Core]: https://github.com/Microsoft/ChakraCore diff --git a/README.md b/README.md index 8c7278c..6d4ba53 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Nodezoo](https://raw.githubusercontent.com/rjrodger/nodezoo-web/to-redux/client/assets/img/logo-nodezoo.png) +![Nodezoo](https://github.com/nodezoo/nodezoo-org/blob/master/assets/logo-nodezoo.png) ## nodezoo-github Nodezoo.com micro-service handling github meta data. Please see the [main repo][] for more details @@ -42,7 +42,7 @@ curl -d '{"role":"github","cmd":"get"}' http://localhost:52472/act ## Contributing The [NodeZoo][] org encourages __open__ and __safe__ participation. If you feel you can help in any way, be it with documentation, examples, extra testing, or new features please get in touch. -- Before contributing please review our __[Code of Conduct][CoC]__ +- Before contributing please review our __[Code of Conduct]__ ## License Copyright (c) 2014-2016, Richard Rodger and other contributors. @@ -50,7 +50,6 @@ Licensed under [MIT][]. [main repo]: https://github.com/rjrodger/nodezoo [MIT]: ./LICENSE -[Code of Conduct]: https://github.com/nearform/vidi-contrib/docs/code_of_conduct.md +[Code of Conduct]: https://github.com/nodezoo/nodezoo-org/blob/master/CoC.md [nearForm]: http://www.nearform.com/ [NodeZoo]: http://www.nodezoo.com/ -[CoC]: ./CoC.md From 1629b6f91ebd85d313317e9702e6a838608ac220 Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Thu, 18 Feb 2016 14:05:41 +0000 Subject: [PATCH 027/117] Contributing section updated Fixed link error Squashed commits --- README.md | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6d4ba53..c84ab88 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ ## nodezoo-github Nodezoo.com micro-service handling github meta data. Please see the [main repo][] for more details +- __Lead:__ [Richard Rodger][Lead] - __Sponsor:__ [nearForm][] ## Install @@ -40,9 +41,12 @@ curl -d '{"role":"github","cmd":"get"}' http://localhost:52472/act ``` ## Contributing -The [NodeZoo][] org encourages __open__ and __safe__ participation. If you feel you can help in any way, be it with documentation, examples, extra testing, or new features please get in touch. +The [NodeZoo org][] encourages __open__ and __safe__ participation. -- Before contributing please review our __[Code of Conduct]__ +- __[Code of Conduct]__ + +If you feel you can help in any way, be it with documentation, examples, extra testing, or new +features please get in touch. ## License Copyright (c) 2014-2016, Richard Rodger and other contributors. @@ -52,4 +56,5 @@ Licensed under [MIT][]. [MIT]: ./LICENSE [Code of Conduct]: https://github.com/nodezoo/nodezoo-org/blob/master/CoC.md [nearForm]: http://www.nearform.com/ -[NodeZoo]: http://www.nodezoo.com/ +[NodeZoo org]: http://www.nodezoo.com/ +[Lead]: https://github.com/rjrodger From 01535c0c060d336f1835b40d15cffc7cd752183c Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Thu, 18 Feb 2016 14:36:36 +0000 Subject: [PATCH 028/117] Changed location of Lead and Sponsor --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index c84ab88..d4b602a 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,12 @@ ![Nodezoo](https://github.com/nodezoo/nodezoo-org/blob/master/assets/logo-nodezoo.png) ## nodezoo-github -Nodezoo.com micro-service handling github meta data. Please see the [main repo][] for more details - __Lead:__ [Richard Rodger][Lead] - __Sponsor:__ [nearForm][] +Nodezoo.com micro-service handling github meta data. Please see the [main repo][] for more details + ## Install 1. clone this repo into a root _/nodezoo_ folder. 2. run `npm install` From d0c6ea470f1d863ae337f27d5eccdd55f0f702f4 Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Sat, 20 Feb 2016 13:57:29 +0000 Subject: [PATCH 029/117] Update to working --- .toolbagrc.js | 6 +- github.js | 208 ++++++++++++++++------------------------------ package.json | 15 +--- srv/github-dev.js | 58 ++++++------- 4 files changed, 101 insertions(+), 186 deletions(-) diff --git a/.toolbagrc.js b/.toolbagrc.js index 9f9f6a0..2453a15 100644 --- a/.toolbagrc.js +++ b/.toolbagrc.js @@ -26,9 +26,9 @@ module.exports = function (defaults, callback) { system: true, cpu: true, memory: true, - gc: true, - handles: true, - requests: true, + gc: false, + handles: false, + requests: false, eventLoop: true, meta: { tags: ['nodezoo-github'] diff --git a/github.js b/github.js index b17842b..1560285 100644 --- a/github.js +++ b/github.js @@ -1,191 +1,123 @@ -'use strict' +/* Copyright (c) 2014-2015 Richard Rodger, MIT License */ +/* jshint node:true, asi:true, eqnull:true */ +"use strict"; -// the github api for node -const GitHubAPI = require('github') -// eraro is a seneca module for error tracking -const Err = require('eraro')({ package: 'nodezoo-github' }) +var GitHubAPI = require('github') -// instatiate our api with a specific version -var gitapi = new GitHubAPI({ - version: '3.0.0' // api version +var gitapi = new GitHubAPI({ + version: "3.0.0" }) -// export our module, to be used as a seneca plugin -module.exports = function github (options) { + + +module.exports = function github( options ){ var seneca = this - // merge options with the defaults - // token is the github api access token, - // you can pass in your own in the plugin options. options = seneca.util.deepextend({ - token: '' - }, options) - - // handle get requests, looking for info on some seneca entity - // see: function comment - seneca.add('role:github,cmd:get', cmd_get) - - // handle queries for some github repo, eg get it stars, num watchers, etc - // see: function comment - seneca.add('role:github,cmd:query', cmd_query) - - // parse some github repo url into a format usable by the query command - // see: function comment - seneca.add('role:github,cmd:parse', cmd_parse) - - /* - * function cmd_get(args, done) - * Param: args. The args received by the seneeca act - * Param: done. The callback - * - * Tries to get data on a github repo from a seneca entity in some connected store. - * If none is found, this founction tries to fallback to a giturl argument - * to fetch the data from github. - * - * Expected input: args.name. The id of the seneca entity to be found/created. - * Expected input: args.giturl. the repo location, used if no entity is found. - * Callback returns (error, output). - * Output is a dynamic object which contains data on a github repo. - */ - function cmd_get (args, done) { - var seneca = this - - // make a github seneca entity, which can then be acted on - var github_ent = seneca.make$('github') - - // the name(id) of the seneca entity (for some repo) + token: '08a32510e52154b411a0d157b044e9972b4e8da6' + },options) + + + + seneca.add( 'role:github,cmd:get', cmd_get ) + seneca.add( 'role:github,cmd:query', cmd_query ) + seneca.add( 'role:github,cmd:parse', cmd_parse ) + + + + function cmd_get( args, done ) { + var seneca = this + var github_ent = seneca.make$('github') + var github_name = args.name - // load the entity based on the name - github_ent.load$(github_name, function (err, github_mod) { - if (err) return done(err) + github_ent.load$( github_name, function(err,github_mod){ + if( err ) return done(err); - // if there is/was an entity stored, send it to the callback - if (github_mod) { - return done(null, github_mod) + if( github_mod ) { + return done(null,github_mod); } - // else if there is no entity stored that matches, try lookup the github - // repo if the url is provided - else if (args.giturl) { - // first we should parse the github repo url + else if( args.giturl ) { seneca.act( 'role:github,cmd:parse', - { name: github_name, giturl: args.giturl }, - function (err, out) { - if (err) return done(err) + {name:github_name,giturl:args.giturl}, + + function(err,out){ + if( err ) return done(err); - // now we can query the api with the info that the parse sent us. - // to query the api, we call our query command seneca.act( 'role:github,cmd:query', - { name: github_name, user: out.user, repo: out.repo }, + {name:github_name,user:out.user,repo:out.repo}, done) }) } - // else, we want to do nothing as not enough info was passed to this - // function - else return done() + else return done(); }) } - /* - * function cmd_query(args, done) - * Param: args. The args received by the seneeca act - * Param: done. The callback - * - * Gets data on some github repo given the owner and repo name - * - * Expected input: args.name. The id of the seneca entity to be created. - * Expected input: args.user. The user who owns some github repo. - * Expected input: args.repo. the repo they own. - * Callback returns (error, output). - * Output is a dynamic object which contains data on a github repo. - */ - function cmd_query (args, done) { - var seneca = this - - // again, make a git seneca entity which we can act against later - var github_ent = seneca.make$('github') - - // the name of that entity + + function cmd_query( args, done ) { + var seneca = this + var github_ent = seneca.make$('github') + var github_name = args.name - // the user who owns the github repo to be queried - var user = args.user - // the repo to be queried - var repo = args.repo + var user = args.user + var repo = args.repo - // setup the githubapi authentication with oauth gitapi.authenticate({ - type: 'basic', - username: options.token, // heres where our token is useful + type: "basic", + username: options.token, password: 'x-oauth-basic' }) - // get some repo data from github, based on some user and their repo names gitapi.repos.get( { - user: user, // the github user - repo: repo // the github repo + user: user, + repo: repo }, - function (err, repo) { - if (err) return done(err) + function(err,repo){ + if( err ) return done(err); var data - if (repo) { - // build some repo data to be passed back to the querier + if( repo ) { data = { - user: args.user, - repo: args.repo, - stars: repo.stargazers_count, + user: args.user, + repo: args.repo, + stars: repo.stargazers_count, watches: repo.subscribers_count, - forks: repo.forks_count, - last: repo.pushed_at + forks: repo.forks_count, + last: repo.pushed_at } - // attempt to load some entity related to the repo - // and then save it with the updated data, or, create a new entity - // and save it with the data - github_ent.load$(github_name, function (err, github_mod) { - if (err) return done(err) + github_ent.load$(github_name, function(err,github_mod){ + if( err ) return done(err); - if (github_mod) { - return github_mod.data$(data).save$(done) + if( github_mod ) { + return github_mod.data$(data).save$(done); } else { data.id$ = github_name - github_ent.make$(data).save$(done) + github_ent.make$(data).save$(done); } }) } else return done() + } ) } - /* - * function cmd_parse(args, done) - * Param: args. The args received by the seneeca act - * Param: done. The callback - * - * Parses a github repo url to its owner and repo name - * - * Expected input: args.giturl. The url of a git repo. - * Callback returns (error, output). - * Output is a dynamic object which contains a `user` and `repo` property - * on a valid `args.giturl`, or it contains an `ok: false` property. - */ - function cmd_parse (args, done) { - // The regex below tries to parse the owner and repo name from a valid - // github url, in the formats: - // git@github.com:owner/repo - // git@github.com:owner/repo.git - // https://github.com/owner/repo.git - // Etc... - var match = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) - if (match) { - return done(null, { user: match[1], repo: match[2] }) + + function cmd_parse( args, done ) { + var seneca = this + + var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) + if( m ) { + return done( null, { user:m[1], repo:m[2] }) } - else return done(null, { ok: false, err: Err('parsing input failed') }) + else return done(); } + + } diff --git a/package.json b/package.json index 8d218e5..74e6458 100644 --- a/package.json +++ b/package.json @@ -27,17 +27,10 @@ "eslint-plugin-standard": "1.3.1", "github": "0.2.2", "lab": "8.2.0", - "pre-commit": "1.1.2", - "seneca": "https://github.com/senecajs/seneca", - "seneca-balance-client": "https://github.com/rjrodger/seneca-balance-client", + "seneca": "1.2.0", + "seneca-balance-client": "0.2.0", "seneca-level-store": "0.2.3", - "seneca-mesh": "https://github.com/rjrodger/seneca-mesh", - "seneca-msgstats": "https://github.com/rjrodger/seneca-msgstats", - "seneca-redis-transport": "0.3.0", + "seneca-mesh": "0.5.0", "toolbag": "0.9.0" - }, - "pre-commit": [ - "test", - "lint" - ] + } } diff --git a/srv/github-dev.js b/srv/github-dev.js index 0b3124d..532463d 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -2,57 +2,47 @@ // your github token can be stored in an env variable named token, // and will be picked up here -const TOKEN = process.env.TOKEN || 'NO_TOKEN' +var TOKEN = process.env.TOKEN || '08a32510e52154b411a0d157b044e9972b4e8da6' require('seneca')() - - .use('redis-transport') - .use('level-store') - // initialise our github plugin with our token - .use('../github.js', { token: TOKEN }) - + .use('../github.js', {token: TOKEN}) .add('role:info,req:part', function (args, done) { done() - this.act( - 'role:github,cmd:get', - { name: args.name }, + this.act('role:github,cmd:get', {name: args.name}, function (err, mod) { + if (err) { + this.log.error(err) + return + } - function (err, mod) { - if (err) return + if (mod) { + return this.act('role:info,res:part,part:github', {name: args.name, data: mod.data$()}) + } - if (mod) { - return this.act( - 'role:info,res:part,part:github', - { name: args.name, data: mod.data$() }) + this.act('role:npm, cmd:get', {name: args.name}, function (err, mod) { + if (err) { + this.log.error(err) + return } - this.act( - 'role:npm,cmd:get', { name: args.name }, - function (err, mod) { - if (err) return + if (mod) { + this.act('role:github,cmd:get', {name: args.name, giturl: mod.giturl}, function (err, mod) { + if (err) { + this.log.error(err) + return + } if (mod) { - this.act( - 'role:github,cmd:get', - { name: args.name, giturl: mod.giturl }, - function (err, mod) { - if (err) return - - if (mod) { - this.act('role:info,res:part,part:github', - { name: args.name, data: mod.data$() }) - } - }) + this.act('role:info,res:part,part:github', {name: args.name, data: mod.data$()}) } }) + } }) + }) }) - // tell our service to use seneca-mesh to find service peers and connect to .use('mesh', { auto: true, - pins: ['role:github', 'role:info,req:part'], + pin: ['role:github', 'role:info,req:part'], model: 'publish' }) - // open a seneeca repl port for debugging .repl(33004) From 42353fd20b772211ed5ba165421f07747d19815b Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Mon, 22 Feb 2016 15:02:53 +0000 Subject: [PATCH 030/117] Remove fake tokens --- github.js | 2 +- srv/github-dev.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/github.js b/github.js index 1560285..801a80a 100644 --- a/github.js +++ b/github.js @@ -15,7 +15,7 @@ module.exports = function github( options ){ var seneca = this options = seneca.util.deepextend({ - token: '08a32510e52154b411a0d157b044e9972b4e8da6' + token: '' },options) diff --git a/srv/github-dev.js b/srv/github-dev.js index 532463d..f858e1a 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -2,7 +2,7 @@ // your github token can be stored in an env variable named token, // and will be picked up here -var TOKEN = process.env.TOKEN || '08a32510e52154b411a0d157b044e9972b4e8da6' +var TOKEN = process.env.TOKEN || '' require('seneca')() .use('../github.js', {token: TOKEN}) From 9956ec01054520c5d9cf25887c0b9439cc8fe897 Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Tue, 1 Mar 2016 19:20:04 +0000 Subject: [PATCH 031/117] tidy up --- .toolbagrc.js | 16 +++-- github.js | 178 ++++++++++++++++++++++---------------------------- package.json | 9 +-- 3 files changed, 92 insertions(+), 111 deletions(-) diff --git a/.toolbagrc.js b/.toolbagrc.js index 2453a15..19ad69a 100644 --- a/.toolbagrc.js +++ b/.toolbagrc.js @@ -1,13 +1,12 @@ 'use strict' -const StatsCollector = require('toolbag/lib/plugins/stats_collector') -const UdpReporter = require('toolbag/lib/plugins/udp_reporter') +const plugins = require('toolbag-plugins') -module.exports = function (defaults, callback) { - callback(null, { +module.exports = (defaults, done) => { + done(null, { plugins: [ { - plugin: UdpReporter, + plugin: plugins.UdpReporter, options: { id: 'udp reporter', socketType: 'udp4', @@ -16,7 +15,7 @@ module.exports = function (defaults, callback) { } }, { - plugin: StatsCollector, + plugin: plugins.StatsCollector, options: { enabled: true, period: 1000, @@ -31,7 +30,10 @@ module.exports = function (defaults, callback) { requests: false, eventLoop: true, meta: { - tags: ['nodezoo-github'] + tags: [ + 'git', + 'nodezoo' + ] } } } diff --git a/github.js b/github.js index 801a80a..ef11ba3 100644 --- a/github.js +++ b/github.js @@ -1,123 +1,101 @@ -/* Copyright (c) 2014-2015 Richard Rodger, MIT License */ -/* jshint node:true, asi:true, eqnull:true */ -"use strict"; - - -var GitHubAPI = require('github') - -var gitapi = new GitHubAPI({ - version: "3.0.0" -}) +'use strict' +var GitHub = require('github') +var github = new GitHub({version: '3.0.0'}) +var opts = { + token: '' +} -module.exports = function github( options ){ +module.exports = function (options) { var seneca = this + var extend = seneca.util.deepextend - options = seneca.util.deepextend({ - token: '' - },options) + opts = (opts, options) + seneca.add('role:github,cmd:get', cmd_get) + seneca.add('role:github,cmd:query', cmd_query) + seneca.add('role:github,cmd:parse', cmd_parse) + return { + name: 'nodezoo-github' + } +} - seneca.add( 'role:github,cmd:get', cmd_get ) - seneca.add( 'role:github,cmd:query', cmd_query ) - seneca.add( 'role:github,cmd:parse', cmd_parse ) +function cmd_get (msg, done) { + var seneca = this + var store = seneca.make$('github') + store.load$(msg.name, function (err, model) { + if (err) return done(err) + if (model) { + return done(null, model) + } - function cmd_get( args, done ) { - var seneca = this - var github_ent = seneca.make$('github') + if (msg.giturl) { + seneca.act('role:github,cmd:parse', {name: msg.name, giturl: msg.giturl}, function (err, out) { + if (err) return done(err) + else seneca.act('role:github,cmd:query', {name: msg.name, user: out.user, repo: out.repo}, done) + }) + } - var github_name = args.name + return done() + }) +} - github_ent.load$( github_name, function(err,github_mod){ - if( err ) return done(err); - if( github_mod ) { - return done(null,github_mod); - } - else if( args.giturl ) { - seneca.act( - 'role:github,cmd:parse', - {name:github_name,giturl:args.giturl}, - - function(err,out){ - if( err ) return done(err); - - seneca.act( - 'role:github,cmd:query', - {name:github_name,user:out.user,repo:out.repo}, - done) - }) - } - else return done(); - }) - } +function cmd_query (msg, done) { + var seneca = this + var store = seneca.make$('github') + + var github_name = msg.name + var user = msg.user + var repo = msg.repo + + github.authenticate({ + type: 'basic', + username: opts.token, + password: 'x-oauth-basic' + }) + + github.repos.get({user: user, repo: repo}, function (err,repo) { + if (err) return done(err) + + var data + if (repo) { + data = { + user: msg.user, + repo: msg.repo, + stars: repo.stargazers_count, + watches: repo.subscribers_count, + forks: repo.forks_count, + last: repo.pushed_at + } + store.load$(github_name, function (err, model) { + if (err) return done(err) - function cmd_query( args, done ) { - var seneca = this - var github_ent = seneca.make$('github') - - var github_name = args.name - var user = args.user - var repo = args.repo - - gitapi.authenticate({ - type: "basic", - username: options.token, - password: 'x-oauth-basic' - }) - - gitapi.repos.get( - { - user: user, - repo: repo - }, - function(err,repo){ - if( err ) return done(err); - - var data - if( repo ) { - data = { - user: args.user, - repo: args.repo, - stars: repo.stargazers_count, - watches: repo.subscribers_count, - forks: repo.forks_count, - last: repo.pushed_at + if (model) { + return model.data$(data).save$(done) } - - github_ent.load$(github_name, function(err,github_mod){ - if( err ) return done(err); - - if( github_mod ) { - return github_mod.data$(data).save$(done); - } - else { - data.id$ = github_name - github_ent.make$(data).save$(done); - } - }) - } - else return done() - + else { + data.id$ = github_name + store.make$(data).save$(done) + } + }) } - ) - } - - - function cmd_parse( args, done ) { - var seneca = this - var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) - if( m ) { - return done( null, { user:m[1], repo:m[2] }) + else return done() } - else return done(); - } + ) +} + +function cmd_parse (msg, done) { + var seneca = this + var matches = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(msg.giturl) + if (matches) done(null, {user: matches[1], repo: matches[2]}) + else done() } diff --git a/package.json b/package.json index 74e6458..a171610 100644 --- a/package.json +++ b/package.json @@ -3,8 +3,7 @@ "version": "5.0.0", "description": "nodezoo.com micro-service handling github meta data", "scripts": { - "start": "node srv/github-dev.js", - "start-dev": "node srv/github-dev.js" + "start": "node srv/github-dev.js" }, "main": "github.js", "keywords": [ @@ -16,7 +15,8 @@ "author": "Richard Rodger (richard.rodger@nearform.com)", "contributors": [ "Isaac Mahon (github.com/CodeWriterWriter)", - "Glen Keane (glenkeane.me)" + "Glen Keane (glenkeane.me)", + "Dean McDonnell (mcdonelldean.me)" ], "license": "MIT", "dependencies": { @@ -31,6 +31,7 @@ "seneca-balance-client": "0.2.0", "seneca-level-store": "0.2.3", "seneca-mesh": "0.5.0", - "toolbag": "0.9.0" + "toolbag": "0.14.0", + "toolbag-plugins": "0.1.0" } } From 9303d2d4fceaef7539579ecb747f07bbf0fec809 Mon Sep 17 00:00:00 2001 From: Jane Quinn Date: Wed, 2 Mar 2016 16:03:34 +0000 Subject: [PATCH 032/117] updated contributors --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a171610..b001841 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ ], "author": "Richard Rodger (richard.rodger@nearform.com)", "contributors": [ - "Isaac Mahon (github.com/CodeWriterWriter)", + "Jane Quinn (github.com/CodeWriterWriter)", "Glen Keane (glenkeane.me)", "Dean McDonnell (mcdonelldean.me)" ], From 85f9fb0b3a170483890366dbc9e6a96c515beb06 Mon Sep 17 00:00:00 2001 From: Matthew O'Connor Date: Wed, 2 Mar 2016 17:15:48 +0000 Subject: [PATCH 033/117] travis CI inclusion --- github.js | 2 +- srv/github-dev.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/github.js b/github.js index 1560285..68cefe2 100644 --- a/github.js +++ b/github.js @@ -15,7 +15,7 @@ module.exports = function github( options ){ var seneca = this options = seneca.util.deepextend({ - token: '08a32510e52154b411a0d157b044e9972b4e8da6' + token: 'd520a5c9b6bd17e6b16ac72493b34a8c0402863f' },options) diff --git a/srv/github-dev.js b/srv/github-dev.js index 532463d..82b100f 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -2,7 +2,7 @@ // your github token can be stored in an env variable named token, // and will be picked up here -var TOKEN = process.env.TOKEN || '08a32510e52154b411a0d157b044e9972b4e8da6' +var TOKEN = process.env.TOKEN || 'd520a5c9b6bd17e6b16ac72493b34a8c0402863f' require('seneca')() .use('../github.js', {token: TOKEN}) @@ -24,7 +24,6 @@ require('seneca')() this.log.error(err) return } - if (mod) { this.act('role:github,cmd:get', {name: args.name, giturl: mod.giturl}, function (err, mod) { if (err) { From 3faab019968edaccef615bad33e5c7b63989aaa7 Mon Sep 17 00:00:00 2001 From: Adrian Rossouw Date: Thu, 3 Mar 2016 17:30:26 +0200 Subject: [PATCH 034/117] improve docker file --- .dockerignore | 2 ++ Dockerfile | 18 ++++++------------ 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/.dockerignore b/.dockerignore index 8d98f9d..0052af6 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1 +1,3 @@ .* +node_modules/ +dist/ diff --git a/Dockerfile b/Dockerfile index 216d147..ac93391 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,18 +1,12 @@ -# nodezoo-github - FROM node:4 -ADD . / - -EXPOSE 44004 -EXPOSE 43004 +RUN mkdir /src +ADD package.json /src/ -CMD ["node","srv/github-dev.js","--seneca.options.tag=github","--seneca.log.all"] +WORKDIR /src -# build and run: -# $ docker build -t nodezoo-github-04 . -# $ docker run -d -p 44004:44004 -p 43004:43004 -e HOST=$(docker-machine ip default) -e REDIS=192.168.99.1 -e TOKEN=`cat srv/.ignore-token` --volumes-from nodezoo-level nodezoo-github-04 -# local docker ip: -# $ docker-machine ip default +RUN npm install +COPY . /src +CMD ["node", "-r", "toolbag", "srv/github-dev.js", "--seneca.options.tag=nodezoo-github", "--seneca-log=type:act"] From be023c0c1563e381a25c01eff24e835b3e3016de Mon Sep 17 00:00:00 2001 From: Matthew O'Connor Date: Wed, 9 Mar 2016 17:09:46 +0000 Subject: [PATCH 035/117] refactored and removed npm dependency --- github.js | 189 ++++++++++++++++++++++++++++------------------ package.json | 2 + srv/github-dev.js | 61 ++++++--------- 3 files changed, 137 insertions(+), 115 deletions(-) diff --git a/github.js b/github.js index 5a8a8e3..f583d18 100644 --- a/github.js +++ b/github.js @@ -2,102 +2,141 @@ var GitHub = require('github') var github = new GitHub({version: '3.0.0'}) +var Request = require('request') +var _ = require('lodash') +var gitUrl var opts = { - token: '' + token: 'e414d503a227bb1445acf5ed619ec0948260babe' } module.exports = function (options) { var seneca = this var extend = seneca.util.deepextend - + options = seneca.util.deepextend({ - token: 'd520a5c9b6bd17e6b16ac72493b34a8c0402863f' + token: 'e414d503a227bb1445acf5ed619ec0948260babe', + registry: 'http://registry.npmjs.org/' },options) - + seneca.add('role:github,cmd:get', cmd_get) seneca.add('role:github,cmd:query', cmd_query) seneca.add('role:github,cmd:parse', cmd_parse) - - return { - name: 'nodezoo-github' + seneca.add('role:github,cmd:extract', cmd_extract) + + function cmd_get (args, done) { + var github_name = args.name + var github_ent = seneca.make$('github') + + var url = options.registry + github_name + // check if in the cache + github_ent.load$(github_name, function (err, github) { + if (err){ + return done(err) + } + if (github && !args.update) { + return done(null, github) + } + else { + //get giturl from npm + Request.get(url, function (err, res, body) { + if (err) { + return done(err) + } + else if (_.isEmpty(JSON.parse(body))) { + return done(err) + } + var data = JSON.parse(body) + //take giturl from npm data + seneca.act('role:github,cmd:extract', {data: data}, function (err, data) { + if (err) { + return done(err) + } + //parse username and repo from giturl + var gitData = cmd_parse(data) + //format url so links work correctly + gitUrl = urlFormat(data.giturl) + + if (gitData){ + var user = gitData[1] + var repo = gitData[2] + } + if (!user) { + return done(err) + } + else { + seneca.act('role:github,cmd:query', {name: github_name, user: user, repo: repo}, done) + } + }) + }) + } + }) } -} - -function cmd_get (msg, done) { - var seneca = this - var store = seneca.make$('github') - - store.load$(msg.name, function (err, model) { - if (err) return done(err) - - if (model) { - return done(null, model) - } - - if (msg.giturl) { - seneca.act('role:github,cmd:parse', {name: msg.name, giturl: msg.giturl}, function (err, out) { - if (err) return done(err) - else seneca.act('role:github,cmd:query', {name: msg.name, user: out.user, repo: out.repo}, done) - }) - } - - return done() - }) -} - - -function cmd_query (msg, done) { - var seneca = this - var store = seneca.make$('github') - - var github_name = msg.name - var user = msg.user - var repo = msg.repo - - github.authenticate({ - type: 'basic', - username: opts.token, - password: 'x-oauth-basic' - }) - - github.repos.get({user: user, repo: repo}, function (err,repo) { - if (err) return done(err) - + + function cmd_query (args, done) { + var github_ent = seneca.make$('github') + var github_name = args.name + var user = args.user + var repo = args.repo + + github.authenticate({ + type: 'basic', + username: opts.token, + password: 'x-oauth-basic' + }) + + github.repos.get({user: user, repo: repo}, function (err,repo) { + if (err) { + return done(err) + } var data if (repo) { data = { - user: msg.user, - repo: msg.repo, + user: args.user, + repo: args.repo, stars: repo.stargazers_count, watches: repo.subscribers_count, forks: repo.forks_count, - last: repo.pushed_at + last: repo.pushed_at, + url: gitUrl } - - store.load$(github_name, function (err, model) { - if (err) return done(err) - - if (model) { - return model.data$(data).save$(done) - } - else { - data.id$ = github_name - store.make$(data).save$(done) - } - }) + data.id$ = github_name + github_ent.make$(data).save$(done) } - else return done() + }) + } + + function urlFormat (url){ + if(url.indexOf('git+') >= 0){ + url = url.slice(4) } - ) -} - -function cmd_parse (msg, done) { - var seneca = this - - var matches = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(msg.giturl) - - if (matches) done(null, {user: matches[1], repo: matches[2]}) - else done() + else if(url.indexOf('git://') >= 0){ + url = 'http://' + url.slice(6) + } + return url + } + + function cmd_extract (args, done) { + var data = args.data + var dist_tags = data['dist-tags'] || {} + var latest = ((data.versions || {})[dist_tags.latest]) || {} + var repository = latest.repository || {} + + var out = { + giturl: repository.url + } + + done(null, out) + } + + function cmd_parse (args) { + var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) + if (m) { + return (m) + } + else { + return null + } + } } diff --git a/package.json b/package.json index b001841..9b1acc8 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,8 @@ "eslint-plugin-standard": "1.3.1", "github": "0.2.2", "lab": "8.2.0", + "lodash": "4.6.1", + "request": "2.69.0", "seneca": "1.2.0", "seneca-balance-client": "0.2.0", "seneca-level-store": "0.2.3", diff --git a/srv/github-dev.js b/srv/github-dev.js index 98bffc5..1f72f66 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -3,46 +3,27 @@ // your github token can be stored in an env variable named token, // and will be picked up here -var TOKEN = process.env.TOKEN || 'd520a5c9b6bd17e6b16ac72493b34a8c0402863f' +var TOKEN = process.env.TOKEN || 'e414d503a227bb1445acf5ed619ec0948260babe' require('seneca')() - .use('../github.js', {token: TOKEN}) - .add('role:info,req:part', function (args, done) { - done() - - this.act('role:github,cmd:get', {name: args.name}, function (err, mod) { - if (err) { - this.log.error(err) - return - } - - if (mod) { - return this.act('role:info,res:part,part:github', {name: args.name, data: mod.data$()}) - } - - this.act('role:npm, cmd:get', {name: args.name}, function (err, mod) { - if (err) { - this.log.error(err) - return - } - if (mod) { - this.act('role:github,cmd:get', {name: args.name, giturl: mod.giturl}, function (err, mod) { - if (err) { - this.log.error(err) - return - } - - if (mod) { - this.act('role:info,res:part,part:github', {name: args.name, data: mod.data$()}) - } - }) - } - }) - }) - }) - .use('mesh', { - auto: true, - pin: ['role:github', 'role:info,req:part'], - model: 'publish' +.use('../github.js', {token: TOKEN}) +.add('role:info,req:part', function (args, done) { + done() + + this.act('role:github,cmd:get', {name: args.name}, function (err, mod) { + if (err) { + return done(err); + } + this.act('role:info,res:part,part:github', {name: args.name, data: mod.data$()}) }) - .repl(33004) +}) + +.add('role:github,info:change', function (args,done) { + done() + this.act('role:info,cmd:get', {name:args.name,update:true}) +}) +.use('mesh', { + auto: true, + pin: ['role:github', 'role:info,req:part'], + model: 'publish' +}) From 33e771711094c2b3fb27c65d19c5965a3763cac1 Mon Sep 17 00:00:00 2001 From: Matthew O'Connor Date: Thu, 10 Mar 2016 10:34:18 +0000 Subject: [PATCH 036/117] updated docker file dockerfile updated contribution updated removed github token --- Dockerfile | 2 ++ github.js | 4 ++-- package.json | 3 ++- srv/github-dev.js | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index ac93391..7b05963 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,8 @@ +# nodezoo-github FROM node:4 RUN mkdir /src + ADD package.json /src/ WORKDIR /src diff --git a/github.js b/github.js index f583d18..10aee74 100644 --- a/github.js +++ b/github.js @@ -7,7 +7,7 @@ var _ = require('lodash') var gitUrl var opts = { - token: 'e414d503a227bb1445acf5ed619ec0948260babe' + token: '' } module.exports = function (options) { @@ -15,7 +15,7 @@ module.exports = function (options) { var extend = seneca.util.deepextend options = seneca.util.deepextend({ - token: 'e414d503a227bb1445acf5ed619ec0948260babe', + token: '', registry: 'http://registry.npmjs.org/' },options) diff --git a/package.json b/package.json index 9b1acc8..410d385 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,8 @@ "contributors": [ "Jane Quinn (github.com/CodeWriterWriter)", "Glen Keane (glenkeane.me)", - "Dean McDonnell (mcdonelldean.me)" + "Dean McDonnell (mcdonelldean.me)", + "Matthew O'Connor (github.com/matt-oc)" ], "license": "MIT", "dependencies": { diff --git a/srv/github-dev.js b/srv/github-dev.js index 1f72f66..f36d526 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -3,7 +3,7 @@ // your github token can be stored in an env variable named token, // and will be picked up here -var TOKEN = process.env.TOKEN || 'e414d503a227bb1445acf5ed619ec0948260babe' +var TOKEN = process.env.TOKEN || '' require('seneca')() .use('../github.js', {token: TOKEN}) From 4c9925520f5eadbb0f87006b7c94ab07f4e50403 Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Mon, 14 Mar 2016 14:40:51 +0000 Subject: [PATCH 037/117] Fix giturl for use in nodezoo-web --- github.js | 41 +++++++++++++++-------------------------- 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/github.js b/github.js index 10aee74..6717c88 100644 --- a/github.js +++ b/github.js @@ -13,22 +13,22 @@ var opts = { module.exports = function (options) { var seneca = this var extend = seneca.util.deepextend - + options = seneca.util.deepextend({ token: '', registry: 'http://registry.npmjs.org/' },options) - + seneca.add('role:github,cmd:get', cmd_get) seneca.add('role:github,cmd:query', cmd_query) seneca.add('role:github,cmd:parse', cmd_parse) - seneca.add('role:github,cmd:extract', cmd_extract) - + seneca.add('role:github,cmd:extract', cmd_extract) + function cmd_get (args, done) { var github_name = args.name var github_ent = seneca.make$('github') - - var url = options.registry + github_name + + var url = options.registry + github_name // check if in the cache github_ent.load$(github_name, function (err, github) { if (err){ @@ -54,12 +54,11 @@ module.exports = function (options) { } //parse username and repo from giturl var gitData = cmd_parse(data) - //format url so links work correctly - gitUrl = urlFormat(data.giturl) - + if (gitData){ var user = gitData[1] var repo = gitData[2] + gitUrl = 'http://github.com/' + user + '/' + repo } if (!user) { return done(err) @@ -72,19 +71,19 @@ module.exports = function (options) { } }) } - + function cmd_query (args, done) { var github_ent = seneca.make$('github') var github_name = args.name var user = args.user var repo = args.repo - + github.authenticate({ type: 'basic', username: opts.token, password: 'x-oauth-basic' }) - + github.repos.get({user: user, repo: repo}, function (err,repo) { if (err) { return done(err) @@ -106,30 +105,20 @@ module.exports = function (options) { else return done() }) } - - function urlFormat (url){ - if(url.indexOf('git+') >= 0){ - url = url.slice(4) - } - else if(url.indexOf('git://') >= 0){ - url = 'http://' + url.slice(6) - } - return url - } - + function cmd_extract (args, done) { var data = args.data var dist_tags = data['dist-tags'] || {} var latest = ((data.versions || {})[dist_tags.latest]) || {} var repository = latest.repository || {} - + var out = { giturl: repository.url } - + done(null, out) } - + function cmd_parse (args) { var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) if (m) { From 05b24cf5e810730d0768df7b88d84724babff508 Mon Sep 17 00:00:00 2001 From: Matthew O'Connor Date: Wed, 16 Mar 2016 10:30:18 +0000 Subject: [PATCH 038/117] added cache update --- github.js | 48 +++++++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/github.js b/github.js index 6717c88..58e1a7d 100644 --- a/github.js +++ b/github.js @@ -13,21 +13,21 @@ var opts = { module.exports = function (options) { var seneca = this var extend = seneca.util.deepextend - + options = seneca.util.deepextend({ token: '', registry: 'http://registry.npmjs.org/' },options) - + seneca.add('role:github,cmd:get', cmd_get) seneca.add('role:github,cmd:query', cmd_query) seneca.add('role:github,cmd:parse', cmd_parse) seneca.add('role:github,cmd:extract', cmd_extract) - + function cmd_get (args, done) { var github_name = args.name var github_ent = seneca.make$('github') - + var url = options.registry + github_name // check if in the cache github_ent.load$(github_name, function (err, github) { @@ -38,7 +38,7 @@ module.exports = function (options) { return done(null, github) } else { - //get giturl from npm + // get giturl from npm Request.get(url, function (err, res, body) { if (err) { return done(err) @@ -47,14 +47,14 @@ module.exports = function (options) { return done(err) } var data = JSON.parse(body) - //take giturl from npm data + // take giturl from npm data seneca.act('role:github,cmd:extract', {data: data}, function (err, data) { if (err) { return done(err) } - //parse username and repo from giturl + // parse username and repo from giturl var gitData = cmd_parse(data) - + if (gitData){ var user = gitData[1] var repo = gitData[2] @@ -64,6 +64,7 @@ module.exports = function (options) { return done(err) } else { + // get github data using github username and repo name seneca.act('role:github,cmd:query', {name: github_name, user: user, repo: repo}, done) } }) @@ -71,24 +72,25 @@ module.exports = function (options) { } }) } - + function cmd_query (args, done) { var github_ent = seneca.make$('github') var github_name = args.name var user = args.user var repo = args.repo - + github.authenticate({ type: 'basic', username: opts.token, password: 'x-oauth-basic' }) - + github.repos.get({user: user, repo: repo}, function (err,repo) { if (err) { return done(err) } var data + if (repo) { data = { user: args.user, @@ -99,26 +101,38 @@ module.exports = function (options) { last: repo.pushed_at, url: gitUrl } - data.id$ = github_name - github_ent.make$(data).save$(done) + // update the data if module exists in cache, if not create it + github_ent.load$(github_name, function(err,github){ + if (err) { + return done(err); + } + if (github) { + return github.data$(data).save$(done); + } + else { + data.id$ = github_name + github_ent.make$(data).save$(done) + } + }) + } else return done() }) } - + function cmd_extract (args, done) { var data = args.data var dist_tags = data['dist-tags'] || {} var latest = ((data.versions || {})[dist_tags.latest]) || {} var repository = latest.repository || {} - + var out = { giturl: repository.url } - + done(null, out) } - + function cmd_parse (args) { var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) if (m) { From face2ce00b1c849d371a3d0e65ce7c6dadb10dbe Mon Sep 17 00:00:00 2001 From: Matthew O'Connor Date: Wed, 16 Mar 2016 11:57:50 +0000 Subject: [PATCH 039/117] readme updated, key removed --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d4b602a..b462719 100644 --- a/README.md +++ b/README.md @@ -33,6 +33,7 @@ This micro-service recognizes the following messages: * _role:github,cmd:get_ * _role:github,cmd:query_ * _role:github,cmd:parse_ + * _role:github,cmd:extract_ ## Running with Curl From ba7d29f3fa4b4f755ebc47eb8e351d509f91f42a Mon Sep 17 00:00:00 2001 From: Matthew O'Connor Date: Fri, 25 Mar 2016 17:36:26 +0000 Subject: [PATCH 040/117] added insert commands --- github.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/github.js b/github.js index 58e1a7d..3ce3633 100644 --- a/github.js +++ b/github.js @@ -7,7 +7,7 @@ var _ = require('lodash') var gitUrl var opts = { - token: '' + token: '1b4d1e30de8597d1b7dd70a11a12131b322deae6' } module.exports = function (options) { @@ -15,7 +15,7 @@ module.exports = function (options) { var extend = seneca.util.deepextend options = seneca.util.deepextend({ - token: '', + token: '1b4d1e30de8597d1b7dd70a11a12131b322deae6', registry: 'http://registry.npmjs.org/' },options) @@ -93,6 +93,7 @@ module.exports = function (options) { if (repo) { data = { + name: args.repo, user: args.user, repo: args.repo, stars: repo.stargazers_count, @@ -112,6 +113,12 @@ module.exports = function (options) { else { data.id$ = github_name github_ent.make$(data).save$(done) + /* DEAN!!!!!!!!!!!!! + This is where were are doing the override command but without the override + possible issue here with it not having the object saved before + the insert is called, not sure yet. + */ + seneca.act('role:search,cmd:insert',{data:data}) } }) From 593261647c5247db577b0a7f76da053972f6bb62 Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Fri, 25 Mar 2016 23:30:42 +0000 Subject: [PATCH 041/117] Fixed issue with options --- github.js | 42 ++++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/github.js b/github.js index 3ce3633..6d2c8cf 100644 --- a/github.js +++ b/github.js @@ -7,28 +7,26 @@ var _ = require('lodash') var gitUrl var opts = { - token: '1b4d1e30de8597d1b7dd70a11a12131b322deae6' + registry: 'http://registry.npmjs.org/', + token: '' } module.exports = function (options) { var seneca = this var extend = seneca.util.deepextend - - options = seneca.util.deepextend({ - token: '1b4d1e30de8597d1b7dd70a11a12131b322deae6', - registry: 'http://registry.npmjs.org/' - },options) - + + opts = extend(opts, options) + seneca.add('role:github,cmd:get', cmd_get) seneca.add('role:github,cmd:query', cmd_query) seneca.add('role:github,cmd:parse', cmd_parse) seneca.add('role:github,cmd:extract', cmd_extract) - + function cmd_get (args, done) { var github_name = args.name var github_ent = seneca.make$('github') - - var url = options.registry + github_name + + var url = opts.registry + github_name // check if in the cache github_ent.load$(github_name, function (err, github) { if (err){ @@ -54,7 +52,7 @@ module.exports = function (options) { } // parse username and repo from giturl var gitData = cmd_parse(data) - + if (gitData){ var user = gitData[1] var repo = gitData[2] @@ -72,25 +70,25 @@ module.exports = function (options) { } }) } - + function cmd_query (args, done) { var github_ent = seneca.make$('github') var github_name = args.name var user = args.user var repo = args.repo - + github.authenticate({ type: 'basic', username: opts.token, password: 'x-oauth-basic' }) - + github.repos.get({user: user, repo: repo}, function (err,repo) { if (err) { return done(err) } var data - + if (repo) { data = { name: args.repo, @@ -115,31 +113,31 @@ module.exports = function (options) { github_ent.make$(data).save$(done) /* DEAN!!!!!!!!!!!!! This is where were are doing the override command but without the override - possible issue here with it not having the object saved before + possible issue here with it not having the object saved before the insert is called, not sure yet. */ seneca.act('role:search,cmd:insert',{data:data}) - } + } }) - + } else return done() }) } - + function cmd_extract (args, done) { var data = args.data var dist_tags = data['dist-tags'] || {} var latest = ((data.versions || {})[dist_tags.latest]) || {} var repository = latest.repository || {} - + var out = { giturl: repository.url } - + done(null, out) } - + function cmd_parse (args) { var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) if (m) { From 7fa757114488b5d3a47af15dd1c78e94301e2558 Mon Sep 17 00:00:00 2001 From: Gege Pincin Date: Mon, 28 Mar 2016 21:43:41 -0400 Subject: [PATCH 042/117] adding git clone url --- github.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/github.js b/github.js index 6d2c8cf..d9eff2a 100644 --- a/github.js +++ b/github.js @@ -88,6 +88,7 @@ module.exports = function (options) { return done(err) } var data + console.log(args, repo, 'args for github') if (repo) { data = { @@ -98,7 +99,8 @@ module.exports = function (options) { watches: repo.subscribers_count, forks: repo.forks_count, last: repo.pushed_at, - url: gitUrl + url: gitUrl, + gitClone: repo.clone_url } // update the data if module exists in cache, if not create it github_ent.load$(github_name, function(err,github){ From 80536f5eb0f83ad853ebdffb95a9920114615078 Mon Sep 17 00:00:00 2001 From: Gege Pincin Date: Mon, 28 Mar 2016 23:58:36 -0400 Subject: [PATCH 043/117] removing log --- github.js | 1 - 1 file changed, 1 deletion(-) diff --git a/github.js b/github.js index d9eff2a..c80dece 100644 --- a/github.js +++ b/github.js @@ -88,7 +88,6 @@ module.exports = function (options) { return done(err) } var data - console.log(args, repo, 'args for github') if (repo) { data = { From eb14475a3774b3ca8ae61ec8d0c2c26b40db5852 Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Tue, 29 Mar 2016 12:16:19 +0100 Subject: [PATCH 044/117] Updated toolbag --- .toolbagrc.js | 7 ++++--- package.json | 5 +++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.toolbagrc.js b/.toolbagrc.js index 19ad69a..1469cdd 100644 --- a/.toolbagrc.js +++ b/.toolbagrc.js @@ -1,12 +1,13 @@ 'use strict' -const plugins = require('toolbag-plugins') +const StatsCollector = require('toolbag-plugin-stats-collector') +const UdpReporter = require('toolbag-plugin-udp-reporter') module.exports = (defaults, done) => { done(null, { plugins: [ { - plugin: plugins.UdpReporter, + plugin: UdpReporter, options: { id: 'udp reporter', socketType: 'udp4', @@ -15,7 +16,7 @@ module.exports = (defaults, done) => { } }, { - plugin: plugins.StatsCollector, + plugin: StatsCollector, options: { enabled: true, period: 1000, diff --git a/package.json b/package.json index 410d385..3f24963 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,8 @@ "seneca-balance-client": "0.2.0", "seneca-level-store": "0.2.3", "seneca-mesh": "0.5.0", - "toolbag": "0.14.0", - "toolbag-plugins": "0.1.0" + "toolbag": "2.0.0", + "toolbag-plugin-stats-collector": "1.0.0", + "toolbag-plugin-udp-reporter": "1.0.0" } } From 2d64157de95b39a4d5cf7ec024a1801facff6b8d Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Fri, 1 Apr 2016 10:22:26 +0100 Subject: [PATCH 045/117] update seneca version --- package.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 3f24963..9b4321b 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,8 @@ "Jane Quinn (github.com/CodeWriterWriter)", "Glen Keane (glenkeane.me)", "Dean McDonnell (mcdonelldean.me)", - "Matthew O'Connor (github.com/matt-oc)" + "Matthew O'Connor (github.com/matt-oc)", + "Shane Lacey (github.com/shanel262)" ], "license": "MIT", "dependencies": { @@ -30,7 +31,7 @@ "lab": "8.2.0", "lodash": "4.6.1", "request": "2.69.0", - "seneca": "1.2.0", + "seneca": "2.0.0", "seneca-balance-client": "0.2.0", "seneca-level-store": "0.2.3", "seneca-mesh": "0.5.0", From e565c925e3966094199d880780f53cb731ed8954 Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Fri, 1 Apr 2016 12:16:00 +0100 Subject: [PATCH 046/117] Inserted repo info --- package.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/package.json b/package.json index 9b4321b..d1f2417 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,14 @@ "Matthew O'Connor (github.com/matt-oc)", "Shane Lacey (github.com/shanel262)" ], + "homepage": "https://github.com/nodezoo/nodezoo-github#readme", + "repository": { + "type": "git", + "url": "git+https://github.com/nodezoo/nodezoo-github.git" + }, + "bugs": { + "url": "https://github.com/nodezoo/nodezoo-github/issues" + }, "license": "MIT", "dependencies": { "code": "2.1.0", From 87c06b13917e88a1b6a62f005778d2cde4e30ea6 Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Fri, 1 Apr 2016 13:53:35 +0100 Subject: [PATCH 047/117] Updated mesh and balance client deps --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index d1f2417..5c724d7 100644 --- a/package.json +++ b/package.json @@ -40,9 +40,9 @@ "lodash": "4.6.1", "request": "2.69.0", "seneca": "2.0.0", - "seneca-balance-client": "0.2.0", + "seneca-balance-client": "0.4.0", "seneca-level-store": "0.2.3", - "seneca-mesh": "0.5.0", + "seneca-mesh": "0.7.0", "toolbag": "2.0.0", "toolbag-plugin-stats-collector": "1.0.0", "toolbag-plugin-udp-reporter": "1.0.0" From 10f558c04dcaf2947310ddce6c9b5a414f6deb42 Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Fri, 1 Apr 2016 15:24:42 +0100 Subject: [PATCH 048/117] Added seneca-entity --- package.json | 1 + srv/github-dev.js | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 5c724d7..d4c8050 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "request": "2.69.0", "seneca": "2.0.0", "seneca-balance-client": "0.4.0", + "seneca-entity": "0.0.1", "seneca-level-store": "0.2.3", "seneca-mesh": "0.7.0", "toolbag": "2.0.0", diff --git a/srv/github-dev.js b/srv/github-dev.js index f36d526..2990c95 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -7,9 +7,10 @@ var TOKEN = process.env.TOKEN || '' require('seneca')() .use('../github.js', {token: TOKEN}) +.use('entity') .add('role:info,req:part', function (args, done) { done() - + this.act('role:github,cmd:get', {name: args.name}, function (err, mod) { if (err) { return done(err); @@ -21,7 +22,7 @@ require('seneca')() .add('role:github,info:change', function (args,done) { done() this.act('role:info,cmd:get', {name:args.name,update:true}) -}) +}) .use('mesh', { auto: true, pin: ['role:github', 'role:info,req:part'], From 43c1fc719654fed3ebf306fda5c24720b16a67aa Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Fri, 1 Apr 2016 15:32:15 +0100 Subject: [PATCH 049/117] Use seneca-entity --- srv/github-dev.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srv/github-dev.js b/srv/github-dev.js index 2990c95..e3a799c 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -6,8 +6,8 @@ var TOKEN = process.env.TOKEN || '' require('seneca')() -.use('../github.js', {token: TOKEN}) .use('entity') +.use('../github.js', {token: TOKEN}) .add('role:info,req:part', function (args, done) { done() From 66305638684550fad62482707fb8aec0ccc006ae Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Fri, 1 Apr 2016 23:04:26 +0100 Subject: [PATCH 050/117] Fixes for search --- github.js | 220 ++++++++++++++++++++++++++------------------------- package.json | 12 +-- 2 files changed, 118 insertions(+), 114 deletions(-) diff --git a/github.js b/github.js index c80dece..5d74864 100644 --- a/github.js +++ b/github.js @@ -22,130 +22,132 @@ module.exports = function (options) { seneca.add('role:github,cmd:parse', cmd_parse) seneca.add('role:github,cmd:extract', cmd_extract) - function cmd_get (args, done) { - var github_name = args.name - var github_ent = seneca.make$('github') - - var url = opts.registry + github_name - // check if in the cache - github_ent.load$(github_name, function (err, github) { - if (err){ - return done(err) - } - if (github && !args.update) { - return done(null, github) - } - else { - // get giturl from npm - Request.get(url, function (err, res, body) { - if (err) { - return done(err) - } - else if (_.isEmpty(JSON.parse(body))) { - return done(err) - } - var data = JSON.parse(body) - // take giturl from npm data - seneca.act('role:github,cmd:extract', {data: data}, function (err, data) { - if (err) { - return done(err) - } - // parse username and repo from giturl - var gitData = cmd_parse(data) - - if (gitData){ - var user = gitData[1] - var repo = gitData[2] - gitUrl = 'http://github.com/' + user + '/' + repo - } - if (!user) { - return done(err) - } - else { - // get github data using github username and repo name - seneca.act('role:github,cmd:query', {name: github_name, user: user, repo: repo}, done) - } - }) - }) - } - }) + return { + name: 'nodezoo-github' } +} - function cmd_query (args, done) { - var github_ent = seneca.make$('github') - var github_name = args.name - var user = args.user - var repo = args.repo - - github.authenticate({ - type: 'basic', - username: opts.token, - password: 'x-oauth-basic' - }) - - github.repos.get({user: user, repo: repo}, function (err,repo) { - if (err) { - return done(err) - } - var data - - if (repo) { - data = { - name: args.repo, - user: args.user, - repo: args.repo, - stars: repo.stargazers_count, - watches: repo.subscribers_count, - forks: repo.forks_count, - last: repo.pushed_at, - url: gitUrl, - gitClone: repo.clone_url +function cmd_get (args, done) { + var seneca = this + + var github_name = args.name + var github_ent = seneca.make$('github') + + var url = opts.registry + github_name + // check if in the cache + github_ent.load$(github_name, function (err, github) { + if (err){ + return done(err) + } + if (github && !args.update) { + return done(null, github) + } + else { + // get giturl from npm + Request.get(url, function (err, res, body) { + if (err) { + return done(err) + } + else if (_.isEmpty(JSON.parse(body))) { + return done(err) } - // update the data if module exists in cache, if not create it - github_ent.load$(github_name, function(err,github){ + var data = JSON.parse(body) + // take giturl from npm data + seneca.act('role:github,cmd:extract', {data: data}, function (err, data) { if (err) { - return done(err); + return done(err) + } + // parse username and repo from giturl + var gitData = cmd_parse(data) + + if (gitData){ + var user = gitData[1] + var repo = gitData[2] + gitUrl = 'http://github.com/' + user + '/' + repo } - if (github) { - return github.data$(data).save$(done); + if (!user) { + return done(err) } else { - data.id$ = github_name - github_ent.make$(data).save$(done) - /* DEAN!!!!!!!!!!!!! - This is where were are doing the override command but without the override - possible issue here with it not having the object saved before - the insert is called, not sure yet. - */ - seneca.act('role:search,cmd:insert',{data:data}) + // get github data using github username and repo name + seneca.act('role:github,cmd:query', {name: github_name, user: user, repo: repo}, done) } }) + }) + } + }) +} - } - else return done() - }) - } +function cmd_query (args, done) { + var seneca = this - function cmd_extract (args, done) { - var data = args.data - var dist_tags = data['dist-tags'] || {} - var latest = ((data.versions || {})[dist_tags.latest]) || {} - var repository = latest.repository || {} + var github_ent = seneca.make$('github') + var github_name = args.name + var user = args.user + var repo = args.repo - var out = { - giturl: repository.url + github.authenticate({ + type: 'basic', + username: opts.token, + password: 'x-oauth-basic' + }) + + github.repos.get({user: user, repo: repo}, function (err,repo) { + if (err) { + return done(err) } + var data + + if (repo) { + data = { + name: args.repo, + user: args.user, + repo: args.repo, + stars: repo.stargazers_count, + watches: repo.subscribers_count, + forks: repo.forks_count, + last: repo.pushed_at, + url: gitUrl, + gitClone: repo.clone_url + } + // update the data if module exists in cache, if not create it + github_ent.load$(github_name, function(err,github){ + if (err) { + return done(err); + } + if (github) { + return github.data$(data).save$(done); + } + else { + data.id$ = github_name + github_ent.make$(data).save$(done) + } + }) - done(null, out) + } + else return done() + }) +} + +function cmd_extract (args, done) { + var data = args.data + var dist_tags = data['dist-tags'] || {} + var latest = ((data.versions || {})[dist_tags.latest]) || {} + var repository = latest.repository || {} + + var out = { + giturl: repository.url } - function cmd_parse (args) { - var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) - if (m) { - return (m) - } - else { - return null - } + done(null, out) +} + +function cmd_parse (args) { + var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) + if (m) { + return (m) + } + else { + return null } } diff --git a/package.json b/package.json index d4c8050..9a98410 100644 --- a/package.json +++ b/package.json @@ -30,13 +30,8 @@ }, "license": "MIT", "dependencies": { - "code": "2.1.0", "eraro": "0.4.1", - "eslint-config-seneca": "1.1.2", - "eslint-plugin-hapi": "4.0.0", - "eslint-plugin-standard": "1.3.1", "github": "0.2.2", - "lab": "8.2.0", "lodash": "4.6.1", "request": "2.69.0", "seneca": "2.0.0", @@ -47,5 +42,12 @@ "toolbag": "2.0.0", "toolbag-plugin-stats-collector": "1.0.0", "toolbag-plugin-udp-reporter": "1.0.0" + }, + "devDependencies": { + "code": "2.1.0", + "eslint-config-seneca": "1.1.2", + "eslint-plugin-hapi": "4.0.0", + "eslint-plugin-standard": "1.3.1", + "lab": "8.2.0" } } From 445485e16a774d48b9f6d2aa31fde04e9e434a04 Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Mon, 4 Apr 2016 14:28:15 +0100 Subject: [PATCH 051/117] Changed name of start file, updated name in package --- package.json | 2 +- srv/{github-dev.js => start.js} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename srv/{github-dev.js => start.js} (100%) diff --git a/package.json b/package.json index 9a98410..d5bb565 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "5.0.0", "description": "nodezoo.com micro-service handling github meta data", "scripts": { - "start": "node srv/github-dev.js" + "start": "node srv/start.js" }, "main": "github.js", "keywords": [ diff --git a/srv/github-dev.js b/srv/start.js similarity index 100% rename from srv/github-dev.js rename to srv/start.js From 8ff7e569c0dd352bc5b3242c065ae86e09ae139f Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Mon, 4 Apr 2016 15:34:44 +0100 Subject: [PATCH 052/117] Readme update --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index b462719..8cf3172 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,12 @@ Nodezoo.com micro-service handling github meta data. Please see the [main repo][] for more details +If you're using this microservice, and need help, you can: + +- Post a [github issue][], +- Tweet to [@nodezoo][], +- Ask on the [Gitter][gitter-url]. + ## Install 1. clone this repo into a root _/nodezoo_ folder. 2. run `npm install` @@ -60,3 +66,6 @@ Licensed under [MIT][]. [nearForm]: http://www.nearform.com/ [NodeZoo org]: http://www.nodezoo.com/ [Lead]: https://github.com/rjrodger +[github issue]: https://github.com/nodezoo/nodezoo-github/issues +[@nodezoo]: http://twitter.com/nodezoo +[gitter-url]: https://gitter.im/nodezoo/nodezoo-org From 7a78733988f78aa4c681912e4df6ce24209d577b Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Mon, 4 Apr 2016 16:00:31 +0100 Subject: [PATCH 053/117] Added link to nodezoo-system --- README.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8cf3172..2e891da 100644 --- a/README.md +++ b/README.md @@ -13,15 +13,12 @@ If you're using this microservice, and need help, you can: - Tweet to [@nodezoo][], - Ask on the [Gitter][gitter-url]. -## Install -1. clone this repo into a root _/nodezoo_ folder. -2. run `npm install` +## Running +This micro-service can be ran as part of the [NodeZoo org][] system. Please follow the +link below for details on obtaining and running the complete system. -## Starting +- [Nodezoo: The complete system][System] -```sh -$ node srvs/github-dev.js --seneca.options.github.token=GITHUB-PERSONAL-ACCESS-TOKEN --seneca.log.all -``` ## Creating a GitHub Personal Access Token - In the top right corner of any page, click your profile photo, then click Settings. @@ -69,3 +66,4 @@ Licensed under [MIT][]. [github issue]: https://github.com/nodezoo/nodezoo-github/issues [@nodezoo]: http://twitter.com/nodezoo [gitter-url]: https://gitter.im/nodezoo/nodezoo-org +[System]: https://github.com/nodezoo/nodezoo-system From 9d05d7a5fd8966111bd87aa8228103ac14a9df0d Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Mon, 4 Apr 2016 17:29:37 +0100 Subject: [PATCH 054/117] Update --- README.md | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 2e891da..3b93162 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Nodezoo](https://github.com/nodezoo/nodezoo-org/blob/master/assets/logo-nodezoo.png) +![Nodezoo](https://raw.githubusercontent.com/nodezoo/nodezoo-org/master/assets/logo-nodezoo.png) ## nodezoo-github @@ -29,21 +29,16 @@ link below for details on obtaining and running the complete system. - Click Generate token. - Copy the token to your clipboard. For security reasons, after you navigate off this page, no one will be able to see the token again. -## Messages - -This micro-service recognizes the following messages: - - * _role:github,cmd:get_ - * _role:github,cmd:query_ - * _role:github,cmd:parse_ - * _role:github,cmd:extract_ +## Patterns Handled +### `role:github,cmd:get` +Request module name and description +```js +seneca.act('role:github, req:get', {name: 'seneca'}) +``` -## Running with Curl +## Patterns Emitted -Any of the messages above can be run using curl in the following format in the command line -``` -curl -d '{"role":"github","cmd":"get"}' http://localhost:52472/act -``` +There are no outgoing messages. ## Contributing The [NodeZoo org][] encourages __open__ and __safe__ participation. From 9bd4b34415d6d1f0147e290a29f6a471fe6bf11d Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Mon, 4 Apr 2016 17:36:05 +0100 Subject: [PATCH 055/117] fix --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3b93162..99f8466 100644 --- a/README.md +++ b/README.md @@ -31,9 +31,9 @@ link below for details on obtaining and running the complete system. ## Patterns Handled ### `role:github,cmd:get` -Request module name and description +Request module details by name ```js -seneca.act('role:github, req:get', {name: 'seneca'}) +seneca.act('role:github, cmd:get', {name: 'seneca'}) ``` ## Patterns Emitted From 1b98570efe0d142b16c8cb9630cac0876b509018 Mon Sep 17 00:00:00 2001 From: Gege Pincin Date: Tue, 5 Apr 2016 02:58:07 -0400 Subject: [PATCH 056/117] Update Dockerfile to use start.js --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 7b05963..b52e813 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,4 +11,4 @@ RUN npm install COPY . /src -CMD ["node", "-r", "toolbag", "srv/github-dev.js", "--seneca.options.tag=nodezoo-github", "--seneca-log=type:act"] +CMD ["node", "-r", "toolbag", "srv/start.js", "--seneca.options.tag=nodezoo-github", "--seneca-log=type:act"] From 64f4bf3e801815838b778fae7f57776b773479fc Mon Sep 17 00:00:00 2001 From: Adrian Rossouw Date: Tue, 5 Apr 2016 11:09:49 +0200 Subject: [PATCH 057/117] less generic token. fixes #3 --- README.md | 3 +++ srv/start.js | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 99f8466..f70d6e7 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,9 @@ link below for details on obtaining and running the complete system. - [Nodezoo: The complete system][System] +## Configuration +Set the `$GITHUB_TOKEN` environment variable with a GitHub Access Token. + ## Creating a GitHub Personal Access Token - In the top right corner of any page, click your profile photo, then click Settings. diff --git a/srv/start.js b/srv/start.js index e3a799c..b239a44 100644 --- a/srv/start.js +++ b/srv/start.js @@ -3,11 +3,11 @@ // your github token can be stored in an env variable named token, // and will be picked up here -var TOKEN = process.env.TOKEN || '' +var GITHUB_TOKEN = process.env.GITHUB_TOKEN || '' require('seneca')() .use('entity') -.use('../github.js', {token: TOKEN}) +.use('../github.js', {token: GITHUB_TOKEN}) .add('role:info,req:part', function (args, done) { done() From 70e7e70035dbb9479725daf5903b8806104e2b9c Mon Sep 17 00:00:00 2001 From: Adrian Rossouw Date: Tue, 5 Apr 2016 13:33:53 +0200 Subject: [PATCH 058/117] enable gzip in request --- github.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/github.js b/github.js index 5d74864..67e0206 100644 --- a/github.js +++ b/github.js @@ -44,7 +44,7 @@ function cmd_get (args, done) { } else { // get giturl from npm - Request.get(url, function (err, res, body) { + Request.get({url: url, gzip: true}, function (err, res, body) { if (err) { return done(err) } From 5908a8ea30c8c476f7cce50d9d318a5699e6bb0a Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Tue, 5 Apr 2016 15:57:14 +0100 Subject: [PATCH 059/117] Linted --- github.js | 13 ++++++------- srv/start.js | 6 +++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/github.js b/github.js index 67e0206..9895369 100644 --- a/github.js +++ b/github.js @@ -36,7 +36,7 @@ function cmd_get (args, done) { var url = opts.registry + github_name // check if in the cache github_ent.load$(github_name, function (err, github) { - if (err){ + if (err) { return done(err) } if (github && !args.update) { @@ -60,7 +60,7 @@ function cmd_get (args, done) { // parse username and repo from giturl var gitData = cmd_parse(data) - if (gitData){ + if (gitData) { var user = gitData[1] var repo = gitData[2] gitUrl = 'http://github.com/' + user + '/' + repo @@ -92,7 +92,7 @@ function cmd_query (args, done) { password: 'x-oauth-basic' }) - github.repos.get({user: user, repo: repo}, function (err,repo) { + github.repos.get({user: user, repo: repo}, function (err, repo) { if (err) { return done(err) } @@ -111,19 +111,18 @@ function cmd_query (args, done) { gitClone: repo.clone_url } // update the data if module exists in cache, if not create it - github_ent.load$(github_name, function(err,github){ + github_ent.load$(github_name, function (err, github) { if (err) { - return done(err); + return done(err) } if (github) { - return github.data$(data).save$(done); + return github.data$(data).save$(done) } else { data.id$ = github_name github_ent.make$(data).save$(done) } }) - } else return done() }) diff --git a/srv/start.js b/srv/start.js index b239a44..03f1165 100644 --- a/srv/start.js +++ b/srv/start.js @@ -13,15 +13,15 @@ require('seneca')() this.act('role:github,cmd:get', {name: args.name}, function (err, mod) { if (err) { - return done(err); + return done(err) } this.act('role:info,res:part,part:github', {name: args.name, data: mod.data$()}) }) }) -.add('role:github,info:change', function (args,done) { +.add('role:github,info:change', function (args, done) { done() - this.act('role:info,cmd:get', {name:args.name,update:true}) + this.act('role:info,cmd:get', {name: args.name, update: true}) }) .use('mesh', { auto: true, From fabaff7f584350d0897879d41d6ea02bd5bd4ca9 Mon Sep 17 00:00:00 2001 From: Adrian Rossouw Date: Wed, 6 Apr 2016 16:07:33 +0200 Subject: [PATCH 060/117] 6.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d5bb565..32e2651 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nodezoo-github", - "version": "5.0.0", + "version": "6.0.0", "description": "nodezoo.com micro-service handling github meta data", "scripts": { "start": "node srv/start.js" From a72d0a9110b1da96bbe5edac18ca887fad9a5bbc Mon Sep 17 00:00:00 2001 From: Jane Quinn Date: Wed, 6 Apr 2016 15:52:51 +0100 Subject: [PATCH 061/117] added pull requests to data object --- github.js | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/github.js b/github.js index 9895369..c20583d 100644 --- a/github.js +++ b/github.js @@ -97,18 +97,27 @@ function cmd_query (args, done) { return done(err) } var data - if (repo) { + var pullRequests = [] + github.pullRequests.getAll({user: user, repo: github_name, state: 'open'}, function (err, response) { + if (err) { + console.log(err) + } + if (response) { + pullRequests = response + } + }) data = { - name: args.repo, - user: args.user, - repo: args.repo, - stars: repo.stargazers_count, - watches: repo.subscribers_count, - forks: repo.forks_count, - last: repo.pushed_at, - url: gitUrl, - gitClone: repo.clone_url + name: args.repo || '', + user: args.user || '', + repo: args.repo || '', + stars: repo.stargazers_count || '', + watches: repo.subscribers_count || '', + forks: repo.forks_count || '', + last: repo.pushed_at || '', + url: gitUrl || '', + gitClone: repo.clone_url || '', + pullRequests: pullRequests.length || '' } // update the data if module exists in cache, if not create it github_ent.load$(github_name, function (err, github) { From b0ac5bb61434dc857934e6eec115341ec133d7a9 Mon Sep 17 00:00:00 2001 From: Jane Quinn Date: Wed, 6 Apr 2016 16:26:54 +0100 Subject: [PATCH 062/117] changed abandoned github module to active one --- github.js | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/github.js b/github.js index c20583d..c085f1c 100644 --- a/github.js +++ b/github.js @@ -1,7 +1,7 @@ 'use strict' -var GitHub = require('github') -var github = new GitHub({version: '3.0.0'}) +var GitHub = require('github4') +var github = new GitHub() var Request = require('request') var _ = require('lodash') var gitUrl diff --git a/package.json b/package.json index 32e2651..047e9b3 100644 --- a/package.json +++ b/package.json @@ -31,7 +31,7 @@ "license": "MIT", "dependencies": { "eraro": "0.4.1", - "github": "0.2.2", + "github4": "0.5.4", "lodash": "4.6.1", "request": "2.69.0", "seneca": "2.0.0", From 0b6faed800b866e41108b0225081c9ae2dc2295d Mon Sep 17 00:00:00 2001 From: Jane Quinn Date: Wed, 6 Apr 2016 16:47:08 +0100 Subject: [PATCH 063/117] renamed variables to cammelCase --- github.js | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/github.js b/github.js index c085f1c..e6906fb 100644 --- a/github.js +++ b/github.js @@ -17,25 +17,25 @@ module.exports = function (options) { opts = extend(opts, options) - seneca.add('role:github,cmd:get', cmd_get) - seneca.add('role:github,cmd:query', cmd_query) - seneca.add('role:github,cmd:parse', cmd_parse) - seneca.add('role:github,cmd:extract', cmd_extract) + seneca.add('role:github,cmd:get', cmdGet) + seneca.add('role:github,cmd:query', cmdQuery) + seneca.add('role:github,cmd:parse', cmdParse) + seneca.add('role:github,cmd:extract', cmdExtract) return { name: 'nodezoo-github' } } -function cmd_get (args, done) { +function cmdGet (args, done) { var seneca = this - var github_name = args.name - var github_ent = seneca.make$('github') + var githubName = args.name + var githubEnt = seneca.make$('github') - var url = opts.registry + github_name + var url = opts.registry + githubName // check if in the cache - github_ent.load$(github_name, function (err, github) { + githubEnt.load$(githubName, function (err, github) { if (err) { return done(err) } @@ -58,7 +58,7 @@ function cmd_get (args, done) { return done(err) } // parse username and repo from giturl - var gitData = cmd_parse(data) + var gitData = cmdParse(data) if (gitData) { var user = gitData[1] @@ -70,7 +70,7 @@ function cmd_get (args, done) { } else { // get github data using github username and repo name - seneca.act('role:github,cmd:query', {name: github_name, user: user, repo: repo}, done) + seneca.act('role:github,cmd:query', {name: githubName, user: user, repo: repo}, done) } }) }) @@ -78,11 +78,11 @@ function cmd_get (args, done) { }) } -function cmd_query (args, done) { +function cmdQuery (args, done) { var seneca = this - var github_ent = seneca.make$('github') - var github_name = args.name + var githubEnt = seneca.make$('github') + var githubName = args.name var user = args.user var repo = args.repo @@ -99,7 +99,7 @@ function cmd_query (args, done) { var data if (repo) { var pullRequests = [] - github.pullRequests.getAll({user: user, repo: github_name, state: 'open'}, function (err, response) { + github.pullRequests.getAll({user: user, repo: githubName, state: 'open'}, function (err, response) { if (err) { console.log(err) } @@ -120,7 +120,7 @@ function cmd_query (args, done) { pullRequests: pullRequests.length || '' } // update the data if module exists in cache, if not create it - github_ent.load$(github_name, function (err, github) { + githubEnt.load$(githubName, function (err, github) { if (err) { return done(err) } @@ -128,8 +128,8 @@ function cmd_query (args, done) { return github.data$(data).save$(done) } else { - data.id$ = github_name - github_ent.make$(data).save$(done) + data.id$ = githubName + githubEnt.make$(data).save$(done) } }) } @@ -137,10 +137,10 @@ function cmd_query (args, done) { }) } -function cmd_extract (args, done) { +function cmdExtract (args, done) { var data = args.data - var dist_tags = data['dist-tags'] || {} - var latest = ((data.versions || {})[dist_tags.latest]) || {} + var distTags = data['dist-tags'] || {} + var latest = ((data.versions || {})[distTags.latest]) || {} var repository = latest.repository || {} var out = { @@ -150,7 +150,7 @@ function cmd_extract (args, done) { done(null, out) } -function cmd_parse (args) { +function cmdParse (args) { var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) if (m) { return (m) From 32ea843177310664dc446c4ecc4a6540eb988935 Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Wed, 6 Apr 2016 22:28:41 +0100 Subject: [PATCH 064/117] Delete seneca.txt --- data/seneca.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 data/seneca.txt diff --git a/data/seneca.txt b/data/seneca.txt deleted file mode 100644 index 1af4c3f..0000000 --- a/data/seneca.txt +++ /dev/null @@ -1 +0,0 @@ -This is a jsonfile-store folder. \ No newline at end of file From f360f863f46d71d4f7c79be97176afb9d0cdb0e3 Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Wed, 6 Apr 2016 22:38:42 +0100 Subject: [PATCH 065/117] removed build.sh --- build.sh | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 build.sh diff --git a/build.sh b/build.sh deleted file mode 100644 index 1ccc34d..0000000 --- a/build.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh -npm install -echo TARGET:. From 1125b46bbc5990ba8d152aef35ff8e2426011b93 Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Wed, 6 Apr 2016 22:39:25 +0100 Subject: [PATCH 066/117] See notes, - added changelog - moved logic file to lib --- CHANGELOG.md | 10 ++++++++++ github.js => lib/github.js | 0 package.json | 2 +- 3 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 CHANGELOG.md rename github.js => lib/github.js (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c987a60 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +Pending - x.x.x +--- +* Added CHANGELOG.md +* Removed redundant data folder +* Removed unneeded build.sh +* Moved logic script into lib + +6 April 2016 - 6.0.0 +--- +* First release of the 6th major revision of nodezoo. diff --git a/github.js b/lib/github.js similarity index 100% rename from github.js rename to lib/github.js diff --git a/package.json b/package.json index 047e9b3..8cf6f4a 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "scripts": { "start": "node srv/start.js" }, - "main": "github.js", + "main": "lib/github.js", "keywords": [ "nodezoo", "seneca", From a8f6bdddfae551e364c4ff0aed869c63a286e85f Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Wed, 6 Apr 2016 23:10:45 +0100 Subject: [PATCH 067/117] refactor start.js for clarity --- lib/github.js | 12 ++++++++++++ srv/start.js | 50 ++++++++++++++++++++++++-------------------------- 2 files changed, 36 insertions(+), 26 deletions(-) diff --git a/lib/github.js b/lib/github.js index e6906fb..4eb2c5b 100644 --- a/lib/github.js +++ b/lib/github.js @@ -22,6 +22,18 @@ module.exports = function (options) { seneca.add('role:github,cmd:parse', cmdParse) seneca.add('role:github,cmd:extract', cmdExtract) + seneca.add('role:info,req:part', function (args, done) { + console.log('foo') + done() + + this.act('role:github,cmd:get', {name: args.name}, function (err, mod) { + if (err) { + return done(err) + } + this.act('role:info,res:part,part:github', {name: args.name, data: mod.data$()}) + }) + }) + return { name: 'nodezoo-github' } diff --git a/srv/start.js b/srv/start.js index 03f1165..e188271 100644 --- a/srv/start.js +++ b/srv/start.js @@ -1,30 +1,28 @@ 'use strict' -// your github token can be stored in an env variable named token, -// and will be picked up here +var Seneca = require('seneca') +var Entities = require('seneca-entity') +var Mesh = require('seneca-mesh') +var Github = require('../lib/github') -var GITHUB_TOKEN = process.env.GITHUB_TOKEN || '' +var envs = process.env +var opts = { + seneca: { + tag: envs.GITHUB_TAG || 'nodezoo-github' + }, + github: { + token: envs.GITHUB_TOKEN || '' + }, + mesh: { + auto: true, + listen: [ + {pin: 'role:github,cmd:get', model: 'consume'}, + {pin: 'role:info,req:part', model: 'observe'} + ] + } +} -require('seneca')() -.use('entity') -.use('../github.js', {token: GITHUB_TOKEN}) -.add('role:info,req:part', function (args, done) { - done() - - this.act('role:github,cmd:get', {name: args.name}, function (err, mod) { - if (err) { - return done(err) - } - this.act('role:info,res:part,part:github', {name: args.name, data: mod.data$()}) - }) -}) - -.add('role:github,info:change', function (args, done) { - done() - this.act('role:info,cmd:get', {name: args.name, update: true}) -}) -.use('mesh', { - auto: true, - pin: ['role:github', 'role:info,req:part'], - model: 'publish' -}) +Seneca(opts.seneca) + .use(Entities) + .use(Github, opts.github) + .use(Mesh, opts.mesh) From 1195a4ef7d94a6331525d52853960563c151b683 Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Thu, 7 Apr 2016 00:49:18 +0100 Subject: [PATCH 068/117] See notes, added isolation mode for easier testing, further tidy to start, began tidy of github.js Updates to changelog --- CHANGELOG.md | 7 ++-- lib/github.js | 111 ++++++++++++++++++++++++++------------------------ package.json | 3 +- srv/start.js | 12 +++++- 4 files changed, 74 insertions(+), 59 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c987a60..5a07b7e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,10 @@ Pending - x.x.x --- * Added CHANGELOG.md -* Removed redundant data folder -* Removed unneeded build.sh -* Moved logic script into lib +* Removed redundant data folder. +* Removed unneeded build.sh. +* Moved logic script into lib. +* Refactored start.js and github.js for clarity. 6 April 2016 - 6.0.0 --- diff --git a/lib/github.js b/lib/github.js index 4eb2c5b..d959780 100644 --- a/lib/github.js +++ b/lib/github.js @@ -8,7 +8,7 @@ var gitUrl var opts = { registry: 'http://registry.npmjs.org/', - token: '' + token: 'NO_TOKEN' } module.exports = function (options) { @@ -21,33 +21,34 @@ module.exports = function (options) { seneca.add('role:github,cmd:query', cmdQuery) seneca.add('role:github,cmd:parse', cmdParse) seneca.add('role:github,cmd:extract', cmdExtract) - - seneca.add('role:info,req:part', function (args, done) { - console.log('foo') - done() - - this.act('role:github,cmd:get', {name: args.name}, function (err, mod) { - if (err) { - return done(err) - } - this.act('role:info,res:part,part:github', {name: args.name, data: mod.data$()}) - }) - }) + seneca.add('role:info,req:part', aliasGet) return { name: 'nodezoo-github' } } +function aliasGet (msg, done) { + var seneca = this + var payload = {name: msg.name} + + seneca.act('role:github,cmd:get', payload, (err, data) => { + if (err) return done(err) + + payload.data = data + seneca.act('role:info,res:part,part:github', payload) + done() + }) +} + function cmdGet (args, done) { var seneca = this + var cache = seneca.make$('github') var githubName = args.name - var githubEnt = seneca.make$('github') - var url = opts.registry + githubName - // check if in the cache - githubEnt.load$(githubName, function (err, github) { + + cache.load$(githubName, function (err, github) { if (err) { return done(err) } @@ -93,33 +94,37 @@ function cmdGet (args, done) { function cmdQuery (args, done) { var seneca = this - var githubEnt = seneca.make$('github') + var cache = seneca.make$('github') var githubName = args.name var user = args.user var repo = args.repo github.authenticate({ - type: 'basic', - username: opts.token, - password: 'x-oauth-basic' + type: 'token', + token: opts.token }) - github.repos.get({user: user, repo: repo}, function (err, repo) { - if (err) { - return done(err) - } + var getRepos = { + user: user, + repo: repo + } + + github.repos.get(getRepos, (err, repo) => { + if (err) return done(err) + if (!repo) return done() + var data - if (repo) { - var pullRequests = [] - github.pullRequests.getAll({user: user, repo: githubName, state: 'open'}, function (err, response) { - if (err) { - console.log(err) - } - if (response) { - pullRequests = response - } - }) - data = { + var pullRequests = [] + var getPullRequests = { + user: user, + repo: githubName, + state: 'open' + } + + github.pullRequests.getAll(getPullRequests, (err, prs) => { + if (err) console.log(err) + + var data = { name: args.repo || '', user: args.user || '', repo: args.repo || '', @@ -127,25 +132,25 @@ function cmdQuery (args, done) { watches: repo.subscribers_count || '', forks: repo.forks_count || '', last: repo.pushed_at || '', - url: gitUrl || '', - gitClone: repo.clone_url || '', - pullRequests: pullRequests.length || '' + urlRepo: gitUrl || '', + urlClone: repo.clone_url || '', + pullRequests: prs && prs.length || 0, + cached: Date.now() } - // update the data if module exists in cache, if not create it - githubEnt.load$(githubName, function (err, github) { - if (err) { - return done(err) - } - if (github) { - return github.data$(data).save$(done) - } - else { - data.id$ = githubName - githubEnt.make$(data).save$(done) - } + + function complete (err) { + if (err) return done (err) + else done (null, data) + } + + cache.load$(githubName, function (err, github) { + if (err) return done(err) + if (github) return github.data$(data).save$(complete) + + data.id$ = githubName + cache.make$(data).save$(complete) }) - } - else return done() + }) }) } diff --git a/package.json b/package.json index 8cf6f4a..ec61165 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,8 @@ "version": "6.0.0", "description": "nodezoo.com micro-service handling github meta data", "scripts": { - "start": "node srv/start.js" + "start": "node srv/start.js", + "isolated": "GITHUB_ISOLATED=true node srv/start.js" }, "main": "lib/github.js", "keywords": [ diff --git a/srv/start.js b/srv/start.js index e188271..293a9af 100644 --- a/srv/start.js +++ b/srv/start.js @@ -11,7 +11,7 @@ var opts = { tag: envs.GITHUB_TAG || 'nodezoo-github' }, github: { - token: envs.GITHUB_TOKEN || '' + token: envs.GITHUB_TOKEN || '668fd718441b4d97699763b9d97f402c8370d331' }, mesh: { auto: true, @@ -19,10 +19,18 @@ var opts = { {pin: 'role:github,cmd:get', model: 'consume'}, {pin: 'role:info,req:part', model: 'observe'} ] + }, + isolated: { + host: envs.GITHUB_HOST || 'localhost', + port: envs.GITHUB_PORT || '8052' } } +var Service = Seneca(opts.seneca) .use(Entities) .use(Github, opts.github) - .use(Mesh, opts.mesh) + +envs.GITHUB_ISOLATED + ? Service.listen(opts.isolated) + : Service.use(Mesh, opts.mesh) From aab558c3643fb1f2324fdad5dc46a72da6a05929 Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Thu, 7 Apr 2016 16:12:27 +0100 Subject: [PATCH 069/117] See changelog --- CHANGELOG.md | 5 +- README.md | 113 +++++++++++++++++++++++++++++------- lib/github.js | 155 ++++++++++++++++---------------------------------- package.json | 8 +-- srv/start.js | 5 +- 5 files changed, 152 insertions(+), 134 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a07b7e..c4fcd30 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,13 @@ -Pending - x.x.x +7 April 2016 - 6.1.0 --- * Added CHANGELOG.md * Removed redundant data folder. * Removed unneeded build.sh. * Moved logic script into lib. * Refactored start.js and github.js for clarity. +* Removed unneeded seneca actions +* Added isolation mode +* Updated docs to reflect changes 6 April 2016 - 6.0.0 --- diff --git a/README.md b/README.md index f70d6e7..407d2dd 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,116 @@ -![Nodezoo](https://raw.githubusercontent.com/nodezoo/nodezoo-org/master/assets/logo-nodezoo.png) +![Nodezoo][Logo] -## nodezoo-github +# nodezoo-github -- __Lead:__ [Richard Rodger][Lead] -- __Sponsor:__ [nearForm][] +- __Lead:__ [Dean McDonnell][Lead] +- __Sponsor:__ [nearForm][Sponsor] -Nodezoo.com micro-service handling github meta data. Please see the [main repo][] for more details +A micro-service that provides Github related information to [NodeZoo][]. This +micro-service requires a valid Github token to function, please see the Config +section below for details on how to obtain. -If you're using this microservice, and need help, you can: +If you're using this micro-service, and need help, you can: - Post a [github issue][], - Tweet to [@nodezoo][], - Ask on the [Gitter][gitter-url]. ## Running -This micro-service can be ran as part of the [NodeZoo org][] system. Please follow the -link below for details on obtaining and running the complete system. +This micro-service can be ran as part of a complete system or as a single isolated +unit. + +### As a complete system +A special system repository is available that runs the complete system using Docker +and Fuge. - [Nodezoo: The complete system][System] +### Isolated mode +To make testing easier this micro-service can be ran in 'isolated' mode. This mode +allows testing over http using a well defined port. Please note isolated mode means +patterns are not exposed via mesh. + +To run in isolated mode, + + - Clone this repository locally, + - Run `npm install`, + - Run `GITHUB_TOKEN=YOUR_TOKEN npm start isolated`, + +__Note:__ You will need to have a valid github token to use isolated mode. + +A simple http service is supported and can be called using Curl or other Rest client. +The default port is `8052`. It can be changed using the `GITHUB_PORT` environment +variable. + +``` +curl -d '{"role":"github","cmd":"get","name":"hapi"}' http://localhost:8052/act +``` + ## Configuration -Set the `$GITHUB_TOKEN` environment variable with a GitHub Access Token. -## Creating a GitHub Personal Access Token +### Creating a GitHub Personal Access Token +You will need a token for this service if regardless of how you choose to run it. - - In the top right corner of any page, click your profile photo, then click Settings. + - On github.com, click your profile photo, then click settings. - In the user settings sidebar, click Personal access tokens. - Click Generate new token - Give your token a descriptive name. - - Select the scopes you wish to grant to this token. The default scopes allow you to interact with public and private repositories, user data, and gists - - Click Generate token. - - Copy the token to your clipboard. For security reasons, after you navigate off this page, no one will be able to see the token again. + - Select the scopes you wish to grant, select all read-only scopes + - Click 'Generate token'. + - Copy the token to your clipboard and keep safe. + +### Environment Variables +Various settings can be changed using environment variables, see the list below for +all available variable names. + +#### GITHUB_TOKEN + - The token to use when calling the GitHub api. + - Defaults to `NO_TOKEN`, + +#### GITHUB_HOST + - The host to listen on in isolated mode. + - Defaults to `localhost` + +#### GITHUB_PORT + - The port to listen on in isolated mode. + - Defaults to `8052` . + +#### GITHUB_ISOLATED + - Starts isolated mode. + - Defaults to `false`. + +#### GITHUB_REGISTRY + - Change the registry used to validate the module name. + - Defaults to `http://registry.npmjs.org/`. + +## Messages Handled +This micro-service handles the following messages. -## Patterns Handled ### `role:github,cmd:get` -Request module details by name +Request a module's Github details. The name supplied must be a valid module on npm. + +```js +seneca.act('role:github,cmd:get', {name: 'seneca'}, (err, data) => {}) +``` + +### `role:info,req:part` +Acts as an alias for `role:github,cmd:get` but instead of returning data directly a +message is emitted using the pattern `role:info,res:part`. Allows integration with +the wider nodezoo system. + ```js -seneca.act('role:github, cmd:get', {name: 'seneca'}) +seneca.act('role:info, req:part', {name: 'seneca'}, (err, data) => {}) ``` -## Patterns Emitted +## Messages Emitted +This micro-service emits the following messages -There are no outgoing messages. +### `role:info,res:part` +Contains the response of an earlier call to `role:info,req:part`. + +```js +seneca.add('role:info,res:part', (msg, done) => {}) +``` ## Contributing The [NodeZoo org][] encourages __open__ and __safe__ participation. @@ -58,10 +127,12 @@ Licensed under [MIT][]. [main repo]: https://github.com/rjrodger/nodezoo [MIT]: ./LICENSE [Code of Conduct]: https://github.com/nodezoo/nodezoo-org/blob/master/CoC.md -[nearForm]: http://www.nearform.com/ +[Sponsor]: http://www.nearform.com/ [NodeZoo org]: http://www.nodezoo.com/ -[Lead]: https://github.com/rjrodger +[NodeZoo]: https://github.com/nodezoo +[Lead]: https://github.com/mcdonnelldean [github issue]: https://github.com/nodezoo/nodezoo-github/issues [@nodezoo]: http://twitter.com/nodezoo [gitter-url]: https://gitter.im/nodezoo/nodezoo-org [System]: https://github.com/nodezoo/nodezoo-system +[Logo]: https://raw.githubusercontent.com/nodezoo/nodezoo-org/master/assets/logo-nodezoo.png diff --git a/lib/github.js b/lib/github.js index d959780..b2271a8 100644 --- a/lib/github.js +++ b/lib/github.js @@ -3,8 +3,6 @@ var GitHub = require('github4') var github = new GitHub() var Request = require('request') -var _ = require('lodash') -var gitUrl var opts = { registry: 'http://registry.npmjs.org/', @@ -16,11 +14,9 @@ module.exports = function (options) { var extend = seneca.util.deepextend opts = extend(opts, options) + opts.cache = seneca.make$('github') seneca.add('role:github,cmd:get', cmdGet) - seneca.add('role:github,cmd:query', cmdQuery) - seneca.add('role:github,cmd:parse', cmdParse) - seneca.add('role:github,cmd:extract', cmdExtract) seneca.add('role:info,req:part', aliasGet) return { @@ -28,6 +24,39 @@ module.exports = function (options) { } } +function cmdGet (msg, done) { + var cache = opts.cache + var registry = opts.registry + msg.name + + cache.load$(msg.name, (err, github) => { + if (err) return done(err) + + if (github && !msg.update) { + return done(null, github) + } + + Request.get({url: registry, gzip: true}, (err, res, body) => { + if (err) return done(err) + + var data = JSON.parse(body) + var distTags = data['dist-tags'] || {} + var latest = ((data.versions || {})[distTags.latest]) || {} + var repository = latest.repository || {} + var url = repository.url || '' + + var matches = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(url) || [] + var params = { + name: msg.name, + url: url, + user: matches[1] || '', + repo: matches[2] || '' + } + + queryGithub(params, done) + }) + }) +} + function aliasGet (msg, done) { var seneca = this var payload = {name: msg.name} @@ -41,98 +70,35 @@ function aliasGet (msg, done) { }) } -function cmdGet (args, done) { - var seneca = this - var cache = seneca.make$('github') - - var githubName = args.name - var url = opts.registry + githubName - - cache.load$(githubName, function (err, github) { - if (err) { - return done(err) - } - if (github && !args.update) { - return done(null, github) - } - else { - // get giturl from npm - Request.get({url: url, gzip: true}, function (err, res, body) { - if (err) { - return done(err) - } - else if (_.isEmpty(JSON.parse(body))) { - return done(err) - } - var data = JSON.parse(body) - // take giturl from npm data - seneca.act('role:github,cmd:extract', {data: data}, function (err, data) { - if (err) { - return done(err) - } - // parse username and repo from giturl - var gitData = cmdParse(data) - - if (gitData) { - var user = gitData[1] - var repo = gitData[2] - gitUrl = 'http://github.com/' + user + '/' + repo - } - if (!user) { - return done(err) - } - else { - // get github data using github username and repo name - seneca.act('role:github,cmd:query', {name: githubName, user: user, repo: repo}, done) - } - }) - }) - } - }) -} - -function cmdQuery (args, done) { - var seneca = this - - var cache = seneca.make$('github') - var githubName = args.name - var user = args.user - var repo = args.repo +function queryGithub (msg, done) { + var cache = opts.cache github.authenticate({ type: 'token', token: opts.token }) - var getRepos = { - user: user, - repo: repo + var params = { + user: msg.user, + repo: msg.repo } - github.repos.get(getRepos, (err, repo) => { + github.repos.get(params, (err, repo) => { if (err) return done(err) if (!repo) return done() - var data - var pullRequests = [] - var getPullRequests = { - user: user, - repo: githubName, - state: 'open' - } - - github.pullRequests.getAll(getPullRequests, (err, prs) => { - if (err) console.log(err) + params.state = 'open' + github.pullRequests.getAll(params, (err, prs) => { var data = { - name: args.repo || '', - user: args.user || '', - repo: args.repo || '', + name: msg.repo || '', + user: msg.user || '', + repo: msg.repo || '', stars: repo.stargazers_count || '', watches: repo.subscribers_count || '', forks: repo.forks_count || '', last: repo.pushed_at || '', - urlRepo: gitUrl || '', + urlRepo: msg.url || '', urlClone: repo.clone_url || '', pullRequests: prs && prs.length || 0, cached: Date.now() @@ -143,36 +109,13 @@ function cmdQuery (args, done) { else done (null, data) } - cache.load$(githubName, function (err, github) { + cache.load$(msg.name, (err, cached) => { if (err) return done(err) - if (github) return github.data$(data).save$(complete) + if (cached) return cached.data$(data).save$(complete) - data.id$ = githubName + data.id$ = msg.name cache.make$(data).save$(complete) }) }) }) } - -function cmdExtract (args, done) { - var data = args.data - var distTags = data['dist-tags'] || {} - var latest = ((data.versions || {})[distTags.latest]) || {} - var repository = latest.repository || {} - - var out = { - giturl: repository.url - } - - done(null, out) -} - -function cmdParse (args) { - var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) - if (m) { - return (m) - } - else { - return null - } -} diff --git a/package.json b/package.json index ec61165..ce49b4b 100644 --- a/package.json +++ b/package.json @@ -13,11 +13,11 @@ "github", "microservice" ], - "author": "Richard Rodger (richard.rodger@nearform.com)", + "author": "Richard Rodger (github.com/rjrodger)", "contributors": [ "Jane Quinn (github.com/CodeWriterWriter)", - "Glen Keane (glenkeane.me)", - "Dean McDonnell (mcdonelldean.me)", + "Glen Keane (github.com/thekemkid)", + "Dean McDonnell (github.com/mcdonnelldean)", "Matthew O'Connor (github.com/matt-oc)", "Shane Lacey (github.com/shanel262)" ], @@ -31,9 +31,7 @@ }, "license": "MIT", "dependencies": { - "eraro": "0.4.1", "github4": "0.5.4", - "lodash": "4.6.1", "request": "2.69.0", "seneca": "2.0.0", "seneca-balance-client": "0.4.0", diff --git a/srv/start.js b/srv/start.js index 293a9af..912ec59 100644 --- a/srv/start.js +++ b/srv/start.js @@ -11,7 +11,8 @@ var opts = { tag: envs.GITHUB_TAG || 'nodezoo-github' }, github: { - token: envs.GITHUB_TOKEN || '668fd718441b4d97699763b9d97f402c8370d331' + token: envs.GITHUB_TOKEN || 'NO_TOKEN', + registry: envs.GITHUB_REGISTRY || 'http://registry.npmjs.org/' }, mesh: { auto: true, @@ -26,6 +27,8 @@ var opts = { } } +console.log(envs.GITHUB_TOKEN) + var Service = Seneca(opts.seneca) .use(Entities) From 05d171c069622f2e1549480d944866cca131771f Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Thu, 7 Apr 2016 16:20:04 +0100 Subject: [PATCH 070/117] v6.1.0 --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index ce49b4b..3aa0899 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nodezoo-github", - "version": "6.0.0", - "description": "nodezoo.com micro-service handling github meta data", + "version": "6.1.0", + "description": "A micro-service that provides Github related information to NodeZoo", "scripts": { "start": "node srv/start.js", "isolated": "GITHUB_ISOLATED=true node srv/start.js" From 164495a5758969c7bf57ea38e4ee7b67b9dbdaac Mon Sep 17 00:00:00 2001 From: Gege Pincin Date: Fri, 8 Apr 2016 02:05:22 -0400 Subject: [PATCH 071/117] bringing in redis store --- package.json | 1 + srv/start.js | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/package.json b/package.json index 3aa0899..51c4241 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "seneca-entity": "0.0.1", "seneca-level-store": "0.2.3", "seneca-mesh": "0.7.0", + "seneca-redis-store": "0.0.8", "toolbag": "2.0.0", "toolbag-plugin-stats-collector": "1.0.0", "toolbag-plugin-udp-reporter": "1.0.0" diff --git a/srv/start.js b/srv/start.js index 912ec59..2f0cf77 100644 --- a/srv/start.js +++ b/srv/start.js @@ -4,6 +4,7 @@ var Seneca = require('seneca') var Entities = require('seneca-entity') var Mesh = require('seneca-mesh') var Github = require('../lib/github') +var RedisStore = require('seneca-redis-store') var envs = process.env var opts = { @@ -24,6 +25,10 @@ var opts = { isolated: { host: envs.GITHUB_HOST || 'localhost', port: envs.GITHUB_PORT || '8052' + }, + redis: { + host: 'localhost', + port: envs.redis_PORT || '6379' } } @@ -32,6 +37,7 @@ console.log(envs.GITHUB_TOKEN) var Service = Seneca(opts.seneca) .use(Entities) + .use(RedisStore, opts.redis) .use(Github, opts.github) envs.GITHUB_ISOLATED From 8b4c65b6758ca0e0eefcafa4ac8ce7f0c4a86b6f Mon Sep 17 00:00:00 2001 From: Jane Quinn Date: Fri, 8 Apr 2016 14:21:41 +0100 Subject: [PATCH 072/117] added urlClone and urlSSH --- lib/github.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/github.js b/lib/github.js index b2271a8..26ebc7e 100644 --- a/lib/github.js +++ b/lib/github.js @@ -90,6 +90,7 @@ function queryGithub (msg, done) { params.state = 'open' github.pullRequests.getAll(params, (err, prs) => { + if (err) return done(err) var data = { name: msg.repo || '', user: msg.user || '', @@ -98,15 +99,16 @@ function queryGithub (msg, done) { watches: repo.subscribers_count || '', forks: repo.forks_count || '', last: repo.pushed_at || '', - urlRepo: msg.url || '', - urlClone: repo.clone_url || '', + urlRepo: 'https://github.com/' + msg.user + '/' + msg.repo, + urlClone: 'git+https://github.com/' + msg.user + '/' + msg.repo + '.git', + urlSSH: 'git@github.com:' + msg.user + '/' + msg.repo + '.git', pullRequests: prs && prs.length || 0, cached: Date.now() } function complete (err) { - if (err) return done (err) - else done (null, data) + if (err) return done(err) + else done(null, data) } cache.load$(msg.name, (err, cached) => { From 98c574f97f04677ea10417d4bf6d81bf6c3e54c6 Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Fri, 8 Apr 2016 15:33:49 +0100 Subject: [PATCH 073/117] Added linting command to package --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 51c4241..ec0eaa9 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "A micro-service that provides Github related information to NodeZoo", "scripts": { "start": "node srv/start.js", - "isolated": "GITHUB_ISOLATED=true node srv/start.js" + "isolated": "GITHUB_ISOLATED=true node srv/start.js", + "lint": "lab test -dL" }, "main": "lib/github.js", "keywords": [ From ae33f665f83174afac1c4f31c5b88f8d2681a742 Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Fri, 8 Apr 2016 16:15:19 +0100 Subject: [PATCH 074/117] Changed urlSSH to urlSsh to match nodezoo-web --- lib/github.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/github.js b/lib/github.js index 26ebc7e..c5017aa 100644 --- a/lib/github.js +++ b/lib/github.js @@ -101,7 +101,7 @@ function queryGithub (msg, done) { last: repo.pushed_at || '', urlRepo: 'https://github.com/' + msg.user + '/' + msg.repo, urlClone: 'git+https://github.com/' + msg.user + '/' + msg.repo + '.git', - urlSSH: 'git@github.com:' + msg.user + '/' + msg.repo + '.git', + urlSsh: 'git@github.com:' + msg.user + '/' + msg.repo + '.git', pullRequests: prs && prs.length || 0, cached: Date.now() } From 3e0d100dc9462dcc46bbec5e2ae0e75ac905e1c9 Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Sun, 10 Apr 2016 21:46:43 +0100 Subject: [PATCH 075/117] allow isolated mode without redis --- CHANGELOG.md | 13 +++++++++---- srv/start.js | 24 +++++++++++++----------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4fcd30..d6d45fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ -7 April 2016 - 6.1.0 ---- +## 10 April - 6.2.0 + +* Added support for redis to enable hard caching +* Updated isolated mode to run without redis + +## 7 April 2016 - 6.1.0 + * Added CHANGELOG.md * Removed redundant data folder. * Removed unneeded build.sh. @@ -9,6 +14,6 @@ * Added isolation mode * Updated docs to reflect changes -6 April 2016 - 6.0.0 ---- +## 6 April 2016 - 6.0.0 + * First release of the 6th major revision of nodezoo. diff --git a/srv/start.js b/srv/start.js index 2f0cf77..a519213 100644 --- a/srv/start.js +++ b/srv/start.js @@ -27,19 +27,21 @@ var opts = { port: envs.GITHUB_PORT || '8052' }, redis: { - host: 'localhost', - port: envs.redis_PORT || '6379' + host: envs.GITHUB_REDIS_HOST || 'localhost', + port: envs.GITHUB_REDIS_PORT || '6379' } } -console.log(envs.GITHUB_TOKEN) +var Service = Seneca(opts.seneca) -var Service = -Seneca(opts.seneca) - .use(Entities) - .use(RedisStore, opts.redis) - .use(Github, opts.github) +Service.use(Entities) -envs.GITHUB_ISOLATED - ? Service.listen(opts.isolated) - : Service.use(Mesh, opts.mesh) +if (envs.GITHUB_ISOLATED) { + Service.listen(opts.isolated) +} +else { + Service.use(Mesh, opts.mesh) + Service.use(RedisStore, opts.redis) +} + +Service.use(Github, opts.github) From 20cc82a195335490b2169fa8b0ce61a34bb81f7b Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Sun, 10 Apr 2016 21:48:45 +0100 Subject: [PATCH 076/117] 6.2.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ec0eaa9..88017fa 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nodezoo-github", - "version": "6.1.0", + "version": "6.2.0", "description": "A micro-service that provides Github related information to NodeZoo", "scripts": { "start": "node srv/start.js", From 2e01bf48f4e3b748601ce7141ced8c13cb7b9ef9 Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Mon, 11 Apr 2016 23:23:00 +0100 Subject: [PATCH 077/117] Initial tests --- .travis.yml | 22 +------ lib/github.js | 9 +-- package.json | 13 ++-- test/github.test.js | 153 ++++++++++++++++++++++++++++++++------------ 4 files changed, 128 insertions(+), 69 deletions(-) diff --git a/.travis.yml b/.travis.yml index acb6bb9..1870926 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,24 +1,6 @@ language: node_js -sudo: true +sudo: false node_js: - - "5" - "4" - -env: - - CXX=g++-4.8 -addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-4.8 - -cache: - directories: - - node_modules - -after_script: - - npm run lint - - npm run coverage - - npm run publish-coverage + - "5" diff --git a/lib/github.js b/lib/github.js index c5017aa..7c44008 100644 --- a/lib/github.js +++ b/lib/github.js @@ -15,6 +15,7 @@ module.exports = function (options) { opts = extend(opts, options) opts.cache = seneca.make$('github') + opts.cache.load$() seneca.add('role:github,cmd:get', cmdGet) seneca.add('role:info,req:part', aliasGet) @@ -32,7 +33,7 @@ function cmdGet (msg, done) { if (err) return done(err) if (github && !msg.update) { - return done(null, github) + return done(null, github.data$(github)) } Request.get({url: registry, gzip: true}, (err, res, body) => { @@ -66,7 +67,7 @@ function aliasGet (msg, done) { payload.data = data seneca.act('role:info,res:part,part:github', payload) - done() + done(null, {ok: true}) }) } @@ -106,9 +107,9 @@ function queryGithub (msg, done) { cached: Date.now() } - function complete (err) { + function complete (err, data) { if (err) return done(err) - else done(null, data) + else done(null, data.data$(data)) } cache.load$(msg.name, (err, cached) => { diff --git a/package.json b/package.json index 88017fa..b8faa4f 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "scripts": { "start": "node srv/start.js", "isolated": "GITHUB_ISOLATED=true node srv/start.js", - "lint": "lab test -dL" + "lint": "lab -P test -dL", + "test": "lab -t 84 -v -P test", + "cov": "lab -s -P test -r lcov | coveralls" }, "main": "lib/github.js", "keywords": [ @@ -33,7 +35,7 @@ "license": "MIT", "dependencies": { "github4": "0.5.4", - "request": "2.69.0", + "request": "2.70.0", "seneca": "2.0.0", "seneca-balance-client": "0.4.0", "seneca-entity": "0.0.1", @@ -45,10 +47,11 @@ "toolbag-plugin-udp-reporter": "1.0.0" }, "devDependencies": { - "code": "2.1.0", + "code": "2.2.0", + "coveralls": "2.11.9", "eslint-config-seneca": "1.1.2", "eslint-plugin-hapi": "4.0.0", - "eslint-plugin-standard": "1.3.1", - "lab": "8.2.0" + "eslint-plugin-standard": "1.3.2", + "lab": "10.3.1" } } diff --git a/test/github.test.js b/test/github.test.js index 6a296a0..cd5f682 100644 --- a/test/github.test.js +++ b/test/github.test.js @@ -2,66 +2,139 @@ var Lab = require('lab') var Code = require('code') -var Seneca = require('seneca') var lab = exports.lab = Lab.script() - var describe = lab.describe var it = lab.it var expect = Code.expect +var Seneca = require('seneca') var Github = require('..') -/* - * Notice: For travis/CI, tests have been configured with a token provided by - * https://github.com/thekemkid. However, This is a read only token which will - * only be able to read from public repos. You can create a similar token in - * your github settings > personal access tokens > generate new token. You do - * not have to enable any special permissions for this token. - */ - -describe('nodezoo-github', function () { - it('Fired the get pattern', function (done) { - var seneca = Seneca({ log: 'silent' }) - seneca.use(Github, { token: process.env.GITHUB_TOKEN }) - - seneca.ready(function () { - seneca.act({ role: 'github', cmd: 'get', name: 'nodejs/node.git', giturl: 'git@github.com:nodejs/node.git' }, function (err, res) { - expect(err).to.not.exist() - expect(res.user).to.equal('nodejs') - expect(res.repo).to.equal('node') - expect(res.id).to.equal('nodejs/node.git') - done() - }) +function createInstance () { + var params = { + log: 'silent', + errhandler: (err) => { + if (err.at) console.log(err.msg) + } + } + + return Seneca(params) + .use('entity') + .use(Github, {token: process.env.GITHUB_TOKEN}) +} + +describe('A valid "role:github,cmd:get" call', () => { + it('has no error', (done) => { + var seneca = createInstance() + var payload = {name: 'seneca'} + + seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + expect(err).to.not.exist() + done() }) }) - it('Fired the query pattern', function (done) { - var seneca = Seneca({ log: 'silent' }) - seneca.use(Github, { token: process.env.GITHUB_TOKEN }) + it('has data', (done) => { + var seneca = createInstance() + var payload = {name: 'seneca'} + + seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + expect(reply).to.exist() + done() + }) + }) - seneca.ready(function () { - seneca.act({ role: 'github', cmd: 'query', name: 'nodejs/node.git', user: 'nodejs', repo: 'node' }, function (err, res) { - expect(err).to.not.exist() - expect(res.user).to.equal('nodejs') - expect(res.repo).to.equal('node') - expect(res.id).to.equal('nodejs/node.git') + it('returns cached data', (done) => { + var seneca = createInstance() + var payload = {name: 'seneca'} + + seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + var cachedOne = reply.cached + + seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + var cachedTwo = reply.cached + + expect(cachedOne).to.equal(cachedTwo) done() }) }) }) - it('Fired the parse pattern', function (done) { - var seneca = Seneca({ log: 'silent' }) - seneca.use(Github, { token: process.env.GITHUB_TOKEN }) + it('can return non-cached data', (done) => { + var seneca = createInstance() + var payload = {name: 'seneca'} + + seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + expect(err).to.not.exist() + + var cachedOne = reply.cached + payload.update = true - seneca.ready(function () { - seneca.act({ role: 'github', cmd: 'parse', giturl: 'git@github.com:nodejs/node.git' }, function (err, res) { - expect(err).to.not.exist() - expect(res.user).to.equal('nodejs') - expect(res.repo).to.equal('node') + seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + var cachedTwo = reply.cached + + expect(cachedOne).to.be.below(cachedTwo) done() }) }) }) }) + +describe('An invalid "role:github,cmd:get" call', () => { + it('has an error', (done) => { + var seneca = createInstance() + var payload = {name: 'shooobydoobydooboop', fatal$: false} + + seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + expect(err).to.exist() + done() + }) + }) + + it('has no data', (done) => { + var seneca = createInstance() + var payload = {name: 'shooobydoobydooboop'} + + seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + expect(reply).to.not.exist() + done() + }) + }) +}) + +describe('A valid "role:info,req:part" call', () => { + it('has no error', (done) => { + var seneca = createInstance() + var payload = {name: 'seneca'} + + seneca.act(`role:info,req:part`, payload, (err, reply) => { + expect(err).to.not.exist() + done() + }) + }) + + it('has data', (done) => { + var seneca = createInstance() + var payload = {name: 'seneca'} + + seneca.act(`role:info,req:part`, payload, (err, reply) => { + expect(reply).to.exist() + done() + }) + }) + + + it('responds via "role:info,res:part"', (done) => { + var seneca = createInstance() + var payload = {name: 'seneca'} + + seneca.add(`role:info,res:part`, (msg, cb) => { + expect(msg).to.exist() + cb() + done() + }) + + seneca.act(`role:info,req:part`, payload) + }) +}) From 7298797cbd8af64f38c50b5bb103f7c8599cbcad Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Mon, 11 Apr 2016 23:32:22 +0100 Subject: [PATCH 078/117] blank --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 1870926..b8fa5f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,3 +4,4 @@ sudo: false node_js: - "4" - "5" + From 0afec018cf7f58fbdd54f67b05e86540cdb1fabd Mon Sep 17 00:00:00 2001 From: Dean McDonnell Date: Tue, 12 Apr 2016 14:54:30 +0100 Subject: [PATCH 079/117] Tests --- lib/github.js | 16 ++++-- package.json | 2 +- test/github.test.js | 84 +++++++++++++++---------------- test/npm-data.js | 119 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 173 insertions(+), 48 deletions(-) create mode 100644 test/npm-data.js diff --git a/lib/github.js b/lib/github.js index 7c44008..0fd8569 100644 --- a/lib/github.js +++ b/lib/github.js @@ -39,18 +39,26 @@ function cmdGet (msg, done) { Request.get({url: registry, gzip: true}, (err, res, body) => { if (err) return done(err) - var data = JSON.parse(body) + var data = null + + try {data = JSON.parse(body)} + catch (e) {return done(e)} + var distTags = data['dist-tags'] || {} var latest = ((data.versions || {})[distTags.latest]) || {} var repository = latest.repository || {} var url = repository.url || '' - var matches = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(url) || [] + var matches = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(url) var params = { name: msg.name, url: url, - user: matches[1] || '', - repo: matches[2] || '' + user: matches[1] || null, + repo: matches[2] || null + } + + if (!params.user || !params.repo) { + return done(new Error('not found on npm')) } queryGithub(params, done) diff --git a/package.json b/package.json index b8faa4f..5cbd7a1 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "start": "node srv/start.js", "isolated": "GITHUB_ISOLATED=true node srv/start.js", "lint": "lab -P test -dL", - "test": "lab -t 84 -v -P test", + "test": "lab -m 5000 -t 75 -v -P test", "cov": "lab -s -P test -r lcov | coveralls" }, "main": "lib/github.js", diff --git a/test/github.test.js b/test/github.test.js index cd5f682..c15cc14 100644 --- a/test/github.test.js +++ b/test/github.test.js @@ -2,20 +2,37 @@ var Lab = require('lab') var Code = require('code') +var Proxyquire = require('proxyquire') +var NpmFakeData = require('./npm-data') var lab = exports.lab = Lab.script() var describe = lab.describe var it = lab.it var expect = Code.expect -var Seneca = require('seneca') -var Github = require('..') +var NpmProxy = { + request: { + get: (opts, done) => { + if (opts.url.includes('seneca')) { + done(null, {}, JSON.stringify(NpmFakeData)) + } + else { + done(new Error('npm error'), null, null) + } + } + } +} + + +var Seneca = Proxyquire('seneca', {}) +var Github = Proxyquire('..', NpmProxy) -function createInstance () { +function createInstance (done) { var params = { log: 'silent', + strict: 'false', errhandler: (err) => { - if (err.at) console.log(err.msg) + if (err.at) done(err) } } @@ -25,34 +42,29 @@ function createInstance () { } describe('A valid "role:github,cmd:get" call', () => { - it('has no error', (done) => { - var seneca = createInstance() + it('has data and no error', (done) => { + var seneca = createInstance(done) var payload = {name: 'seneca'} seneca.act(`role:github,cmd:get`, payload, (err, reply) => { expect(err).to.not.exist() - done() - }) - }) - - it('has data', (done) => { - var seneca = createInstance() - var payload = {name: 'seneca'} - - seneca.act(`role:github,cmd:get`, payload, (err, reply) => { expect(reply).to.exist() done() }) }) it('returns cached data', (done) => { - var seneca = createInstance() + var seneca = createInstance(done) var payload = {name: 'seneca'} seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + expect(err).to.not.exist() + var cachedOne = reply.cached seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + expect(err).to.not.exist() + var cachedTwo = reply.cached expect(cachedOne).to.equal(cachedTwo) @@ -62,7 +74,7 @@ describe('A valid "role:github,cmd:get" call', () => { }) it('can return non-cached data', (done) => { - var seneca = createInstance() + var seneca = createInstance(done) var payload = {name: 'seneca'} seneca.act(`role:github,cmd:get`, payload, (err, reply) => { @@ -72,6 +84,8 @@ describe('A valid "role:github,cmd:get" call', () => { payload.update = true seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + expect(err).to.not.exist() + var cachedTwo = reply.cached expect(cachedOne).to.be.below(cachedTwo) @@ -82,21 +96,12 @@ describe('A valid "role:github,cmd:get" call', () => { }) describe('An invalid "role:github,cmd:get" call', () => { - it('has an error', (done) => { - var seneca = createInstance() - var payload = {name: 'shooobydoobydooboop', fatal$: false} - - seneca.act(`role:github,cmd:get`, payload, (err, reply) => { - expect(err).to.exist() - done() - }) - }) - - it('has no data', (done) => { - var seneca = createInstance() + it('has an error and no data', (done) => { + var seneca = createInstance(done) var payload = {name: 'shooobydoobydooboop'} seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + expect(err).to.exist() expect(reply).to.not.exist() done() }) @@ -104,29 +109,19 @@ describe('An invalid "role:github,cmd:get" call', () => { }) describe('A valid "role:info,req:part" call', () => { - it('has no error', (done) => { - var seneca = createInstance() + it('has no error and has data', (done) => { + var seneca = createInstance(done) var payload = {name: 'seneca'} seneca.act(`role:info,req:part`, payload, (err, reply) => { expect(err).to.not.exist() - done() - }) - }) - - it('has data', (done) => { - var seneca = createInstance() - var payload = {name: 'seneca'} - - seneca.act(`role:info,req:part`, payload, (err, reply) => { expect(reply).to.exist() done() }) }) - it('responds via "role:info,res:part"', (done) => { - var seneca = createInstance() + var seneca = createInstance(done) var payload = {name: 'seneca'} seneca.add(`role:info,res:part`, (msg, cb) => { @@ -135,6 +130,9 @@ describe('A valid "role:info,req:part" call', () => { done() }) - seneca.act(`role:info,req:part`, payload) + seneca.act(`role:info,req:part`, payload, (err, reply) => { + expect(err).to.not.exist() + expect(reply).to.exist() + }) }) }) diff --git a/test/npm-data.js b/test/npm-data.js new file mode 100644 index 0000000..b515733 --- /dev/null +++ b/test/npm-data.js @@ -0,0 +1,119 @@ +module.exports = { + '_id': 'seneca-entity', + '_rev': '3-1a2d436a902cdfaa820f4da8aeeeb4f1', + 'name': 'seneca-entity', + 'description': 'Entity plugin for seneca', + 'dist-tags': { + 'latest': '0.0.1' + }, + 'versions': { + '0.0.1': { + 'name': 'seneca-entity', + 'description': 'Entity plugin for seneca', + 'keywords': [ + 'seneca', + 'plugin' + ], + 'version': '0.0.1', + 'license': 'MIT', + 'homepage': 'http://senecajs.org', + 'author': { + 'name': 'Richard Rodger', + 'url': 'http://richardrodger.com/' + }, + 'dependencies': { + 'eraro': '0.4.1', + 'jsonic': '0.2.2', + 'lodash': '4.0.1' + }, + 'main': 'entity.js', + 'engines': { + 'node': '>=0.10.0' + }, + 'files': [ + 'LICENSE', + 'README.md', + 'lib', + 'entity.js' + ], + 'repository': { + 'type': 'git', + 'url': 'git+https://github.com/senecajs/seneca-entity.git' + }, + 'scripts': { + 'test': 'lab -v -P test -L -t 80', + 'test-html': 'lab -v -P test -L -t 80 -r html > testcov.html', + 'lint': 'lab -P test -dL' + }, + 'devDependencies': { + 'code': '1.5.0', + 'eslint-config-seneca': '1.1.2', + 'eslint-plugin-standard': '1.3.1', + 'joi': '6.10.x', + 'lab': '6.2.x' + }, + 'gitHead': '61371232af57ee37c573cfc114096088def6f478', + 'bugs': { + 'url': 'https://github.com/senecajs/seneca-entity/issues' + }, + '_id': 'seneca-entity@0.0.1', + '_shasum': '184d2251666938639364256836e6d16db2f8f729', + '_from': '.', + '_npmVersion': '3.3.12', + '_nodeVersion': '5.4.1', + '_npmUser': { + 'name': 'wyatt', + 'email': 'wpreul@gmail.com' + }, + 'dist': { + 'shasum': '184d2251666938639364256836e6d16db2f8f729', + 'tarball': 'https://registry.npmjs.org/seneca-entity/-/seneca-entity-0.0.1.tgz' + }, + 'maintainers': [ + { + 'name': 'wyatt', + 'email': 'wpreul@gmail.com' + } + ], + '_npmOperationalInternal': { + 'host': 'packages-5-east.internal.npmjs.com', + 'tmp': 'tmp/seneca-entity-0.0.1.tgz_1455650942742_0.4798124579247087' + }, + 'directories': {} + } + }, + 'readme': '# seneca-entity\nEntity plugin for seneca\n', + 'maintainers': [ + { + 'name': 'rjrodger', + 'email': 'richard.rodger@nearform.com' + }, + { + 'name': 'wyatt', + 'email': 'wpreul@gmail.com' + } + ], + 'time': { + 'modified': '2016-03-07T21:07:05.021Z', + 'created': '2016-02-16T18:49:09.329Z', + '0.0.0': '2016-02-16T18:49:09.329Z', + '0.0.1': '2016-02-16T19:29:05.114Z' + }, + 'homepage': 'http://senecajs.org', + 'keywords': [ + 'seneca', + 'plugin' + ], + 'repository': { + 'type': 'git', + 'url': 'git+https://github.com/senecajs/seneca-entity.git' + }, + 'author': { + 'name': 'Richard Rodger', + 'url': 'http://richardrodger.com/' + }, + 'bugs': { + 'url': 'https://github.com/senecajs/seneca-entity/issues' + }, + 'license': 'MIT' +} From 2b1356aed7347380b898c8149a96ea8036c75628 Mon Sep 17 00:00:00 2001 From: Matthew O'Connor Date: Fri, 15 Apr 2016 14:30:42 +0100 Subject: [PATCH 080/117] toolbag removed toolbag removed updated dockerfile --- .toolbagrc.js | 44 -------------------------------------------- CHANGELOG.md | 4 ++++ Dockerfile | 2 +- package.json | 5 +---- 4 files changed, 6 insertions(+), 49 deletions(-) delete mode 100644 .toolbagrc.js diff --git a/.toolbagrc.js b/.toolbagrc.js deleted file mode 100644 index 1469cdd..0000000 --- a/.toolbagrc.js +++ /dev/null @@ -1,44 +0,0 @@ -'use strict' - -const StatsCollector = require('toolbag-plugin-stats-collector') -const UdpReporter = require('toolbag-plugin-udp-reporter') - -module.exports = (defaults, done) => { - done(null, { - plugins: [ - { - plugin: UdpReporter, - options: { - id: 'udp reporter', - socketType: 'udp4', - port: 5001, - host: 'localhost' - } - }, - { - plugin: StatsCollector, - options: { - enabled: true, - period: 1000, - eventLoopLimit: 30, - features: { - process: true, - system: true, - cpu: true, - memory: true, - gc: false, - handles: false, - requests: false, - eventLoop: true, - meta: { - tags: [ - 'git', - 'nodezoo' - ] - } - } - } - } - ] - }) -} diff --git a/CHANGELOG.md b/CHANGELOG.md index d6d45fc..0298f54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +##Pending - x.x.x + +* toolbag removed. + ## 10 April - 6.2.0 * Added support for redis to enable hard caching diff --git a/Dockerfile b/Dockerfile index b52e813..abde0e4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,4 +11,4 @@ RUN npm install COPY . /src -CMD ["node", "-r", "toolbag", "srv/start.js", "--seneca.options.tag=nodezoo-github", "--seneca-log=type:act"] +CMD ["node", "srv/start.js", "--seneca.options.tag=nodezoo-github", "--seneca-log=type:act"] diff --git a/package.json b/package.json index 88017fa..96b7b34 100644 --- a/package.json +++ b/package.json @@ -39,10 +39,7 @@ "seneca-entity": "0.0.1", "seneca-level-store": "0.2.3", "seneca-mesh": "0.7.0", - "seneca-redis-store": "0.0.8", - "toolbag": "2.0.0", - "toolbag-plugin-stats-collector": "1.0.0", - "toolbag-plugin-udp-reporter": "1.0.0" + "seneca-redis-store": "0.0.8" }, "devDependencies": { "code": "2.1.0", From aeed8d141eb6be694759736b7f3d1a2ff0b2fe0b Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Mon, 18 Apr 2016 17:20:03 +0100 Subject: [PATCH 081/117] Updated readme to show data emitted --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index 407d2dd..bf2d785 100644 --- a/README.md +++ b/README.md @@ -112,6 +112,20 @@ Contains the response of an earlier call to `role:info,req:part`. seneca.add('role:info,res:part', (msg, done) => {}) ``` +## Data Emitted +- name - Name of the module +- user - The User or Organisation that owns the repository +- repo - The repository name +- stars - Number of stars +- forks - Number of forks +- watches - Numbers of watchers +- last - The last commit to the repository +- urlRepo - A link to the repository +- urlClone - A clone URL +- urlSsh - An SSH URL +- pullRequests - Open pull requests +- cached - The time the data was last cached at + ## Contributing The [NodeZoo org][] encourages __open__ and __safe__ participation. From 35cb19f337bec5124e49d6de2e5fb6b8c59c5e65 Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Tue, 19 Apr 2016 17:25:16 +0100 Subject: [PATCH 082/117] Check url exists before extracting user and repo. Assign stars, forks and watches 0 instead of empty string --- CHANGELOG.md | 2 ++ lib/github.js | 35 ++++++++++++++++++++--------------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0298f54..537840e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ ##Pending - x.x.x * toolbag removed. +* Checking that github url exists before trying to extract user and repo +* Stars, forks and watches are now assigned 0 instead of an empty string if repo.* is empty ## 10 April - 6.2.0 diff --git a/lib/github.js b/lib/github.js index 0fd8569..5adc230 100644 --- a/lib/github.js +++ b/lib/github.js @@ -41,27 +41,32 @@ function cmdGet (msg, done) { var data = null - try {data = JSON.parse(body)} - catch (e) {return done(e)} + try { data = JSON.parse(body) } + catch (e) { return done(e) } var distTags = data['dist-tags'] || {} var latest = ((data.versions || {})[distTags.latest]) || {} var repository = latest.repository || {} var url = repository.url || '' - var matches = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(url) - var params = { - name: msg.name, - url: url, - user: matches[1] || null, - repo: matches[2] || null - } + if(url.length > 0) { + var matches = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(url) + var params = { + name: msg.name, + url: url, + user: matches[1] || null, + repo: matches[2] || null + } + + if (!params.user || !params.repo) { + return done(new Error('not found on npm')) + } - if (!params.user || !params.repo) { + queryGithub(params, done) + } + else{ return done(new Error('not found on npm')) } - - queryGithub(params, done) }) }) } @@ -104,9 +109,9 @@ function queryGithub (msg, done) { name: msg.repo || '', user: msg.user || '', repo: msg.repo || '', - stars: repo.stargazers_count || '', - watches: repo.subscribers_count || '', - forks: repo.forks_count || '', + stars: repo.stargazers_count || 0, + watches: repo.subscribers_count || 0, + forks: repo.forks_count || 0, last: repo.pushed_at || '', urlRepo: 'https://github.com/' + msg.user + '/' + msg.repo, urlClone: 'git+https://github.com/' + msg.user + '/' + msg.repo + '.git', From 02199b0932b7b5bf291f19a4ce43a0526f755870 Mon Sep 17 00:00:00 2001 From: Matthew O'Connor Date: Thu, 21 Apr 2016 10:14:16 +0100 Subject: [PATCH 083/117] sample data added to readme --- CHANGELOG.md | 1 + README.md | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 537840e..522aa34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ * toolbag removed. * Checking that github url exists before trying to extract user and repo * Stars, forks and watches are now assigned 0 instead of an empty string if repo.* is empty +* Sample data added to Readme. ## 10 April - 6.2.0 diff --git a/README.md b/README.md index bf2d785..ebb28bd 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,25 @@ all available variable names. - Change the registry used to validate the module name. - Defaults to `http://registry.npmjs.org/`. + ## Sample Data + ```json + { + "entity$": "-\/-\/github_cache", + "name": "fuge", + "user": "apparatus", + "repo": "fuge", + "stars": 155, + "watches": 15, + "forks": 18, + "last": "2016-04-09T21:57:45Z", + "urlRepo": "https:\/\/github.com\/apparatus\/fuge", + "urlClone": "git+https:\/\/github.com\/apparatus\/fuge.git", + "urlSsh": "git@github.com:apparatus\/fuge.git", + "pullRequests": 1, + "cached": 1461229347738 +} + ``` + ## Messages Handled This micro-service handles the following messages. From e4c8a73844ad90ec14d44f6506a91fed7224a704 Mon Sep 17 00:00:00 2001 From: Matthew O'Connor Date: Thu, 21 Apr 2016 11:52:41 +0100 Subject: [PATCH 084/117] test script and deps updated along with error msg test script and deps updated updated error message --- lib/github.js | 4 ++-- package.json | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/github.js b/lib/github.js index 5adc230..a01744d 100644 --- a/lib/github.js +++ b/lib/github.js @@ -59,13 +59,13 @@ function cmdGet (msg, done) { } if (!params.user || !params.repo) { - return done(new Error('not found on npm')) + return done(new Error('not found on github')) } queryGithub(params, done) } else{ - return done(new Error('not found on npm')) + return done(new Error('not found on github')) } }) }) diff --git a/package.json b/package.json index 457473f..d2848cd 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "start": "node srv/start.js", "isolated": "GITHUB_ISOLATED=true node srv/start.js", "lint": "lab -P test -dL", - "test": "lab -m 5000 -t 75 -v -P test", + "test": "lab -v -P test -L -c -t 64", "cov": "lab -s -P test -r lcov | coveralls" }, "main": "lib/github.js", @@ -35,6 +35,7 @@ "license": "MIT", "dependencies": { "github4": "0.5.4", + "proxyquire": "1.7.4", "request": "2.70.0", "seneca": "2.0.0", "seneca-balance-client": "0.4.0", From 77cc4c54979e7a0d46a015f321b76afc7e86db0c Mon Sep 17 00:00:00 2001 From: Matthew O'Connor Date: Thu, 21 Apr 2016 12:57:19 +0100 Subject: [PATCH 085/117] move proxyquire to dev deps --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index d2848cd..2feacff 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,6 @@ "license": "MIT", "dependencies": { "github4": "0.5.4", - "proxyquire": "1.7.4", "request": "2.70.0", "seneca": "2.0.0", "seneca-balance-client": "0.4.0", @@ -50,6 +49,7 @@ "eslint-config-seneca": "1.1.2", "eslint-plugin-hapi": "4.0.0", "eslint-plugin-standard": "1.3.2", + "proxyquire": "1.7.4", "lab": "10.3.1" } } From 00719e71c00af62750f73a33606c2f277ecfd7b1 Mon Sep 17 00:00:00 2001 From: eduardobs79 Date: Thu, 28 Apr 2016 19:06:26 +0200 Subject: [PATCH 086/117] Adding the default README, if any --- lib/github.js | 80 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/lib/github.js b/lib/github.js index a01744d..7af32b2 100644 --- a/lib/github.js +++ b/lib/github.js @@ -3,6 +3,7 @@ var GitHub = require('github4') var github = new GitHub() var Request = require('request') +var async = require('async') var opts = { registry: 'http://registry.npmjs.org/', @@ -92,46 +93,59 @@ function queryGithub (msg, done) { token: opts.token }) - var params = { - user: msg.user, - repo: msg.repo - } + async.parallel({ + getRepository: function (cb) { + github.repos.get({user: msg.user, repo: msg.repo}, cb) + }, + + getReadme: function (cb) { + github.repos.getReadme({user: msg.user, repo: msg.repo}, (err, readme) => { + if (err) return cb(err) + if (!readme.content) return cb(null, false) - github.repos.get(params, (err, repo) => { + github.misc.renderMarkdownRaw({ + data: new Buffer(readme.content, 'base64').toString('ascii') + }, (err, response) => { + if (err && !response) return cb(err) // API fails expecting a JSON object + + cb(null, response.data) + }) + }) + }, + + getPullRequests: function (cb) { + github.pullRequests.getAll({user: msg.user, repo: msg.repo, state: 'open'}, cb) + } + }, (err, results) => { if (err) return done(err) - if (!repo) return done() - params.state = 'open' + var data = { + name: msg.repo || '', + user: msg.user || '', + repo: msg.repo || '', + stars: results.getRepository.stargazers_count || 0, + watches: results.getRepository.subscribers_count || 0, + forks: results.getRepository.forks_count || 0, + last: results.getRepository.pushed_at || '', + urlRepo: 'https://github.com/' + msg.user + '/' + msg.repo, + urlClone: 'git+https://github.com/' + msg.user + '/' + msg.repo + '.git', + urlSsh: 'git@github.com:' + msg.user + '/' + msg.repo + '.git', + readme: results.getReadme, + pullRequests: results.getPullRequests && results.getPullRequests.length || 0, + cached: Date.now() + } - github.pullRequests.getAll(params, (err, prs) => { + function complete (err, data) { if (err) return done(err) - var data = { - name: msg.repo || '', - user: msg.user || '', - repo: msg.repo || '', - stars: repo.stargazers_count || 0, - watches: repo.subscribers_count || 0, - forks: repo.forks_count || 0, - last: repo.pushed_at || '', - urlRepo: 'https://github.com/' + msg.user + '/' + msg.repo, - urlClone: 'git+https://github.com/' + msg.user + '/' + msg.repo + '.git', - urlSsh: 'git@github.com:' + msg.user + '/' + msg.repo + '.git', - pullRequests: prs && prs.length || 0, - cached: Date.now() - } - - function complete (err, data) { - if (err) return done(err) - else done(null, data.data$(data)) - } + else done(null, data.data$(data)) + } - cache.load$(msg.name, (err, cached) => { - if (err) return done(err) - if (cached) return cached.data$(data).save$(complete) + cache.load$(msg.name, (err, cached) => { + if (err) return done(err) + if (cached) return cached.data$(data).save$(complete) - data.id$ = msg.name - cache.make$(data).save$(complete) - }) + data.id$ = msg.name + cache.make$(data).save$(complete) }) }) } From 96cd35477f5ab6eb22a7de92a1c28bf3bb16554a Mon Sep 17 00:00:00 2001 From: Mircea Alexandru Date: Tue, 10 May 2016 09:46:59 +0300 Subject: [PATCH 087/117] added test for matching the url. Fixes #68 --- lib/github.js | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/lib/github.js b/lib/github.js index 7af32b2..f9c7958 100644 --- a/lib/github.js +++ b/lib/github.js @@ -30,6 +30,7 @@ function cmdGet (msg, done) { var cache = opts.cache var registry = opts.registry + msg.name + console.log('Processing module: ', msg.name) cache.load$(msg.name, (err, github) => { if (err) return done(err) @@ -51,19 +52,25 @@ function cmdGet (msg, done) { var url = repository.url || '' if(url.length > 0) { + console.log('Matching URL: ', url) var matches = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(url) - var params = { - name: msg.name, - url: url, - user: matches[1] || null, - repo: matches[2] || null - } - if (!params.user || !params.repo) { - return done(new Error('not found on github')) + if (matches && matches.length ===2) { + var params = { + name: msg.name, + url: url, + user: matches[1] || null, + repo: matches[2] || null + } + + if (!params.user || !params.repo) { + return done(new Error('not found on github')) + } + + queryGithub(params, done) + }else{ + return done(new Error('invalid github url:', url, ' for module:', msg.name)) } - - queryGithub(params, done) } else{ return done(new Error('not found on github')) From 90523341858dbcd48646bd750e64aa31486ba32e Mon Sep 17 00:00:00 2001 From: Mircea Alexandru Date: Tue, 10 May 2016 11:33:51 +0300 Subject: [PATCH 088/117] update packages, linting, some more debug messages --- lib/github.js | 188 ++++++++++++++++++++++++++------------------ package.json | 12 +-- test/github.test.js | 18 ++--- 3 files changed, 127 insertions(+), 91 deletions(-) diff --git a/lib/github.js b/lib/github.js index f9c7958..6928815 100644 --- a/lib/github.js +++ b/lib/github.js @@ -3,7 +3,7 @@ var GitHub = require('github4') var github = new GitHub() var Request = require('request') -var async = require('async') +var Async = require('async') var opts = { registry: 'http://registry.npmjs.org/', @@ -27,11 +27,13 @@ module.exports = function (options) { } function cmdGet (msg, done) { - var cache = opts.cache - var registry = opts.registry + msg.name + let moduleName = msg.name + let cache = opts.cache + let registry = opts.registry + moduleName + let context = this - console.log('Processing module: ', msg.name) - cache.load$(msg.name, (err, github) => { + context.log.debug(`Processing module: ${moduleName}`) + cache.load$(moduleName, (err, github) => { if (err) return done(err) if (github && !msg.update) { @@ -51,108 +53,142 @@ function cmdGet (msg, done) { var repository = latest.repository || {} var url = repository.url || '' - if(url.length > 0) { - console.log('Matching URL: ', url) + context.log.debug(`Module: ${moduleName}, github url: ${url}`) + if (url.length > 0) { var matches = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(url) - if (matches && matches.length ===2) { + if (matches && matches.length >= 2) { var params = { - name: msg.name, + name: moduleName, url: url, user: matches[1] || null, repo: matches[2] || null } if (!params.user || !params.repo) { - return done(new Error('not found on github')) + return done(new Error(`module ${moduleName} not found on github`)) } queryGithub(params, done) - }else{ - return done(new Error('invalid github url:', url, ' for module:', msg.name)) + } + else { + return done(new Error(`invalid github url: ${url}, for module: ${moduleName}`)) } } - else{ - return done(new Error('not found on github')) + else { + return done(new Error(`module ${moduleName} not found on github`)) } }) }) -} -function aliasGet (msg, done) { - var seneca = this - var payload = {name: msg.name} + function queryGithub (params, done) { + var cache = opts.cache - seneca.act('role:github,cmd:get', payload, (err, data) => { - if (err) return done(err) - - payload.data = data - seneca.act('role:info,res:part,part:github', payload) - done(null, {ok: true}) - }) -} + github.authenticate({ + type: 'token', + token: opts.token + }) -function queryGithub (msg, done) { - var cache = opts.cache + Async.parallel({ + getRepository: function (cb) { + github.repos.get({user: params.user, repo: params.repo}, function (err, data) { + if (err) { + context.log.debug(`Read repo for ${moduleName} get error: ${err}`) + } - github.authenticate({ - type: 'token', - token: opts.token - }) + cb(err, data) + }) + }, - async.parallel({ - getRepository: function (cb) { - github.repos.get({user: msg.user, repo: msg.repo}, cb) - }, + getReadme: function (cb) { + github.repos.getReadme({user: params.user, repo: params.repo}, (err, readme) => { + if (err) { + context.log.debug(`Read readme for ${moduleName} get error: ${err}`) + return cb(err) + } - getReadme: function (cb) { - github.repos.getReadme({user: msg.user, repo: msg.repo}, (err, readme) => { - if (err) return cb(err) - if (!readme.content) return cb(null, false) + if (!readme || !readme.content) { + context.log.debug(`Read readme for ${moduleName} no content`) + return cb(null, false) + } - github.misc.renderMarkdownRaw({ - data: new Buffer(readme.content, 'base64').toString('ascii') - }, (err, response) => { - if (err && !response) return cb(err) // API fails expecting a JSON object + github.misc.renderMarkdownRaw({ + data: new Buffer(readme.content, 'base64').toString('ascii') + }, (err, response) => { + if (err && !response) { + context.log.debug(`Render readme for ${moduleName} error: ${err}`) + return cb(err) + } // API fails expecting a JSON object - cb(null, response.data) + cb(null, response.data) + }) }) - }) - }, + }, - getPullRequests: function (cb) { - github.pullRequests.getAll({user: msg.user, repo: msg.repo, state: 'open'}, cb) - } - }, (err, results) => { - if (err) return done(err) + getPullRequests: function (cb) { + github.pullRequests.getAll({user: params.user, repo: params.repo, state: 'open'}, function(err, data){ + if (err) { + context.log.debug(`Read Github pull requests for ${moduleName} get error: ${err}`) + } - var data = { - name: msg.repo || '', - user: msg.user || '', - repo: msg.repo || '', - stars: results.getRepository.stargazers_count || 0, - watches: results.getRepository.subscribers_count || 0, - forks: results.getRepository.forks_count || 0, - last: results.getRepository.pushed_at || '', - urlRepo: 'https://github.com/' + msg.user + '/' + msg.repo, - urlClone: 'git+https://github.com/' + msg.user + '/' + msg.repo + '.git', - urlSsh: 'git@github.com:' + msg.user + '/' + msg.repo + '.git', - readme: results.getReadme, - pullRequests: results.getPullRequests && results.getPullRequests.length || 0, - cached: Date.now() - } + cb(err, data) + }) + } + }, (err, results) => { + if (err) { + context.log.debug(`Read pull requests for ${moduleName} got error: ${err}`) + return complete(err) + } + var data = { + name: params.repo || '', + user: params.user || '', + repo: params.repo || '', + stars: results.getRepository.stargazers_count || 0, + watches: results.getRepository.subscribers_count || 0, + forks: results.getRepository.forks_count || 0, + last: results.getRepository.pushed_at || '', + urlRepo: 'https://github.com/' + params.user + '/' + params.repo, + urlClone: 'git+https://github.com/' + params.user + '/' + params.repo + '.git', + urlSsh: 'git@github.com:' + params.user + '/' + params.repo + '.git', + readme: results.getReadme, + pullRequests: results.getPullRequests && results.getPullRequests.length || 0, + cached: Date.now() + } - function complete (err, data) { - if (err) return done(err) - else done(null, data.data$(data)) - } + context.log.debug(`Read Github data for module ${moduleName} completed.`) + cache.load$(params.name, (err, cached) => { + if (err) { + return complete(err) + } - cache.load$(msg.name, (err, cached) => { - if (err) return done(err) - if (cached) return cached.data$(data).save$(complete) + if (cached) { + return cached.data$(data).save$(complete) + } + + data.id$ = params.name + cache.make$(data).save$(complete) + }) - data.id$ = msg.name - cache.make$(data).save$(complete) + function complete (err, data) { + if (err) { + context.log.debug(`Save Github data for ${moduleName} got error: ${err}`) + return done(err) + } + else done(null, data ? data.data$(data) : data) + } }) + } +} + +function aliasGet (msg, done) { + var seneca = this + var payload = {name: msg.name} + + seneca.act('role:github,cmd:get', payload, (err, data) => { + if (err) return done(err) + + payload.data = data + seneca.act('role:info,res:part,part:github', payload) + done(null, {ok: true}) }) } diff --git a/package.json b/package.json index 2feacff..fd4bd4f 100644 --- a/package.json +++ b/package.json @@ -34,9 +34,9 @@ }, "license": "MIT", "dependencies": { - "github4": "0.5.4", - "request": "2.70.0", - "seneca": "2.0.0", + "github4": "1.0.0", + "request": "2.72.0", + "seneca": "2.0.1", "seneca-balance-client": "0.4.0", "seneca-entity": "0.0.1", "seneca-level-store": "0.2.3", @@ -46,10 +46,10 @@ "devDependencies": { "code": "2.2.0", "coveralls": "2.11.9", - "eslint-config-seneca": "1.1.2", + "eslint-config-seneca": "2.0.0", "eslint-plugin-hapi": "4.0.0", "eslint-plugin-standard": "1.3.2", - "proxyquire": "1.7.4", - "lab": "10.3.1" + "proxyquire": "1.7.8", + "lab": "10.5.1" } } diff --git a/test/github.test.js b/test/github.test.js index c15cc14..3a97b98 100644 --- a/test/github.test.js +++ b/test/github.test.js @@ -46,7 +46,7 @@ describe('A valid "role:github,cmd:get" call', () => { var seneca = createInstance(done) var payload = {name: 'seneca'} - seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + seneca.act('role:github,cmd:get', payload, (err, reply) => { expect(err).to.not.exist() expect(reply).to.exist() done() @@ -57,12 +57,12 @@ describe('A valid "role:github,cmd:get" call', () => { var seneca = createInstance(done) var payload = {name: 'seneca'} - seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + seneca.act('role:github,cmd:get', payload, (err, reply) => { expect(err).to.not.exist() var cachedOne = reply.cached - seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + seneca.act('role:github,cmd:get', payload, (err, reply) => { expect(err).to.not.exist() var cachedTwo = reply.cached @@ -77,13 +77,13 @@ describe('A valid "role:github,cmd:get" call', () => { var seneca = createInstance(done) var payload = {name: 'seneca'} - seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + seneca.act('role:github,cmd:get', payload, (err, reply) => { expect(err).to.not.exist() var cachedOne = reply.cached payload.update = true - seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + seneca.act('role:github,cmd:get', payload, (err, reply) => { expect(err).to.not.exist() var cachedTwo = reply.cached @@ -100,7 +100,7 @@ describe('An invalid "role:github,cmd:get" call', () => { var seneca = createInstance(done) var payload = {name: 'shooobydoobydooboop'} - seneca.act(`role:github,cmd:get`, payload, (err, reply) => { + seneca.act('role:github,cmd:get', payload, (err, reply) => { expect(err).to.exist() expect(reply).to.not.exist() done() @@ -113,7 +113,7 @@ describe('A valid "role:info,req:part" call', () => { var seneca = createInstance(done) var payload = {name: 'seneca'} - seneca.act(`role:info,req:part`, payload, (err, reply) => { + seneca.act('role:info,req:part', payload, (err, reply) => { expect(err).to.not.exist() expect(reply).to.exist() done() @@ -124,13 +124,13 @@ describe('A valid "role:info,req:part" call', () => { var seneca = createInstance(done) var payload = {name: 'seneca'} - seneca.add(`role:info,res:part`, (msg, cb) => { + seneca.add('role:info,res:part', (msg, cb) => { expect(msg).to.exist() cb() done() }) - seneca.act(`role:info,req:part`, payload, (err, reply) => { + seneca.act('role:info,req:part', payload, (err, reply) => { expect(err).to.not.exist() expect(reply).to.exist() }) From f9c01f4813a8dae5e4565df2bbdc1b0ff733b72f Mon Sep 17 00:00:00 2001 From: Mircea Alexandru Date: Tue, 10 May 2016 12:06:49 +0300 Subject: [PATCH 089/117] bump version 6.2.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fd4bd4f..e7b3790 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nodezoo-github", - "version": "6.2.0", + "version": "6.2.1", "description": "A micro-service that provides Github related information to NodeZoo", "scripts": { "start": "node srv/start.js", From ee9a31ca0da40a11fbbb5c5b314e4d804f52d4e8 Mon Sep 17 00:00:00 2001 From: Adrian Rossouw Date: Tue, 10 May 2016 15:08:26 +0200 Subject: [PATCH 090/117] add async to build --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index e7b3790..ef0a7c5 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ }, "license": "MIT", "dependencies": { + "async": "^2.0.0-rc.4", "github4": "1.0.0", "request": "2.72.0", "seneca": "2.0.1", From fdc59b2325a15ffc0cb092d1247bb1dc61594068 Mon Sep 17 00:00:00 2001 From: Mircea Alexandru Date: Wed, 11 May 2016 10:16:59 +0300 Subject: [PATCH 091/117] bump version & change balancer version --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index e7b3790..01df0b6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nodezoo-github", - "version": "6.2.1", + "version": "6.2.2", "description": "A micro-service that provides Github related information to NodeZoo", "scripts": { "start": "node srv/start.js", @@ -37,7 +37,7 @@ "github4": "1.0.0", "request": "2.72.0", "seneca": "2.0.1", - "seneca-balance-client": "0.4.0", + "seneca-balance-client": "0.5.x", "seneca-entity": "0.0.1", "seneca-level-store": "0.2.3", "seneca-mesh": "0.7.0", From af68abea42ecd4820797ed83e97caf25acf08987 Mon Sep 17 00:00:00 2001 From: malex Date: Thu, 12 May 2016 11:18:08 +0300 Subject: [PATCH 092/117] change response for seneca actions --- lib/github.js | 58 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/lib/github.js b/lib/github.js index 6928815..af4dcc5 100644 --- a/lib/github.js +++ b/lib/github.js @@ -34,19 +34,27 @@ function cmdGet (msg, done) { context.log.debug(`Processing module: ${moduleName}`) cache.load$(moduleName, (err, github) => { - if (err) return done(err) + if (err) { + context.log.debug(`Cannot load from cache module ${moduleName}, try now to get it remotely`) + } if (github && !msg.update) { - return done(null, github.data$(github)) + return done(null, {ok: true, data: github.data$(github)}) } Request.get({url: registry, gzip: true}, (err, res, body) => { - if (err) return done(err) + if (err) { + return done(err) + } var data = null - try { data = JSON.parse(body) } - catch (e) { return done(e) } + try { + data = JSON.parse(body) + } + catch (e) { + return done(e) + } var distTags = data['dist-tags'] || {} var latest = ((data.versions || {})[distTags.latest]) || {} @@ -66,17 +74,17 @@ function cmdGet (msg, done) { } if (!params.user || !params.repo) { - return done(new Error(`module ${moduleName} not found on github`)) + return done(null, {ok: false, err: new Error(`module ${moduleName} not found on github`)}) } queryGithub(params, done) } else { - return done(new Error(`invalid github url: ${url}, for module: ${moduleName}`)) + return done(null, {ok: false, err: new Error(`invalid github url: ${url}, for module: ${moduleName}`)}) } } else { - return done(new Error(`module ${moduleName} not found on github`)) + return done(null, {ok: false, err: new Error(`module ${moduleName} not found on github`)}) } }) }) @@ -104,7 +112,8 @@ function cmdGet (msg, done) { github.repos.getReadme({user: params.user, repo: params.repo}, (err, readme) => { if (err) { context.log.debug(`Read readme for ${moduleName} get error: ${err}`) - return cb(err) + // don't report error, as we want to search for other information, even if Readme is not loaded + return cb(null, false) } if (!readme || !readme.content) { @@ -117,7 +126,8 @@ function cmdGet (msg, done) { }, (err, response) => { if (err && !response) { context.log.debug(`Render readme for ${moduleName} error: ${err}`) - return cb(err) + // don't report error, as we want to search for other information, even if Readme is not loaded + return cb(null, false) } // API fails expecting a JSON object cb(null, response.data) @@ -131,22 +141,23 @@ function cmdGet (msg, done) { context.log.debug(`Read Github pull requests for ${moduleName} get error: ${err}`) } - cb(err, data) + // don't report error, as we might have useful data + return cb() }) } }, (err, results) => { if (err) { context.log.debug(`Read pull requests for ${moduleName} got error: ${err}`) - return complete(err) + return done(null, {ok: false, err: err}) } var data = { name: params.repo || '', user: params.user || '', repo: params.repo || '', - stars: results.getRepository.stargazers_count || 0, - watches: results.getRepository.subscribers_count || 0, - forks: results.getRepository.forks_count || 0, - last: results.getRepository.pushed_at || '', + stars: results.getRepository ? results.getRepository.stargazers_count || 0 : 0, + watches: results.getRepository ? results.getRepository.subscribers_count || 0 : 0, + forks: results.getRepository ? results.getRepository.forks_count || 0 : 0, + last: results.getRepository ? results.getRepository.pushed_at || '' : '', urlRepo: 'https://github.com/' + params.user + '/' + params.repo, urlClone: 'git+https://github.com/' + params.user + '/' + params.repo + '.git', urlSsh: 'git@github.com:' + params.user + '/' + params.repo + '.git', @@ -174,7 +185,7 @@ function cmdGet (msg, done) { context.log.debug(`Save Github data for ${moduleName} got error: ${err}`) return done(err) } - else done(null, data ? data.data$(data) : data) + else done(null, {ok: true, data: data ? data.data$(data) : data}) } }) } @@ -184,11 +195,16 @@ function aliasGet (msg, done) { var seneca = this var payload = {name: msg.name} - seneca.act('role:github,cmd:get', payload, (err, data) => { - if (err) return done(err) + seneca.act('role:github,cmd:get', payload, (err, res) => { + if (err) { + return done(null, {ok: false, err: err}) + } + + if (res && res.ok) { + payload.data = res.data + seneca.act('role:info,res:part,part:github', payload) + } - payload.data = data - seneca.act('role:info,res:part,part:github', payload) done(null, {ok: true}) }) } From cc868d35515bc1093bbdbb89cb3f430fd931c1d8 Mon Sep 17 00:00:00 2001 From: malex Date: Thu, 12 May 2016 12:20:42 +0300 Subject: [PATCH 093/117] fix test --- test/github.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/github.test.js b/test/github.test.js index 3a97b98..8750656 100644 --- a/test/github.test.js +++ b/test/github.test.js @@ -80,13 +80,13 @@ describe('A valid "role:github,cmd:get" call', () => { seneca.act('role:github,cmd:get', payload, (err, reply) => { expect(err).to.not.exist() - var cachedOne = reply.cached + var cachedOne = reply.data.cached payload.update = true seneca.act('role:github,cmd:get', payload, (err, reply) => { expect(err).to.not.exist() - var cachedTwo = reply.cached + var cachedTwo = reply.data.cached expect(cachedOne).to.be.below(cachedTwo) done() From 68fb8edc080c06893fb301f373ba0c9bf24608fe Mon Sep 17 00:00:00 2001 From: malex Date: Thu, 12 May 2016 12:21:07 +0300 Subject: [PATCH 094/117] lint --- lib/github.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/github.js b/lib/github.js index af4dcc5..db30cb8 100644 --- a/lib/github.js +++ b/lib/github.js @@ -136,7 +136,7 @@ function cmdGet (msg, done) { }, getPullRequests: function (cb) { - github.pullRequests.getAll({user: params.user, repo: params.repo, state: 'open'}, function(err, data){ + github.pullRequests.getAll({user: params.user, repo: params.repo, state: 'open'}, function (err, data) { if (err) { context.log.debug(`Read Github pull requests for ${moduleName} get error: ${err}`) } From bee20aab1b039d12c05904c5e2007470113172b1 Mon Sep 17 00:00:00 2001 From: Mircea Alexandru Date: Thu, 12 May 2016 13:10:17 +0300 Subject: [PATCH 095/117] Bump version to 6.3.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 7dca491..975ca2b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nodezoo-github", - "version": "6.2.2", + "version": "6.3.0", "description": "A micro-service that provides Github related information to NodeZoo", "scripts": { "start": "node srv/start.js", From 103a15cd600e8adf523cd70a22d3daf0b64d33f6 Mon Sep 17 00:00:00 2001 From: malex Date: Mon, 6 Jun 2016 10:55:10 +0300 Subject: [PATCH 096/117] added env variables --- srv/start.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/srv/start.js b/srv/start.js index a519213..780fa5b 100644 --- a/srv/start.js +++ b/srv/start.js @@ -17,6 +17,8 @@ var opts = { }, mesh: { auto: true, + host: envs.GITHUB_HOST || '127.0.0.1', + bases: [envs.BASE_HOST || '127.0.0.1:39999'], listen: [ {pin: 'role:github,cmd:get', model: 'consume'}, {pin: 'role:info,req:part', model: 'observe'} From 541e4d684f4bc3ac50e4c48dfc42de323e1d46f9 Mon Sep 17 00:00:00 2001 From: malex Date: Mon, 6 Jun 2016 18:25:44 +0300 Subject: [PATCH 097/117] fix for env --- srv/start.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/srv/start.js b/srv/start.js index 780fa5b..fd7fe23 100644 --- a/srv/start.js +++ b/srv/start.js @@ -20,8 +20,8 @@ var opts = { host: envs.GITHUB_HOST || '127.0.0.1', bases: [envs.BASE_HOST || '127.0.0.1:39999'], listen: [ - {pin: 'role:github,cmd:get', model: 'consume'}, - {pin: 'role:info,req:part', model: 'observe'} + {pin: 'role:github,cmd:get', model: 'consume', host: envs.GITHUB_HOST || '127.0.0.1'}, + {pin: 'role:info,req:part', model: 'observe', host: envs.GITHUB_HOST || '127.0.0.1'} ] }, isolated: { From 7e079e5c5f75cb98f910870f785521734d9c18f4 Mon Sep 17 00:00:00 2001 From: malex Date: Tue, 7 Jun 2016 15:07:23 +0300 Subject: [PATCH 098/117] update should be set correctly. Fixes #84 --- lib/github.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/github.js b/lib/github.js index db30cb8..1b35340 100644 --- a/lib/github.js +++ b/lib/github.js @@ -28,6 +28,7 @@ module.exports = function (options) { function cmdGet (msg, done) { let moduleName = msg.name + let cache = opts.cache let registry = opts.registry + moduleName let context = this @@ -39,6 +40,7 @@ function cmdGet (msg, done) { } if (github && !msg.update) { + context.log.debug('Returned cached information: ', moduleName) return done(null, {ok: true, data: github.data$(github)}) } @@ -195,7 +197,7 @@ function aliasGet (msg, done) { var seneca = this var payload = {name: msg.name} - seneca.act('role:github,cmd:get', payload, (err, res) => { + seneca.act(`role:github, cmd:get, update: ${msg.update}`, payload, (err, res) => { if (err) { return done(null, {ok: false, err: err}) } From 52dc586520ebdbf6dd2961a018d50c9ff24d9be4 Mon Sep 17 00:00:00 2001 From: malex Date: Tue, 7 Jun 2016 15:11:27 +0300 Subject: [PATCH 099/117] Log rate limit and available rate. Fixes #82 --- lib/github.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/github.js b/lib/github.js index 1b35340..eb236c4 100644 --- a/lib/github.js +++ b/lib/github.js @@ -102,6 +102,13 @@ function cmdGet (msg, done) { Async.parallel({ getRepository: function (cb) { github.repos.get({user: params.user, repo: params.repo}, function (err, data) { + if (data && data.meta){ + context.log.debug('Github rate limit information: ', { + 'x-ratelimit-remaining': data.meta['x-ratelimit-remaining'], + 'x-ratelimit-limit': data.meta['x-ratelimit-limit'] + }) + } + if (err) { context.log.debug(`Read repo for ${moduleName} get error: ${err}`) } @@ -197,7 +204,7 @@ function aliasGet (msg, done) { var seneca = this var payload = {name: msg.name} - seneca.act(`role:github, cmd:get, update: ${msg.update}`, payload, (err, res) => { + seneca.act(`role:github, cmd:get, update: ${msg.update || false}`, payload, (err, res) => { if (err) { return done(null, {ok: false, err: err}) } From 05c5b61bf2cfd56685b0f226907aa82163a9008b Mon Sep 17 00:00:00 2001 From: Shane Lacey Date: Mon, 13 Jun 2016 11:41:59 +0100 Subject: [PATCH 100/117] List of files for npm publish in package --- package.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/package.json b/package.json index 975ca2b..5174a98 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,14 @@ "github", "microservice" ], + "files": [ + "README.md", + "package.json", + "LICENSE", + "Dockerfile", + "lib", + "srv" + ], "author": "Richard Rodger (github.com/rjrodger)", "contributors": [ "Jane Quinn (github.com/CodeWriterWriter)", From 729f70bc4afa1cf4e2012315cc7378004d49057a Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Wed, 29 Mar 2017 17:27:37 +0100 Subject: [PATCH 101/117] github --- .dockerignore | 1 - Dockerfile | 18 -------------- github.js | 31 ++++++++++++------------ package.json | 35 ++++++++++++++++++-------- srv/github-dev.js | 62 +++++++++++++++++++++++++++++++++++++---------- 5 files changed, 90 insertions(+), 57 deletions(-) delete mode 100644 .dockerignore delete mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 8d98f9d..0000000 --- a/.dockerignore +++ /dev/null @@ -1 +0,0 @@ -.* diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 216d147..0000000 --- a/Dockerfile +++ /dev/null @@ -1,18 +0,0 @@ -# nodezoo-github - -FROM node:4 - -ADD . / - -EXPOSE 44004 -EXPOSE 43004 - -CMD ["node","srv/github-dev.js","--seneca.options.tag=github","--seneca.log.all"] - -# build and run: -# $ docker build -t nodezoo-github-04 . -# $ docker run -d -p 44004:44004 -p 43004:43004 -e HOST=$(docker-machine ip default) -e REDIS=192.168.99.1 -e TOKEN=`cat srv/.ignore-token` --volumes-from nodezoo-level nodezoo-github-04 -# local docker ip: -# $ docker-machine ip default - - diff --git a/github.js b/github.js index c61103d..b7710e8 100644 --- a/github.js +++ b/github.js @@ -1,17 +1,11 @@ -/* Copyright (c) 2014-2015 Richard Rodger, MIT License */ -/* jshint node:true, asi:true, eqnull:true */ -"use strict"; +/* Copyright (c) 2014-2017 Richard Rodger and other contributors, MIT License */ -var GitHubAPI = require('github') +var Github = require('github') -var gitapi = new GitHubAPI({ - version: "3.0.0" -}) - -module.exports = function github( options ){ +module.exports = function github ( options ){ var seneca = this options = seneca.util.deepextend({ @@ -19,6 +13,8 @@ module.exports = function github( options ){ },options) + var gitapi = new Github() + seneca.add( 'role:github,cmd:get', cmd_get ) seneca.add( 'role:github,cmd:query', cmd_query ) @@ -48,7 +44,7 @@ module.exports = function github( options ){ seneca.act( 'role:github,cmd:query', - {name:github_name,user:out.user,repo:out.repo}, + {name:github_name,owner:out.owner,repo:out.repo}, done) }) } @@ -62,27 +58,32 @@ module.exports = function github( options ){ var github_ent = seneca.make$('github') var github_name = args.name - var user = args.user + var owner = args.owner var repo = args.repo + +/* gitapi.authenticate({ type: "basic", username: options.token, password: 'x-oauth-basic' }) +*/ gitapi.repos.get( { - user: user, + owner: owner, repo: repo }, - function(err,repo){ + function (err, out) { if( err ) return done(err); + var repo = out.data + var data if( repo ) { data = { - user: args.user, + owner: args.owner, repo: args.repo, stars: repo.stargazers_count, watches: repo.subscribers_count, @@ -114,7 +115,7 @@ module.exports = function github( options ){ var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) if( m ) { - return done( null, { user:m[1], repo:m[2] }) + return done( null, { owner:m[1], repo:m[2] }) } else return done(); } diff --git a/package.json b/package.json index fc5324b..f179c53 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nodezoo-github", - "version": "5.0.0", - "description": "nodezoo.com micro-service handling github meta data", + "version": "1.0.0-tms-dev", + "description": "nodezoo-github", "main": "github.js", "keywords": [ "nodezoo", @@ -9,15 +9,30 @@ "github", "microservice" ], - "author": "Richard Rodger (richard.rodger@nearform.com)", + "scripts": { + "test": "lab -P test" + }, + "repository": { + "type": "git", + "url": "https://github.com/nodezoo/nodezoo-github.git" + }, + "author": "Richard Rodger (http://richardrodger.com)", "license": "MIT", + "bugs": { + "url": "https://github.com/nodezoo/nodezoo-github/issues" + }, + "homepage": "https://github.com/nodezoo/nodezoo-github", + "dependencies": { - "github": "^0.2.2", - "seneca-redis-transport": "^0.3.0", - "seneca-level-store": "^0.2.3", - "seneca": "https://github.com/senecajs/seneca", - "seneca-msgstats": "https://github.com/rjrodger/seneca-msgstats", - "seneca-mesh": "https://github.com/rjrodger/seneca-mesh", - "seneca-balance-client": "https://github.com/rjrodger/seneca-balance-client" + "github": "9.2.0", + "seneca": "3.3.0", + "seneca-entity": "2.0.0", + "seneca-jsonfile-store": "1.0.0", + "seneca-redis-transport": "0.3.0", + "seneca-repl": "1.0.0" + }, + "devDependencies": { + "code": "4.0.0", + "lab": "13.0.1" } } diff --git a/srv/github-dev.js b/srv/github-dev.js index fe02102..e53fdd4 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -1,15 +1,24 @@ +/* Copyright (c) 2014-2017 Richard Rodger and other contributors, MIT License */ + +var MOCK_NPM = JSON.parse(process.env.MOCK_NPM || 'false') +var MOCK_INFO = JSON.parse(process.env.MOCK_INFO || 'false') +var MOCK = MOCK_NPM || MOCK_INFO -var HOST = process.env.HOST || 'localhost' var TOKEN = process.env.TOKEN || 'NO_TOKEN' -require('seneca')() - .use('redis-transport') - .use('level-store') +var Seneca = require('seneca') + + +Seneca({tag: 'github'}) + .test('print') - .use('../github.js',{token:TOKEN}) + .use('entity') + .use('jsonfile-store', {folder: __dirname+'/data'}) - .add('role:info,req:part',function(args,done){ + .use('..',{token:TOKEN}) + + .add('role:info,need:part',function(args,done){ done() this.act( @@ -21,8 +30,8 @@ require('seneca')() if( mod ) { return this.act( - 'role:info,res:part,part:github', - {name:args.name,data:mod.data$()}) + 'role:info,collect:part,part:github', + {name:args.name,data:this.util.clean(mod.data$())}) } this.act( @@ -38,8 +47,8 @@ require('seneca')() if( err ) return; if( mod ) { - this.act('role:info,res:part,part:github', - {name:args.name,data:mod.data$()}) + this.act('role:info,collect:part,part:github', + {name:args.name,data:this.util.clean(mod.data$())}) } }) } @@ -47,7 +56,34 @@ require('seneca')() }) }) - .use( 'mesh', - {auto:true, pins:['role:github','role:info,req:part'], model:'publish'} ) - .repl(33004) + .use('seneca-repl', {port:10050}) + + .listen(9050) + + .client({pin:'role:info', port:9030}) + .client({pin:'role:npm', port:9040}) + + +// Run mock services that this service depends on. +if (MOCK) { + var mock = Seneca({tag:'mock'}) + .test('print') + .use('entity') + + if (MOCK_NPM) { + mock + .listen(9040) + .add('role:npm', function (msg, reply) { + reply({"entity$":{"name":"npm"},"name":"jsonic","version":"0.2.2","giturl":"git://github.com/rjrodger/jsonic.git","desc":"JSON parser that isn't strict","readme":"","id":"jsonic"}) + }) + } + + if (MOCK_INFO) { + mock + .listen(9030) + .add('role:info', function (msg, reply) { + reply() + }) + } +} From e1951fb21375d2da80cf7161eef0de94bb93cdb3 Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Thu, 30 Mar 2017 20:35:39 +0100 Subject: [PATCH 102/117] stage --- .gitignore | 5 +++- docker/stage/Dockerfile | 11 +++++++++ docker/stage/Makefile | 11 +++++++++ srv/github-stage.js | 55 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 docker/stage/Dockerfile create mode 100644 docker/stage/Makefile create mode 100644 srv/github-stage.js diff --git a/.gitignore b/.gitignore index c6ee3c3..6256eba 100644 --- a/.gitignore +++ b/.gitignore @@ -36,4 +36,7 @@ MANIFEST-* srv/data* -.ignore* \ No newline at end of file +.ignore* + + +docker/stage/app diff --git a/docker/stage/Dockerfile b/docker/stage/Dockerfile new file mode 100644 index 0000000..c055fe2 --- /dev/null +++ b/docker/stage/Dockerfile @@ -0,0 +1,11 @@ + +FROM nodezoo-shared + +ADD app /app/ + +CMD ["node", "/app/srv/github-stage.js"] + + + + + diff --git a/docker/stage/Makefile b/docker/stage/Makefile new file mode 100644 index 0000000..a7a6bf0 --- /dev/null +++ b/docker/stage/Makefile @@ -0,0 +1,11 @@ +build : + mkdir -p app/data + mkdir -p app/srv + cp -r ../../github.js app + cp -r ../../srv/*.js app/srv + docker build -t nodezoo-github . + +clean : + rm *~ + +.PHONY : build clean diff --git a/srv/github-stage.js b/srv/github-stage.js new file mode 100644 index 0000000..a2f31fd --- /dev/null +++ b/srv/github-stage.js @@ -0,0 +1,55 @@ +/* Copyright (c) 2014-2017 Richard Rodger and other contributors, MIT License */ + +var PORT = process.env.PORT || 9000 +var Seneca = require('seneca') + +Seneca({tag: 'github'}) + .listen(PORT) + + .use('entity') + .use('jsonfile-store', {folder: __dirname+'/../data'}) + + .use('../github.js') + + .add('role:info,need:part',function(args,done){ + done() + + this.act( + 'role:github,cmd:get', + {name:args.name}, + + function(err,mod){ + if( err ) return; + + if( mod ) { + return this.act( + 'role:info,collect:part,part:github', + {name:args.name,data:this.util.clean(mod.data$())}) + } + + this.act( + 'role:npm,cmd:get', {name:args.name}, + function(err,mod){ + if( err ) return; + + if( mod ) { + this.act( + 'role:github,cmd:get', + {name:args.name,giturl:mod.giturl}, + function( err, mod ){ + if( err ) return; + + if( mod ) { + this.act('role:info,collect:part,part:github', + {name:args.name,data:this.util.clean(mod.data$())}) + } + }) + } + }) + }) + }) + + .client({pin:'role:info', host:'info', port:PORT}) + .client({pin:'role:npm', host:'npm', port:PORT}) + + From 310ecea4a0811d158b64f79c513bf2f0adddd659 Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Fri, 31 Mar 2017 14:26:35 +0100 Subject: [PATCH 103/117] stage --- srv/github-stage.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/srv/github-stage.js b/srv/github-stage.js index a2f31fd..d008643 100644 --- a/srv/github-stage.js +++ b/srv/github-stage.js @@ -6,6 +6,7 @@ var Seneca = require('seneca') Seneca({tag: 'github'}) .listen(PORT) + .use('redis-transport') .use('entity') .use('jsonfile-store', {folder: __dirname+'/../data'}) @@ -49,7 +50,9 @@ Seneca({tag: 'github'}) }) }) - .client({pin:'role:info', host:'info', port:PORT}) + .listen({pin:'role:info,need:part', type:'redis', host:'redis'}) + .client({pin:'role:info,collect:part', type:'redis', host:'redis'}) + .client({pin:'role:npm', host:'npm', port:PORT}) From f9b4f4ef74ad4b7f76d65ae797a617ab84cacf6a Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Thu, 18 May 2017 10:41:19 +0100 Subject: [PATCH 104/117] tms --- docker/stage/Dockerfile | 2 +- docker/stage/Dockerfile-prod | 9 +++ docker/stage/Makefile | 3 +- github.js | 133 +++++++++++++---------------------- srv/github-prod.js | 54 ++++++++++++++ 5 files changed, 114 insertions(+), 87 deletions(-) create mode 100644 docker/stage/Dockerfile-prod create mode 100644 srv/github-prod.js diff --git a/docker/stage/Dockerfile b/docker/stage/Dockerfile index c055fe2..969b4a7 100644 --- a/docker/stage/Dockerfile +++ b/docker/stage/Dockerfile @@ -1,5 +1,5 @@ -FROM nodezoo-shared +FROM nodezoo-shared:1 ADD app /app/ diff --git a/docker/stage/Dockerfile-prod b/docker/stage/Dockerfile-prod new file mode 100644 index 0000000..db10b4c --- /dev/null +++ b/docker/stage/Dockerfile-prod @@ -0,0 +1,9 @@ + +FROM nodezoo-github:1 + +CMD ["node", "/app/srv/github-prod.js"] + + + + + diff --git a/docker/stage/Makefile b/docker/stage/Makefile index a7a6bf0..838d19f 100644 --- a/docker/stage/Makefile +++ b/docker/stage/Makefile @@ -3,7 +3,8 @@ build : mkdir -p app/srv cp -r ../../github.js app cp -r ../../srv/*.js app/srv - docker build -t nodezoo-github . + docker build -t nodezoo-github:1 . + docker build -t nodezoo-github-prod:1 -f Dockerfile-prod . clean : rm *~ diff --git a/github.js b/github.js index b7710e8..cf4a83b 100644 --- a/github.js +++ b/github.js @@ -18,107 +18,70 @@ module.exports = function github ( options ){ seneca.add( 'role:github,cmd:get', cmd_get ) seneca.add( 'role:github,cmd:query', cmd_query ) - seneca.add( 'role:github,cmd:parse', cmd_parse ) + function cmd_get( msg, reply ) { + this + .make$('github') + .load$( msg.name, function (err, mod) { + if( err ) return reply(err) - function cmd_get( args, done ) { - var seneca = this - var github_ent = seneca.make$('github') - - var github_name = args.name - - github_ent.load$( github_name, function(err,github_mod){ - if( err ) return done(err); + if( mod ) { + return reply(mod) + } - if( github_mod ) { - return done(null,github_mod); - } - else if( args.giturl ) { - seneca.act( - 'role:github,cmd:parse', - {name:github_name,giturl:args.giturl}, + var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(msg.giturl) + if (!m) return reply() - function(err,out){ - if( err ) return done(err); - seneca.act( - 'role:github,cmd:query', - {name:github_name,owner:out.owner,repo:out.repo}, - done) - }) - } - else return done(); - }) + this.act( + { + role: 'github', + cmd: 'query', + name: msg.name, + owner: m[1], + repo: m[2] + }, + reply) + }) } - function cmd_query( args, done ) { + function cmd_query( msg, reply ) { var seneca = this - var github_ent = seneca.make$('github') - - var github_name = args.name - var owner = args.owner - var repo = args.repo - - -/* - gitapi.authenticate({ - type: "basic", - username: options.token, - password: 'x-oauth-basic' - }) -*/ gitapi.repos.get( - { - owner: owner, - repo: repo - }, + { owner: msg.owner, repo: msg.repo }, function (err, out) { - if( err ) return done(err); - - var repo = out.data - - var data - if( repo ) { - data = { - owner: args.owner, - repo: args.repo, - stars: repo.stargazers_count, - watches: repo.subscribers_count, - forks: repo.forks_count, - last: repo.pushed_at - } - - github_ent.load$(github_name, function(err,github_mod){ - if( err ) return done(err); - - if( github_mod ) { - return github_mod.data$(data).save$(done); + if (err) return reply(err) + + var data = { + owner: msg.owner, + repo: msg.repo, + stars: out.data.stargazers_count, + watches: out.data.subscribers_count, + forks: out.data.forks_count, + last: out.data.pushed_at + } + + seneca + .make$('github') + .load$(msg.name, function (err, mod) { + if (err) return reply(err) + + if (mod) { + return mod + .data$(data) + .save$(reply) } else { - data.id$ = github_name - github_ent.make$(data).save$(done); + data.id$ = msg.name + seneca + .make$('github') + .data$(data) + .save$(reply) } }) - } - else return done() - - } - ) + }) } - - - function cmd_parse( args, done ) { - var seneca = this - - var m = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(args.giturl) - if( m ) { - return done( null, { owner:m[1], repo:m[2] }) - } - else return done(); - } - - } diff --git a/srv/github-prod.js b/srv/github-prod.js new file mode 100644 index 0000000..f91a1af --- /dev/null +++ b/srv/github-prod.js @@ -0,0 +1,54 @@ +/* Copyright (c) 2014-2017 Richard Rodger and other contributors, MIT License */ + +var BASES = process.env.BASES.split(',') + +var Seneca = require('seneca') + +Seneca({tag: 'github'}) + .use('entity') + .use('jsonfile-store', {folder: __dirname+'/../data'}) + + .use('../github.js') + + .add('role:info,need:part', function (msg, reply) { + reply() + + this.act( + 'role:github,cmd:get', {name:msg.name}, + function (err, mod) { + if (err) return + + if (mod) { + return this.act('role:info,collect:part,part:github', + {name:msg.name,data:this.util.clean(mod.data$())}) + } + + this.act( + 'role:npm,cmd:get', {name:msg.name}, + function (err, mod) { + if (err) return + + if (mod) { + this.act( + 'role:github,cmd:get', {name:msg.name, giturl:mod.giturl}, + function( err, mod ){ + if( err ) return + + if( mod ) { + this.act('role:info,collect:part,part:github', + {name:msg.name,data:this.util.clean(mod.data$())}) + } + }) + } + }) + }) + }) + + .use('mesh', { + listen: [ + {pin: 'role:github'}, + {pin: 'role:info,need:part', model:'observe'} + ], + bases: BASES, + host: '@eth0', + }) From e739571a91e13ccec5c145d77239bdc627c41dd3 Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Thu, 18 May 2017 11:01:27 +0100 Subject: [PATCH 105/117] tms --- test/github.test.js | 66 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 test/github.test.js diff --git a/test/github.test.js b/test/github.test.js new file mode 100644 index 0000000..4b204e7 --- /dev/null +++ b/test/github.test.js @@ -0,0 +1,66 @@ +/* Copyright (c) 2014-2017 Richard Rodger and other contributors, MIT License */ + +var Code = require('code') +var Lab = require('lab') +var Seneca = require('seneca') + +var lab = exports.lab = Lab.script() +var describe = lab.describe +var it = lab.it +var expect = Code.expect + + +describe('npm', function () { + + it('query', {timeout: 8888}, function (done) { + var seen = {} + + Seneca() + + // Place Seneca into test mode. Errors will be passed to done callback, + // so no need to handle them in callbacks. + .test(done) + + // Uncomment if you want to see detailed logs + //.test(done, 'print') + + .use('entity') + + // Load the github plugin + .use('..') + + .sub('role:entity', function (msg) { + seen[msg.cmd] = 1 + (seen[msg.cmd]||0) + }) + + .gate() + + .act('role:github,cmd:query,owner:senecajs,repo:seneca,name:seneca', function (ignore, out) { + expect(out.owner).equal('senecajs') + expect(out.repo).equal('seneca') + expect(out.stars).above(0) + expect(seen).to.equal({ load: 1, save: 1 }) + }) + + .act('role:github,cmd:get,name:seneca', function (ignore, out) { + expect(out.owner).equal('senecajs') + expect(out.repo).equal('seneca') + expect(out.stars).above(0) + + expect(seen).to.equal({ load: 2, save: 1 }) + }) + + + .act('role:github,cmd:get,name:seneca', function (ignore, out) { + expect(out.owner).equal('senecajs') + expect(out.repo).equal('seneca') + expect(out.stars).above(0) + + expect(seen).to.equal({ load: 3, save: 1 }) + }) + + .ready(done) + }) +}) + + From a529662195c80d1ec872d241e6f8591aa0794638 Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Wed, 24 May 2017 16:58:39 +0000 Subject: [PATCH 106/117] msdlon --- package.json | 5 +++- srv/github-dev-mesh.js | 55 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 srv/github-dev-mesh.js diff --git a/package.json b/package.json index f179c53..9887834 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,10 @@ "dependencies": { "github": "9.2.0", - "seneca": "3.3.0", + "seneca": "../seneca", + "seneca-balance-client": "../seneca-balance-client", + "seneca-monitor": "../seneca-monitor", + "seneca-mesh": "../seneca-mesh", "seneca-entity": "2.0.0", "seneca-jsonfile-store": "1.0.0", "seneca-redis-transport": "0.3.0", diff --git a/srv/github-dev-mesh.js b/srv/github-dev-mesh.js new file mode 100644 index 0000000..cf6bb9d --- /dev/null +++ b/srv/github-dev-mesh.js @@ -0,0 +1,55 @@ +/* Copyright (c) 2014-2017 Richard Rodger and other contributors, MIT License */ + +var Seneca = require('seneca') + +Seneca({tag: 'github'}) + .test() + + .use('entity') + .use('jsonfile-store', {folder: __dirname+'/../data'}) + + .use('../github.js') + + .use('monitor') + + .use('mesh', { + listen: [ + {pin: 'role:github'}, + {pin: 'role:info,need:part', model:'observe'} + ] + }) + + .add('role:info,need:part', function (msg, reply) { + reply() + + this.act( + 'role:github,cmd:get', {name:msg.name}, + function (err, mod) { + if (err) return + + if (mod) { + return this.act('role:info,collect:part,part:github', + {name:msg.name,data:this.util.clean(mod.data$())}) + } + + this.act( + 'role:npm,cmd:get', {name:msg.name}, + function (err, mod) { + if (err) return + + if (mod) { + this.act( + 'role:github,cmd:get', {name:msg.name, giturl:mod.giturl}, + function( err, mod ){ + if( err ) return + + if( mod ) { + this.act('role:info,collect:part,part:github', + {name:msg.name,data:this.util.clean(mod.data$())}) + } + }) + } + }) + }) + }) + From 8779d5b6501ecf914cd171099c0b047217c41629 Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Mon, 7 Aug 2017 13:25:41 +0100 Subject: [PATCH 107/117] ng fix --- package.json | 8 ++++---- srv/github-dev-mesh.js | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 9887834..651137e 100644 --- a/package.json +++ b/package.json @@ -26,13 +26,13 @@ "dependencies": { "github": "9.2.0", "seneca": "../seneca", - "seneca-balance-client": "../seneca-balance-client", + "seneca-balance-client": "0.6.1", "seneca-monitor": "../seneca-monitor", - "seneca-mesh": "../seneca-mesh", - "seneca-entity": "2.0.0", + "seneca-mesh": "0.10.0", + "seneca-entity": "2.0.2", "seneca-jsonfile-store": "1.0.0", "seneca-redis-transport": "0.3.0", - "seneca-repl": "1.0.0" + "seneca-repl": "1.1.2" }, "devDependencies": { "code": "4.0.0", diff --git a/srv/github-dev-mesh.js b/srv/github-dev-mesh.js index cf6bb9d..2a85aca 100644 --- a/srv/github-dev-mesh.js +++ b/srv/github-dev-mesh.js @@ -4,14 +4,13 @@ var Seneca = require('seneca') Seneca({tag: 'github'}) .test() + .use('monitor') .use('entity') .use('jsonfile-store', {folder: __dirname+'/../data'}) .use('../github.js') - .use('monitor') - .use('mesh', { listen: [ {pin: 'role:github'}, From 8bedeefcfa40aaf0e46c6ca34d4d8f3c357366c2 Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Fri, 11 Aug 2017 18:26:00 +0100 Subject: [PATCH 108/117] v1.0.0 --- .travis.yml | 9 +++++++++ package.json | 12 ++++++------ 2 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..f19a6ae --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +sudo: required +language: node_js +dist: trusty + +node_js: + - '4' + - '6' + - '8' + diff --git a/package.json b/package.json index 651137e..d516f58 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nodezoo-github", - "version": "1.0.0-tms-dev", + "version": "1.0.0", "description": "nodezoo-github", "main": "github.js", "keywords": [ @@ -25,17 +25,17 @@ "dependencies": { "github": "9.2.0", - "seneca": "../seneca", + "seneca": "3.4.2", "seneca-balance-client": "0.6.1", - "seneca-monitor": "../seneca-monitor", - "seneca-mesh": "0.10.0", + "seneca-monitor": "0.1.0", + "seneca-mesh": "0.11.0", "seneca-entity": "2.0.2", "seneca-jsonfile-store": "1.0.0", "seneca-redis-transport": "0.3.0", "seneca-repl": "1.1.2" }, "devDependencies": { - "code": "4.0.0", - "lab": "13.0.1" + "code": "4.1.x", + "lab": "14.0.x" } } From fcb20a716e4dd3d453ec61d2ee6cc4b36a79568a Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Fri, 11 Aug 2017 18:27:21 +0100 Subject: [PATCH 109/117] cleanout --- CHANGELOG.md | 26 ------ Dockerfile | 14 --- LICENSE | 21 ----- README.md | 171 ---------------------------------- lib/github.js | 219 -------------------------------------------- package.json | 64 ------------- srv/start.js | 49 ---------- test/github.test.js | 138 ---------------------------- test/npm-data.js | 119 ------------------------ 9 files changed, 821 deletions(-) delete mode 100644 CHANGELOG.md delete mode 100644 Dockerfile delete mode 100644 LICENSE delete mode 100644 README.md delete mode 100644 lib/github.js delete mode 100644 package.json delete mode 100644 srv/start.js delete mode 100644 test/github.test.js delete mode 100644 test/npm-data.js diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index 522aa34..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,26 +0,0 @@ -##Pending - x.x.x - -* toolbag removed. -* Checking that github url exists before trying to extract user and repo -* Stars, forks and watches are now assigned 0 instead of an empty string if repo.* is empty -* Sample data added to Readme. - -## 10 April - 6.2.0 - -* Added support for redis to enable hard caching -* Updated isolated mode to run without redis - -## 7 April 2016 - 6.1.0 - -* Added CHANGELOG.md -* Removed redundant data folder. -* Removed unneeded build.sh. -* Moved logic script into lib. -* Refactored start.js and github.js for clarity. -* Removed unneeded seneca actions -* Added isolation mode -* Updated docs to reflect changes - -## 6 April 2016 - 6.0.0 - -* First release of the 6th major revision of nodezoo. diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index abde0e4..0000000 --- a/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -# nodezoo-github -FROM node:4 - -RUN mkdir /src - -ADD package.json /src/ - -WORKDIR /src - -RUN npm install - -COPY . /src - -CMD ["node", "srv/start.js", "--seneca.options.tag=nodezoo-github", "--seneca-log=type:act"] diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 12abeb9..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014-2016 Richard Rodger - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/README.md b/README.md deleted file mode 100644 index ebb28bd..0000000 --- a/README.md +++ /dev/null @@ -1,171 +0,0 @@ -![Nodezoo][Logo] - -# nodezoo-github - -- __Lead:__ [Dean McDonnell][Lead] -- __Sponsor:__ [nearForm][Sponsor] - -A micro-service that provides Github related information to [NodeZoo][]. This -micro-service requires a valid Github token to function, please see the Config -section below for details on how to obtain. - -If you're using this micro-service, and need help, you can: - -- Post a [github issue][], -- Tweet to [@nodezoo][], -- Ask on the [Gitter][gitter-url]. - -## Running -This micro-service can be ran as part of a complete system or as a single isolated -unit. - -### As a complete system -A special system repository is available that runs the complete system using Docker -and Fuge. - -- [Nodezoo: The complete system][System] - -### Isolated mode -To make testing easier this micro-service can be ran in 'isolated' mode. This mode -allows testing over http using a well defined port. Please note isolated mode means -patterns are not exposed via mesh. - -To run in isolated mode, - - - Clone this repository locally, - - Run `npm install`, - - Run `GITHUB_TOKEN=YOUR_TOKEN npm start isolated`, - -__Note:__ You will need to have a valid github token to use isolated mode. - -A simple http service is supported and can be called using Curl or other Rest client. -The default port is `8052`. It can be changed using the `GITHUB_PORT` environment -variable. - -``` -curl -d '{"role":"github","cmd":"get","name":"hapi"}' http://localhost:8052/act -``` - -## Configuration - -### Creating a GitHub Personal Access Token -You will need a token for this service if regardless of how you choose to run it. - - - On github.com, click your profile photo, then click settings. - - In the user settings sidebar, click Personal access tokens. - - Click Generate new token - - Give your token a descriptive name. - - Select the scopes you wish to grant, select all read-only scopes - - Click 'Generate token'. - - Copy the token to your clipboard and keep safe. - -### Environment Variables -Various settings can be changed using environment variables, see the list below for -all available variable names. - -#### GITHUB_TOKEN - - The token to use when calling the GitHub api. - - Defaults to `NO_TOKEN`, - -#### GITHUB_HOST - - The host to listen on in isolated mode. - - Defaults to `localhost` - -#### GITHUB_PORT - - The port to listen on in isolated mode. - - Defaults to `8052` . - -#### GITHUB_ISOLATED - - Starts isolated mode. - - Defaults to `false`. - -#### GITHUB_REGISTRY - - Change the registry used to validate the module name. - - Defaults to `http://registry.npmjs.org/`. - - ## Sample Data - ```json - { - "entity$": "-\/-\/github_cache", - "name": "fuge", - "user": "apparatus", - "repo": "fuge", - "stars": 155, - "watches": 15, - "forks": 18, - "last": "2016-04-09T21:57:45Z", - "urlRepo": "https:\/\/github.com\/apparatus\/fuge", - "urlClone": "git+https:\/\/github.com\/apparatus\/fuge.git", - "urlSsh": "git@github.com:apparatus\/fuge.git", - "pullRequests": 1, - "cached": 1461229347738 -} - ``` - -## Messages Handled -This micro-service handles the following messages. - -### `role:github,cmd:get` -Request a module's Github details. The name supplied must be a valid module on npm. - -```js -seneca.act('role:github,cmd:get', {name: 'seneca'}, (err, data) => {}) -``` - -### `role:info,req:part` -Acts as an alias for `role:github,cmd:get` but instead of returning data directly a -message is emitted using the pattern `role:info,res:part`. Allows integration with -the wider nodezoo system. - -```js -seneca.act('role:info, req:part', {name: 'seneca'}, (err, data) => {}) -``` - -## Messages Emitted -This micro-service emits the following messages - -### `role:info,res:part` -Contains the response of an earlier call to `role:info,req:part`. - -```js -seneca.add('role:info,res:part', (msg, done) => {}) -``` - -## Data Emitted -- name - Name of the module -- user - The User or Organisation that owns the repository -- repo - The repository name -- stars - Number of stars -- forks - Number of forks -- watches - Numbers of watchers -- last - The last commit to the repository -- urlRepo - A link to the repository -- urlClone - A clone URL -- urlSsh - An SSH URL -- pullRequests - Open pull requests -- cached - The time the data was last cached at - -## Contributing -The [NodeZoo org][] encourages __open__ and __safe__ participation. - -- __[Code of Conduct]__ - -If you feel you can help in any way, be it with documentation, examples, extra testing, or new -features please get in touch. - -## License -Copyright (c) 2014-2016, Richard Rodger and other contributors. -Licensed under [MIT][]. - -[main repo]: https://github.com/rjrodger/nodezoo -[MIT]: ./LICENSE -[Code of Conduct]: https://github.com/nodezoo/nodezoo-org/blob/master/CoC.md -[Sponsor]: http://www.nearform.com/ -[NodeZoo org]: http://www.nodezoo.com/ -[NodeZoo]: https://github.com/nodezoo -[Lead]: https://github.com/mcdonnelldean -[github issue]: https://github.com/nodezoo/nodezoo-github/issues -[@nodezoo]: http://twitter.com/nodezoo -[gitter-url]: https://gitter.im/nodezoo/nodezoo-org -[System]: https://github.com/nodezoo/nodezoo-system -[Logo]: https://raw.githubusercontent.com/nodezoo/nodezoo-org/master/assets/logo-nodezoo.png diff --git a/lib/github.js b/lib/github.js deleted file mode 100644 index eb236c4..0000000 --- a/lib/github.js +++ /dev/null @@ -1,219 +0,0 @@ -'use strict' - -var GitHub = require('github4') -var github = new GitHub() -var Request = require('request') -var Async = require('async') - -var opts = { - registry: 'http://registry.npmjs.org/', - token: 'NO_TOKEN' -} - -module.exports = function (options) { - var seneca = this - var extend = seneca.util.deepextend - - opts = extend(opts, options) - opts.cache = seneca.make$('github') - opts.cache.load$() - - seneca.add('role:github,cmd:get', cmdGet) - seneca.add('role:info,req:part', aliasGet) - - return { - name: 'nodezoo-github' - } -} - -function cmdGet (msg, done) { - let moduleName = msg.name - - let cache = opts.cache - let registry = opts.registry + moduleName - let context = this - - context.log.debug(`Processing module: ${moduleName}`) - cache.load$(moduleName, (err, github) => { - if (err) { - context.log.debug(`Cannot load from cache module ${moduleName}, try now to get it remotely`) - } - - if (github && !msg.update) { - context.log.debug('Returned cached information: ', moduleName) - return done(null, {ok: true, data: github.data$(github)}) - } - - Request.get({url: registry, gzip: true}, (err, res, body) => { - if (err) { - return done(err) - } - - var data = null - - try { - data = JSON.parse(body) - } - catch (e) { - return done(e) - } - - var distTags = data['dist-tags'] || {} - var latest = ((data.versions || {})[distTags.latest]) || {} - var repository = latest.repository || {} - var url = repository.url || '' - - context.log.debug(`Module: ${moduleName}, github url: ${url}`) - if (url.length > 0) { - var matches = /[\/:]([^\/:]+?)[\/:]([^\/]+?)(\.git)*$/.exec(url) - - if (matches && matches.length >= 2) { - var params = { - name: moduleName, - url: url, - user: matches[1] || null, - repo: matches[2] || null - } - - if (!params.user || !params.repo) { - return done(null, {ok: false, err: new Error(`module ${moduleName} not found on github`)}) - } - - queryGithub(params, done) - } - else { - return done(null, {ok: false, err: new Error(`invalid github url: ${url}, for module: ${moduleName}`)}) - } - } - else { - return done(null, {ok: false, err: new Error(`module ${moduleName} not found on github`)}) - } - }) - }) - - function queryGithub (params, done) { - var cache = opts.cache - - github.authenticate({ - type: 'token', - token: opts.token - }) - - Async.parallel({ - getRepository: function (cb) { - github.repos.get({user: params.user, repo: params.repo}, function (err, data) { - if (data && data.meta){ - context.log.debug('Github rate limit information: ', { - 'x-ratelimit-remaining': data.meta['x-ratelimit-remaining'], - 'x-ratelimit-limit': data.meta['x-ratelimit-limit'] - }) - } - - if (err) { - context.log.debug(`Read repo for ${moduleName} get error: ${err}`) - } - - cb(err, data) - }) - }, - - getReadme: function (cb) { - github.repos.getReadme({user: params.user, repo: params.repo}, (err, readme) => { - if (err) { - context.log.debug(`Read readme for ${moduleName} get error: ${err}`) - // don't report error, as we want to search for other information, even if Readme is not loaded - return cb(null, false) - } - - if (!readme || !readme.content) { - context.log.debug(`Read readme for ${moduleName} no content`) - return cb(null, false) - } - - github.misc.renderMarkdownRaw({ - data: new Buffer(readme.content, 'base64').toString('ascii') - }, (err, response) => { - if (err && !response) { - context.log.debug(`Render readme for ${moduleName} error: ${err}`) - // don't report error, as we want to search for other information, even if Readme is not loaded - return cb(null, false) - } // API fails expecting a JSON object - - cb(null, response.data) - }) - }) - }, - - getPullRequests: function (cb) { - github.pullRequests.getAll({user: params.user, repo: params.repo, state: 'open'}, function (err, data) { - if (err) { - context.log.debug(`Read Github pull requests for ${moduleName} get error: ${err}`) - } - - // don't report error, as we might have useful data - return cb() - }) - } - }, (err, results) => { - if (err) { - context.log.debug(`Read pull requests for ${moduleName} got error: ${err}`) - return done(null, {ok: false, err: err}) - } - var data = { - name: params.repo || '', - user: params.user || '', - repo: params.repo || '', - stars: results.getRepository ? results.getRepository.stargazers_count || 0 : 0, - watches: results.getRepository ? results.getRepository.subscribers_count || 0 : 0, - forks: results.getRepository ? results.getRepository.forks_count || 0 : 0, - last: results.getRepository ? results.getRepository.pushed_at || '' : '', - urlRepo: 'https://github.com/' + params.user + '/' + params.repo, - urlClone: 'git+https://github.com/' + params.user + '/' + params.repo + '.git', - urlSsh: 'git@github.com:' + params.user + '/' + params.repo + '.git', - readme: results.getReadme, - pullRequests: results.getPullRequests && results.getPullRequests.length || 0, - cached: Date.now() - } - - context.log.debug(`Read Github data for module ${moduleName} completed.`) - cache.load$(params.name, (err, cached) => { - if (err) { - return complete(err) - } - - if (cached) { - return cached.data$(data).save$(complete) - } - - data.id$ = params.name - cache.make$(data).save$(complete) - }) - - function complete (err, data) { - if (err) { - context.log.debug(`Save Github data for ${moduleName} got error: ${err}`) - return done(err) - } - else done(null, {ok: true, data: data ? data.data$(data) : data}) - } - }) - } -} - -function aliasGet (msg, done) { - var seneca = this - var payload = {name: msg.name} - - seneca.act(`role:github, cmd:get, update: ${msg.update || false}`, payload, (err, res) => { - if (err) { - return done(null, {ok: false, err: err}) - } - - if (res && res.ok) { - payload.data = res.data - seneca.act('role:info,res:part,part:github', payload) - } - - done(null, {ok: true}) - }) -} diff --git a/package.json b/package.json deleted file mode 100644 index 5174a98..0000000 --- a/package.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "name": "nodezoo-github", - "version": "6.3.0", - "description": "A micro-service that provides Github related information to NodeZoo", - "scripts": { - "start": "node srv/start.js", - "isolated": "GITHUB_ISOLATED=true node srv/start.js", - "lint": "lab -P test -dL", - "test": "lab -v -P test -L -c -t 64", - "cov": "lab -s -P test -r lcov | coveralls" - }, - "main": "lib/github.js", - "keywords": [ - "nodezoo", - "seneca", - "github", - "microservice" - ], - "files": [ - "README.md", - "package.json", - "LICENSE", - "Dockerfile", - "lib", - "srv" - ], - "author": "Richard Rodger (github.com/rjrodger)", - "contributors": [ - "Jane Quinn (github.com/CodeWriterWriter)", - "Glen Keane (github.com/thekemkid)", - "Dean McDonnell (github.com/mcdonnelldean)", - "Matthew O'Connor (github.com/matt-oc)", - "Shane Lacey (github.com/shanel262)" - ], - "homepage": "https://github.com/nodezoo/nodezoo-github#readme", - "repository": { - "type": "git", - "url": "git+https://github.com/nodezoo/nodezoo-github.git" - }, - "bugs": { - "url": "https://github.com/nodezoo/nodezoo-github/issues" - }, - "license": "MIT", - "dependencies": { - "async": "^2.0.0-rc.4", - "github4": "1.0.0", - "request": "2.72.0", - "seneca": "2.0.1", - "seneca-balance-client": "0.5.x", - "seneca-entity": "0.0.1", - "seneca-level-store": "0.2.3", - "seneca-mesh": "0.7.0", - "seneca-redis-store": "0.0.8" - }, - "devDependencies": { - "code": "2.2.0", - "coveralls": "2.11.9", - "eslint-config-seneca": "2.0.0", - "eslint-plugin-hapi": "4.0.0", - "eslint-plugin-standard": "1.3.2", - "proxyquire": "1.7.8", - "lab": "10.5.1" - } -} diff --git a/srv/start.js b/srv/start.js deleted file mode 100644 index fd7fe23..0000000 --- a/srv/start.js +++ /dev/null @@ -1,49 +0,0 @@ -'use strict' - -var Seneca = require('seneca') -var Entities = require('seneca-entity') -var Mesh = require('seneca-mesh') -var Github = require('../lib/github') -var RedisStore = require('seneca-redis-store') - -var envs = process.env -var opts = { - seneca: { - tag: envs.GITHUB_TAG || 'nodezoo-github' - }, - github: { - token: envs.GITHUB_TOKEN || 'NO_TOKEN', - registry: envs.GITHUB_REGISTRY || 'http://registry.npmjs.org/' - }, - mesh: { - auto: true, - host: envs.GITHUB_HOST || '127.0.0.1', - bases: [envs.BASE_HOST || '127.0.0.1:39999'], - listen: [ - {pin: 'role:github,cmd:get', model: 'consume', host: envs.GITHUB_HOST || '127.0.0.1'}, - {pin: 'role:info,req:part', model: 'observe', host: envs.GITHUB_HOST || '127.0.0.1'} - ] - }, - isolated: { - host: envs.GITHUB_HOST || 'localhost', - port: envs.GITHUB_PORT || '8052' - }, - redis: { - host: envs.GITHUB_REDIS_HOST || 'localhost', - port: envs.GITHUB_REDIS_PORT || '6379' - } -} - -var Service = Seneca(opts.seneca) - -Service.use(Entities) - -if (envs.GITHUB_ISOLATED) { - Service.listen(opts.isolated) -} -else { - Service.use(Mesh, opts.mesh) - Service.use(RedisStore, opts.redis) -} - -Service.use(Github, opts.github) diff --git a/test/github.test.js b/test/github.test.js deleted file mode 100644 index 8750656..0000000 --- a/test/github.test.js +++ /dev/null @@ -1,138 +0,0 @@ -'use strict' - -var Lab = require('lab') -var Code = require('code') -var Proxyquire = require('proxyquire') -var NpmFakeData = require('./npm-data') - -var lab = exports.lab = Lab.script() -var describe = lab.describe -var it = lab.it -var expect = Code.expect - -var NpmProxy = { - request: { - get: (opts, done) => { - if (opts.url.includes('seneca')) { - done(null, {}, JSON.stringify(NpmFakeData)) - } - else { - done(new Error('npm error'), null, null) - } - } - } -} - - -var Seneca = Proxyquire('seneca', {}) -var Github = Proxyquire('..', NpmProxy) - -function createInstance (done) { - var params = { - log: 'silent', - strict: 'false', - errhandler: (err) => { - if (err.at) done(err) - } - } - - return Seneca(params) - .use('entity') - .use(Github, {token: process.env.GITHUB_TOKEN}) -} - -describe('A valid "role:github,cmd:get" call', () => { - it('has data and no error', (done) => { - var seneca = createInstance(done) - var payload = {name: 'seneca'} - - seneca.act('role:github,cmd:get', payload, (err, reply) => { - expect(err).to.not.exist() - expect(reply).to.exist() - done() - }) - }) - - it('returns cached data', (done) => { - var seneca = createInstance(done) - var payload = {name: 'seneca'} - - seneca.act('role:github,cmd:get', payload, (err, reply) => { - expect(err).to.not.exist() - - var cachedOne = reply.cached - - seneca.act('role:github,cmd:get', payload, (err, reply) => { - expect(err).to.not.exist() - - var cachedTwo = reply.cached - - expect(cachedOne).to.equal(cachedTwo) - done() - }) - }) - }) - - it('can return non-cached data', (done) => { - var seneca = createInstance(done) - var payload = {name: 'seneca'} - - seneca.act('role:github,cmd:get', payload, (err, reply) => { - expect(err).to.not.exist() - - var cachedOne = reply.data.cached - payload.update = true - - seneca.act('role:github,cmd:get', payload, (err, reply) => { - expect(err).to.not.exist() - - var cachedTwo = reply.data.cached - - expect(cachedOne).to.be.below(cachedTwo) - done() - }) - }) - }) -}) - -describe('An invalid "role:github,cmd:get" call', () => { - it('has an error and no data', (done) => { - var seneca = createInstance(done) - var payload = {name: 'shooobydoobydooboop'} - - seneca.act('role:github,cmd:get', payload, (err, reply) => { - expect(err).to.exist() - expect(reply).to.not.exist() - done() - }) - }) -}) - -describe('A valid "role:info,req:part" call', () => { - it('has no error and has data', (done) => { - var seneca = createInstance(done) - var payload = {name: 'seneca'} - - seneca.act('role:info,req:part', payload, (err, reply) => { - expect(err).to.not.exist() - expect(reply).to.exist() - done() - }) - }) - - it('responds via "role:info,res:part"', (done) => { - var seneca = createInstance(done) - var payload = {name: 'seneca'} - - seneca.add('role:info,res:part', (msg, cb) => { - expect(msg).to.exist() - cb() - done() - }) - - seneca.act('role:info,req:part', payload, (err, reply) => { - expect(err).to.not.exist() - expect(reply).to.exist() - }) - }) -}) diff --git a/test/npm-data.js b/test/npm-data.js deleted file mode 100644 index b515733..0000000 --- a/test/npm-data.js +++ /dev/null @@ -1,119 +0,0 @@ -module.exports = { - '_id': 'seneca-entity', - '_rev': '3-1a2d436a902cdfaa820f4da8aeeeb4f1', - 'name': 'seneca-entity', - 'description': 'Entity plugin for seneca', - 'dist-tags': { - 'latest': '0.0.1' - }, - 'versions': { - '0.0.1': { - 'name': 'seneca-entity', - 'description': 'Entity plugin for seneca', - 'keywords': [ - 'seneca', - 'plugin' - ], - 'version': '0.0.1', - 'license': 'MIT', - 'homepage': 'http://senecajs.org', - 'author': { - 'name': 'Richard Rodger', - 'url': 'http://richardrodger.com/' - }, - 'dependencies': { - 'eraro': '0.4.1', - 'jsonic': '0.2.2', - 'lodash': '4.0.1' - }, - 'main': 'entity.js', - 'engines': { - 'node': '>=0.10.0' - }, - 'files': [ - 'LICENSE', - 'README.md', - 'lib', - 'entity.js' - ], - 'repository': { - 'type': 'git', - 'url': 'git+https://github.com/senecajs/seneca-entity.git' - }, - 'scripts': { - 'test': 'lab -v -P test -L -t 80', - 'test-html': 'lab -v -P test -L -t 80 -r html > testcov.html', - 'lint': 'lab -P test -dL' - }, - 'devDependencies': { - 'code': '1.5.0', - 'eslint-config-seneca': '1.1.2', - 'eslint-plugin-standard': '1.3.1', - 'joi': '6.10.x', - 'lab': '6.2.x' - }, - 'gitHead': '61371232af57ee37c573cfc114096088def6f478', - 'bugs': { - 'url': 'https://github.com/senecajs/seneca-entity/issues' - }, - '_id': 'seneca-entity@0.0.1', - '_shasum': '184d2251666938639364256836e6d16db2f8f729', - '_from': '.', - '_npmVersion': '3.3.12', - '_nodeVersion': '5.4.1', - '_npmUser': { - 'name': 'wyatt', - 'email': 'wpreul@gmail.com' - }, - 'dist': { - 'shasum': '184d2251666938639364256836e6d16db2f8f729', - 'tarball': 'https://registry.npmjs.org/seneca-entity/-/seneca-entity-0.0.1.tgz' - }, - 'maintainers': [ - { - 'name': 'wyatt', - 'email': 'wpreul@gmail.com' - } - ], - '_npmOperationalInternal': { - 'host': 'packages-5-east.internal.npmjs.com', - 'tmp': 'tmp/seneca-entity-0.0.1.tgz_1455650942742_0.4798124579247087' - }, - 'directories': {} - } - }, - 'readme': '# seneca-entity\nEntity plugin for seneca\n', - 'maintainers': [ - { - 'name': 'rjrodger', - 'email': 'richard.rodger@nearform.com' - }, - { - 'name': 'wyatt', - 'email': 'wpreul@gmail.com' - } - ], - 'time': { - 'modified': '2016-03-07T21:07:05.021Z', - 'created': '2016-02-16T18:49:09.329Z', - '0.0.0': '2016-02-16T18:49:09.329Z', - '0.0.1': '2016-02-16T19:29:05.114Z' - }, - 'homepage': 'http://senecajs.org', - 'keywords': [ - 'seneca', - 'plugin' - ], - 'repository': { - 'type': 'git', - 'url': 'git+https://github.com/senecajs/seneca-entity.git' - }, - 'author': { - 'name': 'Richard Rodger', - 'url': 'http://richardrodger.com/' - }, - 'bugs': { - 'url': 'https://github.com/senecajs/seneca-entity/issues' - }, - 'license': 'MIT' -} From 3226e739a6229737844f8bd1b701131a338017b8 Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Fri, 11 Aug 2017 18:54:37 +0100 Subject: [PATCH 110/117] data --- data/no-purge.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 data/no-purge.txt diff --git a/data/no-purge.txt b/data/no-purge.txt new file mode 100644 index 0000000..a9af793 --- /dev/null +++ b/data/no-purge.txt @@ -0,0 +1 @@ +no-purge From 4d3961a0b720efdc1868cae099b6c39f81047128 Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Mon, 14 Aug 2017 17:07:48 +0100 Subject: [PATCH 111/117] dev --- srv/github-dev.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/srv/github-dev.js b/srv/github-dev.js index e53fdd4..a66fdc9 100644 --- a/srv/github-dev.js +++ b/srv/github-dev.js @@ -14,7 +14,7 @@ Seneca({tag: 'github'}) .test('print') .use('entity') - .use('jsonfile-store', {folder: __dirname+'/data'}) + .use('jsonfile-store', {folder: __dirname+'/../data'}) .use('..',{token:TOKEN}) From 36f0ccaf8506e0c46f6e0677ee77682bd04ce258 Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Tue, 29 Aug 2017 16:51:35 +0100 Subject: [PATCH 112/117] redis port --- srv/github-stage.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/srv/github-stage.js b/srv/github-stage.js index d008643..82c5336 100644 --- a/srv/github-stage.js +++ b/srv/github-stage.js @@ -3,7 +3,7 @@ var PORT = process.env.PORT || 9000 var Seneca = require('seneca') -Seneca({tag: 'github'}) +Seneca({tag: 'github', legacy: {meta: true}}) .listen(PORT) .use('redis-transport') @@ -50,8 +50,8 @@ Seneca({tag: 'github'}) }) }) - .listen({pin:'role:info,need:part', type:'redis', host:'redis'}) - .client({pin:'role:info,collect:part', type:'redis', host:'redis'}) + .listen({pin:'role:info,need:part', type:'redis', host:'redis', port:6379}) + .client({pin:'role:info,collect:part', type:'redis', host:'redis', port:6379}) .client({pin:'role:npm', host:'npm', port:PORT}) From 55a95cd29500f84aa3ea4f26a2eaba5ae573ee5b Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Thu, 14 Sep 2017 17:51:01 +0100 Subject: [PATCH 113/117] readme --- .dockerignore | 3 -- .eslintrc | 3 -- README.md | 102 ++++++++++++++++++++++++++++++++++++++++++++ github.png | Bin 0 -> 37054 bytes test/github.test.js | 2 +- 5 files changed, 103 insertions(+), 7 deletions(-) delete mode 100644 .dockerignore delete mode 100644 .eslintrc create mode 100644 README.md create mode 100644 github.png diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 0052af6..0000000 --- a/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -.* -node_modules/ -dist/ diff --git a/.eslintrc b/.eslintrc deleted file mode 100644 index dfc6b32..0000000 --- a/.eslintrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "seneca" -} diff --git a/README.md b/README.md new file mode 100644 index 0000000..57ccdff --- /dev/null +++ b/README.md @@ -0,0 +1,102 @@ +# nodezoo-github + +This is a repository in the microservice demonstration system for +the [Tao of Microservices](//bit.ly/rmtaomicro) book (chapter 9). This +code is live at [nodezoo.com](http://nodezoo.com). To get started, +visit the [nodezoo/tao](//github.com/nodezoo/tao) repository. + +__This microservice provides the github module data functionality.__ + + +## Running + +To run this microservice normally, use the tooling describing in +the [nodezoo/tao](//github.com//nodezoo/tao) repository, which shows you how to run +the entire system of microservices (of which this is only one of many) in +production ([Kubernetes](//kubernetes.io)), staging +([Docker](//docker.com)), and development +([fuge](//github.com/apparatus/fuge)) modes. + +To run from the terminal for testing and debugging, see +the [Running from the terminal](#running-from-the-terminal) section +below. + + +## Message flows + +The table shows how this microservice acts on the `Accepted` message +patterns and performs appropriate business `Actions`, as a result of +which, new messages are possibly `Sent`. + +|Accepted |Actions |Sent +|--|--|-- +|`role:github,cmd:get (SC)` |Get github data about a module| +|`role:info,need:part (AO)` |Provide partial module information|`role:info,collect:part (AO)` + +(KEY: A: asynchronous, S: synchronous, O: observed, C: consumed) + +### Service interactions + +![github](github.png?raw=true "suggest") + + +## Testing + +Unit tests are in the [test](test) folder. To run, use: + +```sh +$ npm test +``` + +Note that this is a learning system, and the tests are not intended to +be high coverage. + + +## Running from the terminal + +This microservice is written in [node.js](//nodejs.org), which you +will need to download and install. Fork and checkout this repository, +and then run `npm` inside the repository folder to install its dependencies: + +```sh +$ npm install +``` + +To run this microservice separately, for development, debug, or +testing purposes, use the service scripts in the [`srv`](srv) folder: + +* [`github-dev.js`](srv/github-dev.js) : run the development configuration + with hard-coded network ports. + + ```sh + $ node srv/github-dev.js + ``` + + This script listens for messages on port 9050 and provides a REPL on + port 10050 (try `$ telnet localhost 10050`). + + A [seneca-mesh](//github.com/senecajs/seneca-mesh) version, for + testing purposes, is also shown in the + script [`github-dev-mesh.js`](srv/github-dev-mesh.js). For more on + this, see the [nodezoo-repl](//github.com/nodezoo/nodezoo-repl) + repository. + +* [`github-stage.js`](srv/github-stage.js) : run the staging + configuration. This configuration is intended to run in a Docker + container so listens on port 9000 by default, but you can change + that by providing an optional argument to the script. + + ```sh + $ node srv/github-stage.js [PORT] + ``` + +* [`github-prod.js`](srv/github-prod.js) : run the production + configuration. This configuration is intended to run under + Kubernetes in a [seneca-mesh](//github.com/senecajs/seneca-mesh) + network. If running in a terminal (only do this for testing), you'll + need to provide the mesh base nodes in the `BASES` environment + variable. + + ```sh + $ BASES=x.x.x.x:port node srv/github-prod.js + ``` diff --git a/github.png b/github.png new file mode 100644 index 0000000000000000000000000000000000000000..8f08c1deef096a5db778d4375cde622903033173 GIT binary patch literal 37054 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�dt+1P7C*?8^J3J1#gSkHVa8GN{Wx)h?g@*I20q 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 Date: Thu, 14 Sep 2017 17:57:54 +0100 Subject: [PATCH 114/117] readme travis --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 57ccdff..5485a67 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ # nodezoo-github +[![Build Status](https://travis-ci.org/nodezoo/nodezoo-suggest.svg?branch=master)](https://travis-ci.org/nodezoo/nodezoo-suggest) + + This is a repository in the microservice demonstration system for the [Tao of Microservices](//bit.ly/rmtaomicro) book (chapter 9). This code is live at [nodezoo.com](http://nodezoo.com). To get started, From 66543f0f2ace2db680713a365622916d2921d22b Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Thu, 14 Sep 2017 17:58:54 +0100 Subject: [PATCH 115/117] readme travis --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5485a67..5c1ee32 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # nodezoo-github -[![Build Status](https://travis-ci.org/nodezoo/nodezoo-suggest.svg?branch=master)](https://travis-ci.org/nodezoo/nodezoo-suggest) +[![Build Status](https://travis-ci.org/nodezoo/nodezoo-github.svg?branch=master)](https://travis-ci.org/nodezoo/nodezoo-github) This is a repository in the microservice demonstration system for From 0a4d5204054ee297d5623f0336020339b086c3b6 Mon Sep 17 00:00:00 2001 From: Richard Rodger Date: Thu, 14 Sep 2017 18:18:29 +0100 Subject: [PATCH 116/117] readme gitter --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 5c1ee32..fd9a541 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # nodezoo-github [![Build Status](https://travis-ci.org/nodezoo/nodezoo-github.svg?branch=master)](https://travis-ci.org/nodezoo/nodezoo-github) - +[![Gitter Chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/nodezoo/nodezoo-org) This is a repository in the microservice demonstration system for the [Tao of Microservices](//bit.ly/rmtaomicro) book (chapter 9). This From b19b73fba5abceec2635601cb39b0b70b3079afa Mon Sep 17 00:00:00 2001 From: davidwroche Date: Mon, 6 Nov 2017 00:26:39 +0000 Subject: [PATCH 117/117] consul --- package-lock.json | 2606 ++++++++++++++++++++++++++++++++++++++++++++ package.json | 1 - srv/github-prod.js | 18 +- 3 files changed, 2621 insertions(+), 4 deletions(-) create mode 100644 package-lock.json diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..a7c6b18 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,2606 @@ +{ + "name": "nodezoo-github", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "acorn": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz", + "integrity": "sha512-vOk6uEMctu0vQrvuSqFdJyqj1Q0S5VTDL79qtjo+DhRr+1mmaD+tluFSCZqhvi/JUhXSzoZN2BhtstaPEeE8cw==", + "dev": true + }, + "acorn-jsx": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", + "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", + "dev": true, + "requires": { + "acorn": "3.3.0" + }, + "dependencies": { + "acorn": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", + "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", + "dev": true + } + } + }, + "agent-base": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-2.1.1.tgz", + "integrity": "sha1-1t4Q1a9hMtW9aSQn1G/FOFOQlMc=", + "requires": { + "extend": "3.0.1", + "semver": "5.0.3" + } + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ammo": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/ammo/-/ammo-2.0.4.tgz", + "integrity": "sha1-v4CqshFpjqePY+9efxE91dnokX8=", + "requires": { + "boom": "5.2.0", + "hoek": "4.2.0" + }, + "dependencies": { + "boom": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", + "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", + "requires": { + "hoek": "4.2.0" + } + } + } + }, + "ansi-escapes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", + "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=" + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=" + }, + "argparse": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.9.tgz", + "integrity": "sha1-c9g7wmP4bpf4zE9rrhsOkKfSLIY=", + "dev": true, + "requires": { + "sprintf-js": "1.0.3" + } + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "esutils": "2.0.2", + "js-tokens": "3.0.2" + } + }, + "backoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz", + "integrity": "sha1-9hbtqdPktmuMp/ynn2lXIsX44m8=", + "requires": { + "precond": "0.2.3" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "boom": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/boom/-/boom-3.2.2.tgz", + "integrity": "sha1-DwzF0ErcUAO4x9cfQsynJx/vDng=", + "requires": { + "hoek": "4.2.0" + } + }, + "bossy": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/bossy/-/bossy-3.0.4.tgz", + "integrity": "sha1-+a6fJugbQaMY9O4Ng2huSlwlB7k=", + "dev": true, + "requires": { + "hoek": "4.2.0", + "joi": "10.6.0" + }, + "dependencies": { + "joi": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-10.6.0.tgz", + "integrity": "sha512-hBF3LcqyAid+9X/pwg+eXjD2QBZI5eXnBFJYaAkH4SK3mp9QSRiiQnDYlmlz5pccMvnLcJRS4whhDOTCkmsAdQ==", + "dev": true, + "requires": { + "hoek": "4.2.0", + "isemail": "2.2.1", + "items": "2.1.1", + "topo": "2.0.2" + } + } + } + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "optional": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cjson": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/cjson/-/cjson-0.2.1.tgz", + "integrity": "sha1-c82KrWXZ4VBfmvF0TTt5wVJ2gqU=" + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "optional": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true, + "optional": true + } + } + }, + "clone": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.2.tgz", + "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=" + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true + }, + "code": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/code/-/code-4.1.0.tgz", + "integrity": "sha1-IJrRHQWvigwceq9pTZ+k0sfZW4U=", + "dev": true, + "requires": { + "hoek": "4.2.0" + } + }, + "color-convert": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.0.tgz", + "integrity": "sha1-Gsz5fdc5uYO/mU1W/sj5WFNkG3o=", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "colors": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.5.1.tgz", + "integrity": "sha1-fQAj6usVTo7p/Oddy5I9DtFmd3Q=" + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.0.tgz", + "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "typedarray": "0.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "debug": { + "version": "2.6.8", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", + "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "optional": true + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.1" + } + }, + "diff": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.0.tgz", + "integrity": "sha512-w0XZubFWn0Adlsapj9EAWX0FqWdO4tz8kc3RiYdWLh4k/V8PTb6i0SMgXt0vRM3zyKnT8tKO7mUlieRQHIjMNg==", + "dev": true + }, + "doctrine": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", + "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=", + "dev": true, + "requires": { + "esutils": "2.0.2", + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "ebnf-parser": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/ebnf-parser/-/ebnf-parser-0.1.10.tgz", + "integrity": "sha1-zR9rpHfFY4xAyX7ZtXLbW6tdgzE=" + }, + "eraro": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/eraro/-/eraro-0.4.1.tgz", + "integrity": "sha1-ZThzB2mh6J/8Pwx+LJTVofhmYp0=", + "requires": { + "lodash": "2.4.2" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" + } + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "escodegen": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.21.tgz", + "integrity": "sha1-U9ZSz6EDA4gnlFilJmxf/HCcY8M=", + "requires": { + "esprima": "1.0.4", + "estraverse": "0.0.4", + "source-map": "0.5.7" + }, + "dependencies": { + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" + } + } + }, + "eslint": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.0.0.tgz", + "integrity": "sha1-cnfAFDf99B3M0WjVqg5Jt1yh8mA=", + "dev": true, + "requires": { + "babel-code-frame": "6.26.0", + "chalk": "1.1.3", + "concat-stream": "1.6.0", + "debug": "2.6.8", + "doctrine": "2.0.0", + "eslint-scope": "3.7.1", + "espree": "3.4.3", + "esquery": "1.0.0", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "file-entry-cache": "2.0.0", + "glob": "7.1.2", + "globals": "9.18.0", + "ignore": "3.3.5", + "imurmurhash": "0.1.4", + "inquirer": "3.2.2", + "is-my-json-valid": "2.16.1", + "is-resolvable": "1.0.0", + "js-yaml": "3.9.1", + "json-stable-stringify": "1.0.1", + "levn": "0.3.0", + "lodash": "4.17.4", + "mkdirp": "0.5.1", + "natural-compare": "1.4.0", + "optionator": "0.8.2", + "path-is-inside": "1.0.2", + "pluralize": "4.0.0", + "progress": "2.0.0", + "require-uncached": "1.0.3", + "strip-json-comments": "2.0.1", + "table": "4.0.1", + "text-table": "0.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "eslint-config-hapi": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-hapi/-/eslint-config-hapi-10.1.0.tgz", + "integrity": "sha512-tAUedyvZla1qKt6jhOx7mj5tYDVCwdSyImpEK7wk/A/atKUjg18aHUK6Q6qWWM6rq21I1F/A8JAhIpkk0SvFMQ==", + "dev": true + }, + "eslint-plugin-hapi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-hapi/-/eslint-plugin-hapi-4.0.0.tgz", + "integrity": "sha1-RKouRfeTmlI5Kc2DK7mqEpqV6CM=", + "dev": true, + "requires": { + "hapi-capitalize-modules": "1.1.6", + "hapi-for-you": "1.0.0", + "hapi-scope-start": "2.1.1", + "no-arrowception": "1.0.0" + } + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + "dev": true, + "requires": { + "esrecurse": "4.2.0", + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "espree": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.4.3.tgz", + "integrity": "sha1-KRC1zNSc6JPC//+qtP2LOjG4I3Q=", + "dev": true, + "requires": { + "acorn": "5.1.1", + "acorn-jsx": "3.0.1" + } + }, + "esprima": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz", + "integrity": "sha1-dqD9Zvz+FU/SkmZ9wmQBl1CxZXs=" + }, + "esquery": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.0.tgz", + "integrity": "sha1-z7qLV9f7qT8XKYqKAGoEzaE9gPo=", + "dev": true, + "requires": { + "estraverse": "4.2.0" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.0.tgz", + "integrity": "sha1-+pVo2Y04I/mkHZHpAtyrnqblsWM=", + "dev": true, + "requires": { + "estraverse": "4.2.0", + "object-assign": "4.1.1" + }, + "dependencies": { + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + } + } + }, + "estraverse": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-0.0.4.tgz", + "integrity": "sha1-AaCTLf7ldGhKWYr1pnw7+bZCjbI=" + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=" + }, + "external-editor": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.4.tgz", + "integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=", + "dev": true, + "requires": { + "iconv-lite": "0.4.18", + "jschardet": "1.5.1", + "tmp": "0.0.31" + } + }, + "farmhash": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/farmhash/-/farmhash-1.2.1.tgz", + "integrity": "sha1-Lb8SYE71yh8UIPtmAPzLMNVHTf0=", + "requires": { + "nan": "2.7.0" + } + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "1.2.2", + "object-assign": "4.1.1" + } + }, + "find-rc": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/find-rc/-/find-rc-3.0.1.tgz", + "integrity": "sha1-VKQXg3DxC8k3H6jRssKAmir6DM4=", + "dev": true + }, + "flat-cache": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", + "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", + "dev": true, + "requires": { + "circular-json": "0.3.3", + "del": "2.2.2", + "graceful-fs": "4.1.11", + "write": "0.2.1" + } + }, + "follow-redirects": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-0.0.7.tgz", + "integrity": "sha1-NLkLqyqRGqNHVx2pDyK9NuzYqRk=", + "requires": { + "debug": "2.6.8", + "stream-consume": "0.1.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "gate-executor": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/gate-executor/-/gate-executor-1.1.1.tgz", + "integrity": "sha1-Zn9ncoSg2+hrbEigtK/oxISBLK8=" + }, + "generate-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", + "integrity": "sha1-aFj+fAlpt9TpCTM3ZHrHn2DfvnQ=", + "dev": true + }, + "generate-object-property": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", + "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", + "dev": true, + "requires": { + "is-property": "1.0.2" + } + }, + "gex": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/gex/-/gex-0.2.2.tgz", + "integrity": "sha1-LUCdJDCVlwjaVc9WKUxk9tiXNIc=", + "requires": { + "lodash": "3.10.0" + }, + "dependencies": { + "lodash": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.0.tgz", + "integrity": "sha1-k9UcZygopEFqEq9XIguoqHN+L7s=" + } + } + }, + "github": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/github/-/github-9.2.0.tgz", + "integrity": "sha1-iohtxA3WNjZwfcr5nfPfJsWfFvw=", + "requires": { + "follow-redirects": "0.0.7", + "https-proxy-agent": "1.0.0", + "mime": "1.4.0", + "netrc": "0.1.4" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "globals": { + "version": "9.18.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", + "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "handlebars": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.0.10.tgz", + "integrity": "sha1-PTDHGLCaPZbyPqTMH0A8TTup/08=", + "dev": true, + "requires": { + "async": "1.5.2", + "optimist": "0.6.1", + "source-map": "0.4.4", + "uglify-js": "2.8.29" + }, + "dependencies": { + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "hapi": { + "version": "16.1.1", + "resolved": "https://registry.npmjs.org/hapi/-/hapi-16.1.1.tgz", + "integrity": "sha1-BGbbBwO6Fc0A8HF1zPOU2ctWseA=", + "requires": { + "accept": "2.1.3", + "ammo": "2.0.3", + "boom": "4.2.0", + "call": "4.0.0", + "catbox": "7.1.3", + "catbox-memory": "2.0.4", + "cryptiles": "3.1.1", + "heavy": "4.0.3", + "hoek": "4.1.0", + "iron": "4.0.4", + "items": "2.1.1", + "joi": "10.1.0", + "mimos": "3.0.3", + "podium": "1.2.5", + "shot": "3.4.0", + "statehood": "5.0.1", + "subtext": "4.3.0", + "topo": "2.0.2" + }, + "dependencies": { + "accept": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/accept/-/accept-2.1.3.tgz", + "integrity": "sha1-qw9b2kxEm76SaupgezUiVi9az4Y=", + "requires": { + "boom": "4.2.0", + "hoek": "4.1.0" + } + }, + "ammo": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/ammo/-/ammo-2.0.3.tgz", + "integrity": "sha1-kUu89lsEPtD1ioqdAZbiUOxR5qc=", + "requires": { + "boom": "4.2.0", + "hoek": "4.1.0" + } + }, + "b64": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/b64/-/b64-3.0.2.tgz", + "integrity": "sha1-ep1gRmrfe43hFMvfZRpf38yQiU0=" + }, + "boom": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.2.0.tgz", + "integrity": "sha1-wadBdLEfu6Ij9hYtT9iFGhuCpTY=", + "requires": { + "hoek": "4.1.0" + } + }, + "call": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/call/-/call-4.0.0.tgz", + "integrity": "sha1-zSk4GpgEahMtsm4mKOcL2DIaHd8=", + "requires": { + "boom": "4.2.0", + "hoek": "4.1.0" + } + }, + "catbox": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/catbox/-/catbox-7.1.3.tgz", + "integrity": "sha1-mBft7FqSF0MoKt38nEWs5ShH7rs=", + "requires": { + "boom": "4.2.0", + "hoek": "4.1.0", + "joi": "10.1.0" + } + }, + "catbox-memory": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/catbox-memory/-/catbox-memory-2.0.4.tgz", + "integrity": "sha1-Qz4lWQLK9UIz0ShkKcj03xToItU=", + "requires": { + "hoek": "4.1.0" + } + }, + "content": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/content/-/content-3.0.3.tgz", + "integrity": "sha1-AA+KATcblcZq/pm+k5D6bLkaqHo=", + "requires": { + "boom": "4.2.0" + } + }, + "cryptiles": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.1.tgz", + "integrity": "sha1-hqkgP3NnoOkyS8dVX/D89fgZee4=", + "requires": { + "boom": "4.2.0" + } + }, + "heavy": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/heavy/-/heavy-4.0.3.tgz", + "integrity": "sha1-l2u6EYsBGxX+kEqk8pKhaL/GIy8=", + "requires": { + "boom": "4.2.0", + "hoek": "4.1.0", + "joi": "10.1.0" + } + }, + "hoek": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.1.0.tgz", + "integrity": "sha1-SkVXRg9phC7UY6oAYozCbSaDr6c=" + }, + "iron": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/iron/-/iron-4.0.4.tgz", + "integrity": "sha1-wfjMTJFFQZSriSDZJHuoguUoBho=", + "requires": { + "boom": "4.2.0", + "cryptiles": "3.1.1", + "hoek": "4.1.0" + } + }, + "isemail": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-2.2.1.tgz", + "integrity": "sha1-A1PT2aYpUQgMJiwqoKQrjqjp4qY=" + }, + "items": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/items/-/items-2.1.1.tgz", + "integrity": "sha1-i9FtnIOxlSneWuoyGsqtp4NkoZg=" + }, + "joi": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-10.1.0.tgz", + "integrity": "sha1-jDqHV3wVn/66EppQVPMjj579cVk=", + "requires": { + "hoek": "4.1.0", + "isemail": "2.2.1", + "items": "2.1.1", + "topo": "2.0.2" + } + }, + "mime-db": { + "version": "1.25.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.25.0.tgz", + "integrity": "sha1-wY29fHOl2/b0SgJNwNFloeexw5I=" + }, + "mimos": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/mimos/-/mimos-3.0.3.tgz", + "integrity": "sha1-uRCQcq03jCty9qAQHEPd+ys2ZB8=", + "requires": { + "hoek": "4.1.0", + "mime-db": "1.25.0" + } + }, + "nigel": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/nigel/-/nigel-2.0.2.tgz", + "integrity": "sha1-k6GGb7DFLYc5CqdeKxYfS1x15bE=", + "requires": { + "hoek": "4.1.0", + "vise": "2.0.2" + } + }, + "pez": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/pez/-/pez-2.1.4.tgz", + "integrity": "sha1-c/gi+mLVmdZcRgb0kNVNNFGRvHw=", + "requires": { + "b64": "3.0.2", + "boom": "4.2.0", + "content": "3.0.3", + "hoek": "4.1.0", + "nigel": "2.0.2" + } + }, + "podium": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/podium/-/podium-1.2.5.tgz", + "integrity": "sha1-h8VmwvA2W88KHsdgLE0BlIzdKtU=", + "requires": { + "hoek": "4.1.0", + "items": "2.1.1", + "joi": "10.1.0" + } + }, + "shot": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/shot/-/shot-3.4.0.tgz", + "integrity": "sha1-5xJe5yV1rlIYNJ6TNjaAjXkNS5I=", + "requires": { + "hoek": "4.1.0", + "joi": "10.1.0" + } + }, + "statehood": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/statehood/-/statehood-5.0.1.tgz", + "integrity": "sha1-/BPJezd1HBjnBRPSuX6Jasi3MAU=", + "requires": { + "boom": "4.2.0", + "cryptiles": "3.1.1", + "hoek": "4.1.0", + "iron": "4.0.4", + "items": "2.1.1", + "joi": "10.1.0" + } + }, + "subtext": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/subtext/-/subtext-4.3.0.tgz", + "integrity": "sha1-36yQSS7DVmn9bgDG5dk4sG18z7s=", + "requires": { + "boom": "4.2.0", + "content": "3.0.3", + "hoek": "4.1.0", + "pez": "2.1.4", + "wreck": "10.0.0" + } + }, + "topo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", + "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", + "requires": { + "hoek": "4.1.0" + } + }, + "vise": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/vise/-/vise-2.0.2.tgz", + "integrity": "sha1-awjo+0y3bjpQzW3Q7DczjoEaDTk=", + "requires": { + "hoek": "4.1.0" + } + }, + "wreck": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/wreck/-/wreck-10.0.0.tgz", + "integrity": "sha1-mKuIL4XhalJjMlB/EB9aeEEWIng=", + "requires": { + "boom": "4.2.0", + "hoek": "4.1.0" + } + } + } + }, + "hapi-capitalize-modules": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/hapi-capitalize-modules/-/hapi-capitalize-modules-1.1.6.tgz", + "integrity": "sha1-eZEXFBXhXmqjIx5k3ac8gUZmUxg=", + "dev": true + }, + "hapi-for-you": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hapi-for-you/-/hapi-for-you-1.0.0.tgz", + "integrity": "sha1-02L77o172pwseAHiB+WlzRoLans=", + "dev": true + }, + "hapi-scope-start": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/hapi-scope-start/-/hapi-scope-start-2.1.1.tgz", + "integrity": "sha1-dJWnJv5yt7yo3izcwdh82M5qtPI=", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "hoek": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.0.tgz", + "integrity": "sha512-v0XCLxICi9nPfYrS9RL8HbYnXi9obYAeLbSP00BmnZwCK9+Ih9WOjoZ8YoHCoav2csqn4FOz4Orldsy2dmDwmQ==" + }, + "https-proxy-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-1.0.0.tgz", + "integrity": "sha1-NffabEjOTdv6JkiRrFk+5f+GceY=", + "requires": { + "agent-base": "2.1.1", + "debug": "2.6.8", + "extend": "3.0.1" + } + }, + "iconv-lite": { + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", + "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==", + "dev": true + }, + "ignore": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.5.tgz", + "integrity": "sha512-JLH93mL8amZQhh/p6mfQgVBH3M6epNq3DfsXsTSuSrInVjwyYlFE1nv2AgfRCC8PoOhM0jwQ5v8s9LgbK7yGDw==", + "dev": true + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inert": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/inert/-/inert-4.2.0.tgz", + "integrity": "sha1-aqXajOGZgutyqr70vdpk/WdQsAU=", + "requires": { + "ammo": "2.0.4", + "boom": "4.3.1", + "hoek": "4.2.0", + "items": "2.1.1", + "joi": "10.6.0", + "lru-cache": "4.0.1" + }, + "dependencies": { + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.0" + } + }, + "joi": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/joi/-/joi-10.6.0.tgz", + "integrity": "sha512-hBF3LcqyAid+9X/pwg+eXjD2QBZI5eXnBFJYaAkH4SK3mp9QSRiiQnDYlmlz5pccMvnLcJRS4whhDOTCkmsAdQ==", + "requires": { + "hoek": "4.2.0", + "isemail": "2.2.1", + "items": "2.1.1", + "topo": "2.0.2" + } + } + } + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "inquirer": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.2.2.tgz", + "integrity": "sha512-bTKLzEHJVATimZO/YFdLrom0lRx1BHfRYskFHfIMVkGdp8+dIZaxuU+4yrsS1lcu6YWywVQVVsfvdwESzbeqHw==", + "dev": true, + "requires": { + "ansi-escapes": "2.0.0", + "chalk": "2.1.0", + "cli-cursor": "2.1.0", + "cli-width": "2.2.0", + "external-editor": "2.0.4", + "figures": "2.0.0", + "lodash": "4.17.4", + "mute-stream": "0.0.7", + "run-async": "2.3.0", + "rx-lite": "4.0.8", + "rx-lite-aggregates": "4.0.8", + "string-width": "2.1.1", + "strip-ansi": "4.0.0", + "through": "2.3.8" + }, + "dependencies": { + "ansi-escapes": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-2.0.0.tgz", + "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.2.1" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + }, + "supports-color": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.2.1.tgz", + "integrity": "sha512-qxzYsob3yv6U+xMzPrv170y8AwGP7i74g+pbixCfD6rgso8BscLT2qXIuz6TpOaiJZ3mFgT5O9lyT9nMU4LfaA==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "ip": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.3.tgz", + "integrity": "sha1-ErFilKOJJUhtYYoRA1BuTrT4spY=" + }, + "is-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.5.tgz", + "integrity": "sha1-Hzsm72E7IUuIy8ojzGwB2Hlh7sw=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-my-json-valid": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.16.1.tgz", + "integrity": "sha512-ochPsqWS1WXj8ZnMIV0vnNXooaMhp7cyL4FMSIPKTtnV0Ha/T19G2b9kkhcNsabV9bxYkze7/aLZJb/bYuFduQ==", + "dev": true, + "requires": { + "generate-function": "2.0.0", + "generate-object-property": "1.2.0", + "jsonpointer": "4.0.1", + "xtend": "4.0.1" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, + "is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", + "dev": true + }, + "is-resolvable": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", + "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=", + "dev": true, + "requires": { + "tryit": "1.0.3" + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "isemail": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-2.2.1.tgz", + "integrity": "sha1-A1PT2aYpUQgMJiwqoKQrjqjp4qY=" + }, + "items": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/items/-/items-2.1.1.tgz", + "integrity": "sha1-i9FtnIOxlSneWuoyGsqtp4NkoZg=" + }, + "jison": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/jison/-/jison-0.4.13.tgz", + "integrity": "sha1-kEFwfWIkE2f1iDRTK58ZwsNvrHg=", + "requires": { + "cjson": "0.2.1", + "ebnf-parser": "0.1.10", + "escodegen": "0.0.21", + "esprima": "1.0.4", + "jison-lex": "0.2.1", + "JSONSelect": "0.4.0", + "lex-parser": "0.1.4", + "nomnom": "1.5.2" + }, + "dependencies": { + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" + } + } + }, + "jison-lex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/jison-lex/-/jison-lex-0.2.1.tgz", + "integrity": "sha1-rEuBXozOUTLrErXfz+jXB7iETf4=", + "requires": { + "lex-parser": "0.1.4", + "nomnom": "1.5.2" + } + }, + "joi": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/joi/-/joi-9.0.4.tgz", + "integrity": "sha1-iNZIkJFavrEnzXVwJxFtUN8+aN8=", + "requires": { + "hoek": "4.2.0", + "isemail": "2.2.1", + "items": "2.1.1", + "moment": "2.18.1", + "topo": "2.0.2" + } + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "js-yaml": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz", + "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==", + "dev": true, + "requires": { + "argparse": "1.0.9", + "esprima": "4.0.0" + }, + "dependencies": { + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true + } + } + }, + "jschardet": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.5.1.tgz", + "integrity": "sha512-vE2hT1D0HLZCLLclfBSfkfTTedhVj0fubHpJBHKwwUWX0nSbhPAfk+SG9rTX95BYNmau8rGFfCeaT6T5OW1C2A==", + "dev": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/jsonic/-/jsonic-0.3.0.tgz", + "integrity": "sha1-tUXalfVDkuWLPdoF9fLjd6bJ0b8=" + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "jsonpath": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-0.2.11.tgz", + "integrity": "sha1-v+IuBmW5cS+Oe99+Lh+MCLWUxg4=", + "requires": { + "esprima": "1.2.2", + "jison": "0.4.13", + "static-eval": "0.2.3", + "underscore": "1.7.0" + } + }, + "jsonpointer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", + "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", + "dev": true + }, + "JSONSelect": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz", + "integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40=" + }, + "keypress": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/keypress/-/keypress-0.2.1.tgz", + "integrity": "sha1-HoBFQlABjbrUw/6USX1uZ7YmnHc=" + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.5" + } + }, + "lab": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/lab/-/lab-14.0.1.tgz", + "integrity": "sha512-qFDMhwCcnYu2iNdunWmgBvowXtbJdchU3tEarWgRdnl3ilP66i4G1dCpbdUYPfA8dDEjBU350IXaj6Gz6QzHOw==", + "dev": true, + "requires": { + "bossy": "3.0.4", + "code": "4.1.0", + "diff": "3.3.0", + "eslint": "4.0.0", + "eslint-config-hapi": "10.1.0", + "eslint-plugin-hapi": "4.0.0", + "espree": "3.4.3", + "find-rc": "3.0.1", + "handlebars": "4.0.10", + "hoek": "4.2.0", + "items": "2.1.1", + "json-stable-stringify": "1.0.1", + "json-stringify-safe": "5.0.1", + "mkdirp": "0.5.1", + "seedrandom": "2.4.3", + "source-map": "0.5.7", + "source-map-support": "0.4.16" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true, + "optional": true + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2", + "type-check": "0.3.2" + } + }, + "lex-parser": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/lex-parser/-/lex-parser-0.1.4.tgz", + "integrity": "sha1-ZMTwJfF/1Tv7RXY/rrFvAVp0dVA=" + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "lru-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.1.tgz", + "integrity": "sha1-E0OVXtry432bnn7nJB4nxLn7cr4=", + "requires": { + "pseudomap": "1.0.2", + "yallist": "2.1.2" + } + }, + "mime": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.0.tgz", + "integrity": "sha512-n9ChLv77+QQEapYz8lV+rIZAW3HhAPW2CXnzb1GN5uMkuczshwvkW7XPsbzU0ZQN3sP47Er2KVkp2p3KyqZKSQ==" + }, + "mimic-fn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz", + "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "moment": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", + "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=" + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "msgpack": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/msgpack/-/msgpack-1.0.2.tgz", + "integrity": "sha1-kj4sXP+mXIQY6bIo0RJHk5acQpw=", + "requires": { + "nan": "2.7.0" + } + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.7.0.tgz", + "integrity": "sha1-2Vv3IeyHfgjbJ27T/G63j5CDrUY=" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "ndjson": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-1.4.3.tgz", + "integrity": "sha1-eqAm/jqzin2horStB7EAjnM+sjk=", + "requires": { + "minimist": "1.2.0", + "split2": "0.2.1", + "through2": "0.6.5" + } + }, + "netrc": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/netrc/-/netrc-0.1.4.tgz", + "integrity": "sha1-a+lPysqNd63gqWcNxGCRTJRHJEQ=" + }, + "nid": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/nid/-/nid-0.3.2.tgz", + "integrity": "sha1-l3qTGO1cKjjt1mJj8+r9gUPyJRo=" + }, + "no-arrowception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/no-arrowception/-/no-arrowception-1.0.0.tgz", + "integrity": "sha1-W/PpXrnEG1c4SoBTM9qjtzTuMno=", + "dev": true + }, + "node-discover": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/node-discover/-/node-discover-0.6.0.tgz", + "integrity": "sha1-ajFvVTeqTeyQbpywQ6ArT9NEs2Q=", + "requires": { + "node-uuid": "1.4.8" + } + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + }, + "nomnom": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/nomnom/-/nomnom-1.5.2.tgz", + "integrity": "sha1-9DRUSKhTz71cDSYyDyR3qwUm/i8=", + "requires": { + "colors": "0.5.1", + "underscore": "1.1.7" + }, + "dependencies": { + "underscore": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.1.7.tgz", + "integrity": "sha1-QLq4S60Z0jAJbo1u9ii/8FXYPbA=" + } + } + }, + "norma": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/norma/-/norma-0.3.0.tgz", + "integrity": "sha1-JyZcNBEBjDLJPucZ9pLPkN7Fq2Q=", + "requires": { + "eraro": "0.4.1", + "lodash": "2.4.2" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" + } + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "1.1.0" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.10", + "wordwrap": "0.0.3" + }, + "dependencies": { + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + } + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" + } + }, + "optioner": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/optioner/-/optioner-0.8.0.tgz", + "integrity": "sha1-5hhOs3m0NODl+Ev5fcvIDkCDwbI=", + "requires": { + "hoek": "4.0.1", + "joi": "9.0.4" + }, + "dependencies": { + "hoek": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.0.1.tgz", + "integrity": "sha1-FAsWVI/hYm2R0k9JFMRMi/2pUuM=" + } + } + }, + "ordu": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ordu/-/ordu-0.1.1.tgz", + "integrity": "sha1-nIEJSTaTyvCCmfyoTFlq64YLrqo=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "pad": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pad/-/pad-1.1.0.tgz", + "integrity": "sha1-en0YUgDrrDL58S7nVsOh0IezGQs=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "patrun": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/patrun/-/patrun-0.5.1.tgz", + "integrity": "sha1-W/83V/Tz/SvftqBNJ5QsvsPhLxw=", + "requires": { + "gex": "0.2.2", + "lodash": "4.15.0" + }, + "dependencies": { + "lodash": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.15.0.tgz", + "integrity": "sha1-MWI5HY8BQKoiz49rPDTWt/Y9Oqk=" + } + } + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "pluralize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-4.0.0.tgz", + "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I=", + "dev": true + }, + "precond": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz", + "integrity": "sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=" + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=" + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "reconnect-core": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/reconnect-core/-/reconnect-core-1.3.0.tgz", + "integrity": "sha1-+65SkZp4d9hE4yRtAaLyZwHIM8g=", + "requires": { + "backoff": "2.5.0" + } + }, + "redis": { + "version": "0.12.1", + "resolved": "https://registry.npmjs.org/redis/-/redis-0.12.1.tgz", + "integrity": "sha1-ZN92rQ/IrOuuvSoGReikj6xJGF4=" + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "0.1.0", + "resolve-from": "1.0.1" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "2.0.1", + "signal-exit": "3.0.2" + } + }, + "rif": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/rif/-/rif-0.3.0.tgz", + "integrity": "sha1-aa3Lq8u/rAoRSUlGPRph4ttAkXQ=", + "requires": { + "ip": "1.1.3" + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "optional": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", + "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "rolling-stats": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/rolling-stats/-/rolling-stats-0.1.1.tgz", + "integrity": "sha1-zVr3dKiJOzCmdIMvovSrqkeM/IA=" + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "2.1.0" + } + }, + "rx-lite": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-4.0.8.tgz", + "integrity": "sha1-Cx4Rr4vESDbwSmQH6S2kJGe3lEQ=", + "dev": true + }, + "rx-lite-aggregates": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/rx-lite-aggregates/-/rx-lite-aggregates-4.0.8.tgz", + "integrity": "sha1-dTuHqJoRyVRnxKwWJsTvxOBcZ74=", + "dev": true, + "requires": { + "rx-lite": "4.0.8" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", + "dev": true + }, + "seedrandom": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-2.4.3.tgz", + "integrity": "sha1-JDhQTa0zkXMUv/GKxNeU8W1qrsw=", + "dev": true + }, + "semver": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.0.3.tgz", + "integrity": "sha1-d0Zt5YnNXTyV8TiqeLxWmjy10no=" + }, + "seneca": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/seneca/-/seneca-3.4.2.tgz", + "integrity": "sha1-NAw6GQAF0wX/YZ8x9uIjwNSc/m8=", + "requires": { + "archy": "1.0.0", + "eraro": "0.4.1", + "gate-executor": "1.1.1", + "gex": "0.2.2", + "json-stringify-safe": "5.0.1", + "jsonic": "0.3.0", + "lodash": "4.17.4", + "minimist": "1.2.0", + "nid": "0.3.2", + "norma": "0.3.0", + "ordu": "0.1.1", + "patrun": "0.5.1", + "qs": "6.4.0", + "rolling-stats": "0.1.1", + "semver": "5.3.0", + "seneca-log-filter": "0.1.0", + "seneca-transport": "2.1.1", + "use-plugin": "0.3.2", + "wreck": "12.2.0" + }, + "dependencies": { + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + } + } + }, + "seneca-balance-client": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/seneca-balance-client/-/seneca-balance-client-0.6.1.tgz", + "integrity": "sha1-ocfnNezsz33VAA9ljg1PHLV6HF8=", + "requires": { + "eraro": "0.4.1", + "jsonic": "0.3.0", + "lodash": "4.17.4" + } + }, + "seneca-entity": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/seneca-entity/-/seneca-entity-2.0.2.tgz", + "integrity": "sha1-Ag6nwzdN0J/mXYjSDRsMj59IO5g=", + "requires": { + "eraro": "0.4.1", + "jsonic": "0.3.0", + "lodash": "4.17.4", + "nid": "0.3.2", + "seneca-mem-store": "1.0.0" + } + }, + "seneca-jsonfile-store": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/seneca-jsonfile-store/-/seneca-jsonfile-store-1.0.0.tgz", + "integrity": "sha1-Ep5y6mbfR3ChyhiAXM1/sSa9zzk=", + "requires": { + "eraro": "0.4.1", + "lodash": "4.15.0" + }, + "dependencies": { + "lodash": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.15.0.tgz", + "integrity": "sha1-MWI5HY8BQKoiz49rPDTWt/Y9Oqk=" + } + } + }, + "seneca-log-filter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/seneca-log-filter/-/seneca-log-filter-0.1.0.tgz", + "integrity": "sha1-9RPed9/cwSACP4R6fGDO7Qr8ZrM=", + "requires": { + "lodash": "4.15.0" + }, + "dependencies": { + "lodash": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.15.0.tgz", + "integrity": "sha1-MWI5HY8BQKoiz49rPDTWt/Y9Oqk=" + } + } + }, + "seneca-mem-store": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/seneca-mem-store/-/seneca-mem-store-1.0.0.tgz", + "integrity": "sha1-w5hevWApkzs7SuuRwz72/mvFO4k=", + "requires": { + "lodash": "4.15.0" + }, + "dependencies": { + "lodash": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.15.0.tgz", + "integrity": "sha1-MWI5HY8BQKoiz49rPDTWt/Y9Oqk=" + } + } + }, + "seneca-mesh": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/seneca-mesh/-/seneca-mesh-0.11.0.tgz", + "integrity": "sha1-L+4RCX5lo/WU8weunzwa9leooD4=", + "requires": { + "ip": "1.1.3", + "jsonic": "0.3.0", + "lodash": "4.17.4", + "nid": "0.3.2", + "node-discover": "0.6.0", + "optioner": "0.8.0", + "rif": "0.3.0", + "sneeze": "0.8.0" + } + }, + "seneca-monitor": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/seneca-monitor/-/seneca-monitor-0.1.0.tgz", + "integrity": "sha1-GsnGalLOqrEjXUFK4FeVT7mgsBE=", + "requires": { + "hapi": "16.1.1", + "inert": "4.2.0" + } + }, + "seneca-redis-transport": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/seneca-redis-transport/-/seneca-redis-transport-0.3.0.tgz", + "integrity": "sha1-TDzHnwWv0KTc+nePWiUnhTm7RYQ=", + "requires": { + "lodash": "2.4.2", + "redis": "0.12.1" + }, + "dependencies": { + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" + } + } + }, + "seneca-repl": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/seneca-repl/-/seneca-repl-1.1.2.tgz", + "integrity": "sha512-3MYvd0c9tAl4Pj0gIZonSLO4qDA+RTNjS0nPlWqYSB8IJ6sfShtMvOOJhKxVE/Vm/2XJuhTOTVKwgef3U8INGQ==", + "requires": { + "jsonic": "0.2.2", + "lodash": "4.15.0", + "optioner": "0.8.0" + }, + "dependencies": { + "jsonic": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/jsonic/-/jsonic-0.2.2.tgz", + "integrity": "sha1-Enu5nfTYIWUsSKI9AlzysW5hhJE=" + }, + "lodash": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.15.0.tgz", + "integrity": "sha1-MWI5HY8BQKoiz49rPDTWt/Y9Oqk=" + } + } + }, + "seneca-transport": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/seneca-transport/-/seneca-transport-2.1.1.tgz", + "integrity": "sha1-/40aAzW/4DfKfO3fJ4KL3VUpKiI=", + "requires": { + "eraro": "0.4.1", + "gex": "0.2.2", + "jsonic": "0.2.2", + "lodash": "4.15.0", + "lru-cache": "4.0.1", + "ndjson": "1.4.3", + "nid": "0.3.2", + "patrun": "0.5.0", + "qs": "6.2.1", + "reconnect-core": "1.3.0", + "wreck": "9.0.0" + }, + "dependencies": { + "jsonic": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/jsonic/-/jsonic-0.2.2.tgz", + "integrity": "sha1-Enu5nfTYIWUsSKI9AlzysW5hhJE=" + }, + "lodash": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.15.0.tgz", + "integrity": "sha1-MWI5HY8BQKoiz49rPDTWt/Y9Oqk=" + }, + "patrun": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/patrun/-/patrun-0.5.0.tgz", + "integrity": "sha1-d6UfdzrEkxuzU/1B1Z3mR4/GEY0=", + "requires": { + "gex": "0.2.2", + "lodash": "3.10.0" + }, + "dependencies": { + "lodash": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.0.tgz", + "integrity": "sha1-k9UcZygopEFqEq9XIguoqHN+L7s=" + } + } + }, + "qs": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.2.1.tgz", + "integrity": "sha1-zgPF/wk1vB2daanxTL0Y5WjWdiU=" + }, + "wreck": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wreck/-/wreck-9.0.0.tgz", + "integrity": "sha1-HeY9SbsHuU/nGIZLi+YxduYzMew=", + "requires": { + "boom": "3.2.2", + "hoek": "4.2.0" + } + } + } + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slice-ansi": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", + "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", + "dev": true + }, + "sneeze": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/sneeze/-/sneeze-0.8.0.tgz", + "integrity": "sha1-1U9JJdN/F6SdsuJxSIpGplyo1eg=", + "requires": { + "ansi-escapes": "1.4.0", + "chalk": "1.1.3", + "jsonpath": "0.2.11", + "keypress": "0.2.1", + "lodash": "4.5.0", + "optioner": "0.8.0", + "pad": "1.1.0", + "swim": "0.3.2" + }, + "dependencies": { + "lodash": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.5.0.tgz", + "integrity": "sha1-IoSqBvWxNq29lUuQNRG2L8OdH1k=" + } + } + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "source-map-support": { + "version": "0.4.16", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.16.tgz", + "integrity": "sha512-A6vlydY7H/ljr4L2UOhDSajQdZQ6dMD7cLH0pzwcmwLyc9u8PNI4WGtnfDDzX7uzGL6c/T+ORL97Zlh+S4iOrg==", + "dev": true, + "requires": { + "source-map": "0.5.7" + } + }, + "split2": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/split2/-/split2-0.2.1.tgz", + "integrity": "sha1-At2smtwD7Au3jBKC7Aecpuha6QA=", + "requires": { + "through2": "0.6.5" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "static-eval": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-0.2.3.tgz", + "integrity": "sha1-Aj8XrJ/uQm6niMEuo5IG3Bdfiyo=", + "requires": { + "escodegen": "0.0.28" + }, + "dependencies": { + "escodegen": { + "version": "0.0.28", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-0.0.28.tgz", + "integrity": "sha1-Dk/xcV8yh3XWyrUaxEpAbNer/9M=", + "requires": { + "esprima": "1.0.4", + "estraverse": "1.3.2", + "source-map": "0.5.7" + } + }, + "esprima": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.0.4.tgz", + "integrity": "sha1-n1V+CPw7TSbs6d00+Pv0drYlha0=" + }, + "estraverse": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.3.2.tgz", + "integrity": "sha1-N8K4k+8T1yPydth41g2FNRUqbEI=" + } + } + }, + "stream-consume": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", + "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=" + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0", + "strip-ansi": "4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "swim": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/swim/-/swim-0.3.2.tgz", + "integrity": "sha1-2nIgLrHamkc3ja6r3xOsKTHakP8=", + "requires": { + "clone": "1.0.2", + "commander": "2.11.0", + "debug": "2.6.8", + "farmhash": "1.2.1", + "msgpack": "1.0.2" + } + }, + "table": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.1.tgz", + "integrity": "sha1-qBFsEz+sLGH0pCCrbN9cTWHw5DU=", + "dev": true, + "requires": { + "ajv": "4.11.8", + "ajv-keywords": "1.5.1", + "chalk": "1.1.3", + "lodash": "4.17.4", + "slice-ansi": "0.0.4", + "string-width": "2.1.1" + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "tmp": { + "version": "0.0.31", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", + "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", + "dev": true, + "requires": { + "os-tmpdir": "1.0.2" + } + }, + "topo": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/topo/-/topo-2.0.2.tgz", + "integrity": "sha1-zVYVdSU5BXwNwEkaYhw7xvvh0YI=", + "requires": { + "hoek": "4.2.0" + } + }, + "tryit": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", + "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=", + "dev": true + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "1.1.2" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "optional": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true, + "optional": true + }, + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=" + }, + "use-plugin": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/use-plugin/-/use-plugin-0.3.2.tgz", + "integrity": "sha1-Afi4cvJMzepP15WPBX9NVb8f3/Q=", + "requires": { + "eraro": "0.4.1", + "lodash": "4.15.0", + "nid": "0.3.2", + "norma": "0.3.0" + }, + "dependencies": { + "lodash": { + "version": "4.15.0", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.15.0.tgz", + "integrity": "sha1-MWI5HY8BQKoiz49rPDTWt/Y9Oqk=" + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true, + "optional": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "wreck": { + "version": "12.2.0", + "resolved": "https://registry.npmjs.org/wreck/-/wreck-12.2.0.tgz", + "integrity": "sha1-ocM3HiFSv202AP9YG2acaKTT2Lg=", + "requires": { + "boom": "4.3.1", + "hoek": "4.2.0" + }, + "dependencies": { + "boom": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", + "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", + "requires": { + "hoek": "4.2.0" + } + } + } + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "0.5.1" + } + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "optional": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + } + } +} diff --git a/package.json b/package.json index d516f58..7af4d05 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,6 @@ "url": "https://github.com/nodezoo/nodezoo-github/issues" }, "homepage": "https://github.com/nodezoo/nodezoo-github", - "dependencies": { "github": "9.2.0", "seneca": "3.4.2", diff --git a/srv/github-prod.js b/srv/github-prod.js index f91a1af..8a877e8 100644 --- a/srv/github-prod.js +++ b/srv/github-prod.js @@ -1,11 +1,18 @@ /* Copyright (c) 2014-2017 Richard Rodger and other contributors, MIT License */ -var BASES = process.env.BASES.split(',') +//var BASES = process.env.BASES.split(',') +var CONSUL = process.env.CONSUL_SERVICE_HOST || 'localhost' + var Seneca = require('seneca') Seneca({tag: 'github'}) .use('entity') + + .use('consul-registry', { + host: CONSUL + }) + .use('jsonfile-store', {folder: __dirname+'/../data'}) .use('../github.js') @@ -23,7 +30,7 @@ Seneca({tag: 'github'}) {name:msg.name,data:this.util.clean(mod.data$())}) } - this.act( + this.act( 'role:npm,cmd:get', {name:msg.name}, function (err, mod) { if (err) return @@ -49,6 +56,11 @@ Seneca({tag: 'github'}) {pin: 'role:github'}, {pin: 'role:info,need:part', model:'observe'} ], - bases: BASES, + //bases: BASES, host: '@eth0', + discover: { + registry: { + active: true + } + } })