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 🙏

© 2025 – Pkg Stats / Ryan Hefner

raw-to-schema

v1.0.5

Published

A node package that converts raw data to schema with nested structure

Downloads

20

Readme

Raw to Schema

Description

The motivation behind developing this package is to be able convert signle level plain JSON objects into a set of nested objects to obtain the desired object structure. It's especially useful when converting the raw result of join queries into a nested format just like ORMs do in an effortless way.

How to use it

Converting to Target Schema with Nested Arrays

Here's the source object we will convert into a given schema:

const arr = [
  {
    author_id: 1,
    author_name: 'John Doe',
    book_id: 1,
    book_name: 'My first book',
  },
  {
    author_id: 1,
    author_name: 'John Doe',
    book_id: 2,
    book_name: 'My second book',
  },
  {
    author_id: 1,
    author_name: 'John Doe',
    book_id: 3,
    book_name: 'My third book',
  },
];

Following is the schema that describes the structure of the objects to be created:

class Book {
  @Property({ key: 'book_id' })
  id: number;

  @Property({ key: 'book_name' })
  name: string;
}

class Author {
  @Property({ key: 'author_id' })
  id: number;

  @Property({ key: 'author_name' })
  name: string;

  @NestedProperty({ type: 'array', target: Book })
  books: Book[];
}

From the above schema we can see that there's an author with id and name properties and that author has an array of books. Book schema also has the fields id and name. When conversion is successful, the type of the final object will be as follows:

type FinalOutput = {
  id: number;
  name: string;
  books: {
    id: number;
    name: string;
  }[];
}[];

It should also be noted that the fields in both Author and Book do not directly map to the fields in the given array. In order to make that mapping, we pass an object to the Property decorator that maps the given field to a field in the raw object. As we can see above, author_id from the raw results will be mapped to id, author_name to name etc. However, if the field name is matching the field name of the object in the raw object array, you do not need to do this explicit mapping.

After we define the schema, it's as simple as calling convert method by passing the schema and the array:

const output = convert(Author, arr);

Here's the output:

[
  {
    "id": 1,
    "name": "John Doe",
    "books": [
      {
        "id": 1,
        "name": "My first book"
      },
      {
        "id": 2,
        "name": "My second book"
      },
      {
        "id": 3,
        "name": "My third book"
      }
    ]
  }
]

Converting to Target Schema with Nested Objects

The process is very similar for converting nested objects. The only difference is the nested property will be a plain javascript object istead of an array. That's more suitable when dealing with raw results of one to one relationships. Here's an example:

class BankInfo {
  @Property({ key: 'bank_id' })
  id: number;

  @Property()
  iban: string;
}

class Person {
  @Property()
  id: number;

  @Property()
  name: string;

  @NestedProperty({ type: 'object', target: BankInfo })
  bankInfo: BankInfo;
}

const arr = [
  {
    id: 1,
    name: 'Jane Smith',
    bank_id: 10,
    iban: 'iban',
  },
  {
    id: 2,
    name: 'John Doe',
  },
];

const result = convert(Person, arr);

Output:

[
  {
    "id": 1,
    "name": "Jane Smith",
    "bankInfo": {
      "id": 10,
      "iban": "iban"
    }
  },
  {
    "id": 2,
    "name": "John Doe",
    "bankInfo": null
  }
]

There, we assume each user can have at most one bank account. Therefore, bankInfo property is not an array and we put type as object instead of array in NestedProperty decorator.

Using Transformers During Conversion

When defining schema properties using Property decorator, we can pass a transformer to the configuration object as follows

class SomeClass {
  @Property({ transform: (value: any) => Number(value) })
  someField: number;
}

The transformer function that is specified gets run on the actual value of the object. The callback accepts only a single parameter which is the actual value and the desired transformed value has to be returned from the callback. Despite the ability to create transformers flexibily, we provide a set of predefined transformers to save developers a bit of time as follows:

export function BooleanTransformer(
  value: string | number | boolean
): boolean | null {
  if (value === 'true' || value === 1 || value === '1' || value === true) {
    return true;
  } else if (
    value === 'false' ||
    value === 0 ||
    value === '0' ||
    value === false
  ) {
    return false;
  } else {
    return null;
  }
}

export function NumberTransformer(value: any): number | null {
  const result = Number(value);
  return isNaN(result) ? null : result;
}

export function StringTransformer(value: any): string | null {
  return String(value);
}

BooleanTransformer is aimed at converting boolean values that come from the database driver (0,1,true,false etc) and convert them to actual boolean value in javascript. The other two transformers are obviously converting to Number and String.