@interactive-inc/flume 0.1.0 → 0.3.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 +107 -48
- package/dist/connection-error-BOk97djj.d.ts +6 -0
- package/dist/discord.d.ts +111 -4
- package/dist/discord.js +546 -2
- package/dist/github.d.ts +50 -4
- package/dist/github.js +314 -2
- package/dist/http-error-BtXonO-W.js +12 -0
- package/dist/http-error-K-Ym4lfK.d.ts +11 -0
- package/dist/index.d.ts +39 -222
- package/dist/index.js +107 -52
- package/dist/logger-CpGB9WO_.js +49 -0
- package/dist/parse-error-BAiCLRmk.d.ts +6 -0
- package/dist/{safe-json-parse-D8t_4Vm_.js → reconnector-BDoJ1xNX.js} +1 -15
- package/dist/safe-fetch-30ZzOKHL.js +20 -0
- package/dist/safe-json-parse-BWlzGOLl.js +41 -0
- package/dist/serial-queue-ExmlnpzQ.js +16 -0
- package/dist/slack.d.ts +65 -4
- package/dist/slack.js +452 -2
- package/dist/{types-BVQSU336.d.ts → types-Bm9uKUQz.d.ts} +48 -17
- package/package.json +1 -1
- package/dist/discord-source-Q4JRIbNs.js +0 -525
- package/dist/github-source-D7Z1RUbe.js +0 -280
- package/dist/logger-B9E8zvgj.js +0 -69
- package/dist/slack-source-CszepStG.js +0 -400
package/README.md
CHANGED
|
@@ -4,11 +4,11 @@ Unified notification listener for Discord, Slack, and GitHub. Raw WebSocket + `f
|
|
|
4
4
|
|
|
5
5
|
```
|
|
6
6
|
Discord ─┐
|
|
7
|
-
Slack
|
|
7
|
+
Slack ─┼──▶ Flume ──start(handler)──▶ FlumeEvent (one merged stream)
|
|
8
8
|
GitHub ─┘
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Flume only **receives**. It opens the WebSocket / polls the API, parses the payload with Zod, and hands you a typed event. Sending replies is out of scope — bring your own HTTP call.
|
|
11
|
+
Flume only **receives**. It opens the WebSocket / polls the API, parses the payload with Zod, serializes events through a per-source queue, and hands you a typed event. Sending replies is out of scope — bring your own HTTP call.
|
|
12
12
|
|
|
13
13
|
## Install
|
|
14
14
|
|
|
@@ -19,62 +19,100 @@ npm add @interactive-inc/flume
|
|
|
19
19
|
## Quick start
|
|
20
20
|
|
|
21
21
|
```ts
|
|
22
|
-
import { Flume
|
|
22
|
+
import { Flume } from "@interactive-inc/flume"
|
|
23
|
+
import { FlumeDiscordSource } from "@interactive-inc/flume/discord"
|
|
24
|
+
import { FlumeSlackSource } from "@interactive-inc/flume/slack"
|
|
25
|
+
import { FlumeGitHubSource } from "@interactive-inc/flume/github"
|
|
26
|
+
|
|
27
|
+
const onLog = (log) => console.log(`[${log.level}] ${log.source}/${log.action}: ${log.message}`)
|
|
23
28
|
|
|
24
29
|
const flume = new Flume({
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
30
|
+
sources: [
|
|
31
|
+
new FlumeDiscordSource({ token: process.env.DISCORD_BOT_TOKEN!, onLog, reconnect: true }),
|
|
32
|
+
new FlumeSlackSource({ appToken: process.env.SLACK_APP_TOKEN!, botToken: process.env.SLACK_BOT_TOKEN!, onLog, reconnect: true }),
|
|
33
|
+
new FlumeGitHubSource({ token: process.env.GITHUB_TOKEN!, onLog, pollInterval: 60 }),
|
|
34
|
+
],
|
|
29
35
|
})
|
|
30
36
|
|
|
31
|
-
const
|
|
32
|
-
const slack = flume.slack({ appToken: process.env.SLACK_APP_TOKEN! })
|
|
33
|
-
const github = flume.github({ token: process.env.GITHUB_TOKEN!, pollInterval: 60 })
|
|
34
|
-
|
|
35
|
-
await discord.start((event) => {
|
|
37
|
+
const result = await flume.start((event) => {
|
|
36
38
|
console.log(event.source, event.type, event.meta)
|
|
37
39
|
})
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
if (!result.ok) throw result.error
|
|
42
|
+
|
|
43
|
+
const running = flume.runningState()!
|
|
44
|
+
|
|
45
|
+
// later
|
|
46
|
+
await running.stop()
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Lifecycle (type-state FSM)
|
|
50
|
+
|
|
51
|
+
`Flume` enforces lifecycle correctness through three classes — misuse becomes a compile error.
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
Flume ──start()──▶ FlumeRunning ──stop()──▶ FlumeStopped
|
|
55
|
+
(idle) (running) (terminal)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- `Flume.start(handler)` returns `FlumeStartResult` — a discriminated union `{ ok: true } | { ok: false; error: Error }`. On `ok: true`, the `FlumeRunning` instance is reachable via `flume.runningState()`. On partial failure (one source fails while another succeeds), the already-started sources are rolled back and `ok: false` is returned with per-source detail in `error.message`.
|
|
59
|
+
- `FlumeRunning.stop()` returns a `FlumeStopped` snapshot. `stop()` is idempotent and concurrent-safe.
|
|
60
|
+
- `FlumeStopped` exposes only `statuses()` — a frozen snapshot of each source's final state. No `start`, no `stop`, no leaking source references.
|
|
61
|
+
- An `AbortSignal` on `Flume` drives an automatic transition to `FlumeStopped`.
|
|
62
|
+
|
|
63
|
+
```ts
|
|
64
|
+
const result = await flume.start(handler)
|
|
65
|
+
if (!result.ok) {
|
|
66
|
+
console.error(result.error.message)
|
|
67
|
+
// "Flume.start: 1 source(s) failed: slack: connect refused"
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const running = flume.runningState()!
|
|
72
|
+
|
|
73
|
+
running.start() // type error — `start` is not on FlumeRunning
|
|
74
|
+
|
|
75
|
+
const stopped = await running.stop()
|
|
76
|
+
stopped.stop() // type error
|
|
77
|
+
stopped.start() // type error
|
|
78
|
+
stopped.statuses() // [{ name: "discord", status: "disconnected" }, ...]
|
|
41
79
|
```
|
|
42
80
|
|
|
43
81
|
## Direct source usage
|
|
44
82
|
|
|
45
|
-
|
|
83
|
+
Sources work standalone — `Flume` is only needed for multi-source orchestration.
|
|
46
84
|
|
|
47
85
|
```ts
|
|
48
|
-
import { FlumeDiscordSource
|
|
86
|
+
import { FlumeDiscordSource } from "@interactive-inc/flume/discord"
|
|
49
87
|
|
|
50
88
|
const source = new FlumeDiscordSource({
|
|
51
89
|
token: process.env.DISCORD_BOT_TOKEN!,
|
|
52
|
-
deps: createFlumeDefaultDeps(),
|
|
53
90
|
reconnect: true,
|
|
54
91
|
onLog: (log) => console.log(log),
|
|
55
92
|
})
|
|
56
93
|
|
|
57
|
-
await source.start((event) => { /* ... */ })
|
|
94
|
+
const result = await source.start((event) => { /* ... */ })
|
|
95
|
+
if (!result.ok) throw result.error
|
|
58
96
|
```
|
|
59
97
|
|
|
60
98
|
## Sub-entries
|
|
61
99
|
|
|
62
|
-
Each source
|
|
100
|
+
Each source has a dedicated entry — importing one does not pull the others into your bundle. The root entry never loads source-specific code.
|
|
63
101
|
|
|
64
|
-
| sub-entry
|
|
65
|
-
|
|
66
|
-
| `@interactive-inc/flume
|
|
67
|
-
| `@interactive-inc/flume/
|
|
68
|
-
| `@interactive-inc/flume/
|
|
102
|
+
| sub-entry | exports |
|
|
103
|
+
|------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
104
|
+
| `@interactive-inc/flume` | `Flume`, `FlumeRunning`, `FlumeStopped`, `FlumeLogger`, `FlumeReconnector`, `createFlumeDefaultDeps`, errors, types |
|
|
105
|
+
| `@interactive-inc/flume/discord` | `FlumeDiscordSource`, `FlumeDiscordGateway`, `FlumeDiscordGatewayIntents`, `FlumeDiscordHeartbeat`, `FlumeDiscordGatewaySession`, `parseDiscordGatewayMessage`, `extractDiscordMeta`, `FlumeGatewayMessageSchema` |
|
|
106
|
+
| `@interactive-inc/flume/slack` | `FlumeSlackSource`, `FlumeSlackSocketMode`, `FlumeSlackSeenCache`, `obtainSlackUrl`, `extractSlackMeta`, `FlumeSlackEnvelopeSchema`, `FlumeSlackConnectionResponseSchema` |
|
|
107
|
+
| `@interactive-inc/flume/github` | `FlumeGitHubSource`, `FlumeGitHubPoller`, `FlumeGitHubSeenCache`, `extractGitHubMeta`, `FlumeGitHubNotificationSchema` |
|
|
69
108
|
|
|
70
109
|
```ts
|
|
71
|
-
import {
|
|
110
|
+
import { Flume } from "@interactive-inc/flume"
|
|
72
111
|
import { FlumeDiscordSource } from "@interactive-inc/flume/discord"
|
|
112
|
+
import { FlumeSlackSource } from "@interactive-inc/flume/slack"
|
|
73
113
|
import { FlumeGitHubSource } from "@interactive-inc/flume/github"
|
|
74
114
|
```
|
|
75
115
|
|
|
76
|
-
The root entry exports the `Flume` container, every source class, every protocol class (`FlumeDiscordGateway`, `FlumeSlackSocketMode`, `FlumeGitHubPoller`), `FlumeReconnector`, `FlumeLogger`, `createFlumeDefaultDeps`, every Zod schema, every error class, and all public types.
|
|
77
|
-
|
|
78
116
|
## Event shape
|
|
79
117
|
|
|
80
118
|
Every source emits the same `FlumeEvent`:
|
|
@@ -163,36 +201,54 @@ GitHub populates `detail` with the failure reason (e.g. `"HTTP 500"`, `"network
|
|
|
163
201
|
|
|
164
202
|
## Cancellation
|
|
165
203
|
|
|
166
|
-
Pass an `AbortSignal` to
|
|
204
|
+
Pass an `AbortSignal` to `Flume` (propagates to every source) or to an individual source.
|
|
167
205
|
|
|
168
206
|
```ts
|
|
169
207
|
const controller = new AbortController()
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
208
|
+
|
|
209
|
+
const flume = new Flume({
|
|
210
|
+
sources: [new FlumeDiscordSource({ token, signal: controller.signal })],
|
|
211
|
+
signal: controller.signal,
|
|
212
|
+
})
|
|
213
|
+
|
|
214
|
+
```ts
|
|
215
|
+
const result = await flume.start(handler)
|
|
216
|
+
if (!result.ok) throw result.error
|
|
217
|
+
|
|
218
|
+
const running = flume.runningState()!
|
|
219
|
+
|
|
220
|
+
controller.abort() // FlumeRunning auto-transitions to FlumeStopped
|
|
173
221
|
```
|
|
174
222
|
|
|
223
|
+
If the signal is already aborted at `Flume.start()` time, `start` returns `{ ok: false, error }` and no source is touched.
|
|
224
|
+
|
|
175
225
|
## Dependency injection
|
|
176
226
|
|
|
177
|
-
Every IO boundary (`fetch`, `WebSocket`, `now`, `random`, timers) lives in `FlumeRuntimeDeps`.
|
|
227
|
+
Every IO boundary (`fetch`, `WebSocket`, `now`, `random`, timers) lives in `FlumeRuntimeDeps`. `deps` is optional on every source — when omitted, `createFlumeDefaultDeps()` wraps the global equivalents. Override only when you need mocks or runtime-specific shims.
|
|
178
228
|
|
|
179
229
|
```ts
|
|
180
230
|
import { createFlumeDefaultDeps } from "@interactive-inc/flume"
|
|
181
231
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
}
|
|
232
|
+
new FlumeDiscordSource({
|
|
233
|
+
token,
|
|
234
|
+
deps: {
|
|
235
|
+
...createFlumeDefaultDeps(),
|
|
236
|
+
fetch: mockFetch,
|
|
237
|
+
now: () => 1_000,
|
|
238
|
+
},
|
|
239
|
+
})
|
|
189
240
|
```
|
|
190
241
|
|
|
191
|
-
|
|
242
|
+
## Safety
|
|
243
|
+
|
|
244
|
+
- **Backpressure** — each source has its own `FlumeSerialQueue`. Handler invocations are awaited and run one at a time per source, so async handlers don't race and `stop()` drains in-flight events before transitioning state.
|
|
245
|
+
- **Duplicate suppression** — Slack envelopes are deduped by `envelope_id` (`FlumeSlackSeenCache`) to absorb ack retries. GitHub notifications are deduped by `id + updated_at` (`FlumeGitHubSeenCache`). Discord uses session resume so the Gateway does not re-emit dispatches.
|
|
246
|
+
- **Partial-failure rollback** — if any source fails during `Flume.start()`, the already-started sources are stopped and `{ ok: false, error }` is returned with per-source detail.
|
|
247
|
+
- **Idempotent stop** — `FlumeRunning.stop()` is safe to call concurrently; the first call wins and subsequent callers receive the same `FlumeStopped` snapshot.
|
|
192
248
|
|
|
193
249
|
## Errors
|
|
194
250
|
|
|
195
|
-
Flume does not throw on protocol/network failures.
|
|
251
|
+
Flume does not throw on protocol/network failures. `Source.start()` and `Flume.start()` return `FlumeStartResult` (`{ ok: true } | { ok: false; error: Error }`) — branch on `result.ok`. Protocol-layer helpers (`FlumeDiscordGateway.connect()`, `obtainSlackUrl()`, …) return `T | Error` and you check `instanceof`:
|
|
196
252
|
|
|
197
253
|
- `FlumeConnectionError` — WebSocket closed before ready
|
|
198
254
|
- `FlumeHttpError` — HTTP call returned an error payload (e.g. Slack `ok: false`)
|
|
@@ -205,7 +261,7 @@ Internal handler exceptions are caught and logged (never rethrown into the proto
|
|
|
205
261
|
| source | transport | auth |
|
|
206
262
|
|---------|----------------------------------|-----------------------------------------------|
|
|
207
263
|
| Discord | Gateway WebSocket v10 (JSON) | bot token |
|
|
208
|
-
| Slack | Socket Mode WebSocket | app token
|
|
264
|
+
| Slack | Socket Mode WebSocket | app token + bot token (both required) |
|
|
209
265
|
| GitHub | REST polling `/notifications` | personal access token |
|
|
210
266
|
|
|
211
267
|
GitHub also exposes `gh auth token` if you want to reuse the `gh` CLI's session:
|
|
@@ -213,18 +269,21 @@ GitHub also exposes `gh auth token` if you want to reuse the `gh` CLI's session:
|
|
|
213
269
|
```ts
|
|
214
270
|
import { execSync } from "node:child_process"
|
|
215
271
|
const token = execSync("gh auth token").toString().trim()
|
|
216
|
-
const github =
|
|
272
|
+
const github = new FlumeGitHubSource({ token })
|
|
217
273
|
```
|
|
218
274
|
|
|
219
275
|
## Module layout
|
|
220
276
|
|
|
221
|
-
- `Flume`
|
|
222
|
-
- `FlumeDiscordSource` / `FlumeSlackSource` / `FlumeGitHubSource` — high-level sources
|
|
277
|
+
- `Flume` / `FlumeRunning` / `FlumeStopped` — type-state FSM merging multiple sources into one stream
|
|
278
|
+
- `FlumeDiscordSource` / `FlumeSlackSource` / `FlumeGitHubSource` — high-level sources (each conforms to the structural `FlumeSource` type)
|
|
223
279
|
- `FlumeDiscordGateway` / `FlumeSlackSocketMode` / `FlumeGitHubPoller` — protocol layer
|
|
224
|
-
- `
|
|
280
|
+
- `FlumeDiscordGatewaySession` — immutable session value object (id / seq / resume URL) carried across Discord reconnects
|
|
281
|
+
- `FlumeSlackSeenCache` / `FlumeGitHubSeenCache` — per-source duplicate suppression
|
|
282
|
+
- `FlumeReconnector` — exponential backoff with jitter (the internal `scheduleFlumeReconnect` helper is not exported; sources wire it themselves)
|
|
225
283
|
- `FlumeLogger` — structured log emitter (feeds `onLog`)
|
|
226
|
-
- `FlumeRuntimeDeps` — IO boundary port
|
|
227
|
-
-
|
|
284
|
+
- `FlumeRuntimeDeps` — IO boundary port (`fetch`, `WebSocket`, `now`, `random`, timers)
|
|
285
|
+
- `extractDiscordMeta` / `extractSlackMeta` / `extractGitHubMeta` — pure functions that build `FlumeEvent.meta` from each protocol's payload shape
|
|
286
|
+
- Per-source Zod schemas: `FlumeGatewayMessageSchema` (discord), `FlumeSlackEnvelopeSchema` / `FlumeSlackConnectionResponseSchema` (slack), `FlumeGitHubNotificationSchema` (github)
|
|
228
287
|
|
|
229
288
|
## Development
|
|
230
289
|
|
package/dist/discord.d.ts
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
|
-
import { o as FlumeHandler, t as FlumeDiscordSourceOptions,
|
|
1
|
+
import { A as FlumeGatewayMessageSchema, C as FlumeStartResult, c as FlumeLogHandler, o as FlumeHandler, p as FlumeRuntimeDeps, r as FlumeGatewayMessage, t as FlumeDiscordSourceOptions, w as FlumeStatus } from "./types-Bm9uKUQz.js";
|
|
2
|
+
import { t as FlumeConnectionError } from "./connection-error-BOk97djj.js";
|
|
3
|
+
import { t as FlumeParseError } from "./parse-error-BAiCLRmk.js";
|
|
2
4
|
|
|
3
5
|
//#region lib/discord/discord-source.d.ts
|
|
4
6
|
declare class FlumeDiscordSource {
|
|
5
7
|
private readonly options;
|
|
8
|
+
readonly name: "discord";
|
|
6
9
|
private gateway;
|
|
7
10
|
private reconnector;
|
|
8
11
|
private handler;
|
|
9
12
|
private currentStatus;
|
|
10
13
|
private readonly log;
|
|
11
14
|
private readonly deps;
|
|
15
|
+
private readonly queue;
|
|
12
16
|
constructor(options: FlumeDiscordSourceOptions);
|
|
13
|
-
start(handler: FlumeHandler): Promise<
|
|
17
|
+
start(handler: FlumeHandler): Promise<FlumeStartResult>;
|
|
14
18
|
stop(): Promise<void>;
|
|
15
19
|
status(): FlumeStatus;
|
|
16
20
|
private connectInternal;
|
|
@@ -18,7 +22,110 @@ declare class FlumeDiscordSource {
|
|
|
18
22
|
private handleGatewayStatus;
|
|
19
23
|
private scheduleReconnect;
|
|
20
24
|
private setStatus;
|
|
21
|
-
static extractMeta(eventName: string, eventData: Record<string, unknown>): Record<string, string>;
|
|
22
25
|
}
|
|
23
26
|
//#endregion
|
|
24
|
-
|
|
27
|
+
//#region lib/discord/extract-discord-meta.d.ts
|
|
28
|
+
declare function extractDiscordMeta(eventName: string, eventData: Record<string, unknown>): Record<string, string>;
|
|
29
|
+
//#endregion
|
|
30
|
+
//#region lib/discord/discord-gateway-session.d.ts
|
|
31
|
+
type Props$2 = {
|
|
32
|
+
sessionId: string | null;
|
|
33
|
+
resumeUrl: string | null;
|
|
34
|
+
seq: number | null;
|
|
35
|
+
};
|
|
36
|
+
declare class FlumeDiscordGatewaySession {
|
|
37
|
+
readonly sessionId: string | null;
|
|
38
|
+
readonly resumeUrl: string | null;
|
|
39
|
+
readonly seq: number | null;
|
|
40
|
+
constructor(props: Props$2);
|
|
41
|
+
static empty(): FlumeDiscordGatewaySession;
|
|
42
|
+
canResume(): boolean;
|
|
43
|
+
withSeq(seq: number): FlumeDiscordGatewaySession;
|
|
44
|
+
withReady(sessionId: string, resumeUrl: string): FlumeDiscordGatewaySession;
|
|
45
|
+
withReset(): FlumeDiscordGatewaySession;
|
|
46
|
+
}
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region lib/discord/discord-gateway.d.ts
|
|
49
|
+
type Deps = Pick<FlumeRuntimeDeps, "WebSocket" | "setInterval" | "clearInterval" | "setTimeout" | "random" | "now">;
|
|
50
|
+
type Props$1 = {
|
|
51
|
+
token: string;
|
|
52
|
+
intents: number;
|
|
53
|
+
onDispatch: (event: string, data: Record<string, unknown>) => void;
|
|
54
|
+
onStatus: (status: "connected" | "disconnected") => void;
|
|
55
|
+
onLog?: FlumeLogHandler;
|
|
56
|
+
deps: Deps;
|
|
57
|
+
};
|
|
58
|
+
declare class FlumeDiscordGateway {
|
|
59
|
+
private readonly props;
|
|
60
|
+
private readonly log;
|
|
61
|
+
private ws;
|
|
62
|
+
private heartbeat;
|
|
63
|
+
session: FlumeDiscordGatewaySession;
|
|
64
|
+
stopped: boolean;
|
|
65
|
+
private pendingResolve;
|
|
66
|
+
private pendingResolved;
|
|
67
|
+
constructor(props: Props$1);
|
|
68
|
+
connect(url?: string): Promise<FlumeConnectionError | null>;
|
|
69
|
+
disconnect(): void;
|
|
70
|
+
isConnected(): boolean;
|
|
71
|
+
private completeConnect;
|
|
72
|
+
private onMessage;
|
|
73
|
+
private onHello;
|
|
74
|
+
private onHeartbeatAck;
|
|
75
|
+
private onHeartbeatRequest;
|
|
76
|
+
private onReconnectRequest;
|
|
77
|
+
private onInvalidSession;
|
|
78
|
+
private onDispatch;
|
|
79
|
+
private onClose;
|
|
80
|
+
private onError;
|
|
81
|
+
private send;
|
|
82
|
+
private sendIdentify;
|
|
83
|
+
private sendResume;
|
|
84
|
+
}
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region lib/discord/discord-gateway-intents.d.ts
|
|
87
|
+
declare const FlumeDiscordGatewayIntents: {
|
|
88
|
+
readonly Guilds: number;
|
|
89
|
+
readonly GuildMembers: number;
|
|
90
|
+
readonly GuildModeration: number;
|
|
91
|
+
readonly GuildExpressions: number;
|
|
92
|
+
readonly GuildIntegrations: number;
|
|
93
|
+
readonly GuildWebhooks: number;
|
|
94
|
+
readonly GuildInvites: number;
|
|
95
|
+
readonly GuildVoiceStates: number;
|
|
96
|
+
readonly GuildPresences: number;
|
|
97
|
+
readonly GuildMessages: number;
|
|
98
|
+
readonly GuildMessageReactions: number;
|
|
99
|
+
readonly GuildMessageTyping: number;
|
|
100
|
+
readonly DirectMessages: number;
|
|
101
|
+
readonly DirectMessageReactions: number;
|
|
102
|
+
readonly DirectMessageTyping: number;
|
|
103
|
+
readonly MessageContent: number;
|
|
104
|
+
readonly GuildScheduledEvents: number;
|
|
105
|
+
readonly AutoModerationConfiguration: number;
|
|
106
|
+
readonly AutoModerationExecution: number;
|
|
107
|
+
readonly GuildMessagePolls: number;
|
|
108
|
+
readonly DirectMessagePolls: number;
|
|
109
|
+
};
|
|
110
|
+
//#endregion
|
|
111
|
+
//#region lib/discord/discord-heartbeat.d.ts
|
|
112
|
+
type Props = {
|
|
113
|
+
onSend: () => void;
|
|
114
|
+
onZombie: () => void;
|
|
115
|
+
deps: Pick<FlumeRuntimeDeps, "setInterval" | "clearInterval">;
|
|
116
|
+
};
|
|
117
|
+
declare class FlumeDiscordHeartbeat {
|
|
118
|
+
private readonly props;
|
|
119
|
+
private timer;
|
|
120
|
+
private ackReceived;
|
|
121
|
+
constructor(props: Props);
|
|
122
|
+
start(intervalMs: number): void;
|
|
123
|
+
stop(): void;
|
|
124
|
+
ack(): void;
|
|
125
|
+
isRunning(): boolean;
|
|
126
|
+
}
|
|
127
|
+
//#endregion
|
|
128
|
+
//#region lib/discord/parse-discord-gateway-message.d.ts
|
|
129
|
+
declare function parseDiscordGatewayMessage(raw: string): FlumeGatewayMessage | FlumeParseError;
|
|
130
|
+
//#endregion
|
|
131
|
+
export { FlumeDiscordGateway, FlumeDiscordGatewayIntents, FlumeDiscordGatewaySession, FlumeDiscordHeartbeat, FlumeDiscordSource, FlumeGatewayMessageSchema, extractDiscordMeta, parseDiscordGatewayMessage };
|