New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

graphi

Package Overview
Dependencies
Maintainers
5
Versions
37
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

graphi - npm Package Compare versions

Comparing version 5.6.0 to 5.7.0

lib/utils.js

138

lib/index.js
'use strict';
const Assert = require('assert');
const Boom = require('boom');

@@ -8,2 +7,3 @@ const Graphql = require('graphql');

const Merge = require('lodash.merge');
const Utils = require('./utils');
const Package = require('../package.json');

@@ -23,9 +23,11 @@

exports.register = function (server, options) {
const settings = Object.assign({}, internals.defaults, options);
const settings = Merge({}, internals.defaults, options);
let schema = options.schema;
const resolvers = Merge({}, options.resolvers);
server.expose('resolvers', {});
server.expose('settings', settings);
server.decorate('server', 'makeExecutableSchema', Utils.makeExecutableSchema);
server.decorate('server', 'registerSchema', internals.registerSchema);
if (schema && typeof schema === 'string') {
schema = exports.makeExecutableSchema({ schema, resolvers });
if (settings.schema) {
server.registerSchema({ schema: settings.schema, resolvers: settings.resolvers });
}

@@ -35,45 +37,7 @@

type: 'onPreStart',
method: () => {
const resolver = (prefix = '') => {
return async (payload, request, ast) => {
const url = `${prefix}/${ast.fieldName}`;
const res = await request.server.inject({
method: 'graphql',
url,
payload,
headers: request.headers
});
if (res.statusCode < 400) {
return res.result;
}
return new Boom(res.result.message, {
statusCode: res.statusCode,
data: {
error: res.result.error,
url
}
});
};
};
server.table().forEach((route) => {
if (route.method !== 'graphql') {
return;
}
const prefix = route.realm.modifiers.route.prefix;
const path = prefix ? route.path.substr(prefix.length + 1) : route.path.substr(1);
resolvers[path] = resolver(prefix);
});
server.expose('resolvers', resolvers);
}
method: internals.onPreStart
});
server.expose('schema', schema);
server.expose('settings', settings);
const tags = ['graphql'];
const route = {
server.route({
method: '*',

@@ -86,6 +50,4 @@ path: settings.graphqlPath,

}
};
});
server.route(route);
if (settings.graphiqlPath) {

@@ -108,56 +70,50 @@ server.route({

// Inspired by graphql-tools
exports.makeExecutableSchema = ({ schema, resolvers = {}, preResolve }) => {
const parsed = Graphql.parse(schema);
const astSchema = Graphql.buildASTSchema(parsed, { commentDescriptions: true });
exports.makeExecutableSchema = Utils.makeExecutableSchema;
for (const resolverName of Object.keys(resolvers)) {
const type = astSchema.getType(resolverName);
if (!type) {
continue;
}
const typeResolver = resolvers[resolverName];
internals.onPreStart = function (server) {
const resolver = (prefix = '') => {
return async (payload, request, ast) => {
const url = `${prefix}/${ast.fieldName}`;
const res = await request.server.inject({
method: 'graphql',
url,
payload,
headers: request.headers
});
// go through field resolvers for the parent resolver type
for (const fieldName of Object.keys(typeResolver)) {
let fieldResolver = typeResolver[fieldName];
Assert(typeof fieldResolver === 'function', `${resolverName}.${fieldName} resolver must be a function`);
if (typeof preResolve === 'function') {
fieldResolver = internals.wrapResolve(preResolve, fieldResolver);
if (res.statusCode < 400) {
return res.result;
}
if (type instanceof Graphql.GraphQLScalarType) {
type[fieldName] = fieldResolver;
continue;
}
return new Boom(res.result.message, {
statusCode: res.statusCode,
data: {
error: res.result.error,
url
}
});
};
};
if (type instanceof Graphql.GraphQLEnumType) {
const fieldType = type.getValue(fieldName);
Assert(fieldType, `${resolverName}.${fieldName} enum definition missing from schema`);
fieldType.value = fieldResolver;
continue;
}
// no need to set resolvers unless we are dealing with a type that needs resolvers
if (!(type instanceof Graphql.GraphQLObjectType) && !(type instanceof Graphql.GraphQLInterfaceType)) {
continue;
}
const fields = type.getFields();
fields[fieldName].resolve = fieldResolver;
server.table().forEach((route) => {
if (route.method !== 'graphql') {
return;
}
}
return astSchema;
const prefix = route.realm.modifiers.route.prefix;
const path = prefix ? route.path.substr(prefix.length + 1) : route.path.substr(1);
server.plugins.graphi.resolvers[path] = resolver(prefix);
});
};
internals.wrapResolve = function (preResolve, resolve) {
return (root, args, request) => {
const context = preResolve(root, args, request);
internals.registerSchema = function ({ schema = {}, resolvers = {} }) {
const server = this;
if (typeof schema === 'string') {
schema = Utils.makeExecutableSchema({ schema, resolvers });
}
return resolve.call(context, root, args, request);
};
server.plugins.graphi.resolvers = Merge(server.plugins.graphi.resolvers, resolvers);
server.plugins.graphi.schema = Utils.mergeSchemas(server.plugins.graphi.schema, schema);
};
internals.graphqlHandler = async function (request, h) {

@@ -164,0 +120,0 @@ if (request.method.toUpperCase() === 'OPTIONS') {

{
"name": "graphi",
"version": "5.6.0",
"version": "5.7.0",
"description": "hapi graphql plugin",

@@ -40,4 +40,5 @@ "main": "lib",

"graphql-server-module-graphiql": "1.3.x",
"graphql-tools": "v3.0.0-beta.0",
"lodash.merge": "4.6.x"
}
}

@@ -18,2 +18,9 @@ # graphi

The following decorations are made to the hapi server to make it easier to use a single graphi plugin with multiple other plugins depending on it.
- `server.registerSchema({ schema, resolvers })` - similar to the original registration options for the plugin, but this will merge the schema with any prior schema that is already registered with the server. This is useful for combining multiple graphql schemas/resolvers together into a single server.
- `server.makeExecutableSchema({ schema, resolvers, preResolve })` - combine resolvers with the schema definition into a `GraphQLSchema`.
The follow properties are exported directly when you `require('graphi')`
- `graphql` - exported Graphql module that graphi uses

@@ -20,0 +27,0 @@ - `makeExecutableSchema({ schema, resolvers, preResolve })` - combine resolvers with the schema definition into a `GraphQLSchema`.

@@ -1229,31 +1229,113 @@ 'use strict';

it('converts a graphql schema with custom joi directives', () => {
it('errors when resolver missing from schema', () => {
const schema = `
input Someone {
name: String @JoiString(min: 1)
type Person {
firstname: String!
lastname: String!
email: String!
}
interface IPerson {
firstname: String
type Query {
person(firstname: String!): Person!
}
`;
type Person implements IPerson {
firstname: String! @JoiString(min: 1)
let err;
try {
Graphi.makeExecutableSchema({ schema, resolvers: { Query: { human: () => {} } } });
} catch (ex) {
err = ex;
}
expect(err).to.be.error();
});
});
describe('server.registerGraph()', () => {
it('will merge multiple schemas together', async () => {
const getPerson = function (args, request) {
expect(args.firstname).to.equal('billy');
expect(request.path).to.equal('/graphql');
return { firstname: 'billy', lastname: 'jean' };
};
const createPerson = function (args, request) {
expect(args.firstname).to.equal('billy');
expect(args.lastname).to.equal('jean');
expect(request.path).to.equal('/graphql');
return { firstname: 'billy', lastname: 'jean' };
};
const schema1 = `
type Person {
id: ID!
firstname: String!
lastname: String!
email: String!
description: People
ability: Ability
search: SearchResult
}
scalar People
type Query {
person(firstname: String!): Person!
}
`;
enum Ability {
COOK
PROGRAM
const schema2 = `
type Person {
id: ID!
firstname: String!
lastname: String!
}
union SearchResult = Person | String
type Mutation {
createPerson(firstname: String!, lastname: String!): Person!
}
type Query {
people: [Person]
}
`;
const resolvers1 = {
person: getPerson,
people: () => {}
};
const resolvers2 = {
createPerson
};
const server = Hapi.server({ debug: { request: ['error'] } });
await server.register({ plugin: Graphi, options: { schema: schema1, resolvers: resolvers1 } });
server.registerSchema({ schema: schema2, resolvers: resolvers2 });
await server.initialize();
const payload1 = { query: 'mutation { createPerson(firstname: "billy", lastname: "jean") { lastname } }' };
const res1 = await server.inject({ method: 'POST', url: '/graphql', payload: payload1 });
expect(res1.statusCode).to.equal(200);
expect(res1.result.data.createPerson.lastname).to.equal('jean');
const payload2 = { query: 'query { person(firstname: "billy") { lastname } }' };
const res2 = await server.inject({ method: 'POST', url: '/graphql', payload: payload2 });
expect(res2.statusCode).to.equal(200);
expect(res2.result.data.person.lastname).to.equal('jean');
});
it('will merge new query resolvers', async () => {
const getPerson = function (args, request) {
expect(args.firstname).to.equal('billy');
expect(request.path).to.equal('/graphql');
return { firstname: 'billy', lastname: 'jean' };
};
const getPeople = function (args, request) {
return [{ firstname: 'billy', lastname: 'jean' }];
};
const schema1 = `
type Person {
id: ID!
firstname: String!
lastname: String!
}
type Query {
person(firstname: String!): Person!

@@ -1263,35 +1345,54 @@ }

const resolvers = {
Query: {
person: () => {}
},
People: {
description: () => {}
},
Ability: {
COOK: () => {}
},
Person: {
ability: () => {},
description: () => {},
search: () => {}
},
IPerson: {
firstname: () => {}
},
Someone: {
name: () => {}
const schema2 = `
type Person {
id: ID!
firstname: String!
lastname: String!
}
type Query {
people: [Person]
}
`;
const resolvers1 = {
person: getPerson
};
const executable = Graphi.makeExecutableSchema({ schema, resolvers });
expect(executable instanceof Graphi.graphql.GraphQLSchema).to.be.true();
const resolvers2 = {
people: getPeople
};
const server = Hapi.server({ debug: { request: ['error'] } });
await server.register({ plugin: Graphi, options: { schema: schema1, resolvers: resolvers1 } });
server.registerSchema({ schema: schema2, resolvers: resolvers2 });
await server.initialize();
const payload1 = { query: 'query { people { lastname } }' };
const res1 = await server.inject({ method: 'POST', url: '/graphql', payload: payload1 });
expect(res1.statusCode).to.equal(200);
expect(res1.result.data.people[0].lastname).to.equal('jean');
const payload2 = { query: 'query { person(firstname: "billy") { lastname } }' };
const res2 = await server.inject({ method: 'POST', url: '/graphql', payload: payload2 });
expect(res2.statusCode).to.equal(200);
expect(res2.result.data.person.lastname).to.equal('jean');
});
it('errors when resolver missing from schema', () => {
const schema = `
it('will merge new query resolvers when neither was registered with the plugin', async () => {
const getPerson = function (args, request) {
expect(args.firstname).to.equal('billy');
expect(request.path).to.equal('/graphql');
return { firstname: 'billy', lastname: 'jean' };
};
const getPeople = function (args, request) {
return [{ firstname: 'billy', lastname: 'jean' }];
};
const schema1 = `
type Person {
id: ID!
firstname: String!
lastname: String!
email: String!
}

@@ -1304,14 +1405,40 @@

let err;
try {
Graphi.makeExecutableSchema({ schema, resolvers: { Query: { human: () => {} } } });
} catch (ex) {
err = ex;
}
const schema2 = `
type Person {
id: ID!
firstname: String!
lastname: String!
}
expect(err).to.be.error();
type Query {
people: [Person]
}
`;
const resolvers1 = {
person: getPerson
};
const resolvers2 = {
people: getPeople
};
const server = Hapi.server({ debug: { request: ['error'] } });
await server.register({ plugin: Graphi });
server.registerSchema({ schema: schema1, resolvers: resolvers1 });
server.registerSchema({ schema: schema2, resolvers: resolvers2 });
await server.initialize();
const payload1 = { query: 'query { people { lastname } }' };
const res1 = await server.inject({ method: 'POST', url: '/graphql', payload: payload1 });
expect(res1.statusCode).to.equal(200);
expect(res1.result.data.people[0].lastname).to.equal('jean');
const payload2 = { query: 'query { person(firstname: "billy") { lastname } }' };
const res2 = await server.inject({ method: 'POST', url: '/graphql', payload: payload2 });
expect(res2.statusCode).to.equal(200);
expect(res2.result.data.person.lastname).to.equal('jean');
});
});
// auth token strategy plugin

@@ -1318,0 +1445,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc