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

genese-mapper

v1.0.8

Published

Generic mapper of javascript objects.

Downloads

7

Readme

genese-mapper

Generic mapper of javascript objects.

Table of Contents

Why use genese-mapper

genese-mapper is the core module of the Genese framework. With genese-mapper, you can transform untyped javascript objects into typed objects. The most common use of genese-mapper is to transform json http responses into typed objects (with your own models).

genese-mapper can be used alone if you just need to type some javascript objects, but is much more powerful inside other genese modules, like genese-angular, which is combining generic http data-services and generic mapper service. For example, with genese-angular, you can just remove all your long and fastidious data-services and mappers : one line in your components is enough !

  • Example

Supposing that in your environment.ts, genese.api = http://localhost:3000 .

books.component.ts

export class BooksComponent {

    public booksGenese: Genese<Book>;

    constructor(private geneseService: GeneseService) {
        this.booksGenese = geneseService.getGeneseInstance(Book);
    }

    this.booksGenese.getOne('/books', '1').subscribe((book: Book) => {
         // book is the data returned by 
         // the request http://localhost:3000/books/1
         // and formatted with type Book
    });
}

In this simple example, the line this.booksGenese.getOne('/books', '1') sends a GET request with the Angular HttpClient method, and returns an object of type Book (which is a model that you defined beforehand).

But under the hood, genese-angular calls the genese-mapper module, which is the real generic mapper. The genese-angular module simply added genese-mapper as dependency.

That's why you can use genese-mapper alone, or use it as a dependency of another module, like genese-angular.

A complete demonstration of use of genese-mapper with genese-angular is available here : genese-angular-demo.

Top

Installation

Install the npm module:

npm install genese-mapper --save

Top

Models

Genese needs to be able to find all the properties of your models. That's why it is imperative to set default values to all the properties of your models, including inside nested objects. Respecting this constraint, Genese will be able to return all the objects correctly formatted.

  • Note

A Genese good practice is to set all the properties of your models as optional. It will be easier to create new objects and will not crash if one day you forget to set a property.

Top -> Models

Primitives

  • Example with primitives
export class Book = {
    id ?= '';
    codeNumbers: number[] = [0];
    collectionNumber?: 0;
    isAvailable?: true;
    name ?= '';
}

Top -> Models

Nested objects

  • Example with nested object
export class Book = {
    id ?= '';
    public editor?: {
        name?: string,
        place?: {
            city?: string,
            country?: string
        }
    } = {
        name: '',
        place: {
            city: '',
            country: ''
        }
    };
}

Top -> Models

Indexable types

Suppose that you wait http responses like this

{
    en: 'The caves of steel',
    fr: 'Les cavernes d\'acier'
}

and suppose that you don't know in advance how many properties will have your response. In this example, you don't know in advance how many translations you will receive and in which languages. In this case, you need to use indexable types like this :

export class Book = {
    [key: string]: string
}

This is the simplest example of indexable types. Now, suppose that your http request returns something more complex like this :

{
    en: {
        country: 'England',
        name: 'The caves of steel'
    },
    fr: {
        country: 'France',
        name: 'Les cavernes d\'acier'
    }
}

In this case, you simply need to define your Genese model like this :

export class Book = {
    [key: string]: {
        country?: string,
        name?: string
    } = {
        gnIndexableType: {
            country: '',
            name: ''
        }
    }
}

The gnIndexableType key is a special key used by Genese to understand that you wait a response with indexableTypes. You'll need to use it every time you'll have to use indexable types.

Top

Usage

At first, define your model :

book.model.ts

export class Book = {
    id ?= '';
    collectionNumber ?= 0;
    editor?: {
        country: string,
        name: string
    } = { country: '', name: ''};
    isAvailable?: true;
    name ?= '';
}

Then, simply create a new GeneseMapper defined with the Book class :

    const geneseMapper = new GeneseMapper(Book); 

Now, you're ready to use genese-mapper methods !

Top

Methods

genese-mapper exports two main methods :

map(data: any): T

This method receives a javascript object without any type, and returns a Typescript object with T type. T is the name of the class used to create your GeneseMapper: (Book in our case).

  • Example
class Book = {
    id ?= '';
    collectionNumber ?= 0;
    editor?: {
        country: string,
        name: string
    } = { country: '', name: ''};
    isAvailable?: true;
    name ?= '';
    other ?= undefined;
}

const data = {
    id: 1,
    collectionNumber: 3,
    editor: {
        country: 'France',
        name: 'Gallimard',
        town: 'Paris'
    },
    name: 'The caves of steel',
    other: 'Author: Isaac Asimov',
    price: 10
}

const geneseMapper = new GeneseMapper(Book); 

const book: Book = geneseMapper.map(data);

// book will be equal to :

{
    id: '1',
    collectionNumber: 3,
    editor: {
        country: 'France',
        name: 'Gallimard',
    },
    isAvailable: true,
    name: 'The caves of steel',
    other: 'Author: Isaac Asimov',
}

As you can see, book is a Typescript object with type Book. genese-mapper looped on the properties of the Book class, and checked if data have the same property names with the expected type, including in nested objects.

Note

  • If some properties of data object are not in your model, like price or editor.town, they are simply removed.
  • If some properties of the class are not present in data object, the value by default is used, like for the iSavailable property.
  • Numbers are automatically casted in strings if necessary (like for id property), and inversely (if the string can be cast in number).
  • When you set a default value to undefined in your model, genese accepts any kind of data for this property, like for other property.

arrayMap(data: any[]): T[]

This method simply uses the .map() method for each element of the data array, and returns an array of Typescript object with type T.

  • Example

class Book = {
    id ?= '';
    isAvailable?: true;
    name ?= '';
}

const data = [
    {
        id: 1,
        name: 'The caves of steel',
        price: 10
    },
    {
        id: 2,
        name: 'Robots and Empire',
        price: 20
    }
]

const geneseMapper = new GeneseMapper(Book); 

const books: Book[] = geneseMapper.arrayMap(data);

// books will be equal to :
[
    {
        id: '1',
        isAvailable: true,
        name: 'The caves of steel'
    },
    {
        id: '2',
        isAvailable: true,
        name: 'Robots and Empire'
    }
]

Top

Other tools

.map() and arrayMap() are the main Genese methods, but genese-mapper provides you some other tools which can be very useful :

clone(model: any): any

Makes a deep copy of an object and returns its clone.

isPrimitive(target: any): boolean

Returns true if the type of target is string, boolean or number, false if not.

isSameObject(obj1: any, obj2: any): boolean

Returns true if obj1 and obj2 are "equivalent", ie if they have the same keys with the same values, even in deep nested objects. Returns false if not.