1.2.0 • Published 4 years ago

@muffin-dev/exposer v1.2.0

Weekly downloads
11
License
ISC
Repository
gitlab
Last release
4 years ago

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 = 'test@example.com';
}

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

// Outputs { username: "RandomUser", email: "test@example.com" }
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 = 'test@example.com';
}

// 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: "test@example.com" }
console.log(expose(new User()));

Using TypeScript

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

class User {
    username = 'RandomUser';
    password = 'S3cr3t!';
    email = 'test@example.com';
}

// 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: "test@example.com" }
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 = 'test@example.com';
}

// Outputs { username: "RandomUser", email: "test@example.com" }
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 = 'test@example.com';
    _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: "test@example.com" }
console.log(expose(new User()));
// Outputs { username: "RandomUser", password: "S3cr3t!", email: "test@example.com" }
console.log(expose(new User(), 'private'));

Using TypeScript

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

class User {
    username = 'RandomUser';
    password = 'S3cr3t!';
    email = 'test@example.com';
    _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: "test@example.com" }
console.log(expose(new User()));
// Outputs { username: "RandomUser", password: "S3cr3t!", email: "test@example.com" }
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 = 'test@example.com';

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

// Outputs { username: "RandomUser", email: "test@example.com" }
console.log(expose(new User()));
// Outputs { username: "RandomUser", password: "S3cr3t!", email: "test@example.com" }
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
1.2.0

4 years ago

1.1.1

4 years ago

1.1.2

4 years ago

1.1.0

4 years ago

0.0.6

5 years ago

0.0.5

5 years ago

0.0.4

5 years ago

0.0.3

5 years ago

0.0.2

5 years ago

1.0.0

5 years ago

0.0.1

5 years ago