cloudapi-gql
Advanced tools
@@ -137,2 +137,6 @@ 'use strict'; | ||
process.on('unhandledRejection', (err) => { | ||
console.error(err); | ||
}); | ||
start(); |
@@ -11,7 +11,9 @@ 'use strict'; | ||
class CloudApi { | ||
constructor ({ token, url, keyId, key }) { | ||
module.exports = class CloudApi { | ||
constructor ({ token, url, keyId, key, log }) { | ||
const env = process.env.NODE_ENV; | ||
Assert(token || (env === 'development') || (env === 'test'), 'token is required for production'); | ||
Assert( | ||
token || env === 'development' || env === 'test', | ||
'token is required for production' | ||
); | ||
@@ -27,2 +29,4 @@ this._token = token; | ||
}); | ||
this._log = log.bind(this); | ||
this.fetch = this.fetch.bind(this); | ||
} | ||
@@ -39,3 +43,5 @@ | ||
Date: now, | ||
Authorization: `Signature keyId="${this._keyId}",algorithm="rsa-sha256" ${signature}` | ||
Authorization: `Signature keyId="${ | ||
this._keyId | ||
}",algorithm="rsa-sha256" ${signature}` | ||
}; | ||
@@ -85,3 +91,3 @@ | ||
async fetch (path = '/', options = {}, request) { | ||
async fetch (path = '/', options = {}) { | ||
const wreckOptions = { | ||
@@ -97,3 +103,3 @@ json: true, | ||
const method = options.method && options.method.toLowerCase() || 'get'; | ||
const method = (options.method && options.method.toLowerCase()) || 'get'; | ||
@@ -110,3 +116,3 @@ const cached = this._getCache(method, path, wreckOptions); | ||
} catch (ex) { | ||
request.log(['error', path], (ex.data && ex.data.payload) || ex); | ||
this._log(['error', path], (ex.data && ex.data.payload) || ex); | ||
Bounce.rethrow(ex, 'system'); | ||
@@ -125,9 +131,2 @@ | ||
} | ||
} | ||
module.exports = (path, args, request) => { | ||
const { cloudapi } = request.plugins; | ||
return cloudapi.fetch(path, args, request); | ||
}; | ||
module.exports.CloudApi = CloudApi; |
'use strict'; | ||
const Assert = require('assert'); | ||
const Fs = require('fs'); | ||
@@ -8,4 +9,5 @@ const Path = require('path'); | ||
const Package = require('../package.json'); | ||
const { CloudApi } = require('./cloudapi'); | ||
const Resolvers = require('./resolvers'); | ||
const CloudApi = require('./cloudapi'); | ||
const Formatters = require('./formatters'); | ||
const Routes = require('./routes'); | ||
@@ -24,3 +26,4 @@ const Schema = Fs.readFileSync(Path.join(__dirname, '/schema.graphql')); | ||
keyId, | ||
key | ||
key, | ||
log: request.log.bind(request) | ||
}); | ||
@@ -32,12 +35,24 @@ | ||
const graphqlHandler = function (route, options) { | ||
Assert(typeof options.method === 'function', 'method must be a function'); | ||
return function (request, h) { | ||
const fetch = request.plugins.cloudapi.fetch.bind(request.plugins.cloudapi); | ||
return options.method(fetch, request.payload); | ||
}; | ||
}; | ||
const register = async (server, options) => { | ||
const schema = makeExecutableSchema({ | ||
typeDefs: Schema.toString(), | ||
resolvers: Resolvers | ||
resolvers: Formatters | ||
}); | ||
server.decorate('handler', 'graphql', graphqlHandler); | ||
server.route(Routes); | ||
const graphiOptions = { | ||
graphiqlPath: process.env.NODE_ENV === 'development' ? '/graphiql' : options.graphiqlPath, | ||
schema: schema, | ||
resolvers: Resolvers, | ||
resolvers: Formatters, | ||
authStrategy: options.authStrategy | ||
@@ -44,0 +59,0 @@ }; |
{ | ||
"name": "cloudapi-gql", | ||
"version": "5.0.0", | ||
"version": "6.0.0", | ||
"license": "MPL-2.0", | ||
@@ -15,3 +15,3 @@ "repository": "github:joyent/cloudapi-gql", | ||
"pretest": "npm run lint", | ||
"test": "lab -c" | ||
"test": "lab -t 76 --coverage-path lib -a code" | ||
}, | ||
@@ -21,3 +21,3 @@ "dependencies": { | ||
"boom": "7.x.x", | ||
"bounce": "^1.x.x", | ||
"bounce": "1.x.x", | ||
"force-array": "3.1.x", | ||
@@ -38,3 +38,3 @@ "fwrule": "1.4.x", | ||
"graphql-playground-html": "1.x.x", | ||
"graphql-voyager": "1.0.0-rc.12", | ||
"graphql-voyager": "1.0.0-rc.15", | ||
"hapi": "17.x.x", | ||
@@ -41,0 +41,0 @@ "inert": "5.x.x", |
'use strict'; | ||
const Fs = require('fs'); | ||
const Path = require('path'); | ||
const { expect } = require('code'); | ||
const { graphql } = require('graphi'); | ||
const Hapi = require('hapi'); | ||
const Lab = require('lab'); | ||
const CloudApiGql = require('../lib/'); | ||
const schema = Fs.readFileSync(Path.join(__dirname, '../lib/schema.graphql')); | ||
const lab = exports.lab = Lab.script(); | ||
@@ -15,3 +18,30 @@ const it = lab.it; | ||
const server = new Hapi.Server(); | ||
await server.register({ plugin: CloudApiGql, options: { keyPath: Path.join(__dirname, '/test.key') } }); | ||
await server.register({ plugin: CloudApiGql, options: { keyPath: Path.join(__dirname, 'test.key') } }); | ||
}); | ||
it('has a resolver for every query and mutation in the schema', async () => { | ||
const fields = []; | ||
const parsed = graphql.parse(schema.toString()); | ||
for (const def of parsed.definitions) { | ||
if (def.kind !== 'ObjectTypeDefinition' || (def.name.value !== 'Query' && def.name.value !== 'Mutation')) { | ||
continue; | ||
} | ||
for (const field of def.fields) { | ||
fields.push(field.name.value); | ||
} | ||
} | ||
const server = new Hapi.Server(); | ||
await server.register({ plugin: CloudApiGql, options: { keyPath: Path.join(__dirname, 'test.key') } }); | ||
await server.initialize(); | ||
const paths = server.table().map((route) => { | ||
return route.path.substr(1); | ||
}); | ||
for (const field of fields) { | ||
expect(paths).to.contain(field); | ||
} | ||
}); | ||
'use strict'; | ||
const Code = require('code'); | ||
const { expect } = require('code'); | ||
const Lab = require('lab'); | ||
const Products = require('../lib/products'); | ||
const { products } = require('../lib/handlers'); | ||
@@ -10,3 +10,2 @@ | ||
const { it, describe } = lab; | ||
const expect = Code.expect; | ||
@@ -16,6 +15,4 @@ | ||
it('returns a list of available products with the correct URL', () => { | ||
const products = Products('/test'); | ||
expect(products.length).to.be.greaterThan(1); | ||
expect(products[0].url).to.contain('/test'); | ||
expect(products().length).to.be.greaterThan(1); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
155786
55.61%51
183.33%4090
65.12%13
30%135
13400%