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

json-entity

v0.4.3

Published

Entity class for controlling and formatting data objects

Downloads

18

Readme

json-entity

NPM Version Build Status Coverage Status Dependency Status Dev Dependency Status

The goal of this package is to provide an easy, reusable, and secure way to control and format data for output (e.g. from a REST API). Using an Entity, you can specify the fields you'd like to be included in the output representation of your data, as well as additional options for tweaking the structure. In this manner, this package takes a whitelist-only approach, forcing clear definitions of properties that will be exposed. This package is heavily inspired by Grape::Entity.

Example

const User = new Entity({
  // Use `true` to always expose a field
  id: true,
  firstName: true,
  lastName: true,

  // Use a function to return a custom value (return `undefined` to hide in JSON)
  fullName(user, options) {
    return `${user.firstName} ${user.lastName}`;
  },

  // Use an object to specify additional options
  location: {
    // Expose field using an alternate name
    as: 'hometown',

    // Expose field only if function returns "truthy"
    if: (user, options) => options.output === 'full' },

    // See additional options below
  },
});

User.represent({
  id: 1,
  firstName: 'Josh',
  lastName: 'Swan',
  location: 'San Francisco, CA',
}, { output: 'full' });

/*
    {
      id: 1,
      firstName: "Josh",
      lastName: "Swan",
      fullName: "Josh Swan",
      hometown: "San Francisco, CA"
    }
 */

Methods

Entity.isEntity

Static helper method to determine whether a supplied object is an Entity.

Entity.isEntity(new Entity({})); // true
Entity.isEntity({}); // false

extend

Create a new Entity using the current Entity as a base. The new Entity inherits all exposed properties from the base in addition to any new properties specified on the object passed to extend.

const User = new Entity({
  id: true,
  firstName: true,
});

const UserFull = User.extend({
  lastName: true,
  location: true,
});

User.represent({ id: 1, firstName: 'Josh', lastName: 'Swan', location: 'San Francisco, CA' });
// { id: 1, firstName: "Josh" }

UserFull.represent({ id: 1, firstName: 'Josh', lastName: 'Swan', location: 'San Francisco, CA' });
// { id: 1, firstName: "Josh", lastName: "Swan", location: "San Francisco, CA" }

represent

Use the exposed properties defined on the Entity to create a new object from the supplied data. Only whitelisted/exposed properties will be included in the resulting object, and any options specified will be used to modify the output.

const User = new Entity({
  id: true,
  firstName: true,
});

const user = { id: 1, firstName: 'Josh', lastName: 'Swan' };

const representation = User.represent(user);
// { id: 1, firstName: "Josh" }

console.log(user === representation); // false

// Supply an options object that will be passed to `filter` and `if` functions. You can also set
// `safe` to `false` in your options object to enable strict mode and throw an error on any missing
// property, regardless of `require` option (see below).
const representation = User.represent(user, { options });
const throws = User.represent({}, { safe: false });

Options

The following options can be specified using the { [property]: {options} } syntax shown in the example above. Multiple options can be specified and will work together, though some combinations may be logically incompatible.

as String

Expose a property using an alternate name.

const Example = new Entity({
  fullName: { as: 'name' },
});

Example.represent({ fullName: 'Josh Swan' });
// { name: "Josh Swan" }

default Any

Provide a default value in case the property is not defined.

const Example = new Entity({
  admin: { default: false },
});

Example.represent({});
// { admin: false }

filter Function

Filter an array value based on a function. The function is invoked with three arguments: item (the current item of the array), data (the full data object supplied to represent), and options (the options object supplied to represent). Note: An error will be thrown if filter is applied to a non-array value.

const Example = new Entity({
  roles: { filter: (role, user, options) => role !== 'admin' },
});

Example.represent({ roles: ['admin', 'user'] });
// { roles: ['user'] }

if Function

Conditionally expose a field based on function return value ("truthy" = expose). The function is invoked with the same arguments as represent (i.e. data, [options={}]).

const Example = new Entity({
  country: { if: (obj, opts) => obj.country !== 'US' },
});

Example.represent({ country: 'CA' });
// { country: "CA" }

Example.represent({ country: 'US' });
// { }

merge Boolean

Merge properties into parent directly (or concatenate if array). NOTE: When merging arrays from multiple properties using as, the merge option must be specified on all properties that will be merged or those without will overwrite any existing values during the merge process (see example below).

const Example = new Entity({
  id: true,
  address: { merge: true },
});

Example.represent({ id: 1, address: { city: 'San Francisco', region: 'CA', country: 'US' } });
// { id: 1, city: "San Francisco", region: "CA", country: "US" }

const Example2 = new Entity({
  id: true,
  roles: { merge: true },
  scopes: { as: 'roles', merge: true }, // Merge into `roles` - must also specify `merge` on `roles`
});

Example2.represent({ id: 1, roles: ['admin'], scopes: ['user'] });
// { id: 1, roles: ['admin', 'user'] }

require Boolean

Throw an error if this property is absent from data supplied to represent.

const Example = new Entity({
  id: { require: true },
});

Example.represent({});
// Error: data missing required property id!

using Entity

Apply an Entity to the value of the property (for nesting Entities).

const User = new Entity({
  id: true,
  firstName: true,
});

const Example = new Entity({
  user: { using: User },
});

Example.represent({ user: { id: 1, firstName: 'Josh', lastName: 'Swan', location: 'San Francisco, CA' } });
// { user: { id: 1, firstName: "Josh" } }

value Any

Always use the specified value for this property, regardless of property value in supplied data.

const Example = new Entity({
  id: true,
  type: { value: 'User' },
});

Example.represent({ id: 1, type: 'AdminUser' });
// { id: 1, type: "User" }