manatea
TypeScript icon, indicating that this package has built-in type declarations

0.6.1 • Public • Published

TL;DR

Predictable micro state manager.

This package has no dependencies and weights less than 1kB (and less than 500B gzipped).

Manatea

Designed by Ane Diaz

Table of contents

  1. Lexicon
  2. How to use
    1. Create cup
    2. Read cup's tea
    3. Update cup's tea
    4. Flavoring
      1. Simple flavors
      2. Transformations
      3. Adding flavors based on the previous flavors
    5. Cup's waiters
      1. Calling a waiter
      2. Firing a waiter
    6. Derived cup

Lexicon

Manatea uses weird and funny names because this project is mostly for fun. And also we can do whatever we want with it.

Here is the reason behind all our names:

First you order a cup of tea filled with your first tea. Then you can place a new order and the waiter will refill your cup with a new tea.
Depending on whether or not the tea suits you, you can add flavor to it with a flavoring.

But as those can be confusing, he is an equivalent to all our names in more usual words:

In manatea More generic names Explanation
orderCup create store Create an object that can contain a value, gives access to read or modify this value, and provides a way to add listeners that will get called when the value changes.
flavoredTea value Value stored within the cup
firstTea initial value Value present within the cup when it was first created
Order value setter When the cup needs to be updated, we can either provide a new value, or a function that will give access to the current value in order to compute the new one.
unflavoredTea new value New value provided to the cup that will be used as the new internal value (after going through the flavoring phase). Either the value of the order, or its returned value if it was a function.
flavoring transformer When a unflavoredTea (dirty value) is passed to the cup, you may want to restrict it to a range of allowed values. The flavoring can transform this provided unflavoredTea to a flavoredTea one (a clean value).
waiter listener When the internal tea changes, waiters will get called with the new value.

How to use

Create cup

import { orderCup } from 'manatea';

// Define (order) a cup with a default value (tea) of 0
const cup = orderCup(0);

Read cup's tea

// Return current value (tea) of the cup
cup(); // 0;

Update cup's tea

// Set value (tea) to 1
cup(1);

// increment the stored value (tea) by 1
cup(tea => tea + 1);

// Supports async functions
// wait 1 second and then increment the tea by 5
cup(async tea => {
  await sleep(1);
  return tea + 5;
});

// You can also read from cup to set another cup's value
cup(tea => {
  const otherTea = otherCup();
  return tea + otherTea;
});

Every update made to a cup returns a promise:

// wait for the value to be stored and dispatched
await cup(1);

// you can also use the regular .then() method
cup(tea => tea + 1).then(tea => console.log(tea));

Flavoring

Simple flavors

When a new unflavored tea is passed to the cup, you may want to apply restrictions to it.

For instance, if your flavoredTea is a number, you may want to set bounds to it:

const cup = createCup(0, unflavoredTea =>
  Math.min(10, Math.max(0, unflavoredTea)),
);

cup(12);

// clamp to 10 as we set an upper bound to 10 above
cup(); // 10

Transformations

In addition simple restrictions that have the same type as the flavored tea, you can fully transform it:

interface FlavoredTea {
  value: number;
  label: string;
}

const cup = createCup<FlavoredTea, number>(0, unflavored => {
  return {
    value: unflavored,
    label: `Value of: ${unflavored}`,
  };
});

// even the initialTea will get flavored
cup(); // { value: 0, label: 'Value of: 0' }

cup(5);

// even the initialTea will get flavored
cup(); // { value: 5, label: 'Value of: 5' }

Adding flavors based on the previous flavors

The flavoring function have a second parameters (not passed for the initialTea) that give to you the previously flavoredTea:

const cup = createCup(
  0,
  (unflavored, previouslyFlavoredTea = 0) => unflavored + previouslyFlavoredTea,
);

cup(); // 0

cup(2);
cup(); // 2 – because 2 + 0 = 2

cup(5);
cup(); // 7 – because 5 + 2 = 7

Cup's waiters

From any cup, you can call waiters that will alert you when the tea stored in the cup changes (they are like event listeners).

Calling a waiter

// Call the waiter
const waiter = cup.on(tea => console.log(tea));

Firing a waiter

You can fire a waiter (stop the listener) by calling it:

const waiter = cup.on(console.log);
// here the waiter will be called on each update of the cup

// but by calling `waiter()`, it won't receive any update anymore
waiter();

At any moment, you can check if a waiter is running by checking its listening attribute:

const waiter = cup.on(console.log);

waiter.listening; // true

waiter();
waiter.listening; // false

Derived cup

You can create a cup based on another one, or multiple other ones:

const cup1 = orderCup(0);
const cup2 = orderCup(0);
const derivedCup = orderCup(sip => sip(cup1) + sip(cup2));

derivedCup(); // 0

await cup1(1);
await cup1(4);
derivedCup(); // 5

And it supports the same feature are regular cup:

  • flavoring
  • waiters
  • it's tea can be updated
const countString = orderCup('0');
const cumulatedCountNumber = orderCup(
  sip => sip(countString),
  (newValue, previousTotal = 0) => {
    return Number(newValue) + previousTotal;
  },
);

cumulatedCountNumber.on(newTotal => console.log(newTotal));
await countString('5');
cumulatedCountNumber(); // 5 (0 + 5)

// you can also call `cumulatedCountNumber` directly if yo want:
await cumulatedCountNumber('12');

cumulatedCountNumber(); // 17 (5 + 12)

Package Sidebar

Install

npm i manatea

Weekly Downloads

2

Version

0.6.1

License

MIT

Unpacked Size

31.1 kB

Total Files

11

Last publish

Collaborators

  • ayc0