Ultimate Javascript object mapping tool
yarn add mapex
npm install mapex
Consider a typical blog post. The API response for a single post might look something like this:
{
"id": "123",
"author": {
"id": "1",
"name": "Paul"
},
"title": "My awesome blog post",
"comments": [
{
"id": "324",
"commenter": {
"id": "2",
"name": "Nicole"
}
}
]
}
We have two nested entity types within our article: users and comments. Using various schema, we can normalize all three entity types down:
import mapex from "mapex";
mapex(
{
$result: "article",
// define user schema
user: {},
// define comment schema
comment: {
// define commenter follows user schema
commenter: "user",
},
// define article schema
article: {
author: "user",
// define comments array follow comment schema
comments: "comment",
},
},
data
);
Now, normalizedData will be:
const output = {
$result: "123",
article: {
123: {
id: "123",
author: "1",
title: "My awesome blog post",
comments: ["324"],
},
},
user: {
1: { id: "1", name: "Paul" },
2: { id: "2", name: "Nicole" },
},
comment: {
324: { id: "324", commenter: "2" },
},
};
const schema = {
// A name of schema that use to parse input data
$result: "subSchema1",
// A definition of sub schema
subSchema1: {},
subSchema2: {},
};
A prop name of entity collection in output object
mapex(
{
$result: "article",
article: {
$name: "articles",
},
},
{
id: 1,
}
);
Output
{
"$result": 1,
"articles": { "id": 1 }
}
Indicate which entity property is id, $id can be string or Function
mapex(
{
$result: "article",
article: {
$id: "_id",
},
},
{
_id: 1,
}
);
Output
{
"$result": 1,
"article": { "_id": 1 }
}
Indicate entity property values follow the given schema.
mapex(
{
$result: "item",
},
{ firstThing: { id: 1 }, secondThing: { id: 2 } }
);
{
"$result": { "firstThing": 1, "secondThing": 2 },
"item": { "1": { "id": 1 }, "2": { "id": 2 } }
}
Indicate the property which is schema name.
mapex(
{
$result: "user",
user: {
$type: "roleId",
1: "mod",
2: "admin",
},
mod: {},
admin: {},
},
[
{ id: 1, roleId: 1 },
{ id: 2, roleId: 2 },
{ id: 3, roleId: 1 },
]
);
const output = {
$result: [1, 2, 3],
mod: {
1: { id: 1, roleId: 1 },
3: { id: 3, roleId: 1 },
},
admin: {
2: { id: 2, roleId: 2 },
},
// no user collection generated
};
Use with $type attribute, if entity does not present $type property, $default schema will be used
mapex(
{
$result: "user",
user: {
$type: "roleId",
$default: "guest",
1: "mod",
2: "admin",
},
mod: {},
admin: {},
guest: {},
},
[
{ id: 1, roleId: 1 },
{ id: 2, roleId: 2 },
{ id: 3, roleId: 1 },
// no roleId presents, this entity will follow 'guest' schema
{ id: 4 },
]
);
Use with $type attribute. if $desc = true, a union entity collection will be added.
mapex(
{
$result: "user",
user: {
$type: "roleId",
$desc: true,
1: "mod",
2: "admin",
},
mod: {},
admin: {},
},
[
{ id: 1, roleId: 1 },
{ id: 2, roleId: 2 },
{ id: 3, roleId: 1 },
]
);
const output = {
$result: [1, 2, 3],
mod: {
1: { id: 1, roleId: 1 },
3: { id: 3, roleId: 1 },
},
admin: {
2: { id: 2, roleId: 2 },
},
user: {
1: "mod",
3: "mod",
2: "admin",
},
};
If you want to customize user entity collection, just pass $desc as a function.
mapex(
{
$result: "user",
user: {
$type: "roleId",
$desc(id, schema, entity) {
return `${schema}_${id}`;
},
1: "mod",
2: "admin",
},
mod: {},
admin: {},
},
[
{ id: 1, roleId: 1 },
{ id: 2, roleId: 2 },
{ id: 3, roleId: 1 },
]
);
const output = {
$result: [1, 2, 3],
mod: {
1: { id: 1, roleId: 1 },
3: { id: 3, roleId: 1 },
},
admin: {
2: { id: 2, roleId: 2 },
},
user: {
mod_1: "mod",
mod_3: "mod",
admin_2: "admin",
},
};
mapex(
{
$result: "node",
node: {
children: "node",
},
},
{
id: 1,
name: "root",
children: [
{
id: 2,
name: "node 1",
children: [
{ id: 4, name: "node 1.1" },
{ id: 5, name: "node 1.2" },
],
},
{ id: 3, name: "node 2" },
],
}
);
Output
_ = {
$result: 1,
node: {
1: { id: 1, name: "root", children: [2, 3] },
2: { id: 2, name: "node 1", children: [4, 5] },
3: { id: 3, name: "node 2" },
4: { id: 4, name: "node 1.1" },
5: { id: 5, name: "node 1.2" },
},
};
None.