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

qryq

v1.0.0-rc1

Published

express and run arbitrary sets of dependent queries as directed acyclic graphs.

Downloads

18

Readme

qryq

NPM

Build Status Coverage Status

qryq is a NodeJs library that allows one to express and run arbitrary sets of dependent queries as directed acyclic graphs.

Its name derives from "query queue".

Adding to your project

npm install qryq --save

To use it within your project:

var qryq = require('qryq');

Usage

Create an API object. qryq will look up API methods by keys on this object. The values are expected to be functions which conform to the signature: function(deferred, data) where deferred is a Q deferred promise, and data is an object expected to contain the required inputs for this API.

var myApi = {
  add: function(deferred, data) {
    if (typeof data.num1 !== 'number' || typeof data.num2 !== 'number') {
      deferred.reject('Invalid data');
    }
    else {
      deferred.resolve(data.num1 + data.num2);
    }
  },
  multiply: function(deferred, data) {
    if (typeof data.num1 !== 'number' || typeof data.num2 !== 'number') {
      deferred.reject('Invalid data');
    }
    else {
      deferred.resolve(data.num1 * data.num2);
    }
  },
};

Tell qryq to construct a graph of dependent queries. Initially call the graph() method, and pass in the API object created previously. Next, for each query, name the API method it should invoke using .api(), and what input data it should receive using .input().

Note that the dependencies are inferred automatically from the input data object. If any values are a string that looks like '#{ANOTHER_QUERYS_NAME}', the output value of the other query named will be substituted in its place. This means that this other query is identified as a prerequisite, and thus must complete successfully before this query begins. qryq will automatically identify that this is the case, and wire up the promises as required.

var myQueries = qryq
  .graph({ api: myApi })
  .query('A')
    .api('add')
    .input({ num1: 3, num2: 4 })
  .query('B')
    .api('multiply')
    .input({ num1: '#{A}', num2: 3 })
  .query('C')
    .api('multiply')
    .input({ num1: 7, num2: '#{A}' })
  .query('D')
    .api('add')
    .input({ num1: '#{C}', num2: '#{B}' });

After constructing the graph of dependent queries, we kick off their execution using the run() method. This returns a promise.

var myPromise = myQueries.run();

myPromise.then(function(result) {
  // Do something with result
});

In the above example, we expect result to be:

{
  A: 7,
  B: 21,
  C: 49,
  D: 70,
}

Advanced usage

Manually Specifying Dependents

Use depends() to specify an array of names of queries that this query depends on. This saves qryq from having to analyse the input object, thereby acting as a performance optimisation.

  .query('D')
    .api('add')
    .depends(['C', 'D'])
    .input({ num1: '#{C}', num2: '#{B}' })

This does not result in any difference in the expected output. However, if the dependent queries are specified incorrectly, wrong results may be returned.

The depends are computed upon setting input if not already present, so call it before calling input().

Filtering Results

Call filterOutput() to filter the output of this query from the final result.

  .query('A')
    .api('add')
    .input({ num1: 3, num2: 4 })
    .filterOutput(true)

This would produce an output like this instead:

{
  B: 21,
  C: 49,
  D: 70,
}

Expression Drilldown

qryq also supports drilling down into keys of objects that have been returned by dependent queries.

var myQueries = qryq
  .graph({ api: myApi })
  .query('A')
    .api('foobar')
    .input({})
  .query('B')
    .api('baz')
    .input({ value: '#{A}.foo.bar' });

In the example above, we assume that the foobar API returns this object: { foo: { bar: 123 } }. After this, the baz API is called with this input object: { value: 123 }.

Non-fluent Interface

Instead of using a fluent interface as above, call allQueries() and pass in an array of query objects.

var myQueries = qryq
  .graph({ api: myApi })
  .allQueries([
    { id: 'A', api: 'add', input: { num1: 3, num2: 4 } },
    { id: 'B', api: 'multiply', input: { num1: '#{A}', num2: 3 } },
    { id: 'C', api: 'multiply', input: { num1: 7, num2:  '#{A}' } },
    { id: 'D', api: 'add', input: { num1: '#{C}', num2: '#{B}' } }
  ]);

This approach is made available for two reasons:

  • easy migration from [email protected]
    • note that what is now named input was previously named qry
  • when there is a need to construct the list of queries without qryq,
    • for example if qryq is on a server, and the client makes a request to the server with this list of queries.

Pronunciation

qryq is pronounced as /ˈkwərik/.

Contributing

This repository uses the git flow branching strategy. If you wish to contribute, please branch from the develop branch - pull requests will only be requested if they request merging into the develop branch.

Licence

GPLv3

Author

Brendan Graetz