npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

senegraph

v0.0.19

Published

Hapi JS and Express plugin connecting SenecaJS with GraphQL

Downloads

15

Readme

Senegraph

HapiJS and Express plugin connecting SenecaJS and GraphQL:

Do you like Microservices? Do you like GraphQL?

Me too! Let me then propose this simple plugin for HapiJS and Express Middleware to you. It's fairly simple and flexible tool for creating API endpoints.

Installation:

npm install --save senegraph

Usage:

HAPI JS :

Here is a simple setup for HapiJS:

import * as hapi from 'hapi';
import { senegraphHapi, hapiql } from 'senegraph';

// setup Hapi server
const server = new hapi.Server();
server.connection({ port: 3000 });

// register the plugins
server.register([{
    register: senegraphHapi,
    options: senegraphOptions,
}, {
    register: hapiql,
    options: {
        path: '/graphiql' // Optional default '/graphiql'
        hapiqlOptions: {
            endpointURL: '/graphql', // required - pointing to the graphQL route
        },
    },
}], (err) => {
    if(err) {
        throw err;
    }
    server.start((error) => {
        if (error) {
          throw error;
        }
        server.log('info', `Server running at: ${server.info.uri}`);
    });
});

Now the senegraphOptions variable can look like this:

const senegraphOptions = {
    // Setting up the seneca microservices
    setupSeneca: (seneca) => {
        // we can return a promise if we need it
        // to wait for some async operation
        seneca.add({ role: 'greeter', cmd: 'sayHello' }, (message, done) => {
            if(message.user) {
                done(null, { message: 'Hello ' + message.user });
            } else {
                done(new Error('You forgot to tell me who you are'));
            }
        });
    },
    // Setting up the schema (for this example it's pretty simple
    // but you can for example split it into multiple modules
    schema: `
        type Query {
            hello(name: String!): String
        }
    `,
    resolvers: {
        Query: {
            // third argument is context, which contains
            // the seneca that we can use for our purpose
            hello: (root, { name }, { seneca }) => {
                // we need to use promise
                // but we could use bluebird's Promisify
                // on seneca, check the links below
                return new Promise((resolve, reject) => {
                    seneca.act({
                        role: 'greeter',
                        cmd: 'sayHello',
                        user: name,
                    }, (err, greetings) => {
                        if(err) {
                            reject(err);
                        } else {
                            resolve(greetings.message);
                        }
                    });
                });
            }
        }
    }
}

To split the schema and/or resolvers into multiple modules take a look at this: http://dev.apollodata.com/tools/graphql-tools/generate-schema.html#modularizing

To modularize SenecaJS into multiple files take a look at this: http://jakepruitt.com/2015/02/09/beginners-guide-to-seneca-js.html

To promisify seneca take a look at this: http://senecajs.org/docs/tutorials/seneca-with-promises.html


What if you need to make action for every request called upon your graphql endpoint? What if you need to provide some additional context and/or root value for your resolvers?

Here's how you do that:

  const senegraphOptions = {
    schema: mySchema,
    resolvers: {
      Query: {
        hello: ({ myRootData }, args, { seneca, myContextData }) => {
          // use myRootData = 'random data2' and myContextData = 'random data1'
          return 'world';
        }
      }
    },
    // This function is called before every request
    // on your graphql endpoint:
    perRequest: (seneca) => {
      // It can either return a value or a Promise
      return new Promise((resolve) => {
        setTimeout(() => {
          resolve({
            // returns context and rootValue used in the next graphql call
            context: { myContextData: 'random data1' },
            rootValue: { myRootData: 'random data2' },
          });
        }, 200);
      });
    }
  }

cool isn't it? You can do for example authentication on every single request.

API

SenegraphHapi options:

| option | type | description | required | |:-------------:|:----------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------------------------------------:|:------------------------------:| | schema | String! | | true | | resolvers | Object! or Array | Containing the resolvers of your graphql schema. | true | | path | String | The url for the endpoint route. | false Default: '/graphql' | | methods | String | Array | The methods supported for graphql endpoint | false Default: ['GET', 'POST'] | | setupSeneca | Function (seneca) => {} | Is being called at the beginning. This option is optional. | false | | perRequest | Promise OR Function OR Function<Promise> | Is being called on every request. Can be Promise or function returning object or function returning Promise. This option is optional | false | | senecaOptions | Object | The seneca instantiating options e.g. { log: 'silent' } | false Default: {} |

HapiQL takes this options:

| option | type | description | required | |:-------------:|:------:|:--------------------------------------------------------------------------:|:-----------------------------------------:| | path | String | The path on which the server should serve for graphiql | false Default: '/graphiql' | | hapiqlOptions | Object | The options for the hapiql contains endpoint and many more described below | true At least endpoint should be provided |

hapiqlOptions take these values:

| option | type | description | required | |:---------------------:|:------:|:-----------------------------------------------------:|:--------:| | endpointURL | String | the graphql endpoint by default on address '/graphql' | true | | subscriptionsEndpoint | String | Endpoint for subscriptions | false | | query | String | The default query | false | | variables | Object | The default variables | false | | operationName | String | The default operation name | false | | result | Object | The default results | false |

Check out this video: https://youtu.be/VWPVrJU2upw

EXPRESS :
import * as Express from 'express'
import { senegraphExpress, expressiql }

const app = Express();

app.use('/graphql', senegraphExpress(senegraphOptions));
app.use('/graphiql', expressiql({ endpointURL: '/graphql' }));

app.listen(3000)

Now the senegraphOptions could look the same as in Hapi example...

API

SenegraphExpress Options:

| option | type | description | required | |:-------------:|:----------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------------------------------------:|:-----------------:| | schema | String! | | true | | resolvers | Object! or Array | Containing the resolvers of your graphql schema. | true | | setupSeneca | Function (seneca) => {} | Is being called at the beginning. This option is optional. | false | | perRequest | Promise OR Function OR Function<Promise> | Is being called on every request. Can be Promise or function returning object or function returning Promise. This option is optional | false | | senecaOptions | Object | The seneca instantiating options e.g. { log: 'silent' } | false Default: {} |

The expressiql options should be in this manner:

| option | type | description | required | |:---------------------:|:------:|:-----------------------------------------------------:|:--------:| | endpointURL | String | the graphql endpoint by default on address '/graphql' | true | | subscriptionsEndpoint | String | Endpoint for subscriptions | false | | query | String | The default query | false | | variables | Object | The default variables | false | | operationName | String | The default operation name | false | | result | Object | The default results | false |

Check out the video on how to use Senegraph with Express: https://youtu.be/-XHN1T6r_R4

CONNECT :

With connect framework it's very similar to Express.

We simply instantiate our server and use the senegraph middleware.

import * as Connect from 'connect'
import * as http from 'http'
import { senegraphConnect, connectiql }

const app = Express();

app.use('/graphql', senegraphConnect(senegraphOptions));
app.use('/graphiql', connectiql({ endpointURL: '/graphql' }));

http.createServer(app).listen(3000);

API

The API is the same as in Senegraph Express implementation.

On both server frameworks you can run seneca.actWithPromise which is the act returning a promise.