Skip to main content
store() declares a store, from any file of src/, and the name of its export is the name of the store. It takes an object, StoreConfig, or nothing.
src/warnings.ts
How to use a store, where its data is and how expiration works is in the guide. This page lists what exists.

store()

Declares a store: data the bot keeps from one restart to the next, typed by what it holds. Export the result from any file of src/: the name of the export is the name of the store, and its file in data/ (or its keys in Redis, with storage: 'redis'). Per server unless scope: 'global' is given, with an expiration if expires is.

StoreConfig

What a file gives to store().
StoreScope
'guild' (the default): the data is kept per server, and a function that runs in a server reads and writes the data of that server, with nothing to say. 'global': one set of data for the whole bot.
StoreStorage
Where the data is kept: 'file' (the default), a file in the data/ folder of the project, or 'redis', the Redis of REDIS_URL in .env. Only stores that say 'redis' write anything there.
Duration
How long a value is kept, unless set() says otherwise: a number and a unit, s, m, h or d, like '10m', '1d' or '1h30m'. Kept forever by default.

StoreScope

Where the data of a store is kept apart: per server, or one for the whole bot.

StoreStorage

Where a store keeps its data: what storage of its config names.

Store

What store() returns: a declaration the framework finds in the exports of a file. It is a ScopedStore for the server the code runs in, plus:

in()

The same store, for one server: what a task, or a function that runs outside a server, uses to read and write the data of that server.

ScopedStore

A store, read and written for one server or for the whole bot.

get()

The value at key, or undefined when there is none, or it expired.

set()

Keeps value at key. The value must be JSON: no Date, Map or class instance.

update()

Reads the value at key and keeps what change returns, in one go: nothing written meanwhile is lost, even by another process. change receives undefined when there is no value yet, and may run again when the value changed in between: keep it a plain computation. The expiration stays what it was, unless options say otherwise.

increment()

Adds by (1 by default, negative to take away) to the number at key, starting from 0, in one go like update(), and resolves with the new number. Only for a store of numbers.

delete()

Forgets the value at key. true when there was one.

getMany()

The values at several keys at once, in their order: undefined for a key that has none.

setMany()

Keeps several values at once, each with the same options. Every value is checked before anything is written.

deleteAll()

Forgets every value whose key starts with prefix, or every value of the store (of the server, for a store per server) without one. Resolves with how many there were.

entries()

Every entry, or the ones whose key starts with prefix, in no particular order. Expired ones are left out.

ttl()

How long the value at key is still kept, in milliseconds: null when it is kept forever, undefined when there is no value.

StoreKey

A key of a store: a text, or a list of texts for a key made of several parts ([channel.id, message.id]), which entries() can then list by prefix.

StoreSetOptions

What set() and update() take besides the value.
Duration | Date | null
How long the value is kept: a duration like '10m', a Date, or null to keep it forever. The expires of the store by default.

StoreEntry

One entry of a store, as entries() lists them.
readonly string[]
required
The key, every part of it (the server left out for a store per server).
T
required
The value.
Date | null
required
When the value expires, or null when it is kept forever.

Where the data lives

One file per store, data/<name>.json at the root of the project: { "version": 1, "entries": [[key, value, expiresAt], ...] }, with expiresAt in milliseconds since the epoch or null. Written shortly after a change, in one piece (a temporary file, then a rename), and when the bot stops. Expired entries are dropped when the file is read, when they are asked for, and every minute. In production on several processes, the process you started keeps the data and answers the others over IPC. With storage: 'redis', one Redis key per value: <name>:<part>:<part> (the server id is the first part of a store per server; :, *, ?, [, ], \ and % inside a part are written %XX), its value the JSON of the value, its expiration set on the key (PX), so Redis forgets it alone. chapterjs dev puts dev: in front of every key. entries() is a SCAN on the prefix. Every process reaches Redis itself. update() and increment() are a transaction (WATCH, MULTI, EXEC), run again on the new value when another process wrote the key in between, on a connection of their own (at most 4 at once per process, besides the main one); the updates of one key in one process wait for each other. The address comes from REDIS_URL and REDIS_PASSWORD (see the CLI reference); a Redis that does not answer stops dev and start before Discord is reached, and the connection comes back by itself once it was made.

Errors