@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/README.md +98 -46
- package/dist/connection-error-BOk97djj.d.ts +6 -0
- package/dist/discord.d.ts +111 -4
- package/dist/discord.js +537 -2
- package/dist/github.d.ts +50 -4
- package/dist/github.js +307 -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 +48 -220
- package/dist/index.js +90 -52
- package/dist/logger-CpGB9WO_.js +49 -0
- package/dist/parse-error-BAiCLRmk.d.ts +6 -0
- package/dist/safe-fetch-30ZzOKHL.js +20 -0
- package/dist/safe-json-parse-WCg_x1JS.js +15 -0
- package/dist/{safe-json-parse-D8t_4Vm_.js → schedule-reconnect-DSxZJG3h.js} +24 -12
- package/dist/serial-queue-ExmlnpzQ.js +16 -0
- package/dist/slack.d.ts +65 -4
- package/dist/slack.js +443 -2
- package/dist/{types-BVQSU336.d.ts → types-tnOPBc1p.d.ts} +32 -16
- 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/dist/slack.js
CHANGED
|
@@ -1,2 +1,443 @@
|
|
|
1
|
-
import { t as
|
|
2
|
-
|
|
1
|
+
import { n as createFlumeDefaultDeps, t as FlumeLogger } from "./logger-CpGB9WO_.js";
|
|
2
|
+
import { a as FlumeConnectionError, i as FlumeParseError, n as FlumeReconnector, r as resolveFlumeReconnectConfig, t as scheduleFlumeReconnect } from "./schedule-reconnect-DSxZJG3h.js";
|
|
3
|
+
import { t as FlumeHttpError } from "./http-error-BtXonO-W.js";
|
|
4
|
+
import { t as FlumeSerialQueue } from "./serial-queue-ExmlnpzQ.js";
|
|
5
|
+
import { n as isRecord, t as safeJsonParse } from "./safe-json-parse-WCg_x1JS.js";
|
|
6
|
+
import { t as safeFetch } from "./safe-fetch-30ZzOKHL.js";
|
|
7
|
+
import { z } from "zod/v4";
|
|
8
|
+
//#region lib/slack/extract-slack-meta.ts
|
|
9
|
+
function extractSlackMeta(envelope) {
|
|
10
|
+
const meta = { event_type: envelope.type };
|
|
11
|
+
const eventPayload = isRecord(envelope.payload.event) ? envelope.payload.event : null;
|
|
12
|
+
if (!eventPayload) return meta;
|
|
13
|
+
if (typeof eventPayload.channel === "string") meta.channel_id = eventPayload.channel;
|
|
14
|
+
if (typeof eventPayload.user === "string") meta.user_id = eventPayload.user;
|
|
15
|
+
if (typeof eventPayload.thread_ts === "string") meta.thread_ts = eventPayload.thread_ts;
|
|
16
|
+
if (typeof eventPayload.type === "string") meta.slack_event_type = eventPayload.type;
|
|
17
|
+
return meta;
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region lib/slack/slack-seen-cache.ts
|
|
21
|
+
/**
|
|
22
|
+
* Slack envelope_id の LRU 風キャッシュ。Slack は ack 失敗時に同じ envelope を再送するため、
|
|
23
|
+
* source レイヤで handler への重複配送を防ぐ
|
|
24
|
+
*/
|
|
25
|
+
var FlumeSlackSeenCache = class {
|
|
26
|
+
props;
|
|
27
|
+
seen = /* @__PURE__ */ new Set();
|
|
28
|
+
constructor(props) {
|
|
29
|
+
this.props = props;
|
|
30
|
+
}
|
|
31
|
+
has(envelopeId) {
|
|
32
|
+
return this.seen.has(envelopeId);
|
|
33
|
+
}
|
|
34
|
+
add(envelopeId) {
|
|
35
|
+
this.seen.add(envelopeId);
|
|
36
|
+
}
|
|
37
|
+
trim() {
|
|
38
|
+
if (this.seen.size <= this.props.maxSize) return;
|
|
39
|
+
const entries = [...this.seen];
|
|
40
|
+
this.seen = new Set(entries.slice(entries.length - this.props.maxSize));
|
|
41
|
+
}
|
|
42
|
+
get size() {
|
|
43
|
+
return this.seen.size;
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region lib/slack/slack-envelope-schema.ts
|
|
48
|
+
const FlumeSlackEnvelopeSchema = z.object({
|
|
49
|
+
envelope_id: z.string(),
|
|
50
|
+
type: z.string(),
|
|
51
|
+
payload: z.record(z.string(), z.unknown()),
|
|
52
|
+
accepts_response_payload: z.boolean().optional(),
|
|
53
|
+
retry_attempt: z.number().optional(),
|
|
54
|
+
retry_reason: z.string().optional()
|
|
55
|
+
});
|
|
56
|
+
//#endregion
|
|
57
|
+
//#region lib/slack/slack-connection-response-schema.ts
|
|
58
|
+
const FlumeSlackConnectionResponseSchema = z.object({
|
|
59
|
+
ok: z.boolean(),
|
|
60
|
+
url: z.string().optional(),
|
|
61
|
+
error: z.string().optional()
|
|
62
|
+
});
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region lib/slack/obtain-slack-url.ts
|
|
65
|
+
async function obtainSlackUrl(props) {
|
|
66
|
+
const log = new FlumeLogger({
|
|
67
|
+
source: "slack.url",
|
|
68
|
+
handler: props.onLog,
|
|
69
|
+
deps: props.deps
|
|
70
|
+
});
|
|
71
|
+
const url = "https://slack.com/api/apps.connections.open";
|
|
72
|
+
log.debug({
|
|
73
|
+
action: "http.request",
|
|
74
|
+
message: `POST ${url}`
|
|
75
|
+
});
|
|
76
|
+
const response = await safeFetch({
|
|
77
|
+
fetch: props.deps.fetch,
|
|
78
|
+
url,
|
|
79
|
+
init: {
|
|
80
|
+
method: "POST",
|
|
81
|
+
headers: { Authorization: `Bearer ${props.appToken}` }
|
|
82
|
+
},
|
|
83
|
+
log
|
|
84
|
+
});
|
|
85
|
+
if (response instanceof Error) return new FlumeHttpError({
|
|
86
|
+
message: response.message,
|
|
87
|
+
status: 0
|
|
88
|
+
});
|
|
89
|
+
log.debug({
|
|
90
|
+
action: "http.response",
|
|
91
|
+
message: `POST ${response.status}`,
|
|
92
|
+
detail: {
|
|
93
|
+
status: response.status,
|
|
94
|
+
url
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
const raw = await response.json();
|
|
98
|
+
const peek = isRecord(raw) ? raw : {};
|
|
99
|
+
log.debug({
|
|
100
|
+
action: "http.body",
|
|
101
|
+
message: "apps.connections.open response",
|
|
102
|
+
detail: {
|
|
103
|
+
ok: peek.ok,
|
|
104
|
+
error: peek.error
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
const parsed = FlumeSlackConnectionResponseSchema.safeParse(raw);
|
|
108
|
+
if (!parsed.success) {
|
|
109
|
+
log.warn({
|
|
110
|
+
action: "parse.fail",
|
|
111
|
+
message: "apps.connections.open: invalid response shape",
|
|
112
|
+
detail: { issues: parsed.error.issues.map((i) => ({
|
|
113
|
+
path: i.path,
|
|
114
|
+
message: i.message
|
|
115
|
+
})) }
|
|
116
|
+
});
|
|
117
|
+
return new FlumeHttpError({
|
|
118
|
+
message: "apps.connections.open: invalid response shape",
|
|
119
|
+
status: response.status
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
if (!parsed.data.ok || !parsed.data.url) {
|
|
123
|
+
log.warn({
|
|
124
|
+
action: "api.fail",
|
|
125
|
+
message: `apps.connections.open failed: ${parsed.data.error ?? "no url"}`
|
|
126
|
+
});
|
|
127
|
+
return new FlumeHttpError({
|
|
128
|
+
message: `apps.connections.open failed: ${parsed.data.error ?? "no url"}`,
|
|
129
|
+
status: response.status
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
log.info({
|
|
133
|
+
action: "url.obtained",
|
|
134
|
+
message: "WSS URL obtained"
|
|
135
|
+
});
|
|
136
|
+
return parsed.data.url;
|
|
137
|
+
}
|
|
138
|
+
//#endregion
|
|
139
|
+
//#region lib/slack/slack-socket-mode.ts
|
|
140
|
+
function framePreview(raw) {
|
|
141
|
+
return raw.length > 200 ? `${raw.slice(0, 200)}... (${raw.length} bytes)` : raw;
|
|
142
|
+
}
|
|
143
|
+
var FlumeSlackSocketMode = class {
|
|
144
|
+
props;
|
|
145
|
+
log;
|
|
146
|
+
ws = null;
|
|
147
|
+
stopped = false;
|
|
148
|
+
pendingResolve = null;
|
|
149
|
+
pendingResolved = false;
|
|
150
|
+
constructor(props) {
|
|
151
|
+
this.props = props;
|
|
152
|
+
this.log = new FlumeLogger({
|
|
153
|
+
source: "slack.socket-mode",
|
|
154
|
+
handler: props.onLog,
|
|
155
|
+
deps: props.deps
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
async connect() {
|
|
159
|
+
this.log.info({
|
|
160
|
+
action: "connect.start",
|
|
161
|
+
message: "opening WebSocket connection"
|
|
162
|
+
});
|
|
163
|
+
const url = await obtainSlackUrl({
|
|
164
|
+
appToken: this.props.appToken,
|
|
165
|
+
onLog: this.props.onLog,
|
|
166
|
+
deps: this.props.deps
|
|
167
|
+
});
|
|
168
|
+
if (url instanceof FlumeHttpError) {
|
|
169
|
+
this.log.error({
|
|
170
|
+
action: "http.error",
|
|
171
|
+
message: url.message,
|
|
172
|
+
error: url
|
|
173
|
+
});
|
|
174
|
+
return url;
|
|
175
|
+
}
|
|
176
|
+
this.log.info({
|
|
177
|
+
action: "url.obtained",
|
|
178
|
+
message: "WebSocket URL obtained"
|
|
179
|
+
});
|
|
180
|
+
return this.openSocket(url);
|
|
181
|
+
}
|
|
182
|
+
disconnect() {
|
|
183
|
+
this.log.info({
|
|
184
|
+
action: "disconnect",
|
|
185
|
+
message: "stopping socket mode"
|
|
186
|
+
});
|
|
187
|
+
this.stopped = true;
|
|
188
|
+
if (this.ws) {
|
|
189
|
+
this.ws.close();
|
|
190
|
+
this.ws = null;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
isConnected() {
|
|
194
|
+
return this.ws !== null && this.ws.readyState === WebSocket.OPEN;
|
|
195
|
+
}
|
|
196
|
+
openSocket(url) {
|
|
197
|
+
this.pendingResolved = false;
|
|
198
|
+
return new Promise((resolve) => {
|
|
199
|
+
this.pendingResolve = resolve;
|
|
200
|
+
const socket = new this.props.deps.WebSocket(url);
|
|
201
|
+
this.ws = socket;
|
|
202
|
+
socket.addEventListener("message", (ev) => this.onMessage(String(ev.data), socket));
|
|
203
|
+
socket.addEventListener("close", (ev) => this.onClose(ev));
|
|
204
|
+
socket.addEventListener("error", () => this.onError());
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
completeConnect(error) {
|
|
208
|
+
if (this.pendingResolved || !this.pendingResolve) return;
|
|
209
|
+
this.pendingResolved = true;
|
|
210
|
+
this.pendingResolve(error);
|
|
211
|
+
}
|
|
212
|
+
onMessage(raw, socket) {
|
|
213
|
+
this.log.debug({
|
|
214
|
+
action: "ws.recv",
|
|
215
|
+
message: framePreview(raw)
|
|
216
|
+
});
|
|
217
|
+
const json = safeJsonParse(raw);
|
|
218
|
+
if (!isRecord(json)) {
|
|
219
|
+
this.log.error({
|
|
220
|
+
action: "ws.parse-error",
|
|
221
|
+
message: "invalid JSON",
|
|
222
|
+
error: new FlumeParseError(raw.slice(0, 200))
|
|
223
|
+
});
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (json.type === "hello") {
|
|
227
|
+
this.log.info({
|
|
228
|
+
action: "ws.hello",
|
|
229
|
+
message: "connection ready"
|
|
230
|
+
});
|
|
231
|
+
this.props.onConnected();
|
|
232
|
+
this.completeConnect(null);
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (json.type === "disconnect") {
|
|
236
|
+
const reason = typeof json.reason === "string" ? json.reason : "unknown";
|
|
237
|
+
this.log.info({
|
|
238
|
+
action: "ws.disconnect-requested",
|
|
239
|
+
message: `reason=${reason}`,
|
|
240
|
+
detail: { reason }
|
|
241
|
+
});
|
|
242
|
+
socket.close();
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
if (typeof json.envelope_id === "string") {
|
|
246
|
+
this.log.debug({
|
|
247
|
+
action: "ws.ack",
|
|
248
|
+
message: `envelope_id=${json.envelope_id}`
|
|
249
|
+
});
|
|
250
|
+
const ack = JSON.stringify({ envelope_id: json.envelope_id });
|
|
251
|
+
socket.send(ack);
|
|
252
|
+
this.log.debug({
|
|
253
|
+
action: "ws.send",
|
|
254
|
+
message: framePreview(ack)
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
const envelope = FlumeSlackEnvelopeSchema.safeParse(json);
|
|
258
|
+
if (envelope.success) {
|
|
259
|
+
this.log.debug({
|
|
260
|
+
action: "envelope.recv",
|
|
261
|
+
message: `type=${envelope.data.type} envelope_id=${envelope.data.envelope_id}`,
|
|
262
|
+
detail: {
|
|
263
|
+
type: envelope.data.type,
|
|
264
|
+
envelopeId: envelope.data.envelope_id
|
|
265
|
+
}
|
|
266
|
+
});
|
|
267
|
+
this.props.onMessage(envelope.data);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
this.log.warn({
|
|
271
|
+
action: "envelope.parse-fail",
|
|
272
|
+
message: "unrecognised envelope shape, dropping",
|
|
273
|
+
detail: {
|
|
274
|
+
type: typeof json.type === "string" ? json.type : "unknown",
|
|
275
|
+
issues: envelope.error.issues.map((i) => ({
|
|
276
|
+
path: i.path,
|
|
277
|
+
message: i.message
|
|
278
|
+
}))
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
onClose(ev) {
|
|
283
|
+
this.log.info({
|
|
284
|
+
action: "ws.close",
|
|
285
|
+
message: `code=${ev.code} reason=${ev.reason || "none"}`
|
|
286
|
+
});
|
|
287
|
+
this.ws = null;
|
|
288
|
+
this.props.onDisconnected();
|
|
289
|
+
this.completeConnect(new FlumeConnectionError(`WebSocket closed before hello (code=${ev.code})`));
|
|
290
|
+
}
|
|
291
|
+
onError() {
|
|
292
|
+
this.log.error({
|
|
293
|
+
action: "ws.error",
|
|
294
|
+
message: "WebSocket error event"
|
|
295
|
+
});
|
|
296
|
+
this.completeConnect(new FlumeConnectionError("WebSocket connection error"));
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
//#endregion
|
|
300
|
+
//#region lib/slack/slack-source.ts
|
|
301
|
+
const SEEN_CACHE_MAX = 1024;
|
|
302
|
+
var FlumeSlackSource = class {
|
|
303
|
+
options;
|
|
304
|
+
name = "slack";
|
|
305
|
+
socket = null;
|
|
306
|
+
reconnector = null;
|
|
307
|
+
handler = null;
|
|
308
|
+
currentStatus = "disconnected";
|
|
309
|
+
log;
|
|
310
|
+
deps;
|
|
311
|
+
queue = new FlumeSerialQueue();
|
|
312
|
+
seen = new FlumeSlackSeenCache({ maxSize: SEEN_CACHE_MAX });
|
|
313
|
+
constructor(options) {
|
|
314
|
+
this.options = options;
|
|
315
|
+
this.deps = options.deps ?? createFlumeDefaultDeps();
|
|
316
|
+
this.log = new FlumeLogger({
|
|
317
|
+
source: "slack",
|
|
318
|
+
handler: options.onLog,
|
|
319
|
+
deps: this.deps
|
|
320
|
+
});
|
|
321
|
+
const rc = resolveFlumeReconnectConfig(options.reconnect);
|
|
322
|
+
if (rc) this.reconnector = new FlumeReconnector({
|
|
323
|
+
...rc,
|
|
324
|
+
deps: this.deps
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
async start(handler) {
|
|
328
|
+
if (this.options.signal?.aborted) return /* @__PURE__ */ new Error("Slack source: signal already aborted");
|
|
329
|
+
this.options.signal?.addEventListener("abort", () => this.stop(), { once: true });
|
|
330
|
+
this.handler = handler;
|
|
331
|
+
this.log.info({
|
|
332
|
+
action: "start",
|
|
333
|
+
message: "starting Slack source"
|
|
334
|
+
});
|
|
335
|
+
return this.connectInternal();
|
|
336
|
+
}
|
|
337
|
+
async stop() {
|
|
338
|
+
this.log.info({
|
|
339
|
+
action: "stop",
|
|
340
|
+
message: "stopping Slack source"
|
|
341
|
+
});
|
|
342
|
+
if (this.reconnector && !this.reconnector.aborted) this.log.debug({
|
|
343
|
+
action: "reconnect.cancel",
|
|
344
|
+
message: "aborting reconnector"
|
|
345
|
+
});
|
|
346
|
+
this.reconnector?.cancel();
|
|
347
|
+
this.socket?.disconnect();
|
|
348
|
+
this.socket = null;
|
|
349
|
+
this.handler = null;
|
|
350
|
+
await this.queue.drain();
|
|
351
|
+
this.setStatus("disconnected");
|
|
352
|
+
}
|
|
353
|
+
status() {
|
|
354
|
+
return this.currentStatus;
|
|
355
|
+
}
|
|
356
|
+
async connectInternal() {
|
|
357
|
+
this.setStatus("connecting");
|
|
358
|
+
this.socket = new FlumeSlackSocketMode({
|
|
359
|
+
appToken: this.options.appToken,
|
|
360
|
+
onLog: this.options.onLog,
|
|
361
|
+
deps: this.deps,
|
|
362
|
+
onMessage: (envelope) => this.handleMessage(envelope),
|
|
363
|
+
onConnected: () => {
|
|
364
|
+
if (this.reconnector && this.reconnector.attempt > 0) this.log.info({
|
|
365
|
+
action: "reconnect.reset",
|
|
366
|
+
message: `cleared ${this.reconnector.attempt} attempts`
|
|
367
|
+
});
|
|
368
|
+
this.reconnector?.reset();
|
|
369
|
+
this.setStatus("connected");
|
|
370
|
+
},
|
|
371
|
+
onDisconnected: () => {
|
|
372
|
+
if (!this.socket?.stopped) this.scheduleReconnect();
|
|
373
|
+
}
|
|
374
|
+
});
|
|
375
|
+
const error = await this.socket.connect();
|
|
376
|
+
if (error instanceof Error) {
|
|
377
|
+
this.log.error({
|
|
378
|
+
action: "connect.failed",
|
|
379
|
+
message: error.message,
|
|
380
|
+
error
|
|
381
|
+
});
|
|
382
|
+
if (!this.reconnector || this.reconnector.aborted) {
|
|
383
|
+
this.setStatus("disconnected");
|
|
384
|
+
return error;
|
|
385
|
+
}
|
|
386
|
+
this.scheduleReconnect();
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
handleMessage(envelope) {
|
|
390
|
+
if (this.seen.has(envelope.envelope_id)) {
|
|
391
|
+
this.log.debug({
|
|
392
|
+
action: "dedup.skip",
|
|
393
|
+
message: `duplicate envelope_id=${envelope.envelope_id}`,
|
|
394
|
+
detail: {
|
|
395
|
+
envelope_id: envelope.envelope_id,
|
|
396
|
+
retry_attempt: envelope.retry_attempt
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
this.seen.add(envelope.envelope_id);
|
|
402
|
+
this.seen.trim();
|
|
403
|
+
const event = {
|
|
404
|
+
source: "slack",
|
|
405
|
+
type: envelope.type,
|
|
406
|
+
data: envelope.payload,
|
|
407
|
+
meta: extractSlackMeta(envelope),
|
|
408
|
+
receivedAt: this.deps.now()
|
|
409
|
+
};
|
|
410
|
+
this.queue.add(async () => {
|
|
411
|
+
try {
|
|
412
|
+
await this.handler?.(event);
|
|
413
|
+
} catch (err) {
|
|
414
|
+
this.log.error({
|
|
415
|
+
action: "handler.error",
|
|
416
|
+
message: "user handler threw",
|
|
417
|
+
error: err instanceof Error ? err : new Error(String(err))
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
scheduleReconnect() {
|
|
423
|
+
scheduleFlumeReconnect({
|
|
424
|
+
reconnector: this.reconnector,
|
|
425
|
+
log: this.log,
|
|
426
|
+
setStatus: (status) => this.setStatus(status),
|
|
427
|
+
retry: () => {
|
|
428
|
+
this.connectInternal();
|
|
429
|
+
}
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
setStatus(next) {
|
|
433
|
+
if (this.currentStatus === next) return;
|
|
434
|
+
this.log.info({
|
|
435
|
+
action: "status",
|
|
436
|
+
message: `${this.currentStatus} → ${next}`
|
|
437
|
+
});
|
|
438
|
+
this.currentStatus = next;
|
|
439
|
+
this.options.onStatus?.(next);
|
|
440
|
+
}
|
|
441
|
+
};
|
|
442
|
+
//#endregion
|
|
443
|
+
export { FlumeSlackConnectionResponseSchema, FlumeSlackEnvelopeSchema, FlumeSlackSeenCache, FlumeSlackSocketMode, FlumeSlackSource, extractSlackMeta, obtainSlackUrl };
|
|
@@ -1,25 +1,14 @@
|
|
|
1
1
|
import { z } from "zod/v4";
|
|
2
2
|
|
|
3
|
-
//#region lib/schema.d.ts
|
|
3
|
+
//#region lib/discord/discord-gateway-message-schema.d.ts
|
|
4
4
|
declare const FlumeGatewayMessageSchema: z.ZodObject<{
|
|
5
5
|
op: z.ZodNumber;
|
|
6
6
|
d: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
7
7
|
s: z.ZodNullable<z.ZodNumber>;
|
|
8
8
|
t: z.ZodNullable<z.ZodString>;
|
|
9
9
|
}, z.core.$strip>;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
type: z.ZodString;
|
|
13
|
-
payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
14
|
-
accepts_response_payload: z.ZodOptional<z.ZodBoolean>;
|
|
15
|
-
retry_attempt: z.ZodOptional<z.ZodNumber>;
|
|
16
|
-
retry_reason: z.ZodOptional<z.ZodString>;
|
|
17
|
-
}, z.core.$strip>;
|
|
18
|
-
declare const FlumeSlackConnectionResponseSchema: z.ZodObject<{
|
|
19
|
-
ok: z.ZodBoolean;
|
|
20
|
-
url: z.ZodOptional<z.ZodString>;
|
|
21
|
-
error: z.ZodOptional<z.ZodString>;
|
|
22
|
-
}, z.core.$strip>;
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region lib/github/github-notification-schema.d.ts
|
|
23
12
|
declare const FlumeGitHubNotificationSchema: z.ZodObject<{
|
|
24
13
|
id: z.ZodString;
|
|
25
14
|
reason: z.ZodString;
|
|
@@ -35,6 +24,23 @@ declare const FlumeGitHubNotificationSchema: z.ZodObject<{
|
|
|
35
24
|
}, z.core.$strip>;
|
|
36
25
|
}, z.core.$strip>;
|
|
37
26
|
//#endregion
|
|
27
|
+
//#region lib/slack/slack-connection-response-schema.d.ts
|
|
28
|
+
declare const FlumeSlackConnectionResponseSchema: z.ZodObject<{
|
|
29
|
+
ok: z.ZodBoolean;
|
|
30
|
+
url: z.ZodOptional<z.ZodString>;
|
|
31
|
+
error: z.ZodOptional<z.ZodString>;
|
|
32
|
+
}, z.core.$strip>;
|
|
33
|
+
//#endregion
|
|
34
|
+
//#region lib/slack/slack-envelope-schema.d.ts
|
|
35
|
+
declare const FlumeSlackEnvelopeSchema: z.ZodObject<{
|
|
36
|
+
envelope_id: z.ZodString;
|
|
37
|
+
type: z.ZodString;
|
|
38
|
+
payload: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
39
|
+
accepts_response_payload: z.ZodOptional<z.ZodBoolean>;
|
|
40
|
+
retry_attempt: z.ZodOptional<z.ZodNumber>;
|
|
41
|
+
retry_reason: z.ZodOptional<z.ZodString>;
|
|
42
|
+
}, z.core.$strip>;
|
|
43
|
+
//#endregion
|
|
38
44
|
//#region lib/types.d.ts
|
|
39
45
|
type FlumeTimerHandle = ReturnType<typeof setTimeout>;
|
|
40
46
|
type FlumeRuntimeDeps = {
|
|
@@ -56,6 +62,16 @@ type FlumeEvent = {
|
|
|
56
62
|
receivedAt: number;
|
|
57
63
|
};
|
|
58
64
|
type FlumeHandler = (event: FlumeEvent) => void | Promise<void>;
|
|
65
|
+
type FlumeSource = {
|
|
66
|
+
readonly name: FlumeSourceName;
|
|
67
|
+
start(handler: FlumeHandler): Promise<void | Error>;
|
|
68
|
+
stop(): Promise<void>;
|
|
69
|
+
status(): FlumeStatus;
|
|
70
|
+
};
|
|
71
|
+
type FlumeSourceStatus = {
|
|
72
|
+
name: FlumeSourceName;
|
|
73
|
+
status: FlumeStatus;
|
|
74
|
+
};
|
|
59
75
|
type FlumeStatus = "disconnected" | "connecting" | "connected" | "reconnecting";
|
|
60
76
|
type FlumeStatusHandler = (status: FlumeStatus, detail?: string) => void;
|
|
61
77
|
type FlumeLogLevel = "debug" | "info" | "warn" | "error";
|
|
@@ -90,7 +106,7 @@ type FlumeSourceOptions = {
|
|
|
90
106
|
onStatus?: FlumeStatusHandler;
|
|
91
107
|
onLog?: FlumeLogHandler;
|
|
92
108
|
signal?: AbortSignal;
|
|
93
|
-
deps
|
|
109
|
+
deps?: FlumeRuntimeDeps;
|
|
94
110
|
};
|
|
95
111
|
type FlumeDiscordSourceOptions = FlumeSourceOptions & {
|
|
96
112
|
token: string;
|
|
@@ -109,4 +125,4 @@ type FlumeSlackEnvelope = z.infer<typeof FlumeSlackEnvelopeSchema>;
|
|
|
109
125
|
type FlumeSlackConnectionResponse = z.infer<typeof FlumeSlackConnectionResponseSchema>;
|
|
110
126
|
type FlumeGitHubNotification = z.infer<typeof FlumeGitHubNotificationSchema>;
|
|
111
127
|
//#endregion
|
|
112
|
-
export {
|
|
128
|
+
export { FlumeTimerHandle as C, FlumeGatewayMessageSchema as D, FlumeGitHubNotificationSchema as E, FlumeStatusHandler as S, FlumeSlackConnectionResponseSchema as T, FlumeSource as _, FlumeGitHubSourceOptions as a, FlumeSourceStatus as b, FlumeLogHandler as c, FlumeReconnectConfig as d, FlumeReconnectOptions as f, FlumeSlackSourceOptions as g, FlumeSlackEnvelope as h, FlumeGitHubNotification as i, FlumeLogInput as l, FlumeSlackConnectionResponse as m, FlumeEvent as n, FlumeHandler as o, FlumeRuntimeDeps as p, FlumeGatewayMessage as r, FlumeLog as s, FlumeDiscordSourceOptions as t, FlumeLogLevel as u, FlumeSourceName as v, FlumeSlackEnvelopeSchema as w, FlumeStatus as x, FlumeSourceOptions as y };
|
package/package.json
CHANGED