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

smallorange-graphql-subscriptions

v1.2.4

Published

Graphql subscription manager

Downloads

12

Readme

CircleCI

Small Orange GraphQL Subscriptions Manager

Wht it does

This is a simple GraphQl subscriptions manager, it takes care to group similar subscriptions which belongs to same namespace, type and variables, runs with maximum concurrency (thank u rxjs again), and dispatch data via stream.

Wht is doesn't

It doesn't take care subscribe to your pub/sub mechanism, you should do it by yourself and call run when some event happens, this way, you have freedom to choose the best implementation type for your app. If u're using Redis, you shouldn't create a channel for each event type, instead, you cant just pass an object along with this info, redis is very sensitive with many channels, so, it avoids CPU and memory overhead at Redis machine ;), if you don't know how to do this, you should study more.

It doesn't take care to broadcast messages to right subscribers, it just broadcast, at this way, you can plug in your custom ACL implementation to keep with a single point of truthness.

Important

Subscribers are objects that you intend to send messages afterwards, this lib takes care to manage internal subscriptions state, but once one subscriber is removed (eg. a WebSocket client's close event) you should call unsubscribe(subscriber) manually to remove remove subscription request for there;

API

### Subscriptions
	stream: Observable<{
		args: object,
		contextValue: object,
		event: string,
		hash: string,
		namespace: string,
		operationName: string,
		result: object,
		rootName: string,
		rootValue: object,
		subscribers: Set<object>,
		variableValues: object
	}>;
	
	constructor(
		schema: GraphQLSchema, 
		events: object = {}, 
		customExecutor: function = (/* args like http://graphql.org/graphql-js/execution/#execute*/) => Observable, 
		concurrency: Number = Number.MAX_SAFE_INTEGER
	);
	
	run(
		namespace: string, 
		event: string, 
		rootValue?: object = {}, 
		extendContextValue?: object = {}
	): void;
	
	subscribe(
		namespace: string, 
		subscriber: object, 
		requestString: string, 
		variableValues?: object = {}, 
		contextValue?: object = {}
	): Array<string> (subscription hashes);
	
	unsubscribe(
		subscriber: object, 
		hash?: string
	): void;

Sample

	const Subscriptions = require('smallorange-graphql-subscriptions');
	const {
		Redis
	} = require('smallorange-redis-client');

	const schema = new GraphQLSchema({
	    query: new GraphQLObjectType({
	        name: 'QueryType',
	        fields: {
	            user: {
	                type: UserType
	            }
	        }
	    }),
	    subscription: new GraphQLObjectType({
	        name: 'SubscriptionType',
	        fields: {
	            user: {
	                type: UserType,
	                args: {
	                    age: {
	                        type: GraphQLInt
	                    },
	                    city: {
	                        type: GraphQLString
	                    },
	                    name: {
	                        type: GraphQLString
	                    }
	                },
	                resolve: (root, args) => {
	                    return Object.assign({}, root, args);
	                }
	            }
	        }
	    })
	});

	// declare root names and events whose should trigger this subscription
    const events = {
    	// root name
    	user: [
    		// events
            'user.update',
            'user.delete'
        ]
    };
	
	const redis = new Redis();

	// 3rd argument is a custom executor, it should follow the same default graphQL-js execute signature (http://graphql.org/graphql-js/execution/#execute) but might return an Observable, in our case, we use a remote executor into an AWS lambda, if you provide null, it will use default graphQL-js execute function
	// 4th agument is max concurrency
	const subscriptions = new Subscriptions(schema, events, null, 10);
	
	const requestString = `subscription($name: String!, $age: Int, $city: String) {
	        user(name: $name, age: $age, city: $city) {
	            name
	            city
	            age
	        }
	    }`;
	
	const pseudoWebSocketClient = {
		send(data){
			// send
		}
	};
	
	const subscriptionHash = subscriptions.subscribe('myNamespace', pseudoWebSocketClient, requestString);

	redis.onChannel('updateStream', ({
		namespace, //'myNamespace'
		event, //'user.update'
		data // {age: 20}
	}) => {
		graphqlSubscriptions.run(namespace, event, data);
	});

	// you can can just subscribe direct on stream

	subscriptions.stream
	    .subscribe(({
	    		operationName,
	    		result,
	    		root,
	    		subscribers,
	    		event
	    	}) => {
	    		subscribers.forEach(subscriber => subscriber.send({
	    			operationName,
	    			result,
	    			root,
	    			event
	    		}));
		});

		// is gonna send to all subscribers
		//
		// {
		//	   operationName: 'userUpdate',
		//     result: {
		//         data: {
		//             user: {
		//                 age: 20,
		//                 city: null,
		//                 name: null
		//             }
		//         }
		//     },
		//     root: {
		//         age: 20
		//     },
		//     event: 'event'
		// }