@interactive-inc/flume 0.1.0 → 0.2.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/dist/github.js CHANGED
@@ -1,2 +1,307 @@
1
- import { t as FlumeGitHubSource } from "./github-source-D7Z1RUbe.js";
2
- export { FlumeGitHubSource };
1
+ import { n as createFlumeDefaultDeps, t as FlumeLogger } from "./logger-CpGB9WO_.js";
2
+ import { t as FlumeSerialQueue } from "./serial-queue-ExmlnpzQ.js";
3
+ import { t as safeFetch } from "./safe-fetch-30ZzOKHL.js";
4
+ import { z } from "zod/v4";
5
+ //#region lib/github/extract-github-meta.ts
6
+ function extractGitHubMeta(notification) {
7
+ return {
8
+ event_type: "notification",
9
+ reason: notification.reason,
10
+ subject_type: notification.subject.type,
11
+ repository: notification.repository.full_name,
12
+ thread_id: notification.id
13
+ };
14
+ }
15
+ //#endregion
16
+ //#region lib/github/github-notification-schema.ts
17
+ const FlumeGitHubNotificationSchema = z.object({
18
+ id: z.string(),
19
+ reason: z.string(),
20
+ unread: z.boolean(),
21
+ updated_at: z.string(),
22
+ subject: z.object({
23
+ title: z.string(),
24
+ url: z.string().nullable(),
25
+ type: z.string()
26
+ }),
27
+ repository: z.object({ full_name: z.string() })
28
+ });
29
+ //#endregion
30
+ //#region lib/github/github-seen-cache.ts
31
+ var FlumeGitHubSeenCache = class {
32
+ props;
33
+ seen = /* @__PURE__ */ new Map();
34
+ constructor(props) {
35
+ this.props = props;
36
+ }
37
+ has(id, updatedAt) {
38
+ return this.seen.get(id) === updatedAt;
39
+ }
40
+ add(id, updatedAt) {
41
+ this.seen.set(id, updatedAt);
42
+ }
43
+ trim() {
44
+ if (this.seen.size <= this.props.maxSize) return;
45
+ const entries = [...this.seen.entries()];
46
+ this.seen = new Map(entries.slice(entries.length - this.props.maxSize));
47
+ }
48
+ get size() {
49
+ return this.seen.size;
50
+ }
51
+ };
52
+ //#endregion
53
+ //#region lib/github/github-poller.ts
54
+ var FlumeGitHubPoller = class {
55
+ props;
56
+ log;
57
+ cache = new FlumeGitHubSeenCache({ maxSize: 5e3 });
58
+ timer = null;
59
+ since = null;
60
+ bootstrapped = false;
61
+ stopped = false;
62
+ consecutiveErrors = 0;
63
+ constructor(props) {
64
+ this.props = props;
65
+ this.log = new FlumeLogger({
66
+ source: "github.poller",
67
+ handler: props.onLog,
68
+ deps: props.deps
69
+ });
70
+ }
71
+ async start() {
72
+ this.stopped = false;
73
+ this.log.info({
74
+ action: "start",
75
+ message: `polling every ${this.props.interval}s`
76
+ });
77
+ await this.poll();
78
+ this.timer = this.props.deps.setInterval(() => {
79
+ this.poll().catch((err) => {
80
+ this.log.error({
81
+ action: "poll.unhandled",
82
+ message: "unexpected error in poll loop",
83
+ error: err instanceof Error ? err : new Error(String(err))
84
+ });
85
+ });
86
+ }, this.props.interval * 1e3);
87
+ }
88
+ stop() {
89
+ this.log.info({
90
+ action: "stop",
91
+ message: "stopping poller"
92
+ });
93
+ this.stopped = true;
94
+ if (this.timer !== null) {
95
+ this.props.deps.clearInterval(this.timer);
96
+ this.timer = null;
97
+ }
98
+ }
99
+ async poll() {
100
+ const params = new URLSearchParams({ all: "false" });
101
+ if (this.since) params.set("since", this.since);
102
+ const url = `https://api.github.com/notifications?${params}`;
103
+ this.log.debug({
104
+ action: "http.request",
105
+ message: `GET ${url}`
106
+ });
107
+ const response = await this.safeFetch(url);
108
+ if (response instanceof Error) return;
109
+ this.log.debug({
110
+ action: "http.response",
111
+ message: `GET ${response.status}`,
112
+ detail: {
113
+ status: response.status,
114
+ url
115
+ }
116
+ });
117
+ if (!response.ok) {
118
+ this.consecutiveErrors++;
119
+ this.log.error({
120
+ action: "http.error",
121
+ message: `HTTP ${response.status} (consecutive=${this.consecutiveErrors})`
122
+ });
123
+ if (this.consecutiveErrors >= 3) this.props.onDisconnected(`HTTP ${response.status}`);
124
+ return;
125
+ }
126
+ this.consecutiveErrors = 0;
127
+ const body = await response.json();
128
+ if (!Array.isArray(body)) {
129
+ this.log.warn({
130
+ action: "http.body",
131
+ message: "response body is not an array, dropping",
132
+ detail: { bodyType: typeof body }
133
+ });
134
+ return;
135
+ }
136
+ this.processNotifications(body);
137
+ }
138
+ processNotifications(raw) {
139
+ let dropped = 0;
140
+ const notifications = raw.flatMap((item) => {
141
+ const parsed = FlumeGitHubNotificationSchema.safeParse(item);
142
+ if (!parsed.success) {
143
+ dropped++;
144
+ this.log.warn({
145
+ action: "parse.skip",
146
+ message: "notification did not match schema",
147
+ detail: { issues: parsed.error.issues.map((i) => ({
148
+ path: i.path,
149
+ message: i.message
150
+ })) }
151
+ });
152
+ return [];
153
+ }
154
+ return [parsed.data];
155
+ });
156
+ if (dropped > 0) this.log.warn({
157
+ action: "parse.summary",
158
+ message: `${dropped}/${raw.length} notifications dropped by schema`
159
+ });
160
+ if (!this.bootstrapped) {
161
+ this.bootstrapped = true;
162
+ for (const notification of notifications) this.cache.add(notification.id, notification.updated_at);
163
+ this.since = new Date(this.props.deps.now()).toISOString();
164
+ this.log.info({
165
+ action: "bootstrap",
166
+ message: `seeded ${notifications.length} existing notifications`
167
+ });
168
+ this.props.onConnected();
169
+ return;
170
+ }
171
+ const fresh = [];
172
+ for (const notification of notifications) {
173
+ if (this.cache.has(notification.id, notification.updated_at)) continue;
174
+ this.cache.add(notification.id, notification.updated_at);
175
+ fresh.push(notification);
176
+ }
177
+ this.cache.trim();
178
+ this.since = new Date(this.props.deps.now()).toISOString();
179
+ if (fresh.length > 0) {
180
+ this.log.info({
181
+ action: "poll.fresh",
182
+ message: `${fresh.length} new notifications`
183
+ });
184
+ this.props.onNotifications(fresh);
185
+ } else this.log.debug({
186
+ action: "poll.idle",
187
+ message: "0 new notifications"
188
+ });
189
+ }
190
+ async safeFetch(url) {
191
+ const result = await safeFetch({
192
+ fetch: this.props.deps.fetch,
193
+ url,
194
+ init: { headers: {
195
+ Authorization: `Bearer ${this.props.token}`,
196
+ Accept: "application/vnd.github+json",
197
+ "X-GitHub-Api-Version": "2022-11-28"
198
+ } },
199
+ log: this.log
200
+ });
201
+ if (result instanceof Error) {
202
+ this.consecutiveErrors++;
203
+ this.log.warn({
204
+ action: "http.error",
205
+ message: `consecutive=${this.consecutiveErrors}`
206
+ });
207
+ if (this.consecutiveErrors >= 3) this.props.onDisconnected("network error");
208
+ }
209
+ return result;
210
+ }
211
+ };
212
+ //#endregion
213
+ //#region lib/github/github-source.ts
214
+ var FlumeGitHubSource = class {
215
+ options;
216
+ name = "github";
217
+ poller = null;
218
+ currentStatus = "disconnected";
219
+ log;
220
+ deps;
221
+ queue = new FlumeSerialQueue();
222
+ constructor(options) {
223
+ this.options = options;
224
+ this.deps = options.deps ?? createFlumeDefaultDeps();
225
+ this.log = new FlumeLogger({
226
+ source: "github",
227
+ handler: options.onLog,
228
+ deps: this.deps
229
+ });
230
+ }
231
+ async start(handler) {
232
+ if (this.options.signal?.aborted) return /* @__PURE__ */ new Error("GitHub source: signal already aborted");
233
+ this.options.signal?.addEventListener("abort", () => this.stop(), { once: true });
234
+ this.log.info({
235
+ action: "start",
236
+ message: "starting GitHub source"
237
+ });
238
+ this.setStatus("connecting");
239
+ this.poller = new FlumeGitHubPoller({
240
+ token: this.options.token,
241
+ interval: this.options.pollInterval ?? 60,
242
+ onLog: this.options.onLog,
243
+ deps: this.deps,
244
+ onNotifications: (notifications) => this.handleNotifications(handler, notifications),
245
+ onConnected: () => this.setStatus("connected"),
246
+ onDisconnected: (detail) => this.setStatus("disconnected", detail)
247
+ });
248
+ try {
249
+ await this.poller.start();
250
+ } catch (error) {
251
+ const err = error instanceof Error ? error : new Error(String(error));
252
+ this.log.error({
253
+ action: "start.failed",
254
+ message: err.message,
255
+ error: err
256
+ });
257
+ this.setStatus("disconnected");
258
+ return err;
259
+ }
260
+ }
261
+ async stop() {
262
+ this.log.info({
263
+ action: "stop",
264
+ message: "stopping GitHub source"
265
+ });
266
+ this.poller?.stop();
267
+ this.poller = null;
268
+ await this.queue.drain();
269
+ this.setStatus("disconnected");
270
+ }
271
+ status() {
272
+ return this.currentStatus;
273
+ }
274
+ handleNotifications(handler, notifications) {
275
+ for (const notification of notifications) {
276
+ const event = {
277
+ source: "github",
278
+ type: "notification",
279
+ data: notification,
280
+ meta: extractGitHubMeta(notification),
281
+ receivedAt: this.deps.now()
282
+ };
283
+ this.queue.add(async () => {
284
+ try {
285
+ await handler(event);
286
+ } catch (err) {
287
+ this.log.error({
288
+ action: "handler.error",
289
+ message: "user handler threw",
290
+ error: err instanceof Error ? err : new Error(String(err))
291
+ });
292
+ }
293
+ });
294
+ }
295
+ }
296
+ setStatus(next, detail) {
297
+ if (this.currentStatus === next) return;
298
+ this.log.info({
299
+ action: "status",
300
+ message: `${this.currentStatus} → ${next}${detail ? ` (${detail})` : ""}`
301
+ });
302
+ this.currentStatus = next;
303
+ this.options.onStatus?.(next, detail);
304
+ }
305
+ };
306
+ //#endregion
307
+ export { FlumeGitHubNotificationSchema, FlumeGitHubPoller, FlumeGitHubSeenCache, FlumeGitHubSource, extractGitHubMeta };
@@ -0,0 +1,12 @@
1
+ //#region lib/errors/http-error.ts
2
+ var FlumeHttpError = class extends Error {
3
+ status;
4
+ constructor(props) {
5
+ super(props.message);
6
+ this.name = "FlumeHttpError";
7
+ this.status = props.status;
8
+ Object.freeze(this);
9
+ }
10
+ };
11
+ //#endregion
12
+ export { FlumeHttpError as t };
@@ -0,0 +1,11 @@
1
+ //#region lib/errors/http-error.d.ts
2
+ type Props = {
3
+ message: string;
4
+ status: number;
5
+ };
6
+ declare class FlumeHttpError extends Error {
7
+ readonly status: number;
8
+ constructor(props: Props);
9
+ }
10
+ //#endregion
11
+ export { FlumeHttpError as t };
package/dist/index.d.ts CHANGED
@@ -1,40 +1,20 @@
1
- import { C as FlumeGitHubNotificationSchema, S as FlumeGatewayMessageSchema, T as FlumeSlackEnvelopeSchema, _ as FlumeSourceName, a as FlumeGitHubSourceOptions, b as FlumeStatusHandler, c as FlumeLogHandler, d as FlumeReconnectConfig, f as FlumeReconnectOptions, g as FlumeSlackSourceOptions, h as FlumeSlackEnvelope, i as FlumeGitHubNotification, l as FlumeLogInput, m as FlumeSlackConnectionResponse, n as FlumeEvent, o as FlumeHandler, p as FlumeRuntimeDeps, r as FlumeGatewayMessage, s as FlumeLog, t as FlumeDiscordSourceOptions, u as FlumeLogLevel, v as FlumeSourceOptions, w as FlumeSlackConnectionResponseSchema, x as FlumeTimerHandle, y as FlumeStatus } from "./types-BVQSU336.js";
2
- import { FlumeDiscordSource } from "./discord.js";
3
- import { FlumeGitHubSource } from "./github.js";
4
- import { FlumeSlackSource } from "./slack.js";
1
+ import { C as FlumeTimerHandle, S as FlumeStatusHandler, _ as FlumeSource, a as FlumeGitHubSourceOptions, b as FlumeSourceStatus, c as FlumeLogHandler, d as FlumeReconnectConfig, f as FlumeReconnectOptions, g as FlumeSlackSourceOptions, h as FlumeSlackEnvelope, i as FlumeGitHubNotification, l as FlumeLogInput, m as FlumeSlackConnectionResponse, n as FlumeEvent, o as FlumeHandler, p as FlumeRuntimeDeps, r as FlumeGatewayMessage, s as FlumeLog, t as FlumeDiscordSourceOptions, u as FlumeLogLevel, v as FlumeSourceName, x as FlumeStatus, y as FlumeSourceOptions } from "./types-tnOPBc1p.js";
2
+ import { t as FlumeConnectionError } from "./connection-error-BOk97djj.js";
3
+ import { t as FlumeParseError } from "./parse-error-BAiCLRmk.js";
4
+ import { t as FlumeHttpError } from "./http-error-K-Ym4lfK.js";
5
5
 
6
6
  //#region lib/deps.d.ts
7
7
  declare function createFlumeDefaultDeps(): FlumeRuntimeDeps;
8
8
  //#endregion
9
- //#region lib/errors/connection-error.d.ts
10
- declare class FlumeConnectionError extends Error {
11
- constructor(message: string);
12
- }
13
- //#endregion
14
- //#region lib/errors/http-error.d.ts
15
- type Props$10 = {
16
- message: string;
17
- status: number;
18
- };
19
- declare class FlumeHttpError extends Error {
20
- readonly status: number;
21
- constructor(props: Props$10);
22
- }
23
- //#endregion
24
- //#region lib/errors/parse-error.d.ts
25
- declare class FlumeParseError extends Error {
26
- constructor(message: string);
27
- }
28
- //#endregion
29
9
  //#region lib/logger.d.ts
30
- type Props$9 = {
10
+ type Props$5 = {
31
11
  source: string;
32
12
  handler?: FlumeLogHandler;
33
13
  deps: Pick<FlumeRuntimeDeps, "now">;
34
14
  };
35
15
  declare class FlumeLogger {
36
16
  private readonly props;
37
- constructor(props: Props$9);
17
+ constructor(props: Props$5);
38
18
  debug(entry: FlumeLogInput): void;
39
19
  info(entry: FlumeLogInput): void;
40
20
  warn(entry: FlumeLogInput): void;
@@ -46,7 +26,7 @@ declare class FlumeLogger {
46
26
  declare function resolveFlumeReconnectConfig(input: boolean | FlumeReconnectOptions | undefined): FlumeReconnectConfig | null;
47
27
  //#endregion
48
28
  //#region lib/reconnector.d.ts
49
- type Props$8 = {
29
+ type Props$4 = {
50
30
  maxAttempts: number;
51
31
  baseDelay: number;
52
32
  maxDelay: number;
@@ -57,222 +37,70 @@ declare class FlumeReconnector {
57
37
  attempt: number;
58
38
  aborted: boolean;
59
39
  private timer;
60
- constructor(props: Props$8);
40
+ constructor(props: Props$4);
61
41
  schedule(fn: () => void): number;
62
42
  reset(): void;
63
43
  cancel(): void;
64
44
  private nextDelay;
65
45
  }
66
46
  //#endregion
67
- //#region lib/flume.d.ts
68
- type Props$7 = {
69
- onLog?: FlumeLogHandler;
70
- onStatus?: FlumeStatusHandler;
71
- reconnect?: boolean | FlumeReconnectOptions;
72
- signal?: AbortSignal;
73
- deps?: Partial<FlumeRuntimeDeps>;
47
+ //#region lib/schedule-reconnect.d.ts
48
+ type Props$3 = {
49
+ reconnector: FlumeReconnector | null;
50
+ log: FlumeLogger;
51
+ setStatus: (status: FlumeStatus) => void;
52
+ retry: () => void;
74
53
  };
75
54
  /**
76
- * 共有設定を持つ DI コンテナ。各 Source に共通の deps / logging / reconnect を注入する
55
+ * 接続が落ちた際の共通再接続スケジューラ。reconnector の状態を見て次回試行を予約し、
56
+ * 試行回数が尽きていれば disconnected に落とす
77
57
  */
78
- declare class Flume {
79
- private readonly props;
80
- private readonly resolvedDeps;
81
- constructor(props: Props$7);
82
- discord(options: {
83
- token: string;
84
- intents?: number;
85
- }): FlumeDiscordSource;
86
- slack(options: {
87
- appToken: string;
88
- botToken?: string;
89
- }): FlumeSlackSource;
90
- github(options: {
91
- token: string;
92
- pollInterval?: number;
93
- }): FlumeGitHubSource;
94
- }
58
+ declare function scheduleFlumeReconnect(props: Props$3): void;
95
59
  //#endregion
96
- //#region lib/discord/discord-gateway-intents.d.ts
97
- declare const FlumeDiscordGatewayIntents: {
98
- readonly Guilds: number;
99
- readonly GuildMembers: number;
100
- readonly GuildModeration: number;
101
- readonly GuildExpressions: number;
102
- readonly GuildIntegrations: number;
103
- readonly GuildWebhooks: number;
104
- readonly GuildInvites: number;
105
- readonly GuildVoiceStates: number;
106
- readonly GuildPresences: number;
107
- readonly GuildMessages: number;
108
- readonly GuildMessageReactions: number;
109
- readonly GuildMessageTyping: number;
110
- readonly DirectMessages: number;
111
- readonly DirectMessageReactions: number;
112
- readonly DirectMessageTyping: number;
113
- readonly MessageContent: number;
114
- readonly GuildScheduledEvents: number;
115
- readonly AutoModerationConfiguration: number;
116
- readonly AutoModerationExecution: number;
117
- readonly GuildMessagePolls: number;
118
- readonly DirectMessagePolls: number;
119
- };
120
- //#endregion
121
- //#region lib/discord/discord-gateway-session.d.ts
122
- type Props$6 = {
123
- sessionId: string | null;
124
- resumeUrl: string | null;
125
- seq: number | null;
126
- };
127
- declare class FlumeDiscordGatewaySession {
128
- readonly sessionId: string | null;
129
- readonly resumeUrl: string | null;
130
- readonly seq: number | null;
131
- constructor(props: Props$6);
132
- static empty(): FlumeDiscordGatewaySession;
133
- canResume(): boolean;
134
- withSeq(seq: number): FlumeDiscordGatewaySession;
135
- withReady(sessionId: string, resumeUrl: string): FlumeDiscordGatewaySession;
136
- withReset(): FlumeDiscordGatewaySession;
137
- }
138
- //#endregion
139
- //#region lib/discord/discord-gateway.d.ts
140
- type Deps$2 = Pick<FlumeRuntimeDeps, "WebSocket" | "setInterval" | "clearInterval" | "setTimeout" | "random" | "now">;
141
- type Props$5 = {
142
- token: string;
143
- intents: number;
144
- onDispatch: (event: string, data: Record<string, unknown>) => void;
145
- onStatus: (status: "connected" | "disconnected") => void;
146
- onLog?: FlumeLogHandler;
147
- deps: Deps$2;
148
- };
149
- declare class FlumeDiscordGateway {
150
- private readonly props;
151
- private readonly log;
152
- private ws;
153
- private heartbeat;
154
- session: FlumeDiscordGatewaySession;
155
- stopped: boolean;
156
- private pendingResolve;
157
- private pendingResolved;
158
- constructor(props: Props$5);
159
- connect(url?: string): Promise<FlumeConnectionError | null>;
160
- disconnect(): void;
161
- isConnected(): boolean;
162
- private completeConnect;
163
- private onMessage;
164
- private onHello;
165
- private onHeartbeatAck;
166
- private onHeartbeatRequest;
167
- private onReconnectRequest;
168
- private onInvalidSession;
169
- private onDispatch;
170
- private onClose;
171
- private onError;
172
- private send;
173
- private sendIdentify;
174
- private sendResume;
175
- }
176
- //#endregion
177
- //#region lib/discord/discord-heartbeat.d.ts
178
- type Props$4 = {
179
- onSend: () => void;
180
- onZombie: () => void;
181
- deps: Pick<FlumeRuntimeDeps, "setInterval" | "clearInterval">;
182
- };
183
- declare class FlumeDiscordHeartbeat {
184
- private readonly props;
185
- private timer;
186
- private ackReceived;
187
- constructor(props: Props$4);
188
- start(intervalMs: number): void;
189
- stop(): void;
190
- ack(): void;
191
- isRunning(): boolean;
192
- }
193
- //#endregion
194
- //#region lib/discord/parse-discord-gateway-message.d.ts
195
- declare function parseDiscordGatewayMessage(raw: string): FlumeGatewayMessage | FlumeParseError;
196
- //#endregion
197
- //#region lib/slack/slack-socket-mode.d.ts
198
- type Deps$1 = Pick<FlumeRuntimeDeps, "WebSocket" | "fetch" | "now">;
199
- type Props$3 = {
200
- appToken: string;
201
- onMessage: (envelope: FlumeSlackEnvelope) => void;
202
- onConnected: () => void;
203
- onDisconnected: () => void;
204
- onLog?: FlumeLogHandler;
205
- deps: Deps$1;
60
+ //#region lib/flume-stopped.d.ts
61
+ type Props$2 = {
62
+ finalStatuses: ReadonlyArray<FlumeSourceStatus>;
206
63
  };
207
- declare class FlumeSlackSocketMode {
64
+ /**
65
+ * 停止済みの終端状態。最終ステータスのスナップショットのみ観測できる
66
+ */
67
+ declare class FlumeStopped {
208
68
  private readonly props;
209
- private readonly log;
210
- private ws;
211
- stopped: boolean;
212
- private pendingResolve;
213
- private pendingResolved;
214
- constructor(props: Props$3);
215
- connect(): Promise<FlumeConnectionError | FlumeHttpError | null>;
216
- disconnect(): void;
217
- isConnected(): boolean;
218
- private openSocket;
219
- private completeConnect;
220
- private onMessage;
221
- private onClose;
222
- private onError;
69
+ constructor(props: Props$2);
70
+ statuses(): ReadonlyArray<FlumeSourceStatus>;
223
71
  }
224
72
  //#endregion
225
- //#region lib/slack/obtain-slack-url.d.ts
226
- type Props$2 = {
227
- appToken: string;
228
- onLog?: FlumeLogHandler;
229
- deps: Pick<FlumeRuntimeDeps, "fetch" | "now">;
230
- };
231
- declare function obtainSlackUrl(props: Props$2): Promise<string | FlumeHttpError>;
232
- //#endregion
233
- //#region lib/github/github-poller.d.ts
234
- type Deps = Pick<FlumeRuntimeDeps, "fetch" | "setInterval" | "clearInterval" | "now">;
73
+ //#region lib/flume-running.d.ts
235
74
  type Props$1 = {
236
- token: string;
237
- interval: number;
238
- onNotifications: (notifications: FlumeGitHubNotification[]) => void;
239
- onConnected: () => void;
240
- onDisconnected: (detail: string) => void;
241
- onLog?: FlumeLogHandler;
242
- deps: Deps;
75
+ sources: ReadonlyArray<FlumeSource>;
76
+ signal?: AbortSignal;
243
77
  };
244
- declare class FlumeGitHubPoller {
78
+ /**
79
+ * 稼働中の Flume。stop() で FlumeStopped へ遷移する。signal が abort されると自動 stop
80
+ */
81
+ declare class FlumeRunning {
245
82
  private readonly props;
246
- private readonly log;
247
- private readonly cache;
248
- private timer;
249
- private since;
250
- private bootstrapped;
251
- stopped: boolean;
252
- private consecutiveErrors;
83
+ private stopPromise;
84
+ private readonly onAbort;
253
85
  constructor(props: Props$1);
254
- start(): Promise<void>;
255
- stop(): void;
256
- private poll;
257
- private processNotifications;
258
- private safeFetch;
86
+ stop(): Promise<FlumeStopped>;
87
+ statuses(): ReadonlyArray<FlumeSourceStatus>;
88
+ private runStop;
259
89
  }
260
90
  //#endregion
261
- //#region lib/github/github-seen-cache.d.ts
91
+ //#region lib/flume.d.ts
262
92
  type Props = {
263
- maxSize: number;
93
+ sources: ReadonlyArray<FlumeSource>;
94
+ signal?: AbortSignal;
264
95
  };
265
- declare class FlumeGitHubSeenCache {
96
+ /**
97
+ * 起動前の Flume。start() で FlumeRunning へ遷移する
98
+ */
99
+ declare class Flume {
266
100
  private readonly props;
267
- private seen;
101
+ private consumed;
268
102
  constructor(props: Props);
269
- has(id: string, updatedAt: string): boolean;
270
- add(id: string, updatedAt: string): void;
271
- trim(): void;
272
- get size(): number;
103
+ start(handler: FlumeHandler): Promise<FlumeRunning | Error>;
273
104
  }
274
105
  //#endregion
275
- //#region lib/index.d.ts
276
- type FlumeSource = FlumeDiscordSource | FlumeSlackSource | FlumeGitHubSource;
277
- //#endregion
278
- export { Flume, FlumeConnectionError, FlumeDiscordGateway, FlumeDiscordGatewayIntents, FlumeDiscordGatewaySession, FlumeDiscordHeartbeat, FlumeDiscordSource, type FlumeDiscordSourceOptions, type FlumeEvent, type FlumeGatewayMessage, FlumeGatewayMessageSchema, type FlumeGitHubNotification, FlumeGitHubNotificationSchema, FlumeGitHubPoller, FlumeGitHubSeenCache, FlumeGitHubSource, type FlumeGitHubSourceOptions, type FlumeHandler, FlumeHttpError, type FlumeLog, type FlumeLogHandler, type FlumeLogInput, type FlumeLogLevel, FlumeLogger, FlumeParseError, type FlumeReconnectConfig, type FlumeReconnectOptions, FlumeReconnector, type FlumeRuntimeDeps, type FlumeSlackConnectionResponse, FlumeSlackConnectionResponseSchema, type FlumeSlackEnvelope, FlumeSlackEnvelopeSchema, FlumeSlackSocketMode, FlumeSlackSource, type FlumeSlackSourceOptions, FlumeSource, type FlumeSourceName, type FlumeSourceOptions, type FlumeStatus, type FlumeStatusHandler, type FlumeTimerHandle, createFlumeDefaultDeps, obtainSlackUrl, parseDiscordGatewayMessage, resolveFlumeReconnectConfig };
106
+ export { Flume, FlumeConnectionError, type FlumeDiscordSourceOptions, type FlumeEvent, type FlumeGatewayMessage, type FlumeGitHubNotification, type FlumeGitHubSourceOptions, type FlumeHandler, FlumeHttpError, type FlumeLog, type FlumeLogHandler, type FlumeLogInput, type FlumeLogLevel, FlumeLogger, FlumeParseError, type FlumeReconnectConfig, type FlumeReconnectOptions, FlumeReconnector, FlumeRunning, type FlumeRuntimeDeps, type FlumeSlackConnectionResponse, type FlumeSlackEnvelope, type FlumeSlackSourceOptions, type FlumeSource, type FlumeSourceName, type FlumeSourceOptions, type FlumeSourceStatus, type FlumeStatus, type FlumeStatusHandler, FlumeStopped, type FlumeTimerHandle, createFlumeDefaultDeps, resolveFlumeReconnectConfig, scheduleFlumeReconnect };