@interactive-inc/flume 0.10.0 → 0.11.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/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as FlumeStatus, B as FlumeTimerHandle, C as FlumeSlackEvent, D as FlumeSourceStartContext, E as FlumeSourceName, F as FlumeTimeEvent, I as FlumeTimeMessage, L as FlumeTimeSourceOptions, M as FlumeStreamItem, N as FlumeStreamOptions, O as FlumeSourceStatus, P as FlumeStreamOverflow, R as FlumeTimeSourceState, S as FlumeSlackEnvelope, T as FlumeSourceLocalStatusHandler, V as FlumeLogger, _ as FlumeLogLevel, a as FlumeDiscordEvent, b as FlumeRuntimeDeps, c as FlumeEvent, d as FlumeGitHubEvent, f as FlumeGitHubNotification, g as FlumeLogInput, h as FlumeLogHandler, i as FlumeConfluenceItemHandler, j as FlumeStreamHandler, k as FlumeStatePersister, l as FlumeEventHandler, m as FlumeLog, n as FlumeCatchupPolicy, o as FlumeDiscordSourceOptions, p as FlumeGitHubSourceOptions, r as FlumeConfluenceItem, s as FlumeErrorHandler, t as FlumeSource, u as FlumeGatewayMessage, v as FlumeReconnectConfig, w as FlumeSlackSourceOptions, x as FlumeSlackConnectionResponse, y as FlumeReconnectOptions, z as FlumeTimeTick } from "./flume-source.js";
2
- import { i as FlumeParseError, r as FlumeTimeSource, t as FlumeCron } from "./parse-cron.js";
1
+ import { A as FlumeStatePersister, B as FlumeTimeTick, C as FlumeSlackEnvelope, D as FlumeSourceName, E as FlumeSourceLocalStatusHandler, F as FlumeStreamOverflow, H as FlumeLogger, I as FlumeTimeEvent, L as FlumeTimeMessage, M as FlumeStreamHandler, N as FlumeStreamItem, O as FlumeSourceStartContext, P as FlumeStreamOptions, R as FlumeTimeSourceOptions, S as FlumeSlackConnectionResponse, T as FlumeSlackSourceOptions, V as FlumeTimerHandle, _ as FlumeLogInput, a as FlumeCustomEvent, b as FlumeReconnectOptions, c as FlumeErrorHandler, d as FlumeGatewayMessage, f as FlumeGitHubEvent, g as FlumeLogHandler, h as FlumeLog, i as FlumeConfluenceItemHandler, j as FlumeStatus, k as FlumeSourceStatus, l as FlumeEvent, m as FlumeGitHubSourceOptions, n as FlumeCatchupPolicy, o as FlumeDiscordEvent, p as FlumeGitHubNotification, r as FlumeConfluenceItem, s as FlumeDiscordSourceOptions, t as FlumeSource, u as FlumeEventHandler, v as FlumeLogLevel, w as FlumeSlackEvent, x as FlumeRuntimeDeps, y as FlumeReconnectConfig, z as FlumeTimeSourceState } from "./flume-source.js";
2
+ import { t as FlumeParseError } from "./parse-error.js";
3
3
 
4
4
  //#region lib/deps.d.ts
5
5
  /**
@@ -29,14 +29,18 @@ declare class FlumeConnectionError extends Error {
29
29
  }
30
30
  //#endregion
31
31
  //#region lib/errors/http-error.d.ts
32
- type Props$5 = {
32
+ type Props$11 = {
33
33
  message: string;
34
34
  status: number;
35
- cause?: unknown;
35
+ cause?: unknown; /** API 固有のエラーコード (Slack の `invalid_auth` 等)。呼び出し側が恒久/一時を分類するのに使う */
36
+ code?: string | null; /** サーバーが `Retry-After` 等で指示した再試行までの待機時間 (ms) */
37
+ retryAfterMs?: number | null;
36
38
  };
37
39
  declare class FlumeHttpError extends Error {
38
40
  readonly status: number;
39
- constructor(props: Props$5);
41
+ readonly code: string | null;
42
+ readonly retryAfterMs: number | null;
43
+ constructor(props: Props$11);
40
44
  }
41
45
  //#endregion
42
46
  //#region lib/errors/start-error.d.ts
@@ -48,37 +52,56 @@ declare class FlumeStartError extends Error {
48
52
  }
49
53
  //#endregion
50
54
  //#region lib/flume-stream.d.ts
51
- type Props$4 = {
55
+ type Props$10 = {
52
56
  buffer: number;
53
57
  onOverflow: FlumeStreamOverflow;
54
- onClose: () => void;
58
+ onClose: () => void; /** buffer 溢れで item を落とした時の通知 (この stream で最初の 1 回だけ発火する) */
59
+ onDrop?: (input: {
60
+ dropped: number;
61
+ }) => void;
55
62
  };
56
63
  /**
57
64
  * push (`FlumeStreamHub.publish`) を pull (`for await`) に変換する async iterator。
58
65
  * consumer が待っていれば即 resolve、いなければ buffer に積み、溢れたら onOverflow に従う。
59
- * `return()` (break / 例外) hub.close() のどちらでも自然に done へ落ちる
66
+ * hub.close() ではバッファ済み item を吐き切ってから done へ落ちる (graceful tail drain)。
67
+ * consumer 側の `return()` (break / 例外) はバッファを破棄して即 done になる (iterator 仕様)。
68
+ * drop の観測は onDrop 経由 — drop 通知自体が firehose に還流して再帰しないよう初回のみ発火
60
69
  */
61
70
  declare class FlumeStream implements AsyncIterableIterator<FlumeStreamItem> {
62
71
  private readonly props;
63
72
  private readonly items;
64
73
  private readonly resolvers;
65
74
  private closed;
66
- constructor(props: Props$4);
75
+ private droppedCount;
76
+ constructor(props: Props$10);
67
77
  push(item: FlumeStreamItem): void;
68
78
  close(): void;
69
79
  next(): Promise<IteratorResult<FlumeStreamItem>>;
70
80
  return(): Promise<IteratorResult<FlumeStreamItem>>;
81
+ throw(error?: unknown): Promise<IteratorResult<FlumeStreamItem>>;
71
82
  [Symbol.asyncIterator](): AsyncIterableIterator<FlumeStreamItem>;
83
+ private recordDrop;
72
84
  }
73
85
  //#endregion
74
86
  //#region lib/flume-stream-hub.d.ts
87
+ type Props$9 = {
88
+ /** buffer 溢れ通知。Flume が warn ログへ橋渡しする */onDrop?: (input: {
89
+ dropped: number;
90
+ }) => void;
91
+ };
75
92
  /**
76
93
  * firehose (`onEvent` / `stream()`) の item を複数の pull consumer へ fan-out する内部ハブ。
77
94
  * subscriber が居なければ publish は実質 no-op。Flume 停止時に close() で全 stream を終端する
78
95
  */
79
96
  declare class FlumeStreamHub {
97
+ private readonly props;
80
98
  private readonly streams;
99
+ private readonly startupItems;
100
+ private startupDropNotified;
101
+ private hasSubscribed;
81
102
  private closed;
103
+ constructor(props?: Props$9);
104
+ get isClosed(): boolean;
82
105
  publish(item: FlumeStreamItem): void;
83
106
  subscribe(options?: FlumeStreamOptions): FlumeStream;
84
107
  close(): void;
@@ -89,7 +112,7 @@ type FlumeCloseError = {
89
112
  source: string;
90
113
  error: Error;
91
114
  };
92
- type Props$3 = {
115
+ type Props$8 = {
93
116
  finalStatuses: ReadonlyArray<FlumeSourceStatus>;
94
117
  closeErrors: ReadonlyArray<FlumeCloseError>;
95
118
  };
@@ -99,9 +122,10 @@ type Props$3 = {
99
122
  * きれいに close したか / どれが失敗したか」を直接判定できる
100
123
  */
101
124
  declare class FlumeClosed {
102
- private readonly props;
103
125
  readonly kind: "closed";
104
- constructor(props: Props$3);
126
+ private readonly finalStatuses;
127
+ private readonly closeErrors;
128
+ constructor(props: Props$8);
105
129
  statuses(): ReadonlyArray<FlumeSourceStatus>;
106
130
  /**
107
131
  * `runClose` 中に `source.stop()` が rejected で settle した source の名前と
@@ -111,40 +135,63 @@ declare class FlumeClosed {
111
135
  errors(): ReadonlyArray<FlumeCloseError>;
112
136
  }
113
137
  //#endregion
138
+ //#region lib/utils/serial-queue.d.ts
139
+ /**
140
+ * 投入順を保ったまま task を直列実行する。各 task は前の完了を待ってから走る。
141
+ * task が throw しても後続には伝播しない (キュー自体は止まらない)。
142
+ * drain() は待機中に追加された task も含めてキューが空になるまで待つ
143
+ */
144
+ declare class FlumeSerialQueue {
145
+ private chain;
146
+ add(task: () => Promise<void>): Promise<void>;
147
+ drain(): Promise<void>;
148
+ }
149
+ //#endregion
114
150
  //#region lib/flume-running.d.ts
115
- type Props$2 = {
151
+ type Props$7 = {
116
152
  sources: ReadonlyArray<FlumeSource>;
117
153
  signal?: AbortSignal;
118
154
  log: FlumeLogger;
119
155
  hub: FlumeStreamHub;
156
+ callbackQueue: FlumeSerialQueue;
157
+ seal: () => void;
120
158
  };
121
159
  /**
122
160
  * 稼働中の Flume。close() で FlumeClosed へ遷移する。signal が abort されると自動 close。
123
161
  * 全ての source 呼び出し・signal 操作・status 読み取りを `attempt` 経由で扱い、
124
- * `runClose` の最外殻 try/catch で想定外の throw `FlumeClosed` の resolve に変換する
162
+ * `runClose` の最外殻でも `attempt` を通して想定外の throw `FlumeClosed` の resolve に変換する
125
163
  */
126
164
  declare class FlumeRunning {
127
165
  private readonly props;
128
166
  readonly kind: "running";
129
167
  private closePromise;
130
168
  private readonly onAbort;
131
- constructor(props: Props$2);
169
+ constructor(props: Props$7);
170
+ /** Source の停止まで待つ。callback の完了は callback 外から drain() で待つ。 */
132
171
  close(): Promise<FlumeClosed>;
172
+ /**
173
+ * 配送済み callback とその失敗診断が完了するまで待つ。通常は close() の後に呼ぶ。
174
+ * onEvent / onError 内では自身の完了待ちになるため呼ばない。
175
+ */
176
+ drain(): Promise<void>;
133
177
  statuses(): ReadonlyArray<FlumeSourceStatus>;
134
178
  /**
135
179
  * 統合 firehose を pull で受け取る async iterator。`for await (const item of running.stream())`。
136
180
  * item は events + 全ログの union (`FlumeStreamItem`)。`item.kind` で判別する。
137
- * close() / signal abort iterator は自然に終了し、`break` すると hub から自動 unsubscribe する。
181
+ * close() / signal abort 後、callback の失敗診断まで配送して終了する。
182
+ * `break` すると hub から自動 unsubscribe する。
138
183
  * consumer が遅れて buffer を超えたら `onOverflow` (既定 drop-oldest) に従う
139
184
  */
140
185
  stream(options?: FlumeStreamOptions): AsyncIterableIterator<FlumeStreamItem>;
141
186
  /**
142
- * Host が `Flume({ signal })` で渡した AbortSignal をそのまま公開する。
187
+ * `Flume({ signal })` に渡された AbortSignal をそのまま公開する。
143
188
  * 直接の controller を持っていない呼び出し元が `running.signal?.aborted`
144
- * で abort 状態を確認できる
189
+ * で abort 状態を確認できる。`FlumeConfluence` 経由で開かれたグループでは
190
+ * host の signal ではなく confluence 内部の timeout controller の signal になる点に注意
145
191
  */
146
192
  get signal(): AbortSignal | undefined;
147
193
  private runClose;
194
+ private closeSources;
148
195
  private snapshotStatuses;
149
196
  private sourceName;
150
197
  }
@@ -161,44 +208,74 @@ type FlumeOptions = {
161
208
  onError?: FlumeErrorHandler;
162
209
  signal?: AbortSignal;
163
210
  deps?: FlumeRuntimeDeps;
164
- reconnect?: FlumeReconnectOptions;
211
+ /**
212
+ * 再接続方針。未指定 / false は無効 (接続断で source は disconnected のまま)。
213
+ * true は既定値 (maxAttempts: Infinity / baseDelay: 1s / maxDelay: 30s)。
214
+ * 常駐リスナー用途では明示的に有効化を推奨
215
+ */
216
+ reconnect?: boolean | FlumeReconnectOptions;
165
217
  };
166
218
  /**
167
219
  * 起動前の Flume。`open()` で `FlumeRunning` へ遷移する。
168
220
  * コンストラクタは単一オブジェクト `{ sources, ...options }` を受け取る (`sources` のみ必須)。
169
221
  * events も全ログも 1 本の firehose (`onEvent` push / `stream()` pull) に流れ、購読側が filter する。
170
- * いずれかの source 失敗時は既に成功した source を全て `stop()` してロールバックし
171
- * `FlumeStartError` を返す。
222
+ * 起動失敗時はこの open が取得した source `stop()` してロールバックする。
223
+ * 半接続状態で失敗した source も含むが、再利用を拒否した source は他の所有者のため停止しない。
172
224
  * `source.start()` / `source.stop()` の sync throw も `Promise.resolve().then` 経由で
173
225
  * Promise rejection に正規化して `allSettled` で捕捉する (`open()` は決して reject しない)
174
226
  */
175
227
  declare class Flume {
176
228
  private readonly options;
177
229
  private consumed;
230
+ private isAcceptingItems;
178
231
  private readonly log;
179
232
  private readonly deps;
180
233
  private readonly sources;
181
234
  private readonly sourceEventHandler;
182
235
  private readonly hub;
236
+ private readonly callbackQueue;
183
237
  constructor(options: FlumeOptions);
238
+ /**
239
+ * stream の buffer 溢れ通知 (stream ごとに初回 1 回)。
240
+ * firehose (hub) には流さない — 溢れている stream 自身に還流して実イベントを
241
+ * さらに追い出す自己破壊になるため、push の `onEvent` にだけ warn log として届ける
242
+ */
243
+ private notifyStreamOverflow;
184
244
  /** source が受信したログを firehose へ流す handler。error は onError にも分岐する */
185
245
  private buildLogHandler;
186
246
  /**
187
247
  * firehose の単一 sink: pull の hub と push の onEvent の両方へ item を配る。
188
- * onEvent への転送は this.log を経由しない (経由すると log item 経路で再帰する) ため
189
- * 例外をここで握り潰す
248
+ * close 後の遅延 emit (stop 中の straggler) は push 側にも流さない (pull 側と対称にする)
249
+ * onEvent への転送は this.log を経由しない (経由すると log item 経路で再帰する)。
250
+ * callback failure は reportCallbackFailure が pull hub と peer callback へ直接診断する。
190
251
  */
191
252
  private emitItem;
253
+ private enqueueCallback;
254
+ /**
255
+ * error log 専用 sink も callbackQueue に載せ、drain() が in-flight callback と
256
+ * その失敗診断まで drain できるようにする
257
+ */
258
+ private invokeOnError;
259
+ /**
260
+ * 観測 sink 自身の失敗は同じ sink へ戻すと再帰するため、まず pull stream へ直接 publish し、
261
+ * もう一方の callback にだけ転送する。peer も失敗した場合は hub-only の診断を残して終端する
262
+ */
263
+ private reportCallbackFailure;
192
264
  open(): Promise<FlumeRunning | FlumeStartError>;
265
+ /** 起動失敗の戻り値は callback を待たず、配送済み診断の完了後に hub を閉じる。 */
266
+ private finishFailedOpen;
193
267
  private guardOpen;
268
+ /** reconnect オプションの解決。throwing getter を持つ hostile 入力でも open() を reject させない */
269
+ private resolveReconnect;
194
270
  private isSignalAborted;
195
271
  private sourceName;
196
272
  private safeStart;
197
273
  private rollback;
274
+ private logRollbackFailure;
198
275
  }
199
276
  //#endregion
200
277
  //#region lib/flume-confluence.d.ts
201
- type Props$1 = {
278
+ type Props$6 = {
202
279
  /**
203
280
  * 配下の全 Flume の firehose をここへ合流させる単一 sink。
204
281
  * 各 item には発信元グループの id が `groupId` としてスタンプされる
@@ -206,7 +283,7 @@ type Props$1 = {
206
283
  onEvent?: FlumeConfluenceItemHandler; /** error レベル log だけ (全 Flume 共通) */
207
284
  onError?: FlumeErrorHandler;
208
285
  deps?: FlumeRuntimeDeps;
209
- reconnect?: FlumeReconnectOptions;
286
+ reconnect?: boolean | FlumeReconnectOptions;
210
287
  };
211
288
  /**
212
289
  * 複数の `Flume` を束ねて動的に増減させる上位レイヤー。各 Flume は immutable のまま、
@@ -217,14 +294,26 @@ type Props$1 = {
217
294
  * `replace(id, sources)` は同じ id のグループを差し替える。新グループを先に起動し、
218
295
  * 起動成功時にのみ旧グループを停止するので連続稼働を維持できる (token rotation 用途)。
219
296
  * 起動失敗時は旧グループはそのまま走り続ける。
297
+ * 注意: 失敗した replace / add に渡した source インスタンスは consumed になるため、
298
+ * リトライには新しいインスタンスを構築する必要がある。
299
+ *
300
+ * `closeAll()` は終端操作。以後の `add()` / `replace()` は拒否され、closeAll と並行して
301
+ * 起動中だったグループも abort して完了を待つ (シャットダウン後に誰にも止められない
302
+ * グループが残らない)。
220
303
  *
221
304
  * throw しない流儀に従い `add()` / `replace()` は `Error | null` を返す
222
305
  */
223
306
  declare class FlumeConfluence {
224
307
  private readonly props;
225
308
  private readonly running;
309
+ /** open() を await 中でまだ Map に commit されていないグループの id (add 重複と remove 追跡用) */
310
+ private readonly pendingIds;
311
+ private readonly removedWhilePending;
312
+ private readonly pendingOpens;
313
+ private isClosedFlag;
226
314
  private readonly deps;
227
- constructor(props?: Props$1);
315
+ constructor(props?: Props$6);
316
+ get isClosed(): boolean;
228
317
  /** sources を 1 グループとして起動。id 重複や起動失敗は `Error` で返す (throw しない) */
229
318
  add(id: string, sources: ReadonlyArray<FlumeSource>): Promise<Error | null>;
230
319
  /**
@@ -235,38 +324,126 @@ declare class FlumeConfluence {
235
324
  replace(id: string, sources: ReadonlyArray<FlumeSource>, options?: {
236
325
  readonly replaceTimeoutMs?: number;
237
326
  }): Promise<Error | null>;
238
- /** 指定グループだけ close。他グループは無停止。未知の id は no-op */
327
+ /**
328
+ * 指定グループだけ close。他グループは無停止。未知の id は no-op。
329
+ * 起動中 (add が open を await 中) の id は commit 時点で破棄されるよう予約する
330
+ */
239
331
  remove(id: string): Promise<void>;
332
+ /** 終端操作。全グループを close し、以後の add / replace を拒否する */
240
333
  closeAll(): Promise<void>;
241
334
  has(id: string): boolean;
242
335
  ids(): ReadonlyArray<string>;
243
336
  /**
244
- * 1 グループ分の Flume を開いて FlumeRunning を返す。timeoutMs を指定すると open()
245
- * AbortSignal でレース掛けし、超過時に新グループ起動を中止する。失敗時の rollback
246
- * Flume 本体に任せる
337
+ * 1 グループ分の Flume を開いて FlumeRunning を返す。timeoutMs を指定すると AbortSignal
338
+ * ctx.signal として各 source へ注入し、超過時に abort して進行中の connect ごと中止する
339
+ * (source 側は base クラスが signal を購読して stop() を発火する)。
340
+ * 失敗時の rollback は Flume 本体に任せる
247
341
  */
248
342
  private openGroup;
343
+ private createPendingOpen;
249
344
  private wrapOnEvent;
345
+ private wrapOnError;
250
346
  }
251
347
  //#endregion
252
- //#region lib/time/time-catchup.d.ts
253
- type Props = {
254
- cron: FlumeCron;
255
- lastFiredAt: number;
256
- now: number;
257
- policy: FlumeCatchupPolicy;
258
- };
348
+ //#region lib/utils/attempt.d.ts
259
349
  /**
260
- * `lastFiredAt` から `now` までに過ぎ去った cron マッチを policy に従って列挙する。
350
+ * 関数を呼び出して throw / async reject `T | Error` に変換する。
261
351
  *
262
- * - policy.mode === "off" : 常に空配列
263
- * - policy.mode === "lastOnly" : 過ぎ去ったマッチの中で最も新しいもの 1
264
- * - policy.mode === "missed" : maxWindowMs (既定 24h) 以内に過ぎ去ったすべてのマッチ。
265
- * window の起点は `max(lastFiredAt, now - maxWindowMs)`
352
+ * - sync 関数を渡すと `T | Error` を返す
353
+ * - Promise を返す関数を渡すと `Promise<T | Error>` を返す (caller は `await` する)
354
+ * - `new X(...)` や `obj.method(...)` `() => new X(...)` のようにアローで包む
266
355
  *
267
- * 到達不能 cron catastrophic policy ミス指定の場合は FlumeParseError を返す
268
- * (catchup 列挙だけで失敗させる。source 本体の起動は別判断)
356
+ * sync / async arrow の戻り型から TS が推論する。
357
+ * native Promise でない thenable (DI モックや promise ライブラリ) の reject も
358
+ * `Promise.resolve` で吸収する — その代償として、`.then` メソッドを持つ純粋な値を
359
+ * sync overload で返すことはできない (Promise 扱いになる)
360
+ */
361
+ declare function attempt<T>(fn: () => Promise<T>): Promise<T | Error>;
362
+ declare function attempt<T>(fn: () => T): T | Error;
363
+ //#endregion
364
+ //#region lib/utils/is-record.d.ts
365
+ declare function isRecord(value: unknown): value is Record<string, unknown>;
366
+ //#endregion
367
+ //#region lib/utils/safe-error-message.d.ts
368
+ type Props$5 = {
369
+ error: unknown;
370
+ };
371
+ /**
372
+ * 任意の値から人が読めるメッセージ文字列を取り出す。
373
+ * `Error.message` getter / `Symbol.toPrimitive` / `toString` / `valueOf` が throw しても固定文字列に fallback。
374
+ * `instanceof` 自体が throw する値 (revoked Proxy 等) にも耐える。自身は決して throw しない
375
+ */
376
+ declare function safeErrorMessage(props: Props$5): string;
377
+ //#endregion
378
+ //#region lib/utils/safe-invoke-callback.d.ts
379
+ type Props$4 = {
380
+ fn: () => void;
381
+ onError: (error: Error) => void;
382
+ };
383
+ /**
384
+ * fire-and-forget でユーザーコールバックを呼び出す。sync throw と async reject のどちらも
385
+ * `onError(Error)` に正規化して通知。`onError` 自身が throw しても外に漏らさない。
386
+ * 戻り値を持たない fire-and-forget 専用のため log/出力先には依存しない (caller が onError で決める)
387
+ */
388
+ declare function safeInvokeCallback(props: Props$4): void;
389
+ //#endregion
390
+ //#region lib/utils/safe-json-parse.d.ts
391
+ declare function safeJsonParse(raw: string): unknown | FlumeParseError;
392
+ //#endregion
393
+ //#region lib/utils/safe-normalize-error.d.ts
394
+ type Props$3 = {
395
+ value: unknown;
396
+ };
397
+ /**
398
+ * 任意の値を `Error` インスタンスへ正規化する。すでに Error ならそのまま返し、
399
+ * それ以外は `safeErrorMessage` で安全な文字列化を経由して new Error する。
400
+ * `instanceof` 自体が throw する値 (revoked Proxy 等) や Error コンストラクタが throw する
401
+ * 病的環境でも fallback を返し、決して throw しない
402
+ */
403
+ declare function safeNormalizeError(props: Props$3): Error;
404
+ //#endregion
405
+ //#region lib/utils/safe-now.d.ts
406
+ type Props$2 = {
407
+ deps: Pick<FlumeRuntimeDeps, "now">;
408
+ };
409
+ /**
410
+ * `deps.now()` を保護する。throw / 非数値 / 非有限値が返った場合は `Date.now()` へ
411
+ * フォールバックする (0 を返すと epoch 1970 が TTL / cron / レート計算へ伝播するため)。
412
+ * `Date.now` 自体まで壊れている病的環境でのみ 0 を返す。
413
+ * IO 境界のため呼び出し側はこの戻り値を信頼できる
414
+ */
415
+ declare function safeNow(props: Props$2): number;
416
+ //#endregion
417
+ //#region lib/utils/safe-random.d.ts
418
+ type Props$1 = {
419
+ deps: Pick<FlumeRuntimeDeps, "random">;
420
+ };
421
+ /**
422
+ * `deps.random()` を保護する。throw / 範囲外値 / 非数値が返った場合は `Math.random()` へ
423
+ * フォールバックする。0 以上 1 未満 (Math.random と同等) の値のみそのまま透過。
424
+ * `Math.random` 自体まで壊れている病的環境でのみ 0.5 を返す
425
+ */
426
+ declare function safeRandom(props: Props$1): number;
427
+ //#endregion
428
+ //#region lib/utils/safe-read-text.d.ts
429
+ type Props = {
430
+ response: Response;
431
+ context: string;
432
+ };
433
+ /**
434
+ * `response.text()` を保護する。body 読み取り中の reject (接続切断 / 解凍失敗 / 二重消費) を
435
+ * `FlumeHttpError` (status / cause 保持) に変換する。DI モックの `status` getter が throw
436
+ * しても reject しない。log には書かない (呼び出し側で書く)
437
+ */
438
+ declare function safeReadText(props: Props): Promise<string | FlumeHttpError>;
439
+ //#endregion
440
+ //#region lib/utils/safe-stringify.d.ts
441
+ /**
442
+ * `JSON.stringify` を `string | Error` に変換するラッパ。
443
+ * cyclic / BigInt / throwing toJSON など標準が throw するケースを Error として返す。
444
+ * `undefined` / function / symbol は `JSON.stringify` が (型定義に反して) `undefined` を
445
+ * 返すため、これも Error に正規化して戻り値を必ず string にする
269
446
  */
270
- declare function flumeCollectCatchupMatches(props: Props): ReadonlyArray<number> | FlumeParseError;
447
+ declare function safeStringify(value: unknown): string | Error;
271
448
  //#endregion
272
- export { Flume, type FlumeCatchupPolicy, type FlumeCloseError, FlumeClosed, FlumeConfluence, type FlumeConfluenceItem, type FlumeConfluenceItemHandler, FlumeConnectionError, type FlumeDiscordEvent, type FlumeDiscordSourceOptions, type FlumeErrorHandler, type FlumeEvent, type FlumeEventHandler, type FlumeGatewayMessage, type FlumeGitHubEvent, type FlumeGitHubNotification, type FlumeGitHubSourceOptions, FlumeHttpError, type FlumeLog, type FlumeLogHandler, type FlumeLogInput, type FlumeLogLevel, type FlumeOptions, FlumeParseError, type FlumeReconnectConfig, type FlumeReconnectOptions, FlumeRunning, type FlumeRuntimeDeps, type FlumeSlackConnectionResponse, type FlumeSlackEnvelope, type FlumeSlackEvent, type FlumeSlackSourceOptions, FlumeSource, type FlumeSourceLocalStatusHandler, type FlumeSourceName, type FlumeSourceStartContext, type FlumeSourceStatus, FlumeStartError, type FlumeStatePersister, type FlumeStatus, type FlumeStreamHandler, type FlumeStreamItem, type FlumeStreamOptions, type FlumeStreamOverflow, type FlumeTimeEvent, type FlumeTimeMessage, FlumeTimeSource, type FlumeTimeSourceOptions, type FlumeTimeSourceState, type FlumeTimeTick, type FlumeTimerHandle, createFlumeDefaultDeps, flumeCollectCatchupMatches };
449
+ export { Flume, type FlumeCatchupPolicy, type FlumeCloseError, FlumeClosed, FlumeConfluence, type FlumeConfluenceItem, type FlumeConfluenceItemHandler, FlumeConnectionError, type FlumeCustomEvent, type FlumeDiscordEvent, type FlumeDiscordSourceOptions, type FlumeErrorHandler, type FlumeEvent, type FlumeEventHandler, type FlumeGatewayMessage, type FlumeGitHubEvent, type FlumeGitHubNotification, type FlumeGitHubSourceOptions, FlumeHttpError, type FlumeLog, type FlumeLogHandler, type FlumeLogInput, type FlumeLogLevel, type FlumeOptions, FlumeParseError, type FlumeReconnectConfig, type FlumeReconnectOptions, FlumeRunning, type FlumeRuntimeDeps, type FlumeSlackConnectionResponse, type FlumeSlackEnvelope, type FlumeSlackEvent, type FlumeSlackSourceOptions, FlumeSource, type FlumeSourceLocalStatusHandler, type FlumeSourceName, type FlumeSourceStartContext, type FlumeSourceStatus, FlumeStartError, type FlumeStatePersister, type FlumeStatus, type FlumeStreamHandler, type FlumeStreamItem, type FlumeStreamOptions, type FlumeStreamOverflow, type FlumeTimeEvent, type FlumeTimeMessage, type FlumeTimeSourceOptions, type FlumeTimeSourceState, type FlumeTimeTick, type FlumeTimerHandle, attempt, createFlumeDefaultDeps, isRecord, safeErrorMessage, safeInvokeCallback, safeJsonParse, safeNormalizeError, safeNow, safeRandom, safeReadText, safeStringify };