# @e-scape/store

> Library for storing values and subscribing to their changes.

Latest version **0.2.9** (published 2024-01-30) · ISC license · 0 weekly downloads

## Install

```sh
npm install @e-scape/store
pnpm add @e-scape/store
yarn add @e-scape/store
bun add @e-scape/store
```

## Health

**Score 25/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities.

Warnings: low downloads; pre 1.0.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 0.2.9 |
| Published | 2024-01-30 |
| First published | 2023-12-15 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 3 |
| Unpacked size | 26.2 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Maintainers | nomorejalapenos |

## Links

- npm: https://www.npmjs.com/package/@e-scape/store
- Repository: https://github.com/nomorejalapenos/e-scape
- Homepage: https://github.com/nomorejalapenos/e-scape/tree/master/packages/store#readme
- Issues: https://github.com/nomorejalapenos/e-scape/issues
- npm.io page: https://npm.io/package/@e-scape/store

## Dependencies (3)

- [@e-scape/utils](https://npm.io/package/@e-scape/utils.md) *
- [@e-scape/notifier](https://npm.io/package/@e-scape/notifier.md) *
- [@e-scape/provider](https://npm.io/package/@e-scape/provider.md) *

## Recent versions

- 0.2.9 (latest) — 2024-01-30
- 0.2.8 — 2024-01-30
- 0.2.7 — 2024-01-30
- 0.2.6 — 2024-01-30
- 0.2.5 — 2024-01-11
- 0.2.4 — 2024-01-06
- 0.2.3 — 2024-01-06
- 0.2.2 — 2023-12-30
- 0.2.1 — 2023-12-30
- 0.2.0 — 2023-12-23
- 0.1.5 — 2023-12-23
- 0.1.4 — 2023-12-23
- 0.1.3 — 2023-12-23
- 0.1.2 — 2023-12-23
- 0.1.1 — 2023-12-22
- … 1 more at https://npm.io/package/@e-scape/store/versions

## README

# Store

Library for storing values and subscribing to their changes.

## Creation

The `Store` takes absolutely any value as its first parameter.

```ts
import { Store } from '@e-scape/store'

const myStore = new Store('hello world')
```

## Subscription

Subscribing to changes in the store is done by passing a callback to the `subscribe` method. This callback will be added to the call queue, and after the store value changes, the callback will be invoked.

```ts
myStore.subscribe(() => {
  console.log('Store value has changed')
})
```

When called, the callback receives the current and previous values.

```ts
myStore.subscribe(({ current, previous }) => {
  console.log(current, previous)
})
```

By default, callbacks will be invoked in the order of subscription to the store. You can change this by passing a second parameter with a value other than `undefined`.

```ts
// Will be called third
myStore.subscribe(callback, 20)
// Will be called second
myStore.subscribe(callback, 0)
// Will be called first
myStore.subscribe(callback, -10)
```

## Unsubscription

Subscribing to the store returns a function that can be called to unsubscribe from the store.

```ts
const unsubscribe = myStore.subscribe(callback)

unsubscribe()
```

Alternatively, you can call the `unsubscribe` method.

```ts
const callback = () => {}

myStore.subscribe(callback)

myStore.unsubscribe(callback)
```

## Removing all subscriptions

```ts
myStore.close()
```

## Resetting the value to the initial one

Calling the `reset` method sets the current value of the store to the value passed to its constructor during creation.

```ts
myStore.reset()
```

## Current value

To see the current value of the store outside of subscription, you can access the `current` getter.

```ts
console.log(myStore.current)
```

To change the current value of the store, assign a new value to the `current` setter.

```
myStore.current = 123
```

## Previous value

To see the previous value of the store outside of subscription, you can access the `previous` getter. Initially, this value is `undefined`.

```ts
console.log(myStore.previous)
```

## Initial value

```ts
console.log(myStore.initial)
```

## Types of stores

### Derived

Takes any store as the first parameter and a callback as the second parameter, which reacts to changes in the passed store. The value returned from this callback will be set as the current value of the derived store.

```ts
import { Store, Derivative } from '@e-scape/store'

const numberStore = new Store(2)
const doubleNumberStore = new Derivative(numberStore, (v) => v * 2)

doubleNumberStore.subscribe(({ current }) => {
  console.log(current) // 4
})
```

### Derived from an array

Same as the `Derivative` store but only accepts stores whose values are arrays.

```ts
import { Store, Derivatives } from '@e-scape/store'

const numberStore = new Store([1, 2, 3])
const doubleNumberStore = new Derivatives(numberStore, (v) => v * 2)

doubleNumberStore.subscribe(({ current }) => {
  console.log(current) // [2, 4, 6]
})
```

### Resource

Takes the initial value as the first parameter and a function as the second parameter that returns a `Promise`. The data obtained from the `Promise` will be set as the current value.

```ts
import { Resource } from '@e-scape/store'

const todoStore = new Resource(null, async () => {
  const response = await fetch('https://jsonplaceholder.typicode.com/todos/1')
  const data = await response.json()

  return data
})

todoStore.isPending.subscribe(({ current }) => {
  console.log(current)
})

todoStore.subscribe(({ current }) => {
  console.log(current)
})
```

To fetch the data again, call the `refetch` method.

```ts
todoStore.refetch()
```

## Store parameters

All stores accept the following optional object as the last parameter:

#### **equalityCheck**

By default, all values are compared using `===,` and if the values are equal, subscribers will not be notified that a new value has been assigned. You can change this by providing a custom comparison function:

```ts
const store = new Store(0, {
  equalityCheck: (currentValue, newValue) => currentValue === newValue,
})
```

#### **passport**

All stores with a specified `name` in `passport` will be added to the store registry:

```ts
new Store(0, {
  passport: {
    name: 'My Store',
  },
})
```

For example, this property is actively used by the [tweaker](https://www.npmjs.com/package/tweaker) library to create a GUI that controls values in stores.

## Store Registry

### Purpose

he main task of the store registry is to quickly replace all store values with some previously saved state, for example, from [tweaker](https://www.npmjs.com/package/tweaker).

The entire setup for the project will look like this:

```ts
import { Store, storeRegistry } from '@e-scape/store'
import state from 'state.json'

// Load and save the state
storeRegistry.loadState(state)

// Now all stores will be initialized with values from the state loaded above, not the values passed in the constructor.
const store = new Store(0, {
  passport: {
    name: 'My Store',
  },
})
```

### How to add to the registry

All stores with a specified `name` in `passport` will be added to the registry as soon as the first subscription occurs, and will be removed from the registry if there are no more subscriptions to the store.

```ts
import { Store, storeRegistry } from '@e-scape/store'

const store = new Store(0, {
  passport: {
    name: 'My Store',
  },
})

store.subscribe(() => {})

console.log(storeRegistry.getState())
```

### Registry Methods and Properties

#### **storeRegistry.getState**_()_

Returns the current state of all named stores.

#### **storeRegistry.resetState**_()_

Resets the values of all named stores to their initial values.

#### **storeRegistry.saveState**_()_

Saves the state of all named stores to `localStorage`. By default, the save is done under the name _store-state_. You can change this by setting a value for the `data-project` attribute on the `<html>` tag:

```html
<html data-project="my-project"></html>
```

Now, in `localStorage`, the state will be saved under the name _my-project-store-state_.

#### **storeRegistry.loadState**_(string | StoreRegistryState | undefinded)_

If no parameter is passed, it loads data from `localStorage`. If a string is passed, it will try to parse it into a `StorageState` object, and if a `StoreRegistryState` is passed, it takes the data directly from it and updates all current named

#### **storeRegistry.loadedState**

Here, the state loaded by `loadState` is stored.

---
_Source: https://npm.io/package/@e-scape/store · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
