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

parakeet-mapper

v3.0.0

Published

Simple data converter

Downloads

1,531

Readme

Parakeet Mapper

npm npm bundle size (minified) dependencies (minified)

Simple data conversion library

npm install --save parakeet-mapper

For more options see installation


What is this?

It's a small collection of utility functions and types that help with mapping (transforming) data.

You can find it useful if:

  • You work with complex data objects and tired of it
  • You need to quickly and efficiently transform objects or tuples regularly
  • Your data models need additional functionality
  • You need a type-safe way of initializing a class from an object
  • You need to convert data types back and forth multiple times
  • You don't like your backend's API and GraphQL is not an option 😁

Installation

Install as dependency

npm install --save parakeet-mapper
# or
yarn add parakeet-mapper

Import and use

ES

import { mapTypes, mapFactory } from 'parakeet-mapper'

CommonJS

const { mapTypes, mapFactory } = require('parakeet-mapper');

Script tag

<!-- Modern es-modules: -->
<script>
  import { mapTypes, mapFactory } from 'https://unpkg.com/parakeet-mapper';
</script>

<!-- Or a legacy IIFE script: -->
<script src="https://unpkg.com/parakeet-mapper/dist/parakeet-mapper.iife.js"></script>
<script>
  // global variable parakeetMapper
  const { mapTypes, mapFactory } = parakeetMapper;
</script>

API

parakeet-mapper exposes several helpers to deal with type conversions.
All of them use the TypeMap interface to communicate.

name | overloads | description -----|-----------|----------------------------------- mapFactory | 3 | Accepts a TypeMap. Returns a function that accepts one input and returns an output converted using rules defined in the TypeMap. mapTypes | 3 | Same as mapFactory, but instead of returning a function, accepts input as its first argument and returns an output right away. Convertable | 2 | Class mixin. Allows creation of convertable classes.

TypeMap

object

It is a set of rules that define how the output type is made from the input type.\

The rules are simple:\

  • Each key corresponds to a key in the output.
  • Each value tells what to assign to that key from the input.
    • true = the value is assigned from the same key in the input.
    • A string = the value is assigned from this string key in the input.
    • An object = the value is assigned from this object's first key in the input and is processed using the value as converter.
    • An array of a single element = the first element in the array is used as converter for the input value by the output key.
    • A function = the value is mapped using this function from the input.

Examples

const input = {
  transferred: 'foo',
  renamed: 'bar',
  converted: '42',
  mapped: [1, 1, 2],
  omitted: 'won\'t transfer to output'
};

const TypeMap = {
  // Transferred straight to the output
  transferred: true,

  // Renamed from `renamed` into `outputRenamed`
  outputRenamed: 'renamed',

  // Renamed from `converted` into `convertedNumber`
  // and converted from string to number
  convertedNumber: { converted: Number },

  // Mapped using a function and also renamed.
  mappedSum: input => input.mapped.reduce((a, b) => a + b),

  // Output object is also accessible in the function as a second parameter
  // This allows to reuse operations for already converted values
  // (like mappedSum and convertedNumber, in this example)
  mappedPlusConverted: (_input, output) => output.mappedSum + output.convertedNumber
};

/* output */ {
  transferred: 'foo',
  outputRenamed: 'bar',
  convertedNumber: 42, // Number('42')
  mappedSum: 4,
  mappedPlusConverted: 46 // 4 + 42
  // notice the absence of `ommited` property
}

object/array shorthand with the same key

new in v2.1.2

It's not necessary to specify the correct key in the conversion object:

const input = {
  number: '42',
};

const TypeMap = {
  // Simply converts from string to number using the `Number` function
  number: { Number },
};

/* output */ {
  number: 42, // Number('42')
  // Notice that the property name stayed the same,
  // even though we used a `{ Number: Number }` shorthand.
}

It only works if the input has the same property key as the output.

Can also be written using the array (tuple) syntax:

const input = {
  number: '42',
};

const TypeMap = {
  // Simply converts from string to number using the `Number` function
  number: [Number],
};

/* output */ {
  number: 42, // Number('42')
  // Notice that the property name stayed the same,
  // even though we used a `{ Number: Number }` shorthand.
}

mapFactory

function

A factory function that produces a converter from a TypeMap:

import { mapFactory } from 'parakeet-mapper';

const inputToOutput = mapFactory(TypeMap);

const output = inputToOutput(input); /* {
  transferred: 'foo',
  outputRenamed: 'bar',
  convertedNumber: 42, // Number('42')
  mappedSum: 4,
  mappedPlusConverted: 46 // 4 + 42
  // notice the absence of `ommited` property
} */

Overloads

This function has 3 overloads, all of which are needed for type safety and type inference (TypeScript).

There are basically 3 typed use-cases of using this function (hence 3 overloads):

  1. Input and output types are known, and TypeMap needs to convert them precisely.
    declare const input: InputType;
    const inputConverter = mapFactory<InputType, OutputType>(TypeMap);
    // output is OutputType now
  2. Input type is known, output needs to be inferred from the TypeMap.
    The first call without arguments is a noop. Reasons: first, second.
    declare const input: InputType; // The empty braces are here due to TS issues.
    const inputConverter = mapFactory<InputType>()(TypeMap);
  3. Input and output types are known, but the output type needs to be modified slightly.
    The first call without arguments is a noop. Reasons: first, second.
    declare const input: InputType; // The empty braces are here due to TS issues.
    const inputConverter = mapFactory<InputType, OutputType>()(TypeMap);

mapTypes

function

Basically, a mapFactory, called in-place.

First Argument | Second Argument -----------------|------------------------------- The input object | Corresponding TypeMap

import { mapTypes } from 'parakeet-mapper';

const output = mapTypes(input, TypeMap); /* {
  transferred: 'foo',
  outputRenamed: 'bar',
  convertedNumber: 42, // Number('42')
  mappedSum: 4,
  mappedPlusConverted: 46 // 4 + 42
  // notice the absence of `ommited` property
} */

// Same as
// const output = mapFactory(TypeMap)(input);

Overloads

There are 3. All are semantically the same as the overloads of mapFactory, including the noop call:

/* 1 */ mapTypes<InputType, OutputType>(input, TypeMap);
/* 2 */ mapTypes<InputType>()(input, TypeMap);
/* 3 */ mapTypes<InputType, OutputType>()(input, TypeMap);

Wait

function
new in v2.1

A complementary function to mapFactory that helps to flatten out promises

It produces a converter that returns a flat promise from a converter that returns an object with promises.

In a typical situation, when some convertations are asyncronous, you'd end up with this:

import { mapTypes } from 'parakeet-mapper';

// Imagine that this is requesting something from an API and returns a promise
const requestFromApi = (value) => Promise.resolve(value);

const input = {
  a: ['a'],
  b: 42,
  c: 'c'
};

const getAandBfromAPI = mapFactory({
  b: true,
  a: { a: requestFromApi },
  c: { c: requestFromApi }
});

const output = getAandBfromAPI(input);
// Result:
/* {
  a: Promise<['a']>,
  b: 42,
  c: Promise<'b'>
} */
// Not very comfortable to await every single value after this

Now with wait:

import { wait } from 'parakeet-mapper';

const waitForAandB = wait(getAandBfromAPI);


const output = getAandBfromAPI(input);
// Result:
/* Promise<{
  a: ['a'],
  b: 42,
  c: 'b'
}> */
// Much more useful now

flattenPromises

function
new in v2.1

Internally used in wait, flattens top-level promises in an object:

import { flattenPromises } from 'parakeet-mapper';

const objWithPromises = {
  a: [Promise.resolve('a')],
  b: 42,
  c: Promise.resolve('b')
};

const flat = flattenPromises(objWithPromises);
// Result
/* Promise<{
  a: ['a'],
  b: 42,
  c: 'b'
}> */

Convertable

function
new in v2.0

Allows to create classes from converters.
This makes possible adding extra functionality, including reverse convertations.

import { Convertable, mapFactory } from 'parakeet-mapper';

const inputConverter = () => mapFactory(mapTypes);

class Output extends Convertable(inputConverter) {}

const output = new Output(input);

console.log(output); /*
> Output {
    transferred: 'foo',
    outputRenamed: 'bar',
    convertedNumber: 42,
    mappedSum: 4,
    mappedPlusConverted: 46
  }
*/

Accepts a function that returns a converter as its only argument.
Returns a Convertable class with all the required functionality.

Can also infer arguments from its converter factory:

import { Convertable, mapFactory } from 'parakeet-mapper';

const input: InputType = {
  foo: 'foo',
  bar: 'bar'
}

const inputConverter = (convertFoo?: boolean) => mapFactory<InputType>()({
  zoo: convertFoo,
  zar: convertFoo ? 'bar' : 'foo'
});

class Output extends Convertable(inputConverter) {}

const outputWithFoo = new Output(input, /* convertFoo? */ true);
console.log(outputWithFoo); /*
> Output {
    zoo: 'foo',
    zar: 'bar'
  }
*/

const outputWithoutFoo = new Output(input, /* convertFoo? */ false);
console.log(outputWithoutFoo); /*
> Output {
    zar: 'foo'
  }
*/

And accept a reverse converter:

import { Convertable, mapFactory } from 'parakeet-mapper';

const input: InputType = {
  foo: 'foo',
  bar: 'bar'
}

const inputConverter = (convertFoo?: boolean) => mapFactory<InputType>()({
  zoo: convertFoo,
  zar: convertFoo ? 'bar' : 'foo'
});

const outputConverter = (convertZoo?: boolean) => mapFactory<OutputType>()({
  foo: convertZoo,
  bar: convertZoo ? 'zar' : 'zoo'
});

class Output extends Convertable(inputConverter, outputConverter) {}

const output = new Output(input, /* convertFoo? */ true);
console.log(output); /*
> Output {
    zoo: 'foo',
    zar: 'bar'
  }
*/

// Convert back to input type
const newInput = output.toInput(/* convertZoo? */ true);
console.log(newInput); /*
> {
    foo: 'foo',
    bar: 'bar'
  }
*/

Convertable class

constructor

Accepts an input as its first argument and converter factory parameters as other spread arguments.

toInput

Available only if reverse converter was passed into the Convertable.

Accepts a spread of reverse converter arguments

Convertable.createConverter

static

A converter factory, passed to the Convertable.

Convertable.reverseConverter

static

A reverse converter factory, passed to the Convertable.