Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/michalzalecki/mappet
Lightweight, composable mappers for object transformations/normalization
https://github.com/michalzalecki/mappet
composable-mappers transformations
Last synced: 2 months ago
JSON representation
Lightweight, composable mappers for object transformations/normalization
- Host: GitHub
- URL: https://github.com/michalzalecki/mappet
- Owner: MichalZalecki
- Created: 2016-06-18T21:54:24.000Z (over 8 years ago)
- Default Branch: master
- Last Pushed: 2023-01-03T15:16:37.000Z (about 2 years ago)
- Last Synced: 2024-04-14T12:19:08.252Z (9 months ago)
- Topics: composable-mappers, transformations
- Language: TypeScript
- Homepage: https://michalzalecki.github.io/mappet/
- Size: 1.3 MB
- Stars: 51
- Watchers: 5
- Forks: 4
- Open Issues: 15
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
Awesome Lists containing this project
README
# mappet
[![CircleCI](https://circleci.com/gh/MichalZalecki/mappet.svg?style=svg)](https://circleci.com/gh/MichalZalecki/mappet)
Lightweight, composable mappers for object transformations/normalization.
***
[API Docs](https://michalzalecki.github.io/mappet) | [Examples](#examples)
***## Installation ([npm](https://www.npmjs.com/package/mappet))
```
npm i -S mappet
```## Use cases
* Fault tolerant object transformations, no more `Cannot read property of undefined`.
* Normalizing API responses shape and key names e.g. to camelCase or flattening nested payloads
* Preparing nested API request payloads from flat form data
* Filtering object entries e.g. omitting entries with `undefined` value
* Per field modifications e.g. `null` to empty string to make React inputs happy## Examples
### Basic
Simple value to value transformation
```js
const schema = {
firstName: "first_name",
cardNumber: "card.number",
};
const mapper = mappet(schema);
const source = {
first_name: "Michal",
last_name: "Zalecki",
card: {
number: "5555-5555-5555-4444",
},
};
const result = mapper(source);
// {
// firstName: "Michal",
// cardNumber: "5555-5555-5555-4444",
// }
```### Mapping values
Schema entries can be also option objects of `path`, `modifier`, and `include`. Modifier accepts selected value and original source object.
```js
const formatDate = (date, source) => moment(date).format(source.country === "us" ? "MM/DD/YY" : "DD/MM/YY");
const upperCase = v => v.toUpperCase();const schema = {
country: { path: "country", modifier: upperCase },
date: { path: "date", modifier: formatDate },
};
const mapper = mappet(schema);
const source = {
country: "gb",
date: "2016-07-30",
};
const result = mapper(source);
// {
// country: "GB",
// date: "30/07/16",
// }
```### Filtering entries
Using `include` you can control which values should be keept and what dropped.
```js
const isGift = (value, source) => source.isGift;const schema = {
quantity: ["quantity"],
message: { path: "giftMessage", include: isGift },
remind_before_renewing: { path: "remindBeforeRenewingGift", include: isGift },
};
const mapper = mappet(schema);
const source = {
quantity: 3,
isGift: false,
giftMessage: "All best!",
remindBeforeRenewingGift: true,
};
const result = mapper(source);
// {
// quantity: 3,
// };
```### Composing mappers
Mappers are just closures. It's easy to combine them using modifiers.
```js
const userSchema = {
firstName: "first_name",
lastName: "last_name",
};
const userMapper = mappet(userSchema);const usersSchema = {
totalCount: "total_count",
users: { path: "items", modifier: users => users.map(userMapper) },
};
const usersMapper = mappet(usersSchema);const source = {
total_count: 5,
items: [
{ first_name: "Michal", last_name: "Zalecki" },
{ first_name: "John", last_name: "Doe" },
],
};
const result = usersMapper(source);
// {
// totalCount: 5,
// users: [
// { firstName: "Michal", lastName: "Zalecki" },
// { firstName: "John", lastName: "Doe" },
// ],
// }
```### Strict mode
Mappers in strict mode will throw exception when value is not found on source object.
```js
const schema = {
firstName: "first_name",
lastName: "last_name",
};
const mapper = mappet(schema, { strict: true });
const source = {
first_name: "Michal",
};
const result = mapper(source);
// Uncaught Mappet: last_name not found
```You can specify mapper name for easier debugging.
```js
const userMapper = mappet(schema, { strictMode: true, name: "User Mapper" });
const user = mapper(source);
// Uncaught User Mapper: last_name not found
```### Greedy mode
Mappers in greedy mode will copy all properties from source object.
```js
const schema = {
last_name: { path: "last_name", modifier: str => str.toUpperCase() },
};
const mapper = mappet(schema, { greedy: true });
const source = {
first_name: "Michal",
last_name: "Zalecki",
email: "[email protected]",
};
const actual = mapper(source);
// {
// first_name: "Michal",
// last_name: "ZALECKI",
// email: "[email protected]",
// }
```See [tests](src/mappet.spec.ts) for more examples.