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

@muffin-dev/exposer

v1.2.0

Published

This module allows you use property decorators on an object to define which of its properties are exposed, and so you can retrieve it using expose() method.

Downloads

6

Readme

Muffin Dev for Node - Exposer

This module allows you to mark object properties or accessors "exposable", and so make a new object that contains only the exposed properties.

Installation

Install it with npm:

npm i @muffin-dev/exposer

Usage

A common use case for exposing properties when making a web API is to expose only public properties of an entity (e.g. User) when sending the data to the client.

The following examples will show you how to setup an exposed class and its properties for the User entity scenario with different languages.

Using vanilla JS

const { expose, markExposed } = require('@muffin-dev/exposer');

class User {
    username = 'RandomUser';
    password = 'S3cr3t!';
    email = '[email protected]';
}

// Mark the username and email properties exposables
markExposed(User, 'username');
markExposed(User, 'email');

// Outputs { username: "RandomUser", email: "[email protected]" }
console.log(expose(new User()));

You can do the same by making all a class properties exposables, and then ignoring only the properties you don't want to be exposed with markExcluded():

const { expose, markExposed, markExcluded } = require('@muffin-dev/exposer');

class User {
    username = 'RandomUser';
    password = 'S3cr3t!';
    email = '[email protected]';
}

// Mark the entire User class exposed, so all its properties are also exposed
markExposed(User);
// Then, exclude the password property
markExcluded(User, 'password');

// Outputs { username: "RandomUser", email: "[email protected]" }
console.log(expose(new User()));

Using TypeScript

import { expose, markExposed, markExcluded } from '@muffin-dev/exposer';

class User {
    username = 'RandomUser';
    password = 'S3cr3t!';
    email = '[email protected]';
}

// Mark the entire User class exposed, so all its properties are also exposed
markExposed(User);
// Then, exclude the password property
markExcluded(User, 'password');

// Outputs { username: "RandomUser", email: "[email protected]" }
console.log(expose(new User()));

Using TypeScript decorators

The decorators are still an experimental feature of TypeScript that you need to enable in your tsconfig.json file:

{
    "compilerOptions": {
        "experimentalDecorators": true
    }
}
import { expose, Expose, Exclude } from '@muffin-dev/exposer';

// Mark the entire User class exposed, so all its properties are also exposed
@Expose()
class User {
    username = 'RandomUser';

    // Then, exclude the password property
    @Exclude()
    password = 'S3cr3t!';
    
    email = '[email protected]';
}

// Outputs { username: "RandomUser", email: "[email protected]" }
console.log(expose(new User()));

Advanced usage: groups

You can also setup "groups" on your exposed classes and properties, which allow to filter the exposed properties.

Using vanilla JavaScript

const { expose, markExposed, markExcluded } = require('@muffin-dev/exposer');

class User {
    username = 'RandomUser';
    password = 'S3cr3t!';
    email = '[email protected]';
    _privateProperty = { };
}

// Mark the entire class exposed
markExposed(User);
// Exclude password property first
markExcluded(User, 'password');
// Then expose it only for the "private" group
markExposed(User, 'password', 'private');
// Exclude _privateProperty for any group
markExcluded(User, '_privateProperty');

// Outputs { username: "RandomUser", email: "[email protected]" }
console.log(expose(new User()));
// Outputs { username: "RandomUser", password: "S3cr3t!", email: "[email protected]" }
console.log(expose(new User(), 'private'));

Using TypeScript

import { expose, markExposed, markExcluded } from '@muffin-dev/exposer';

class User {
    username = 'RandomUser';
    password = 'S3cr3t!';
    email = '[email protected]';
    _privateProperty = { };
}

// Mark the entire class exposed
markExposed(User);
// Exclude password property first
markExcluded(User, 'password');
// Then expose it only for the "private" group
markExposed(User, 'password', 'private');
// Exclude _privateProperty for any group
markExcluded(User, '_privateProperty');

// Outputs { username: "RandomUser", email: "[email protected]" }
console.log(expose(new User()));
// Outputs { username: "RandomUser", password: "S3cr3t!", email: "[email protected]" }
console.log(expose(new User(), 'private'));

Using TypeScript decorators

import { expose, Expose, Exclude } from '@muffin-dev/exposer';

// Mark the entire class exposed
@Expose()
class User {
    username = 'RandomUser';

    // Exclude password property first, then expose it only for the "private" group
    @Exclude() @Expose('private')
    password = 'S3cr3t!';

    email = '[email protected]';

    // Exclude _privateProperty for any group
    @Exclude()
    _privateProperty = { };
}

// Outputs { username: "RandomUser", email: "[email protected]" }
console.log(expose(new User()));
// Outputs { username: "RandomUser", password: "S3cr3t!", email: "[email protected]" }
console.log(expose(new User(), 'private'));

API documentation

Methods

markExposed()

function markExposed(
    objectClass: TConstructor | string | Record <string, unknown>,
    propertyName: string = null,
    groups: string | string[] = null
): void

Marks a class or a property "exposed".

  • objectClass: TConstructor | string | Record <string, unknown>: A constructor method, an instance or the name of the class on which the operation will be performed
  • propertyName: string = null: The name of the property on which to apply the operation. Null if the operation applies to a class
  • groups: string | string[] = null: The eventual group(s) that the class or the property should be exposed for. If null given, the class or the property is exposed to any group

markExcluded()

function markExcluded(objectClass: TConstructor | string | Record <string, unknown>, propertyName: string): void

Marks a property "excluded", so it won't be exposed to any group.

  • objectClass: TConstructor | string | Record <string, unknown>: A constructor method, an instance or the name of the class on which the operation will be performed
  • propertyName: string: The name of the property on which to apply the operation

expose()

function expose<TObject = Record<string, unknown>>(instance: TObject, groups?: string | string[]): Partial<TObject>;
function expose<TObject = Record<string, unknown>>(className: string, obj: TObject | Record<string, unknown>, groups?: string | string[]): Partial<TObject>;
function expose<TObject = Record<string, unknown>>(
    objectClass: new () => TObject | TObject,
    obj: TObject | Record<string, unknown>,
    groups?: string | string[]
): Partial<TObject>

Makes a new object that contains only the exposed properties.

  • template TObject: The type of the input object.
  • instance: TObject: An instance of the class you want to expose
  • className: string: The class name of the object you want to expose
  • objectClass: The constructor method or an instance of the class you want to expose
  • obj: The object that contains the data to expose
  • groups: If given, only the properties exposed for the named groups will be set on the output object

Returns a new object with the exposed properties.

Decorators

@Expose()

@Expose(groups: string|string[] = null)

Marks a class or a property as exposed.

  • group: string | string[]: The eventual group(s) you want that class or property to be exposed for. If null or empty array given, the class or the property is exposed to every groups

@Exclude()

Exclude()

Marks a property "excluded", so it won't be exposed to any group.

You can use this decorator before using the @Expose() decorator in order to make a property "excluded but for these groups" in an exposed class:

@Expose()
class MyClass {
    public exposedForAllGroups;

    @Exclude() @Expose('demo')
    public exposedOnlyForDemoGroup;
}

Future improvements

  • Add an option for expose() to return null instead of an any object if no exposed properties are found