## @labdigital/toolkit

This package contains a set of common utility functions we use for most of our
typescript projects. It is unopinionated, should have almost no dependencies and
is meant to be used in any project.

### Installation

```
pnpm add @labdigital/toolkit
```

### API

`isValue`

(function)

Utility for lists to ensure there are no empty values.

```
const products = [
{ id: "a", price: { centAmount: 20 } },
{ id: "b", price: null },
{ id: "c", price: { centAmount: 30 } },
];
products
.map((x) => x.price)
.filter(isValue)
.map((p) => p.centAmount)[
(20, 30)
];
```

`unique`

(function)

Filter utility to filter out duplicate values

```
const names = ["john", "john", "jane"].filter(unique);
```

`uniqueBy`

(function)

`groupByMap`

(function)

Groups a list based on a callback.
Returns a Map where the keys are the result of the callback.

```
groupByMap(
[{age: 18, name: 'John'}, {age: 18, name: 'Joe'}, {age: 16, name: 'Jack'}],
p => p.age,
)
Map {
16: [{age: 16, name: 'Jack'}],
18: [{age: 18, name: 'John'}, {age: 18, name: 'Joe'}],
}
```

`groupBy`

(function)

Groups a list based on a callback.
Returns a Map where the keys are the result of the callback.

```
groupBy(
[{age: 18, name: 'John'}, {age: 18, name: 'Joe'}, {age: 16, name: 'Jack'}],
p => p.age,
)
[
[16, [{age: 16, name: 'Jack'}]],
[18, [{age: 18, name: 'John'}, {age: 18, name: 'Joe'}]],
]
```

`findFirst`

(function)

Finds the first item in a list of items by a list of ids.

```
const products = [
{id: 'a', price: 1},
{id: 'b', price: 1},
{id: 'c', price: 1}
]
findFirst(['x', 'b'], products, p => p.id)
### `range` (function)
Creates a range of numbers, staring at `start` and ending at `end` .
```ts
range({start: 0, end: 3}) // [0, 1, 2]
range({start: 1, end: 3}) // [1, 2]
```

`zip`

(function)

Merges two arrays, creating a single array with tuples from both arrays.

```
const a = [1, 2, 3];
const b = ["a", "b", "c"];
zip(a, b);
```

`getLocalizedValue`

(function)

Attempts to find a matching value for the provided locale by trying the given
locale and its language tag, followed by locale without subtags and then by
any additional fallback locales specified.

It performs both an exact case-sensitive match and a case-insensitive match
to ensure compatibility with different case conventions. Notably, if a
specific locale (e.g., 'en-GB') does not have a direct match, the function
will try to fall back to a more general locale (e.g., 'en') before moving on
to the next fallback locales.

```
const greetings = {
en: "Hello",
"en-US": "Howdy",
fr: "Bonjour",
};
getLocalizedValue(greetings, "en-GB");
```

```
getLocalizedValue(greetings, "en-US");
```

```
getLocalizedValue(greetings, "es", "en");
```

`sum`

(function)

Sums the values of a list of objects calculated by a callback.

```
sum([{ price: 1 }, { price: 2 }], (x) => x.price);
```

`byMin`

(function)

Reducer callback to find object with some minimum value.

```
[{ price: 1 }, { price: 2 }].reduce(byMin((x) => x.price));
```

`byMax`

(function)

Reducer callback to find object with some maximum value.

```
[{ price: 1 }, { price: 2 }].reduce(byMax((x) => x.price));
```

`clamp`

(function)

Clamps the value between `min`

and `max`

.

I.e. returns `min`

if `value < min`

, or `max`

if value > `max`

, or the value
itself otherwise.

`roundHalfEven`

(function)

Rounds a number to the nearest integer using the "half to even" strategy,
also known as "bankers' rounding". This method minimizes bias in rounding
over a large set of numbers. When the fractional part of the number is
exactly 0.5, it rounds to the nearest even number.

**Parameters:**

- value (
`number`

) - The number to round.

```
roundHalfEven(2.5);
```

```
roundHalfEven(3.5);
```

`roundHalfUp`

(function)

Rounds a number to the nearest integer using the "half up" strategy. This
method rounds up when the fractional part of the number is 0.5 or greater.
It's the most common form of rounding.

**Parameters:**

- value (
`number`

) - The number to round.

```
roundHalfUp(2.5);
```

```
roundHalfUp(2.4);
```

`roundHalfDown`

(function)

Rounds a number to the nearest integer using the "half down" strategy. This
method rounds down when the fractional part of the number is exactly 0.5,
contrary to the "half up" method.

**Parameters:**

- value (
`number`

) - The number to round.

```
roundHalfDown(2.5);
```

```
roundHalfDown(2.6);
```

`pruneObject`

(function)

Removes all undefined properties

```
pruneObject({
a: 1,
b: undefined,
});
```

`pick`

(function)

Pick a subset of items from an object

**Parameters:**

- base (
`T`

) - The object - keys (
`K[]`

) - A list of keys to pick

**returns:** Pick<T, K>

```
pick({ a: 1, b: 2, c: 3 }, "a", "c");
```

`objectMap`

(function)

Transforms an object using the given value and or key transformers.

```
objectMap(
{
a: 1,
b: 2,
c: 3,
},
{
getKey: (key, value) => key.toUpperCase(),
getValue: (value, key) => value * 2,
},
);
```

`createObjectHash`

(function)

Generates a deterministic key for an object ignoring the order of the fields.

JSON stringifies the object and generates a base64 SHA-256 hash.
The keys of the object are sorted in order to get a deterministic key.