Skip to content

Commit 6ae6474

Browse files
committed
Use repository instead of direct access kv
1 parent ef4bfd0 commit 6ae6474

14 files changed

+1094
-1239
lines changed

docs/.vitepress/config.mts

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ const concepts = {
3636
{ text: "Events", link: "/concepts/events.md" },
3737
{ text: "Message", link: "/concepts/message.md" },
3838
{ text: "Text", link: "/concepts/text.md" },
39+
{ text: "Repository", link: "/concepts/repository.md" },
3940
],
4041
};
4142

docs/concepts/bot.md

+10
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ Additional options
8181

8282
There are other options to customize your `Bot` instance:
8383

84+
### `~CreateBotOptions.repository`
85+
86+
The [repository](./repository.md) (data access object) to be used by
87+
the bot. It is used to store and retrieve data from the bot's database.
88+
89+
By default, it uses the [`KvRepository`](./repository.md#kvrepository) with
90+
the key–value store specified in the [`kv`](#createbotoptions-kv) option.
91+
92+
For more information, see the [*Repository* section](./repository.md).
93+
8494
### `~CreateBotOptions.identifier`
8595

8696
The internal identifier of the bot actor. It is used for the URI of the bot

docs/concepts/repository.md

+167
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
---
2+
description: >-
3+
A repository is a data access object that provides an abstraction over the
4+
underlying data source. This document provides an overview of repositories
5+
and how they are used in the framework.
6+
---
7+
8+
Repository
9+
==========
10+
11+
A repository is a data access object that provides an abstraction over the
12+
underlying data source. BotKit provides a few built-in repositories that
13+
can be used to interact with the database, but you can also create your own
14+
repositories to interact with other data sources.
15+
16+
17+
`KvRepository`
18+
--------------
19+
20+
It is the default repository provided by BotKit. If you omit the
21+
[`repository`](./bot.md#createbotoptions-repository) option of
22+
the [`createBot()`](./bot.md#instantiation) function, BotKit will use
23+
the `KvRepository` by default.
24+
25+
The `KvRepository` is a repository that stores data in a key–value store
26+
through the [`KvStore`] interface, which is provided by the Fedify.
27+
Since the [`KvStore`] interface itself also abstracts over the underlying
28+
data source, you can easily switch between different key–value stores
29+
without changing the repository implementation.
30+
31+
There are several [`KvStore`] implementations available in the Fedify:
32+
33+
[`RedisKvStore`]
34+
: [`RedisKvStore`] is a key–value store implementation that uses Redis as
35+
the backend storage. It provides scalability and high performance, making
36+
it suitable for production use in distributed systems. It requires
37+
a Redis server setup and maintenance.
38+
39+
> [!NOTE]
40+
> The [`RedisKvStore`] class is available in the [@fedify/redis] package.
41+
42+
[`PostgresKvStore`]
43+
: [`PostgresKvStore`] is a key–value store implementation that uses
44+
PostgreSQL as the backend storage. It provides scalability and high
45+
performance, making it suitable for production use in distributed systems.
46+
It requires a PostgreSQL server setup and maintenance.
47+
48+
> [!NOTE]
49+
> The [`PostgresKvStore`] class is available in the [@fedify/postgres]
50+
> package.
51+
52+
[`DenoKvStore`] (Deno only)
53+
: [`DenoKvStore`] is a key–value store implementation for [Deno] runtime
54+
that uses Deno's built-in [`Deno.openKv()`] API. It provides persistent
55+
storage and good performance for Deno environments. It's suitable for
56+
production use in Deno applications.
57+
58+
> [!NOTE]
59+
> The [`DenoKvStore`] class is available in *x/deno* module of
60+
> the [@fedify/fedify] package.
61+
62+
[`MemoryKvStore`]
63+
: A simple in-memory key–value store that doesn't persist data. It's
64+
best suited for development and testing environments where data don't
65+
have to be shared across multiple nodes. No setup is required, making
66+
it easy to get started.
67+
68+
> [!TIP]
69+
> Although [`MemoryKvStore`] is provided by Fedify, BotKit also re-exports
70+
> it for convenience.
71+
72+
[`KvStore`]: https://fedify.dev/manual/kv
73+
[`RedisKvStore`]: https://fedify.dev/manual/kv#rediskvstore
74+
[@fedify/redis]: https://github.com/dahlia/fedify-redis
75+
[`PostgresKvStore`]: https://fedify.dev/manual/kv#postgreskvstore
76+
[@fedify/postgres]: https://github.com/dahlia/fedify-postgres
77+
[`DenoKvStore`]: https://fedify.dev/manual/kv#denokvstore-deno-only
78+
[Deno]: https://deno.com/
79+
[`Deno.openKv()`]: https://docs.deno.com/api/deno/~/Deno.openKv
80+
[@fedify/fedify]: https://fedify.dev/
81+
[`MemoryKvStore`]: https://fedify.dev/manual/kv#memorykvstore
82+
83+
84+
`MemoryRepository`
85+
------------------
86+
87+
The `MemoryRepository` is a repository that stores data in memory, which means
88+
that data is not persisted across restarts. It's best suited for development
89+
and testing environments where data don't have to be shared across multiple
90+
nodes. No setup is required, making it easy to get started.
91+
92+
> [!TIP]
93+
> How does it differ from using [`KvRepository`](#kvrepository) with
94+
> [`MemoryKvStore`]?—In practice, there's no difference between using
95+
> `MemoryRepository` and [`KvRepository`](#kvrepository) with
96+
> [`MemoryKvStore`]. The only differences are that `MemoryRepository` is
97+
> a more convenient way to use `MemoryKvStore` and that it's slightly more
98+
> efficient because it doesn't have to go through the [`KvStore`] interface.
99+
100+
101+
Implementing a custom repository
102+
--------------------------------
103+
104+
You can create your own repository by implementing the `Repository` interface.
105+
The `Repository` interface is a generic interface that defines the basic
106+
CRUD (create, read, update, delete) operations for data access.
107+
108+
The `Repository` interface consists of the following five domains of operations
109+
in general:
110+
111+
Key pairs
112+
: Key pairs are the singleton data that are used for the bot actor.
113+
At the surface level, the key pairs are represented as [`CryptoKeyPair`]
114+
objects, but you would typically store them as [JWK].
115+
116+
> [!TIP]
117+
> Fedify provides `exportJwk()` and `importJwk()` functions to convert
118+
> a [`CryptoKey`] object to a JWK object and vice versa.
119+
120+
Messages
121+
: Messages are the data of the messages that are published by the bot.
122+
Remote messages received from the remote server are not included in this
123+
domain. Each message has its own UUID and represented by either
124+
a `Create` object or an `Announce` object (which both are provided by
125+
Fedify).
126+
127+
You probably want to serialize the messages into JSON before
128+
storing them, so you can use [`toJsonLd()`] method that belong to
129+
the `Create` and `Announce` objects, and use [`fromJsonLd()`] method
130+
to deserialize them.
131+
132+
Followers
133+
: Followers are the data of the actors that follow the bot. Each follower
134+
is represented by `Actor` object (provided by Fedify) and is associated
135+
with a follow ID, a URI of the `Follow` activity.
136+
137+
Similar to messages, you can serialize the `Actor` object into JSON
138+
using the [`toJsonLd()`] method, and deserialize it using the
139+
[`fromJsonLd()`] method.
140+
141+
> [!CAUTION]
142+
> The `Repository.hasFollower()` method takes the URI of an `Actor`, not
143+
> the follow ID.
144+
145+
Sent follows
146+
: Sent follows are the data of the follow requests that the bot has sent.
147+
Each sent follow is represented by a `Follow` object (provided by Fedify)
148+
and is associated with its own UUID.
149+
150+
Similar to messages and followers, you can serialize the `Follow` object
151+
into JSON using the [`toJsonLd()`] method, and deserialize it using the
152+
[`fromJsonLd()`] method.
153+
154+
Followees
155+
: Followees are the data of the actors that the bot follows. Each followee
156+
is represented by a `Follow` object (provided by Fedify) instead of `Actor`,
157+
and associated with an actor ID (not a follow ID).
158+
159+
Similar to messages, followers, and sent follows, you can serialize
160+
the `Follow` object into JSON using the [`toJsonLd()`] method, and
161+
deserialize it using the [`fromJsonLd()`] method.
162+
163+
[`CryptoKeyPair`]: https://developer.mozilla.org/en-US/docs/Web/API/CryptoKeyPair
164+
[JWK]: https://datatracker.ietf.org/doc/html/rfc7517
165+
[`CryptoKey`]: https://developer.mozilla.org/en-US/docs/Web/API/CryptoKey
166+
[`toJsonLd()`]: https://fedify.dev/manual/vocab#json-ld
167+
[`fromJsonLd()`]: https://fedify.dev/manual/vocab#json-ld

0 commit comments

Comments
 (0)