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.7.0 to 6.0.0

test/utils.js

13

lib/index.js

@@ -38,3 +38,2 @@ 'use strict';

const tags = ['graphql'];
server.route({

@@ -44,3 +43,2 @@ method: '*',

config: {
tags,
auth: settings.authStrategy,

@@ -56,3 +54,2 @@ handler: internals.graphqlHandler

config: {
tags,
auth: settings.graphiAuthStrategy,

@@ -73,7 +70,7 @@ handler: internals.graphiqlHandler

internals.onPreStart = function (server) {
const resolver = (prefix = '') => {
const resolver = ({ prefix = '', method = 'graphql' }) => {
return async (payload, request, ast) => {
const url = `${prefix}/${ast.fieldName}`;
const res = await request.server.inject({
method: 'graphql',
method,
url,

@@ -99,8 +96,10 @@ payload,

server.table().forEach((route) => {
if (route.method !== 'graphql') {
const tags = route.settings.tags || [];
if (route.method !== 'graphql' && tags.indexOf('graphql') === -1) {
return;
}
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);
server.plugins.graphi.resolvers[path] = resolver({ prefix, method: route.method });
});

@@ -107,0 +106,0 @@ };

@@ -6,2 +6,3 @@ 'use strict';

const GraphqlTools = require('graphql-tools');
const Scalars = require('scalars');

@@ -16,2 +17,3 @@

const astSchema = Graphql.buildASTSchema(parsed, { commentDescriptions: true });
internals.decorateDirectives(astSchema, parsed);

@@ -31,3 +33,3 @@ for (const resolverName of Object.keys(resolvers)) {

if (typeof preResolve === 'function') {
fieldResolver = internals.wrapResolve(preResolve, fieldResolver);
fieldResolver = internals.wrapResolve.call(preResolve, fieldResolver);
}

@@ -56,2 +58,4 @@

}
// console.log(astSchema._typeMap['Person']._fields.firstname.type.__proto__)
return astSchema;

@@ -68,4 +72,60 @@ };

internals.wrapResolve = function (preResolve, resolve) {
internals.decorateDirectives = function (astSchema, parsed) {
for (const definition of parsed.definitions) {
if (definition.kind !== 'ObjectTypeDefinition') {
continue;
}
for (const field of definition.fields) {
for (const directive of field.directives) {
const scalar = internals.createScalar(directive.name.value, directive.arguments);
if (!scalar) {
continue;
}
// Set the type on the schame directly (not the parsed object)
astSchema._typeMap[definition.name.value]._fields[field.name.value].type = scalar;
}
for (const argument of field.arguments) {
for (const directive of argument.directives) {
const scalar = internals.createScalar(directive.name.value, directive.arguments);
if (!scalar) {
continue;
}
const foundArg = astSchema._typeMap[definition.name.value]._fields[field.name.value].args.find((arg) => {
return arg.name === argument.name.value;
});
foundArg.type = scalar;
}
}
}
}
};
internals.createScalar = function (name, args) {
const scalarFn = Scalars[name];
if (typeof scalarFn !== 'function') {
return;
}
const formattedArgs = {};
for (const arg of args) {
let value = arg.value.value;
if (arg.value.kind === 'IntValue') {
value = parseInt(value, 10);
} else if (arg.value.kind === 'BooleanValue') {
value = Boolean(value);
}
formattedArgs[arg.name.value] = value;
}
return scalarFn(formattedArgs);
};
internals.wrapResolve = function (resolve) {
return (root, args, request) => {
const preResolve = this;
const context = preResolve(root, args, request);

@@ -72,0 +132,0 @@

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

@@ -33,3 +33,2 @@ "main": "lib",

"lab": "15.x.x",
"scalars": "0.x.x",
"wreck": "14.x.x"

@@ -41,5 +40,6 @@ },

"graphql-server-module-graphiql": "1.3.x",
"graphql-tools": "v3.0.0-beta.0",
"lodash.merge": "4.6.x"
"graphql-tools": "3.0.x",
"lodash.merge": "4.6.x",
"scalars": "1.x.x"
}
}
# graphi
hapi GraphQL server plugin
hapi GraphQL server plugin with Joi scalars

@@ -33,3 +33,3 @@ [![Build Status](https://secure.travis-ci.org/geek/graphi.svg)](http://travis-ci.org/geek/graphi)

type Person {
firstname: String!
firstname: String! @JoiString(min 4)
lastname: String!

@@ -82,3 +82,3 @@ }

You can also define resolvers as hapi routes. As a result, each resolver is able to benefit from route caching, custom auth strategies, and all of the other powerful hapi routing features. Each route should use the custom method `'graphql'` and the path should be the key name for the resolver prefixed with `/`. You can also mix and match existing resolvers with routes.
You can also define resolvers as hapi routes. As a result, each resolver is able to benefit from route caching, custom auth strategies, and all of the other powerful hapi routing features. Each route should either use the custom method `'graphql'` or it should add a tag named `'graphql'` and the path should be the key name for the resolver prefixed with `/`. You can also mix and match existing resolvers with routes.

@@ -110,1 +110,37 @@ ```javascript

```
This enables existing RESTful APIs to be easily converted over to GraphQL resolvers:
```javascript
server.route({
method: 'POST',
path: '/person',
config: {
tags: ['graphql'],
handler: (request, h) => {
// request.payload contains any arguments sent to the query
return { firstname: 'billy', lastname: 'jean' };
}
}
});
```
## Joi scalar support
Any schema that is expressed with JoiType directives is converted to valid scalars. As a result, using graphi you are able to create more expressive GraphQL schema definitions. For example, if you want to allow the creation of a well formed user the schema can look like the following, resulting in validated input fields before the fields are passed to any resolvers.
```
type Mutation {
createUser(name: String @JoiString(min 2), email: String @JoiString(email: true, max: 128))
}
```
Additionally, you can also use the Joi scalars to perform extra preprosessing or postprocessing on you data. For example, the following schema will result in `firstname` being uppercased on the response.
```
type Person {
firstname: String @JoiString(uppercase: true)
}
```

@@ -266,8 +266,11 @@ 'use strict';

server.route({
method: 'graphql',
method: 'POST',
path: '/createPerson',
handler: (request, h) => {
expect(request.payload.firstname).to.equal('billy');
expect(request.payload.lastname).to.equal('jean');
return { firstname: 'billy', lastname: 'jean' };
config: {
tags: ['graphql'],
handler: (request, h) => {
expect(request.payload.firstname).to.equal('billy');
expect(request.payload.lastname).to.equal('jean');
return { firstname: 'billy', lastname: 'jean' };
}
}

@@ -1120,31 +1123,24 @@ });

describe('makeExecutableSchema()', () => {
it('converts a graphql schema into executable graphql objects', () => {
const schema = `
input Someone {
name: String
}
describe('server.registerSchema()', () => {
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' };
};
interface IPerson {
firstname: String
}
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' };
};
type Person implements IPerson {
const schema1 = `
type Person {
id: ID!
firstname: String!
lastname: String!
email: String!
description: People
ability: Ability
search: SearchResult
}
scalar People
enum Ability {
COOK
PROGRAM
}
union SearchResult = Person | String
type Query {

@@ -1155,32 +1151,5 @@ person(firstname: String!): Person!

const resolvers = {
Query: {
person: () => {}
},
People: {
description: () => {}
},
Ability: {
COOK: () => {}
},
Person: {
ability: () => {},
description: () => {},
search: () => {}
},
IPerson: {
firstname: () => {}
},
Someone: {
name: () => {}
}
};
const executable = Graphi.makeExecutableSchema({ schema, resolvers });
expect(executable instanceof Graphi.graphql.GraphQLSchema).to.be.true();
});
it('converts a graphql schema and executes preResolve first', async () => {
const schema = `
const schema2 = `
type Person {
id: ID!
firstname: String!

@@ -1190,70 +1159,37 @@ lastname: String!

type Mutation {
createPerson(firstname: String!, lastname: String!): Person!
}
type Query {
person(firstname: String!): Person!
people: [Person]
}
`;
const resolvers = {
Query: {
person: () => {
return { firstname: 'peter', lastname: 'pluck' };
}
},
Person: {
firstname: function (root, args, request) {
expect(this.fu).to.equal('bar');
return root.firstname.toUpperCase();
},
lastname: function (root, args, request) {
expect(this.fu).to.equal('bar');
return root.lastname.toUpperCase();
}
}
const resolvers1 = {
person: getPerson,
people: () => {}
};
const preResolve = () => {
return { fu: 'bar' };
const resolvers2 = {
createPerson
};
const executable = Graphi.makeExecutableSchema({ schema, resolvers, preResolve });
expect(executable instanceof Graphi.graphql.GraphQLSchema).to.be.true();
const server = Hapi.server();
await server.register({ plugin: Graphi, options: { schema: executable } });
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 payload = { query: 'query { person(firstname: "peter") { firstname lastname } }' };
const res = await server.inject({ method: 'POST', url: '/graphql', payload });
expect(res.statusCode).to.equal(200);
expect(res.result.data.person.firstname).to.equal('PETER');
expect(res.result.data.person.lastname).to.equal('PLUCK');
});
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');
it('errors when resolver missing from schema', () => {
const schema = `
type Person {
firstname: String!
lastname: String!
email: String!
}
type Query {
person(firstname: String!): Person!
}
`;
let err;
try {
Graphi.makeExecutableSchema({ schema, resolvers: { Query: { human: () => {} } } });
} catch (ex) {
err = ex;
}
expect(err).to.be.error();
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');
});
});
describe('server.registerGraph()', () => {
it('will merge multiple schemas together', async () => {
it('will merge new query resolvers', async () => {
const getPerson = function (args, request) {

@@ -1265,7 +1201,4 @@ expect(args.firstname).to.equal('billy');

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 getPeople = function (args, request) {
return [{ firstname: 'billy', lastname: 'jean' }];
};

@@ -1292,6 +1225,2 @@

type Mutation {
createPerson(firstname: String!, lastname: String!): Person!
}
type Query {

@@ -1303,8 +1232,7 @@ people: [Person]

const resolvers1 = {
person: getPerson,
people: () => {}
person: getPerson
};
const resolvers2 = {
createPerson
people: getPeople
};

@@ -1317,6 +1245,6 @@

const payload1 = { query: 'mutation { createPerson(firstname: "billy", lastname: "jean") { lastname } }' };
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.createPerson.lastname).to.equal('jean');
expect(res1.result.data.people[0].lastname).to.equal('jean');

@@ -1329,3 +1257,3 @@ const payload2 = { query: 'query { person(firstname: "billy") { lastname } }' };

it('will merge new query resolvers', async () => {
it('will merge new query resolvers when neither was registered with the plugin', async () => {
const getPerson = function (args, request) {

@@ -1374,3 +1302,4 @@ expect(args.firstname).to.equal('billy');

const server = Hapi.server({ debug: { request: ['error'] } });
await server.register({ plugin: Graphi, options: { schema: schema1, resolvers: resolvers1 } });
await server.register({ plugin: Graphi });
server.registerSchema({ schema: schema1, resolvers: resolvers1 });
server.registerSchema({ schema: schema2, resolvers: resolvers2 });

@@ -1390,3 +1319,3 @@ await server.initialize();

it('will merge new query resolvers when neither was registered with the plugin', async () => {
it('will merge new query resolvers with formatters', async () => {
const getPerson = function (args, request) {

@@ -1407,2 +1336,3 @@ expect(args.firstname).to.equal('billy');

lastname: String!
friend: Person
}

@@ -1420,2 +1350,3 @@

lastname: String!
friend: Person
}

@@ -1433,3 +1364,8 @@

const resolvers2 = {
people: getPeople
people: getPeople,
Person: {
friend: (root, args, request) => {
return root;
}
}
};

@@ -1448,3 +1384,3 @@

const payload2 = { query: 'query { person(firstname: "billy") { lastname } }' };
const payload2 = { query: 'query { person(firstname: "billy") { lastname friend { firstname } } }' };
const res2 = await server.inject({ method: 'POST', url: '/graphql', payload: payload2 });

@@ -1451,0 +1387,0 @@ expect(res2.statusCode).to.equal(200);

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