0.1.1 • Published 9 months ago

dto-serializer v0.1.1

Weekly downloads
-
License
ISC
Repository
github
Last release
9 months ago

DTO Serializer

Fast, minimal, type-safe, zero-dependency DTO serializer for Node

Get Started

Install the package

npm i dto-serializer
yarn dto-serializer

To create a DTO schema, simply declare an object with the properties you wish to expose:

const TestDto = {
    foo: true,
    bar: true
};

Then, simply pass the data to be serialized to the serialize function along with the schema.

import { serialize } from 'dto-serializer';
const data = {
    foo: 123,
    bar: 'abc',
    notExposed: 'abcd'
}
const serializedData = serialize(data, TestDto)

Usage with NestJS

To use this package with NestJS, create an interceptor, pass it the schema and serialize the data in the intercept method.

import { CallHandler, ExecutionContext, NestInterceptor } from '@nestjs/common';
import { map, Observable } from 'rxjs';
import { serialize, Schema } from 'dto-serializer';

export class SerializerInterceptor implements NestInterceptor {
  constructor(private schema: Schema) {}

  intercept(context: ExecutionContext, handler: CallHandler): Observable<any> {
    return handler.handle().pipe(map((data: any) => serialize(data, this.schema)));
  }
}

Design Principles

  1. Purely declarative
  • no need to write ugly maps or other functions
  1. Properties are hidden by default
  • unless you specify a property in your DTO object, it will be omitted from the output. This ensures that, as your data changes, you won't unintentionally leak properties in the output.
  1. Type-safe

Usage

  1. Declare a DTO object:
const TestDto = {
    foo: true,
    bar: true
};
  1. Import the serialize function and provide the data and the DTO:
const data = {
    foo: 'abc',
    bar: [12, 34]
};
serialize(data, TestDto)

Features

  1. Expose properties

To expose a property, it suffices to set its value in the DTO object to true.

Conversely, to omit a property, don't add it in the DTO object, or set the value to false.

  1. Transformations

You can pass custom transformation functions to each property

const TestDto = {
    foo: (value) => Number(value, 10),
    bar: (value) => value.toUppercase()
};
  1. Exposing in a different key

To expose a property in a different key, use the ":key" value where key is the name of the original key

const data = {
    _id: '123'
}

// this will map the _id property of the data to id in the output
const UserDto = {
    id: ':_id'
}
  1. Multiple transformations

To apply multiple transformations to a property, combine them in an array. This is especially useful when a different field than the exposed one needs to be transformed:

const data = {
    user: ' User Name '
}

// this will trim the user field and expose it as userName
const UserDto = {
    userName: [':user', ( value ) => value.trim()]
}
  1. Wildcards

Dealing with dynamically shaped objects is a huge pain point when working with libraries like class-transformer. Sometimes we only know the object values, but not the exact keys:

const features = {
    someFeature: true,
    otherFeature: false
}

Other times, part the object we want to serialize is so dynamic that we simply want to return it as-is. Consider an endpoint which returns the responses of one or multiple API calls. Depending on the number of calls it could return short or long responses.

const data = {
    status: 'OK',
}

const data1 = {
    status: {status: 200, response: 'OK'},
}

const data2 = {
    status: {statuses: [200, 404], responses: ['OK', 'NOT_FOUND']},
}

For both of these cases, dto-serializer provides a handy feature called wildcards:

To serialize an object with dynamic key names, use the * symbol as a key:

const FeaturesDTO = {
    '*': true
}

To serialize a dynamic object, use the wildcard as a value.

// this will serialize all properties from the status key, whatever the value is:
const ResponseDTO = {
    status: '*'
}

Inheritance

To inherit a DTO class, simply merge it with another one as you would do with plain objects:

const TestDto = {
    foo: true,
    bar: true
};

const HideBarDto = {
    ...TestDto,
    bar: false
}

This will keep the foo property of TestDto, but hide the bar property.

0.1.0

9 months ago

0.1.1

9 months ago

0.0.3

9 months ago

0.0.1

1 year ago