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

hapi-dribble

v2.0.2

Published

dynamically filter api responses

Downloads

4

Readme

hapi-dribble

hapi-dribble allows api responses to be filtered dynamically based upon a request state.

Install

npm install --save hapi-dribble

Usage

const Hapi = require('hapi');
const Dribble = require('hapi-dribble');

(async () => {
  const server = Hapi.server({ port: 8080 });
  await server.register(Dribble);

  server.route({
    method: 'GET',
    path: '/users',
    config: {
      auth: 'session',
      plugins: {
        dribble: {
          hasAdminScope: {
            rule: (request) =>
              request.auth.credentials.scope.includes('admin'),
            filter: {
              omit: ['user.id'],
              deep: [
                { for: 'user.data', omit: ['personal'] }
              ]
            }
          },
          hasSuperAdminScope: {
            rule: (request) =>
              request.auth.credentials.scope.includes('super-admin'),
            filter: {
              keep: ['user', 'meta'],
              deep: [
                { for: 'user.data', omit: ['personal'] }
              ]
            }
          }
        }
      },
      handler: (request, h) => request.auth.artifacts.scopeContext
    }
  });

  await server.start();
})();

Objects consisting of a rule and filter can be assigned to the dribble plugin object. The first rule that evaluates to true will be used by dribble in order to conditionally filter the response. The schema defined in the filter will be used to process the data.

Filters can specify keep, omit and deep properties. All are optional, keep is processed first, followed by omit and finally deep. This order may be critical to your design.

keep and omit are string arrays representing property paths. Properties specified in these paths can be nested objects, nested arrays, jaggered arrays, or a combination of any of these. deep is slightly different. Here, an array of objects is specified, with for - a string property path pointing to a nested property object, and omit or keep array detailing first class properties on the object pointed to by for.

Some example property paths are outlined below:

  • flat object
{
  a: 'a',
  b: 'b',
  c: 'c' 
}

'c' - this path points to the first class property 'c' on the above object

  • nested object
{
  a: {
    b: 'b'
    c: 'c'
  }
}

'a.c' - this path points to the nested property 'c' on the above object

  • object within an array (or a nested array)
[
  a: {
    b: 'b'
    c: [{
      d: 'd' 
    }, {
      d: 'd'
    }]
  }
]

'a.c.d' - this path points to the nested array properties 'd' on the above object

  • object within a jaggered array
[
  [{
    a: 'a',
    b: 'b'
  }, {
    a: 'a',
    b: 'b'
  }]
]

'[].a' - this path points to the nested jaggered array properties 'a' on the above object

Example

Given the following object:

 {
  a: {
    b: {
      c: 'c',
      d: 'd'
    },
    e: 'e'
  },
  f: [{
    g: 'g',
    h: [{
      i: 'i'
    }]
  }],
  j: {
    k: 'k',
    l: 'l'
  }
}

When the following filter is applied

{
  omit: ['f.g'],
  keep: ['a.e', 'f', 'a.b.c', 'j'],
  deep: [{
    for: 'j', keep: ['l']
  }]
};

The object is transformed to:

{
  a: {
    b: {
      c: 'c'
    },
    e: 'e'
  },
  f: [{
    h: [{
      i: 'i'
    }]
  }],
  j: {
    l: 'l'
  }
};

Note:

  • A filter array containing any inferred properties are reduced to lowest parent property during processing. For example, take the following object:
{
  a: {
    b: {
      c: 'c'
      d: 'd'
    }
  }
}

A filter which specifies: Keep: ['a.b.c', 'a.b'] is reduced to: Keep: ['a.b'] as pointing to path 'a.b' will keep all of the properties in object b ('c' here is inferred).

  • If the path contains an array property, it is assumed each item in the array has a consistent schema.