Skip to content

Easy to use store and event emitter — async, immutable, self-documenting, highly extensible

Notifications You must be signed in to change notification settings

invrs/dot-store

Repository files navigation

dot-store

Easy to use store and event emitter — async, immutable, self-documenting, highly extensible

pale blue dot

Install

npm install --save dot-store

Using the store

import Store from "dot-store"
const store = new Store()

Pass an object to the Store constructor to set a default state.

Set values (immutably)

await store.set("users.bob.admin", true)

Get values

store.get("users.bob.admin") // true
store.get() // {users: {bob: {admin: true}}}

Subscribe to changes

This subscriber responds to any change within users.bob:

store.on("users.bob", async () => {
  console.log("bob changed")
})

Store operations

Operation Async Description
get(props) no Read prop value
delete(props) yes Delete prop value
merge(props, value) yes Merge prop value with array or object
set(props, value) yes Set prop value
time(props) yes Set prop value to current timestamp
toggle(props) yes Toggle boolean prop value

Store subscribers

Subscriber functions like store.on(event, props, fn) allow you to subscribe to any change within the prop location.

Subscriber Timing
on(event, props, fn) Subscribe to prop value change
once(event, props, fn) Subscribe to a single prop value change
onceExists(event, props, fn) Subscribe to a single prop value change and immediately emit if value exists

The event string consists of a preposition (before or after), plus an operation. For example, a valid event string would be beforeSet or afterDelete.

The after preposition is used by default when it is not specified. You may also use update in place of the operation to subscribe to all updates.

When omitted entirely, the event parameter defaults to "afterUpdate".

Order of operation

  1. Call operation function (e.g. store.set(props, value))
  2. Execute all before subscribers and wait for them to resolve
  3. Perform operation on store
  4. Execute all after subscribers and wait for them to resolve
  5. Operation function resolves

Subscriber options

Subscribers receive an options argument with lots of useful stuff:

store.on(
  "users.bob",
  async ({
    change,
    event,
    prevState,
    state,
    store,
    subscriber,
  }) => {
    // see example values below
  }
)

await store.set("users.bob.admin", true)
Argument Example value Description
change.prevValue undefined Pre-op change value
change.props "users.bob.admin" Change props
change.propKeys ["users", "bob", "admin"] Change prop keys
change.test(props) <Function> Test for change @ prop
change.value true Change value
event.prep "after" Event preposition
event.op "set" Event operation
prevState {} Pre-op state
state {users: {bob: {admin: true}}} Current state
store <DotStore> Store instance
subscriber.prevValue undefined Pre-op subscriber value
subscriber.props "users.bob" Subscriber props
subscriber.propKeys ["users", "bob"] Subscriber prop keys
subscriber.value {admin: true} Subscriber value

Dynamic subscribers

Use curly braces around a prop key to capture its value:

store.on("users.{userId}", async ({ userId }) => {
  userId // "bob", then "ted"
})

await store.set("users.bob.admin", true)
await store.set("users.ted.admin", true)

Check if prop value changed

The change.test(props) function tests if a prop value changed.

The return value is truthy and doubles as a way to retrieve prop keys:

store.on("users", async ({ change }) => {
  // ✓ Value did change
  change.test("users.{userId}.{attr}") // { userId: "bob", attr: "admin" }
  change.test("users.bob.admin") // {}
  change.test("users.bob") // {}
  change.test("users") // {}

  // ⃠ Value didn't change
  change.test("users.ted.{attr}") // false
  change.test("users.ted") // false
})

await store.set("users.bob.admin", true)

Unsubscribe

const off = store.on("users.bob", async () => {})
off()

Custom operations

Custom operations do not modify the store. They allow you to leverage store eventing to run your own logic.

After initializing the store, add a custom operation:

const store = new Store()
store.op("fetch")

Subscribe to the custom event:

store.on("fetch", "users", async function({ value }) {
  value // { admin: "true" }
})

await store.fetch("users", { admin: "true" })

Extensions

Package Description
dot-store-analyze Documentation generator
dot-store-cookie Cookie access
dot-store-fs Filesystem access
dot-store-message postMessage API access
dot-store-react React integration

About

Easy to use store and event emitter — async, immutable, self-documenting, highly extensible

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published