@fedify/botkit-postgres 0.4.0-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,130 @@
1
+ @fedify/botkit-postgres
2
+ =======================
3
+
4
+ [![JSR][JSR badge]][JSR]
5
+ [![npm][npm badge]][npm]
6
+ [![GitHub Actions][GitHub Actions badge]][GitHub Actions]
7
+
8
+ This package is a [PostgreSQL]-based repository implementation for [BotKit].
9
+ It provides persistent shared storage for bots running on either [Deno] or
10
+ [Node.js], supports connection pooling through [Postgres.js], and stores BotKit
11
+ repository data in ordinary PostgreSQL tables under a dedicated schema.
12
+
13
+ [JSR badge]: https://jsr.io/badges/@fedify/botkit-postgres
14
+ [JSR]: https://jsr.io/@fedify/botkit-postgres
15
+ [npm badge]: https://img.shields.io/npm/v/@fedify/botkit-postgres?logo=npm
16
+ [npm]: https://www.npmjs.com/package/@fedify/botkit-postgres
17
+ [GitHub Actions badge]: https://github.com/fedify-dev/botkit/actions/workflows/main.yaml/badge.svg
18
+ [GitHub Actions]: https://github.com/fedify-dev/botkit/actions/workflows/main.yaml
19
+ [PostgreSQL]: https://www.postgresql.org/
20
+ [BotKit]: https://botkit.fedify.dev/
21
+ [Deno]: https://deno.land/
22
+ [Node.js]: https://nodejs.org/
23
+ [Postgres.js]: https://github.com/porsager/postgres
24
+
25
+
26
+ Installation
27
+ ------------
28
+
29
+ ~~~~ sh
30
+ deno add jsr:@fedify/botkit-postgres
31
+ npm add @fedify/botkit-postgres
32
+ pnpm add @fedify/botkit-postgres
33
+ yarn add @fedify/botkit-postgres
34
+ ~~~~
35
+
36
+
37
+ Usage
38
+ -----
39
+
40
+ The `PostgresRepository` can be used as a drop-in repository implementation for
41
+ BotKit:
42
+
43
+ ~~~~ typescript
44
+ import { createBot } from "@fedify/botkit";
45
+ import { PostgresRepository } from "@fedify/botkit-postgres";
46
+
47
+ const bot = createBot({
48
+ username: "mybot",
49
+ repository: new PostgresRepository({
50
+ url: "postgresql://localhost/botkit",
51
+ schema: "botkit",
52
+ maxConnections: 10,
53
+ }),
54
+ });
55
+ ~~~~
56
+
57
+ You can also inject an existing [Postgres.js] client. In that case the
58
+ repository does not own the client and `close()` will not shut it down:
59
+
60
+ ~~~~ typescript
61
+ import postgres from "postgres";
62
+ import { PostgresRepository } from "@fedify/botkit-postgres";
63
+
64
+ const sql = postgres("postgresql://localhost/botkit");
65
+ const repository = new PostgresRepository({
66
+ sql,
67
+ schema: "botkit",
68
+ });
69
+ ~~~~
70
+
71
+
72
+ Options
73
+ -------
74
+
75
+ The `PostgresRepository` constructor accepts the following options:
76
+
77
+ - **`sql`**: An existing [Postgres.js] client to use.
78
+
79
+ - **`url`**: A PostgreSQL connection string for an internally managed
80
+ connection pool.
81
+
82
+ - **`schema`** (optional): The PostgreSQL schema name used for BotKit tables.
83
+ Defaults to `"botkit"`.
84
+
85
+ - **`maxConnections`** (optional): Maximum number of connections for an
86
+ internally managed pool created from `url`.
87
+
88
+ - **`prepare`** (optional): Whether to use prepared statements for queries.
89
+ Defaults to `true`.
90
+
91
+ The options are mutually exclusive: use either `sql` or `url`. The
92
+ `maxConnections` option is only valid together with `url`.
93
+
94
+
95
+ Schema setup
96
+ ------------
97
+
98
+ The repository creates its schema and tables automatically on first use.
99
+ If you want to provision them explicitly ahead of time, use the exported
100
+ `initializePostgresRepositorySchema()` helper:
101
+
102
+ ~~~~ typescript
103
+ import postgres from "postgres";
104
+ import { initializePostgresRepositorySchema } from "@fedify/botkit-postgres";
105
+
106
+ const sql = postgres("postgresql://localhost/botkit");
107
+ await initializePostgresRepositorySchema(sql, "botkit");
108
+ ~~~~
109
+
110
+ If you disable prepared statements, pass `false` as the third argument so
111
+ schema initialization uses the same setting.
112
+
113
+
114
+ Features
115
+ --------
116
+
117
+ - **Cross-runtime**: Works with both Deno and Node.js using [Postgres.js]
118
+
119
+ - **Shared persistent storage**: Suitable for multi-process and
120
+ multi-instance deployments backed by PostgreSQL
121
+
122
+ - **Schema namespacing**: Keeps BotKit tables grouped under a dedicated
123
+ PostgreSQL schema
124
+
125
+ - **Full `Repository` API**: Implements BotKit repository storage for key
126
+ pairs, messages, followers, follows, followees, and poll votes
127
+
128
+ - **Explicit resource ownership**: Repositories created from a URL own their
129
+ pool, while repositories created from an injected client leave lifecycle
130
+ control to the caller
package/dist/mod.d.ts ADDED
@@ -0,0 +1,121 @@
1
+ import { Actor, Announce, Create, Follow } from "@fedify/vocab";
2
+ import postgres from "postgres";
3
+ import { Repository, RepositoryGetFollowersOptions, RepositoryGetMessagesOptions, Uuid } from "@fedify/botkit/repository";
4
+
5
+ //#region src/mod.d.ts
6
+ type Queryable = Pick<postgres.Sql, "unsafe">;
7
+ /**
8
+ * Common options for creating a PostgreSQL repository.
9
+ * @since 0.4.0
10
+ */
11
+ interface PostgresRepositoryOptionsBase {
12
+ /**
13
+ * The PostgreSQL schema name to use.
14
+ * @default `"botkit"`
15
+ */
16
+ readonly schema?: string;
17
+ /**
18
+ * Whether to use prepared statements for queries.
19
+ * @default true
20
+ */
21
+ readonly prepare?: boolean;
22
+ }
23
+ /**
24
+ * Options for creating a PostgreSQL repository from an injected client.
25
+ * @since 0.4.0
26
+ */
27
+ interface PostgresRepositoryOptionsWithClient extends PostgresRepositoryOptionsBase {
28
+ /**
29
+ * A pre-configured PostgreSQL client to use.
30
+ */
31
+ readonly sql: postgres.Sql;
32
+ /**
33
+ * Disallowed when `sql` is provided.
34
+ */
35
+ readonly url?: never;
36
+ /**
37
+ * Disallowed when `sql` is provided.
38
+ */
39
+ readonly maxConnections?: never;
40
+ }
41
+ /**
42
+ * Options for creating a PostgreSQL repository from a connection string.
43
+ * @since 0.4.0
44
+ */
45
+ interface PostgresRepositoryOptionsWithUrl extends PostgresRepositoryOptionsBase {
46
+ /**
47
+ * A PostgreSQL connection string to connect with.
48
+ */
49
+ readonly url: string | URL;
50
+ /**
51
+ * Disallowed when `url` is provided.
52
+ */
53
+ readonly sql?: never;
54
+ /**
55
+ * The maximum number of connections for an owned pool.
56
+ */
57
+ readonly maxConnections?: number;
58
+ }
59
+ /**
60
+ * Options for creating a PostgreSQL repository.
61
+ * @since 0.4.0
62
+ */
63
+ type PostgresRepositoryOptions = PostgresRepositoryOptionsWithClient | PostgresRepositoryOptionsWithUrl;
64
+ /**
65
+ * Initializes the PostgreSQL schema used by BotKit repositories.
66
+ * @param sql The PostgreSQL client to initialize the schema with.
67
+ * @param schema The PostgreSQL schema name to initialize.
68
+ * @param prepare Whether to use prepared statements for schema queries.
69
+ * @since 0.4.0
70
+ */
71
+ declare function initializePostgresRepositorySchema(sql: Queryable, schema?: string, prepare?: boolean): Promise<void>;
72
+ /**
73
+ * A repository for storing bot data using PostgreSQL.
74
+ * @since 0.4.0
75
+ */
76
+ declare class PostgresRepository implements Repository, AsyncDisposable {
77
+ readonly sql: postgres.Sql;
78
+ readonly schema: string;
79
+ readonly prepare: boolean;
80
+ private readonly ownsSql;
81
+ private readonly ready;
82
+ constructor(options: PostgresRepositoryOptions);
83
+ [Symbol.asyncDispose](): Promise<void>;
84
+ /**
85
+ * Closes the underlying PostgreSQL connection pool if owned by the
86
+ * repository.
87
+ */
88
+ close(): Promise<void>;
89
+ setKeyPairs(keyPairs: CryptoKeyPair[]): Promise<void>;
90
+ getKeyPairs(): Promise<CryptoKeyPair[] | undefined>;
91
+ addMessage(id: Uuid, activity: Create | Announce): Promise<void>;
92
+ updateMessage(id: Uuid, updater: (existing: Create | Announce) => Create | Announce | undefined | Promise<Create | Announce | undefined>): Promise<boolean>;
93
+ removeMessage(id: Uuid): Promise<Create | Announce | undefined>;
94
+ getMessages(options?: RepositoryGetMessagesOptions): AsyncIterable<Create | Announce>;
95
+ getMessage(id: Uuid): Promise<Create | Announce | undefined>;
96
+ countMessages(): Promise<number>;
97
+ addFollower(followId: URL, follower: Actor): Promise<void>;
98
+ removeFollower(followId: URL, followerId: URL): Promise<Actor | undefined>;
99
+ hasFollower(followerId: URL): Promise<boolean>;
100
+ getFollowers(options?: RepositoryGetFollowersOptions): AsyncIterable<Actor>;
101
+ countFollowers(): Promise<number>;
102
+ addSentFollow(id: Uuid, follow: Follow): Promise<void>;
103
+ removeSentFollow(id: Uuid): Promise<Follow | undefined>;
104
+ getSentFollow(id: Uuid): Promise<Follow | undefined>;
105
+ addFollowee(followeeId: URL, follow: Follow): Promise<void>;
106
+ removeFollowee(followeeId: URL): Promise<Follow | undefined>;
107
+ getFollowee(followeeId: URL): Promise<Follow | undefined>;
108
+ vote(messageId: Uuid, voterId: URL, option: string): Promise<void>;
109
+ countVoters(messageId: Uuid): Promise<number>;
110
+ countVotes(messageId: Uuid): Promise<Readonly<Record<string, number>>>;
111
+ private table;
112
+ private lockFollowRequest;
113
+ private lockFollower;
114
+ private lockFollowers;
115
+ private cleanupFollower;
116
+ private ensureReady;
117
+ private query;
118
+ }
119
+ //#endregion
120
+ export { PostgresRepository, PostgresRepositoryOptions, initializePostgresRepositorySchema };
121
+ //# sourceMappingURL=mod.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mod.d.ts","names":[],"sources":["../src/mod.ts"],"sourcesContent":[],"mappings":"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"}