@arbitro/client 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/LICENSE +21 -0
- package/README.md +266 -0
- package/dist/index.d.mts +602 -0
- package/dist/index.d.ts +602 -0
- package/dist/index.js +1634 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1576 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +83 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,602 @@
|
|
|
1
|
+
import { ZodRawShape, ZodObject, output } from 'zod';
|
|
2
|
+
|
|
3
|
+
type LogFn = {
|
|
4
|
+
(msg: string): void;
|
|
5
|
+
(obj: object, msg: string): void;
|
|
6
|
+
};
|
|
7
|
+
interface Logger {
|
|
8
|
+
trace: LogFn;
|
|
9
|
+
debug: LogFn;
|
|
10
|
+
info: LogFn;
|
|
11
|
+
warn: LogFn;
|
|
12
|
+
error: LogFn;
|
|
13
|
+
child(bindings: Record<string, unknown>): Logger;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
declare enum DeliverPolicy {
|
|
17
|
+
All = "All",
|
|
18
|
+
Last = "Last",
|
|
19
|
+
New = "New",
|
|
20
|
+
BySeq = "ByStartSeq",
|
|
21
|
+
ByTime = "ByStartTime"
|
|
22
|
+
}
|
|
23
|
+
declare enum JournalType {
|
|
24
|
+
Memory = "Memory",
|
|
25
|
+
Tolerant = "Tolerant",
|
|
26
|
+
Strict = "Strict"
|
|
27
|
+
}
|
|
28
|
+
declare enum AckPolicy {
|
|
29
|
+
Explicit = "explicit",
|
|
30
|
+
None = "none"
|
|
31
|
+
}
|
|
32
|
+
interface FlushConfig {
|
|
33
|
+
intervalMs?: number;
|
|
34
|
+
maxMessages?: number;
|
|
35
|
+
maxBytes?: number;
|
|
36
|
+
}
|
|
37
|
+
type JournalConfig = {
|
|
38
|
+
type: JournalType.Memory;
|
|
39
|
+
} | {
|
|
40
|
+
type: JournalType.Tolerant;
|
|
41
|
+
} | {
|
|
42
|
+
type: JournalType.Strict;
|
|
43
|
+
flush?: FlushConfig;
|
|
44
|
+
};
|
|
45
|
+
interface StreamConfig {
|
|
46
|
+
subjectFilter: string;
|
|
47
|
+
journal?: JournalConfig;
|
|
48
|
+
maxMsgs?: number;
|
|
49
|
+
maxBytes?: number;
|
|
50
|
+
maxAgeMs?: number;
|
|
51
|
+
/**
|
|
52
|
+
* Per-stream broker-side dedup window in milliseconds.
|
|
53
|
+
*
|
|
54
|
+
* - `0` or undefined (default): no dedup. Every publish is stored;
|
|
55
|
+
* `msgId` is ignored.
|
|
56
|
+
* - `>0`: any publish that carries a `msgId` matching one the
|
|
57
|
+
* broker has stored for THIS stream within the last
|
|
58
|
+
* `idempotencyWindowMs` is rejected with the `IdempotencyDuplicate`
|
|
59
|
+
* wire error. Useful for safe retries — the first publish wins.
|
|
60
|
+
*
|
|
61
|
+
* The broker clamps requested windows above 5 minutes (300 000 ms)
|
|
62
|
+
* down to that ceiling, matching JetStream behaviour.
|
|
63
|
+
*/
|
|
64
|
+
idempotencyWindowMs?: number;
|
|
65
|
+
}
|
|
66
|
+
interface DeleteStreamOpts {
|
|
67
|
+
deleteData?: boolean;
|
|
68
|
+
}
|
|
69
|
+
interface StreamInfo {
|
|
70
|
+
name: string;
|
|
71
|
+
config: StreamConfig;
|
|
72
|
+
lastSeq: number;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Per-subject inflight cap. Each entry caps the number of in-flight
|
|
76
|
+
* (delivered, unacked) messages on subjects matching `pattern`. Patterns
|
|
77
|
+
* may use NATS-style wildcards (`*`, `>`).
|
|
78
|
+
*
|
|
79
|
+
* Only enforced when the owning consumer's `ackPolicy` is `Explicit`;
|
|
80
|
+
* silently dropped server-side for fire-and-forget consumers (because
|
|
81
|
+
* fire-and-forget bindings skip inflight tracking entirely).
|
|
82
|
+
*/
|
|
83
|
+
interface SubjectInflightLimit {
|
|
84
|
+
pattern: string;
|
|
85
|
+
limit: number;
|
|
86
|
+
}
|
|
87
|
+
interface ConsumerConfig {
|
|
88
|
+
name?: string;
|
|
89
|
+
filter?: string;
|
|
90
|
+
fanout?: boolean;
|
|
91
|
+
/** Consumer-side ACK policy. None = fire-and-forget delivery, Explicit = consumer must ACK. */
|
|
92
|
+
ackPolicy?: AckPolicy;
|
|
93
|
+
deliverPolicy?: DeliverPolicy;
|
|
94
|
+
startSeq?: bigint;
|
|
95
|
+
startTime?: bigint;
|
|
96
|
+
maxAckPending?: number;
|
|
97
|
+
ackWaitMs?: number;
|
|
98
|
+
maxDeliver?: number;
|
|
99
|
+
removeUnusedAfterMs?: number;
|
|
100
|
+
/**
|
|
101
|
+
* Per-subject max inflight (list of pattern → limit pairs).
|
|
102
|
+
* Only effective with `ackPolicy: Explicit`.
|
|
103
|
+
*/
|
|
104
|
+
maxSubjectInflights?: SubjectInflightLimit[];
|
|
105
|
+
}
|
|
106
|
+
interface ConsumerInfo {
|
|
107
|
+
group: string;
|
|
108
|
+
stream: string;
|
|
109
|
+
config: ConsumerConfig;
|
|
110
|
+
}
|
|
111
|
+
interface SubscribeOptions {
|
|
112
|
+
fetchTimeoutMs?: number;
|
|
113
|
+
}
|
|
114
|
+
interface ReconnectConfig {
|
|
115
|
+
enabled?: boolean;
|
|
116
|
+
maxAttempts?: number;
|
|
117
|
+
intervalMs?: number;
|
|
118
|
+
jitter?: boolean;
|
|
119
|
+
}
|
|
120
|
+
interface TlsConfig {
|
|
121
|
+
enabled?: boolean;
|
|
122
|
+
ca?: Buffer | string;
|
|
123
|
+
cert?: Buffer | string;
|
|
124
|
+
key?: Buffer | string;
|
|
125
|
+
}
|
|
126
|
+
interface ClientConfig {
|
|
127
|
+
servers: string[];
|
|
128
|
+
prefix?: string;
|
|
129
|
+
timeout?: number;
|
|
130
|
+
reconnect?: ReconnectConfig;
|
|
131
|
+
tls?: TlsConfig;
|
|
132
|
+
logger?: Logger;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
declare class ArbitroError extends Error {
|
|
136
|
+
readonly code: 'connect' | 'timeout' | 'protocol' | 'server' | 'closed';
|
|
137
|
+
readonly brokerName?: string | undefined;
|
|
138
|
+
readonly brokerDetails?: unknown | undefined;
|
|
139
|
+
/**
|
|
140
|
+
* Numeric wire error code from the broker's `RepError` frame. Only
|
|
141
|
+
* populated when `code === 'server'`. Use the `ErrorCode` enum to
|
|
142
|
+
* compare (e.g. `err.wireCode === ErrorCode.IdempotencyDuplicate`).
|
|
143
|
+
*/
|
|
144
|
+
readonly wireCode?: number | undefined;
|
|
145
|
+
constructor(message: string, code: 'connect' | 'timeout' | 'protocol' | 'server' | 'closed', brokerName?: string | undefined, brokerDetails?: unknown | undefined,
|
|
146
|
+
/**
|
|
147
|
+
* Numeric wire error code from the broker's `RepError` frame. Only
|
|
148
|
+
* populated when `code === 'server'`. Use the `ErrorCode` enum to
|
|
149
|
+
* compare (e.g. `err.wireCode === ErrorCode.IdempotencyDuplicate`).
|
|
150
|
+
*/
|
|
151
|
+
wireCode?: number | undefined);
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Wire-level error codes. Mirrors the `ErrorCode` enum in
|
|
155
|
+
* `arbitro-proto`. New codes added to the broker MUST be appended here
|
|
156
|
+
* with the matching numeric value.
|
|
157
|
+
*/
|
|
158
|
+
declare const ErrorCode: {
|
|
159
|
+
readonly UnknownAction: 1;
|
|
160
|
+
readonly BufferTooShort: 2;
|
|
161
|
+
readonly InvalidLength: 3;
|
|
162
|
+
readonly InvalidEntryCount: 4;
|
|
163
|
+
readonly AuthRequired: 257;
|
|
164
|
+
readonly AuthFailed: 258;
|
|
165
|
+
readonly StreamNotFound: 513;
|
|
166
|
+
readonly StreamAlreadyExists: 514;
|
|
167
|
+
readonly StreamFull: 515;
|
|
168
|
+
readonly StreamFilterOverlap: 516;
|
|
169
|
+
readonly SubjectNotFound: 517;
|
|
170
|
+
/** Publish carried a `msgId` already seen for this stream within
|
|
171
|
+
* `idempotencyWindowMs`. Original write stands; safe to treat as
|
|
172
|
+
* a successful publish at the application level. */
|
|
173
|
+
readonly IdempotencyDuplicate: 518;
|
|
174
|
+
readonly ConsumerNotFound: 769;
|
|
175
|
+
readonly ConsumerAlreadyExists: 770;
|
|
176
|
+
readonly ConsumerFilterOverlap: 771;
|
|
177
|
+
readonly InvalidSequence: 1025;
|
|
178
|
+
readonly MaxInflightReached: 1026;
|
|
179
|
+
readonly AckTimeout: 1027;
|
|
180
|
+
readonly ServerShuttingDown: 1281;
|
|
181
|
+
readonly InternalError: 1282;
|
|
182
|
+
};
|
|
183
|
+
type ErrorCodeValue = (typeof ErrorCode)[keyof typeof ErrorCode];
|
|
184
|
+
|
|
185
|
+
interface ClientMetricsSnapshot {
|
|
186
|
+
/** Calls to `publish` / `publishAck` / `publishBatch` entries. */
|
|
187
|
+
publishesSent: number;
|
|
188
|
+
/** Total entries inside `publishBatch` calls (summed across batches). */
|
|
189
|
+
publishBatchEntries: number;
|
|
190
|
+
/** `Deliver` frames received from the broker (one per message). */
|
|
191
|
+
deliveriesReceived: number;
|
|
192
|
+
/** Currently-open subscriptions (gauge — inc at subscribe, dec at close). */
|
|
193
|
+
activeSubscriptions: number;
|
|
194
|
+
/** `Ack` frames sent to the broker. */
|
|
195
|
+
acksSent: number;
|
|
196
|
+
/** `Nack` frames sent to the broker. */
|
|
197
|
+
nacksSent: number;
|
|
198
|
+
/** Successful reconnections after a session drop. */
|
|
199
|
+
reconnects: number;
|
|
200
|
+
/** Outstanding pending request-reply slots (gauge). */
|
|
201
|
+
pendingReplies: number;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Live atomic-ish counters. JavaScript is single-threaded per worker so
|
|
205
|
+
* plain `++` is sufficient — no `Atomics` needed.
|
|
206
|
+
*
|
|
207
|
+
* Held on `ArbitroClient` and shared with `Connection` so the demux loop
|
|
208
|
+
* can bump `deliveriesReceived` directly. Public `snapshot()` returns a
|
|
209
|
+
* frozen copy for logging or external scraping.
|
|
210
|
+
*/
|
|
211
|
+
declare class ClientMetrics {
|
|
212
|
+
publishesSent: number;
|
|
213
|
+
publishBatchEntries: number;
|
|
214
|
+
deliveriesReceived: number;
|
|
215
|
+
activeSubscriptions: number;
|
|
216
|
+
acksSent: number;
|
|
217
|
+
nacksSent: number;
|
|
218
|
+
reconnects: number;
|
|
219
|
+
pendingReplies: number;
|
|
220
|
+
snapshot(): ClientMetricsSnapshot;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
type DeliveryHandler = (frame: Buffer) => void;
|
|
224
|
+
declare class Connection {
|
|
225
|
+
private readonly reconnectAddr?;
|
|
226
|
+
private readonly reconnectCfg?;
|
|
227
|
+
private seq;
|
|
228
|
+
private connId;
|
|
229
|
+
private framer;
|
|
230
|
+
private routes;
|
|
231
|
+
private pending;
|
|
232
|
+
private socket;
|
|
233
|
+
private closing;
|
|
234
|
+
private readonly log;
|
|
235
|
+
private activeSubs;
|
|
236
|
+
private metrics?;
|
|
237
|
+
private constructor();
|
|
238
|
+
private attachSocket;
|
|
239
|
+
static connect(addr: string, timeoutMs?: number, tlsCfg?: TlsConfig, reconnectCfg?: ReconnectConfig, logger?: Logger): Promise<Connection>;
|
|
240
|
+
nextSeq(): bigint;
|
|
241
|
+
/**
|
|
242
|
+
* Attach a metrics sink. Called by `ArbitroClient` after `connect()`.
|
|
243
|
+
* The connection bumps `deliveriesReceived` on every Deliver/RepBatch
|
|
244
|
+
* entry and `reconnects` on successful reconnections. Unset = no-op.
|
|
245
|
+
*/
|
|
246
|
+
setMetrics(m: ClientMetrics): void;
|
|
247
|
+
private resolvePending;
|
|
248
|
+
private rejectPending;
|
|
249
|
+
private onFrame;
|
|
250
|
+
private handleBatchDeliver;
|
|
251
|
+
sendSubscribeV2(consumerId: number, filter: Buffer, handler: DeliveryHandler, onRenew?: (newConsumerId: number) => void): Promise<number>;
|
|
252
|
+
cancelSubscription(consumerId: number): void;
|
|
253
|
+
private resubscribeAll;
|
|
254
|
+
registerRoute(consumerId: number, handler: DeliveryHandler): void;
|
|
255
|
+
unregisterRoute(consumerId: number): void;
|
|
256
|
+
send(frame: Buffer): void;
|
|
257
|
+
/** Send frame and wait for RepOk. Returns the ref_seq from body. */
|
|
258
|
+
sendExpectReply(frame: Buffer, timeoutMs?: number): Promise<bigint>;
|
|
259
|
+
/** Send frame and wait for full reply frame buffer. */
|
|
260
|
+
sendExpectReplyRaw(frame: Buffer, timeoutMs?: number): Promise<Buffer>;
|
|
261
|
+
close(): Promise<void>;
|
|
262
|
+
private drain;
|
|
263
|
+
private handleClose;
|
|
264
|
+
private tryReconnect;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* One entry of a `publishBatch` call.
|
|
269
|
+
*
|
|
270
|
+
* `msgId` (optional) is an opaque byte string the broker uses for
|
|
271
|
+
* per-stream deduplication when the target stream was created with
|
|
272
|
+
* `idempotencyWindowMs > 0`. Leaving it empty/undefined disables
|
|
273
|
+
* dedup for this entry (mixing dedup + non-dedup entries in a single
|
|
274
|
+
* batch is allowed).
|
|
275
|
+
*/
|
|
276
|
+
interface BatchPublishEntry {
|
|
277
|
+
subject: string;
|
|
278
|
+
payload: Buffer;
|
|
279
|
+
msgId?: Buffer;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/**
|
|
283
|
+
* Optional per-publish options.
|
|
284
|
+
*
|
|
285
|
+
* `msgId` is an opaque byte string the broker uses for dedup when the
|
|
286
|
+
* target stream was created with `idempotencyWindowMs > 0`. Empty or
|
|
287
|
+
* undefined means "no dedup for this publish" — safe to omit on
|
|
288
|
+
* non-idempotent streams.
|
|
289
|
+
*/
|
|
290
|
+
interface PublishOpts {
|
|
291
|
+
msgId?: Buffer | string;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
declare function encodeString(s: string): Buffer;
|
|
295
|
+
declare function decodeString(buf: Buffer): string;
|
|
296
|
+
|
|
297
|
+
declare function encodeJson(value: unknown): Buffer;
|
|
298
|
+
declare function decodeJson<T = unknown>(buf: Buffer): T;
|
|
299
|
+
|
|
300
|
+
/** Core encode/decode contract. `fields` is required only for schema-based codecs
|
|
301
|
+
* that power LazyMessage<T> getters — other encodings may omit it. */
|
|
302
|
+
interface Encoding<T> {
|
|
303
|
+
encode(value: T): Buffer;
|
|
304
|
+
decode(buf: Buffer): T;
|
|
305
|
+
readonly fields?: string[];
|
|
306
|
+
}
|
|
307
|
+
/** Maps a FieldType string literal to its corresponding TypeScript type. */
|
|
308
|
+
type FieldTypeMap = {
|
|
309
|
+
string: string;
|
|
310
|
+
number: number;
|
|
311
|
+
boolean: boolean;
|
|
312
|
+
bigint: bigint;
|
|
313
|
+
buffer: Buffer;
|
|
314
|
+
unknown: unknown;
|
|
315
|
+
};
|
|
316
|
+
/** Infers the TypeScript record type from a schema definition.
|
|
317
|
+
* Eliminates the need to define both an interface and a Schema<T>. */
|
|
318
|
+
type InferSchema<S extends Record<string, FieldType>> = {
|
|
319
|
+
[K in keyof S]: FieldTypeMap[S[K]];
|
|
320
|
+
};
|
|
321
|
+
declare abstract class TextEncoding implements Encoding<string> {
|
|
322
|
+
abstract readonly encoding: BufferEncoding;
|
|
323
|
+
encode(value: string): Buffer;
|
|
324
|
+
decode(buf: Buffer): string;
|
|
325
|
+
}
|
|
326
|
+
declare class StringCodec extends TextEncoding {
|
|
327
|
+
readonly encoding: BufferEncoding;
|
|
328
|
+
constructor(encoding?: BufferEncoding);
|
|
329
|
+
}
|
|
330
|
+
declare class JsonCodec<T> implements Encoding<T> {
|
|
331
|
+
private readonly text;
|
|
332
|
+
constructor(encoding?: BufferEncoding);
|
|
333
|
+
encode(value: T): Buffer;
|
|
334
|
+
decode(buf: Buffer): T;
|
|
335
|
+
}
|
|
336
|
+
type FieldType = 'string' | 'number' | 'boolean' | 'bigint' | 'buffer' | 'unknown';
|
|
337
|
+
type Schema<T> = {
|
|
338
|
+
[K in keyof Required<T>]: FieldType;
|
|
339
|
+
};
|
|
340
|
+
declare class Codec<T extends Record<string, unknown>> implements Encoding<T> {
|
|
341
|
+
readonly fields: (keyof T & string)[];
|
|
342
|
+
private readonly packr;
|
|
343
|
+
private readonly unpackr;
|
|
344
|
+
constructor(schema: Schema<T>);
|
|
345
|
+
encode(value: T): Buffer;
|
|
346
|
+
decode(buf: Buffer): T;
|
|
347
|
+
}
|
|
348
|
+
/** Creates a msgpack Codec with the TypeScript type inferred from the schema definition. */
|
|
349
|
+
declare function schema<S extends Record<string, FieldType>>(def: S): Codec<InferSchema<S>>;
|
|
350
|
+
|
|
351
|
+
type SendFn = (frame: Buffer) => void;
|
|
352
|
+
declare class Message {
|
|
353
|
+
private readonly frame;
|
|
354
|
+
private readonly send;
|
|
355
|
+
private readonly seqFn;
|
|
356
|
+
private _subjectLen;
|
|
357
|
+
constructor(frame: Buffer, send: SendFn, seqFn: () => bigint);
|
|
358
|
+
/** Delivery sequence — used to ack/nack this message. */
|
|
359
|
+
seq(): bigint;
|
|
360
|
+
/** Consumer ID that received this delivery. */
|
|
361
|
+
consumerId(): number;
|
|
362
|
+
/** Subject hash — echoed back in ack for O(1) credit release. */
|
|
363
|
+
subjectHash(): number;
|
|
364
|
+
private subjLen;
|
|
365
|
+
/** Zero-copy view of the subject bytes. */
|
|
366
|
+
subject(): Buffer;
|
|
367
|
+
/** Zero-copy view of the payload bytes. */
|
|
368
|
+
data(): Buffer;
|
|
369
|
+
/** Acknowledge — fire-and-forget to broker. */
|
|
370
|
+
ack(): void;
|
|
371
|
+
/** Negative acknowledge — immediate requeue. */
|
|
372
|
+
nack(): void;
|
|
373
|
+
/** Negative acknowledge with redelivery delay (ms). */
|
|
374
|
+
nackDelay(ms: number): void;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
type MsgCallback$1 = (msg: Message) => void;
|
|
378
|
+
declare class Subscription {
|
|
379
|
+
private consumerId;
|
|
380
|
+
private readonly conn;
|
|
381
|
+
private readonly streamName;
|
|
382
|
+
private readonly fetchTimeoutMs;
|
|
383
|
+
private callback;
|
|
384
|
+
private fetchQueue;
|
|
385
|
+
private msgBuf;
|
|
386
|
+
private closed;
|
|
387
|
+
constructor(consumerId: number, conn: Connection, streamName: string, fetchTimeoutMs: number);
|
|
388
|
+
/** Consumer ID assigned by the server. */
|
|
389
|
+
id(): number;
|
|
390
|
+
deliver(frame: Buffer): void;
|
|
391
|
+
onMessage(cb: MsgCallback$1): void;
|
|
392
|
+
fetch(count: number, timeoutMs?: number): Promise<Message[]>;
|
|
393
|
+
close(): void;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
type LazyMessage<T> = T & {
|
|
397
|
+
readonly _raw: Buffer;
|
|
398
|
+
decode(): T;
|
|
399
|
+
ack(): void;
|
|
400
|
+
nack(): void;
|
|
401
|
+
nackDelay(delayMs: number): void;
|
|
402
|
+
};
|
|
403
|
+
declare function makeLazyMessage<T extends Record<string, unknown>>(raw: Buffer, codec: Encoding<T>, fields: string[], onAck: () => void, onNack: () => void, onNackDelay?: (ms: number) => void): LazyMessage<T>;
|
|
404
|
+
|
|
405
|
+
type RawCallback = (msg: Message) => void;
|
|
406
|
+
declare class Consumer {
|
|
407
|
+
private readonly client;
|
|
408
|
+
readonly streamName: string;
|
|
409
|
+
readonly config: ConsumerConfig;
|
|
410
|
+
private _consumerId?;
|
|
411
|
+
constructor(client: ArbitroClient, streamName: string, config: ConsumerConfig, _consumerId?: number | undefined);
|
|
412
|
+
get name(): string;
|
|
413
|
+
get consumerId(): number | undefined;
|
|
414
|
+
/**
|
|
415
|
+
* Publish through this consumer's stream. Returns `Promise<void>` that
|
|
416
|
+
* resolves on broker `RepOk`. Await to wait, or ignore for
|
|
417
|
+
* fire-and-forget semantics — the caller's choice, on the same call.
|
|
418
|
+
*/
|
|
419
|
+
publish(subject: string, data: Buffer): Promise<void>;
|
|
420
|
+
create(): Promise<this>;
|
|
421
|
+
upsert(): Promise<this>;
|
|
422
|
+
delete(): Promise<void>;
|
|
423
|
+
exists(): Promise<boolean>;
|
|
424
|
+
/**
|
|
425
|
+
* Live pending-ack count for this consumer (delivered, not yet acked).
|
|
426
|
+
* Uses the cached consumer ID when available; otherwise looks it up
|
|
427
|
+
* from `streamName + name`. Equivalent of NATS `num_ack_pending`.
|
|
428
|
+
*/
|
|
429
|
+
getPendings(): Promise<number>;
|
|
430
|
+
subscribe(cb?: RawCallback, opts?: SubscribeOptions): Promise<Subscription>;
|
|
431
|
+
subscribe<T extends Record<string, unknown>>(codec: Encoding<T>, cb: (msg: LazyMessage<T>) => void, opts?: SubscribeOptions): Promise<Subscription>;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
type MsgCallback = (msg: Message) => void;
|
|
435
|
+
declare class ArbitroClient {
|
|
436
|
+
private conn;
|
|
437
|
+
private readonly cfg;
|
|
438
|
+
private readonly tls;
|
|
439
|
+
private readonly logger;
|
|
440
|
+
private readonly sidCache;
|
|
441
|
+
private readonly _metrics;
|
|
442
|
+
constructor(config: ClientConfig);
|
|
443
|
+
connect(): Promise<this>;
|
|
444
|
+
/**
|
|
445
|
+
* Point-in-time snapshot of client counters: publishes sent, deliveries
|
|
446
|
+
* received, acks/nacks, active subscriptions, reconnects. Cheap — just
|
|
447
|
+
* reads plain integer fields. Call on a timer to chart throughput.
|
|
448
|
+
*/
|
|
449
|
+
metrics(): ClientMetricsSnapshot;
|
|
450
|
+
/** Internal connection accessor for Stream/Consumer publish methods. */
|
|
451
|
+
_conn(): Connection;
|
|
452
|
+
/** Default timeout from config. */
|
|
453
|
+
get timeout(): number;
|
|
454
|
+
/** Apply prefix to subject if configured. */
|
|
455
|
+
private prefixed;
|
|
456
|
+
/**
|
|
457
|
+
* Publish a message. Returns a `Promise<void>` that resolves once the
|
|
458
|
+
* broker confirms receipt (`RepOk`). The TS idiom is "everything async,
|
|
459
|
+
* the caller chooses to await":
|
|
460
|
+
*
|
|
461
|
+
* await client.publish(s, subj, data) // wait for ack
|
|
462
|
+
* client.publish(s, subj, data) // fire-and-forget
|
|
463
|
+
* client.publish(s, subj, data).catch(handleError) // async error path
|
|
464
|
+
*
|
|
465
|
+
* The broker always emits `RepOk` regardless of whether the caller
|
|
466
|
+
* awaits — that's what enables the same call site to support both
|
|
467
|
+
* semantics. A "no-reply" path doesn't save wire bytes, so it isn't
|
|
468
|
+
* exposed.
|
|
469
|
+
*/
|
|
470
|
+
publish(streamName: string, subject: string, data: Buffer, opts?: PublishOpts): Promise<void>;
|
|
471
|
+
/**
|
|
472
|
+
* @deprecated alias for {@link publish}. The default `publish` already
|
|
473
|
+
* waits for `RepOk` and returns a Promise, so this method is identical.
|
|
474
|
+
*/
|
|
475
|
+
publishAck(streamName: string, subject: string, data: Buffer, opts?: PublishOpts): Promise<void>;
|
|
476
|
+
/** Batch publish — single V2 BatchPubFrame, ONE round-trip. Resolves
|
|
477
|
+
* to `first_seq` (sequence of the first message in the batch; the N
|
|
478
|
+
* messages occupy `[first_seq, first_seq + N - 1]`).
|
|
479
|
+
*
|
|
480
|
+
* Mirrors `publish`: the call always exchanges request/response with
|
|
481
|
+
* the broker. The caller decides whether to actually wait:
|
|
482
|
+
*
|
|
483
|
+
* await client.publishBatch(stream, msgs) // barrier
|
|
484
|
+
* client.publishBatch(stream, msgs) // fire-and-forget (promise dropped)
|
|
485
|
+
* client.publishBatch(stream, msgs) // (suppress unhandled rejection)
|
|
486
|
+
* .catch(() => {})
|
|
487
|
+
*
|
|
488
|
+
* Each entry may carry an optional `msgId` for broker-side dedup on
|
|
489
|
+
* streams created with `idempotencyWindowMs > 0`. If any entry
|
|
490
|
+
* collides with a previously-stored id (or another entry in the
|
|
491
|
+
* SAME batch), the whole batch is rejected — `publishBatch` is
|
|
492
|
+
* atomic.
|
|
493
|
+
*/
|
|
494
|
+
publishBatch(streamName: string, messages: BatchPublishEntry[]): Promise<bigint>;
|
|
495
|
+
/** Request-reply. */
|
|
496
|
+
request(streamName: string, subject: string, data: Buffer, timeoutMs?: number): Promise<Buffer>;
|
|
497
|
+
/** Subscribe with explicit consumer config. */
|
|
498
|
+
subscribe(streamName: string, config: ConsumerConfig, callback?: MsgCallback, opts?: SubscribeOptions): Promise<Subscription>;
|
|
499
|
+
/** Subscribe by consumer name only (consumer must already exist). */
|
|
500
|
+
subscribe(streamName: string, callback: MsgCallback): Promise<Subscription>;
|
|
501
|
+
createStream(name: string, config: StreamConfig): Promise<Stream>;
|
|
502
|
+
upsertStream(name: string, config: StreamConfig): Promise<Stream>;
|
|
503
|
+
deleteStream(name: string, _opts?: DeleteStreamOpts): Promise<void>;
|
|
504
|
+
getStreamInfo(name: string): Promise<StreamInfo | null>;
|
|
505
|
+
listStreams(): Promise<StreamInfo[]>;
|
|
506
|
+
streamExists(name: string): Promise<boolean>;
|
|
507
|
+
purgeStream(name: string): Promise<number>;
|
|
508
|
+
drainSubject(streamName: string, subject: string): Promise<number>;
|
|
509
|
+
createConsumer(streamName: string, config: ConsumerConfig): Promise<Consumer>;
|
|
510
|
+
private createConsumerRaw;
|
|
511
|
+
upsertConsumer(streamName: string, config: ConsumerConfig): Promise<Consumer>;
|
|
512
|
+
/** Delete consumer by server-assigned ID. */
|
|
513
|
+
deleteConsumer(consumerId: number): Promise<void>;
|
|
514
|
+
/** Delete consumer by stream + name (lookup ID first). */
|
|
515
|
+
deleteConsumer(streamName: string, name: string): Promise<void>;
|
|
516
|
+
getConsumerId(streamName: string, name: string): Promise<number | null>;
|
|
517
|
+
consumerExists(streamName: string, name: string): Promise<boolean>;
|
|
518
|
+
/**
|
|
519
|
+
* Live pending-ack count for one consumer — the number of messages the
|
|
520
|
+
* consumer has been delivered but not yet acked. Equivalent of NATS
|
|
521
|
+
* JetStream's `num_ack_pending`. Single broker round-trip; engine cost
|
|
522
|
+
* is one O(1) Vec read per shard.
|
|
523
|
+
*/
|
|
524
|
+
getPending(consumerId: number): Promise<number>;
|
|
525
|
+
getPending(streamName: string, name: string): Promise<number>;
|
|
526
|
+
getConsumerInfo(streamName: string, name: string): Promise<ConsumerInfo | null>;
|
|
527
|
+
listConsumers(streamName?: string): Promise<ConsumerInfo[]>;
|
|
528
|
+
/** Resolve stream name → server wire_hash_32. Caches the result. */
|
|
529
|
+
private resolveStreamId;
|
|
530
|
+
/** Get cached stream_id or throw (for sync fire-and-forget paths). */
|
|
531
|
+
private cachedSid;
|
|
532
|
+
private ensureConsumer;
|
|
533
|
+
/** Pre-resolve stream_id from server (GetStream). Required before sync publish(). */
|
|
534
|
+
resolveStream(name: string): Promise<void>;
|
|
535
|
+
stream(name: string, config?: StreamConfig): Stream;
|
|
536
|
+
close(): Promise<void>;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
declare class Stream {
|
|
540
|
+
private readonly client;
|
|
541
|
+
readonly name: string;
|
|
542
|
+
private _config;
|
|
543
|
+
constructor(client: ArbitroClient, name: string, config?: StreamConfig);
|
|
544
|
+
get config(): StreamConfig | undefined;
|
|
545
|
+
create(config?: StreamConfig): Promise<this>;
|
|
546
|
+
upsert(config?: StreamConfig): Promise<this>;
|
|
547
|
+
delete(opts?: DeleteStreamOpts): Promise<void>;
|
|
548
|
+
exists(): Promise<boolean>;
|
|
549
|
+
info(): Promise<StreamInfo | null>;
|
|
550
|
+
/**
|
|
551
|
+
* Publish to this stream. Returns a `Promise<void>` that resolves on
|
|
552
|
+
* broker `RepOk`. Await it to wait for confirmation, or ignore the
|
|
553
|
+
* returned promise for fire-and-forget semantics.
|
|
554
|
+
*
|
|
555
|
+
* Pass `opts.msgId` to opt this publish into broker-side dedup on
|
|
556
|
+
* streams created with `idempotencyWindowMs > 0`. Duplicate ids
|
|
557
|
+
* within the window are rejected with a `ClientError` carrying the
|
|
558
|
+
* `IdempotencyDuplicate` code.
|
|
559
|
+
*/
|
|
560
|
+
publish(subject: string, data: Buffer, opts?: PublishOpts): Promise<void>;
|
|
561
|
+
/** @deprecated alias for {@link publish}. */
|
|
562
|
+
publishAck(subject: string, data: Buffer, opts?: PublishOpts): Promise<void>;
|
|
563
|
+
/** Batch publish — single V2 BatchPubFrame, ONE round-trip.
|
|
564
|
+
* Resolves with `first_seq` (the N messages occupy
|
|
565
|
+
* `[first_seq, first_seq + N - 1]`).
|
|
566
|
+
*
|
|
567
|
+
* Like {@link publish}, the call always exchanges request/response
|
|
568
|
+
* with the broker; the caller decides whether to wait via `await`. */
|
|
569
|
+
publishBatch(messages: BatchPublishEntry[]): Promise<bigint>;
|
|
570
|
+
request(subject: string, data: Buffer, timeoutMs?: number): Promise<Buffer>;
|
|
571
|
+
consumer(overrides?: Partial<ConsumerConfig>): Consumer;
|
|
572
|
+
topic<T extends Record<string, unknown>>(subject: string, codec: Encoding<T>): Topic<T>;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
declare class Topic<T extends Record<string, unknown>> {
|
|
576
|
+
private readonly stream;
|
|
577
|
+
private readonly subject;
|
|
578
|
+
private readonly codec;
|
|
579
|
+
private readonly fields;
|
|
580
|
+
constructor(stream: Stream, subject: string, codec: Encoding<T>);
|
|
581
|
+
publish(value: T): void;
|
|
582
|
+
publishAck(value: T): Promise<void>;
|
|
583
|
+
publishBatch(values: T[]): void;
|
|
584
|
+
subscribe(group: string, cb: (msg: LazyMessage<T>) => void): Promise<Subscription>;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
declare function streamId(name: Buffer | string): number;
|
|
588
|
+
|
|
589
|
+
/** Wraps a ZodObject schema as an Encoding<T>.
|
|
590
|
+
*
|
|
591
|
+
* - encode: msgpack (no Zod overhead — bytes out)
|
|
592
|
+
* - decode: msgpack unpack → schema.parse() (validates on inbound data)
|
|
593
|
+
* - fields: Object.keys(schema.shape) — powers LazyMessage<T> getters
|
|
594
|
+
*
|
|
595
|
+
* Validation cost on decode is intentional and acceptable on the management
|
|
596
|
+
* path. Do NOT use zodCodec on a hot publish loop.
|
|
597
|
+
*/
|
|
598
|
+
declare function zodCodec<S extends ZodRawShape>(zodSchema: ZodObject<S>): Encoding<output<ZodObject<S>>> & {
|
|
599
|
+
readonly fields: string[];
|
|
600
|
+
};
|
|
601
|
+
|
|
602
|
+
export { AckPolicy, ArbitroClient, ArbitroError, type BatchPublishEntry, type ClientConfig, type ClientMetricsSnapshot, Codec, Consumer, type ConsumerConfig, type ConsumerInfo, type DeleteStreamOpts, DeliverPolicy, type Encoding, ErrorCode, type ErrorCodeValue, type FieldType, type FieldTypeMap, type FlushConfig, type InferSchema, type JournalConfig, JournalType, JsonCodec, type LazyMessage, type LogFn, type Logger, Message, type PublishOpts, type ReconnectConfig, type Schema, Stream, type StreamConfig, type StreamInfo, StringCodec, type SubjectInflightLimit, type SubscribeOptions, Subscription, type TlsConfig, Topic, decodeJson, decodeString, encodeJson, encodeString, makeLazyMessage, schema, streamId, zodCodec };
|