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 6.3.1 to 7.0.0

10

lib/index.js

@@ -16,3 +16,4 @@ 'use strict';

authStrategy: false,
graphiAuthStrategy: false
graphiAuthStrategy: false,
formatError: null
}

@@ -126,3 +127,5 @@ };

let span;
/* $lab:coverage:off$ */
if (parentSpan && request.server.tracer) {
/* $lab:coverage:on$ */
span = request.server.tracer.startSpan('graphql_request', { childOf: parentSpan.context() });

@@ -167,2 +170,7 @@ span.log({ event: 'onGraphQL', payload: request.payload, info: request.info });

if (result.errors) {
const formatError = request.server.plugins.graphi.settings.formatError;
if (typeof formatError === 'function') {
result.errors = result.errors.map(formatError);
}
if (span) {

@@ -169,0 +177,0 @@ span.log({ event: 'error', method: 'graphql.execute', error: result.errors });

57

lib/utils.js

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

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

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

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

@@ -107,57 +105,2 @@ for (const resolverName of Object.keys(resolvers)) {

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) {

@@ -164,0 +107,0 @@ return (root, args, request) => {

{
"name": "graphi",
"version": "6.3.1",
"version": "7.0.0",
"description": "hapi graphql plugin",

@@ -31,6 +31,6 @@ "main": "lib",

"code": "5.x.x",
"hapi": "17.x.x",
"hapi": "18.x.x",
"hapi-auth-bearer-token": "6.x.x",
"lab": "17.x.x",
"nes": "9.0.x",
"lab": "18.x.x",
"nes": "10.0.x",
"opentracing": "0.14.3",

@@ -42,8 +42,7 @@ "traci": "1.4.0",

"boom": "7.x.x",
"graphql": "14.0.x",
"graphql": "14.1.x",
"apollo-server-module-graphiql": "1.4.x",
"graphql-tools": "4.0.x",
"lodash.merge": "4.6.x",
"scalars": "1.x.x"
"lodash.merge": "4.6.x"
}
}
# graphi
hapi GraphQL server plugin with Joi scalars
hapi GraphQL server plugin

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

- `graphiAuthStrategy` - (optional) Authentication strategy to apply to `/graphiql` route. Default is `false`.
- `formatError` - (optional) Function that receives a [GraphQLError](https://github.com/graphql/graphql-js/blob/271e23e13ec093e7ffb844e7ffaf340ab92f053e/src/error/GraphQLError.js) as its only argument and returns a custom error object, which is returned to the client.

@@ -35,3 +36,3 @@ ## API

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

@@ -67,3 +68,3 @@ }

args: {
firstname: { type: new Scalars.JoiString({ min: [2, 'utf8'], max: 10 }) }
firstname: { type: GraphQLString }
},

@@ -157,21 +158,1 @@ resolve: (root, { firstname }, request) => {

At the moment clients are required to use a nes compatible library and to subscribe to events using the `client.subscribe` function. The path that clients should use depends on the message, but in the previous example this would be `'/personCreated/peter'`.
## 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)
}
```

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

const { MockTracer } = require('opentracing');
const Scalars = require('scalars');
const Traci = require('traci');

@@ -20,3 +19,2 @@ const Wreck = require('wreck');

const { GraphQLObjectType, GraphQLSchema, GraphQLString } = GraphQL;
const lab = exports.lab = Lab.script();

@@ -75,30 +73,2 @@ const describe = lab.describe;

it('will handle graphql GET requests GraphQL instance schema', async () => {
const schema = new GraphQLSchema({
query: new GraphQLObjectType({
name: 'RootQueryType',
fields: {
person: {
type: GraphQLString,
args: {
firstname: { type: new Scalars.JoiString({ min: [2, 'utf8'], max: 10 }) }
},
resolve: (root, { firstname }, request) => {
return firstname;
}
}
}
})
});
const server = Hapi.server({ debug: { request: ['error'] } });
await server.register({ plugin: Graphi, options: { schema } });
await server.initialize();
const url = '/graphql?query=' + encodeURIComponent('{ person(firstname: "tom")}');
const res = await server.inject({ method: 'GET', url });
expect(res.statusCode).to.equal(200);
expect(res.result.data.person).to.equal('tom');
});
it('will handle graphql POST requests with query', async () => {

@@ -566,3 +536,3 @@ const schema = `

args: { firstname: { type: GraphQL.GraphQLString } },
resolve: (root, args) => {
resolve: (rootValue, args) => {
expect(args.firstname).to.equal('billy');

@@ -925,2 +895,43 @@ return 'jean';

it('allows errors to be formatted', async () => {
const schema = `
type Person {
firstname: String!
lastname: String!
}
type Query {
person: Person!
}
`;
const getPerson = function (args, request) {
const error = new Error('my silly error');
error.id = 'my id';
throw error;
};
const resolvers = {
person: getPerson
};
const formatError = function (error) {
expect(error.originalError.message).to.equal('my silly error');
expect(error.originalError.id).to.equal('my id');
error.originalError.custom = 'field';
return error.originalError;
};
const server = Hapi.server();
await server.register({ plugin: Graphi, options: { schema, resolvers, formatError } });
await server.initialize();
const payload = { query: 'query { person { lastname } }' };
const res = await server.inject({ method: 'POST', url: '/graphql', payload });
expect(res.statusCode).to.equal(200);
expect(res.result.errors[0].message).to.equal('my silly error');
expect(res.result.errors[0].id).to.equal('my id');
expect(res.result.errors[0].custom).to.equal('field');
});
it('will log result with errors property', async () => {

@@ -1749,4 +1760,4 @@ const schema = `

Person: {
friend: (root, args, request) => {
return root;
friend: (rootValue, args, request) => {
return rootValue;
}

@@ -1753,0 +1764,0 @@ }

@@ -80,75 +80,2 @@ 'use strict';

it('converts a graphql schema with joi scalars', async () => {
const schema = `
type Person {
firstname: String @JoiString(min: 2, max: 100, normalize: "NFC", uppercase: true)
lastname: String
email: String!
}
type Query {
person(personname: String @JoiString(max: 5)): Person!
}
`;
const resolvers = {
Query: {
person: (root, { personname }) => {
return { firstname: personname, lastname: 'pluck' };
}
}
};
const executable = Utils.makeExecutableSchema({ schema, resolvers });
expect(executable instanceof GraphQL.GraphQLSchema).to.be.true();
const server = Hapi.server({ debug: { request: ['error'] } });
await server.register({ plugin: Graphi, options: { schema: executable } });
await server.initialize();
const payload = { query: 'query { person(personname: "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');
});
it('converts a graphql schema with joi scalars and validation errors in query', async () => {
const schema = `
type Person {
firstname: String @JoiString(min: 2, max: 100, trim: true)
lastname: String
email: String!
}
type Query {
person(personname: String @JoiString(max: 4)): Person!
}
`;
const resolvers = {
Query: {
person: (root, { personname }) => {
expect(personname).to.be.error();
expect(personname.message).to.contain('length must be less than or equal to 4 characters');
return { lastname: 'pluck' };
}
}
};
const executable = Utils.makeExecutableSchema({ schema, resolvers });
expect(executable instanceof GraphQL.GraphQLSchema).to.be.true();
const server = Hapi.server({ debug: { request: ['error'] } });
await server.register({ plugin: Graphi, options: { schema: executable } });
await server.initialize();
const payload = { query: 'query { person(personname: "peter") { lastname } }' };
const res = await server.inject({ method: 'POST', url: '/graphql', payload });
expect(res.statusCode).to.equal(200);
expect(res.result.data.person.lastname).to.equal('pluck');
});
it('only converts valid Joi directives', async () => {

@@ -155,0 +82,0 @@ const schema = `

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