@prosody-events/prosody 0.3.1 → 0.5.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.
Files changed (6) hide show
  1. package/README.md +657 -353
  2. package/bindings.d.ts +780 -48
  3. package/bindings.js +226 -83
  4. package/index.d.ts +706 -22
  5. package/index.js +1446 -105
  6. package/package.json +23 -20
package/bindings.d.ts CHANGED
@@ -31,6 +31,45 @@ export declare class AdminClient {
31
31
  deleteTopic(name: string): Promise<void>
32
32
  }
33
33
 
34
+ /** A Kafka excise record received from a consumer. */
35
+ export declare class ExciseMessage {
36
+ /** The Kafka topic this record was consumed from. */
37
+ get topic(): string
38
+ /** The partition number within the topic. */
39
+ get partition(): number
40
+ /** The offset of this record within its partition. */
41
+ get offset(): bigint
42
+ /** The timestamp when the record was produced. */
43
+ get timestamp(): Date
44
+ /** The key that this record excises. */
45
+ get key(): string
46
+ }
47
+
48
+ /** A Kafka message received from a consumer. */
49
+ export declare class Message {
50
+ /** The Kafka topic this message was consumed from. */
51
+ get topic(): string
52
+ /** The partition number within the topic. */
53
+ get partition(): number
54
+ /** The offset of this message within its partition. */
55
+ get offset(): bigint
56
+ /** The timestamp when the message was produced. */
57
+ get timestamp(): Date
58
+ /** The message key used for partitioning. */
59
+ get key(): string
60
+ /**
61
+ * The payload as the raw JSON text read from the wire.
62
+ *
63
+ * Borrowed from the wrapped message and copied once into a JavaScript
64
+ * string; no intermediate Rust buffer is allocated. The typed layer parses
65
+ * it lazily, so a handler that reads only metadata never pays for a parse.
66
+ *
67
+ * @throws Error if the payload is not valid UTF-8, which valid JSON always
68
+ * is.
69
+ */
70
+ get payload(): string
71
+ }
72
+
34
73
  /**
35
74
  * A native client wrapper for the Prosody high-level client.
36
75
  * Provides methods for sending messages, subscribing to topics, and managing
@@ -43,7 +82,7 @@ export declare class NativeClient {
43
82
  * @param config - The configuration for the client
44
83
  * @throws Error if the client creation fails
45
84
  */
46
- constructor(config: Configuration)
85
+ static create(config: Configuration): Promise<NativeClient>
47
86
  /**
48
87
  * Gets the current state of the consumer.
49
88
  *
@@ -51,19 +90,37 @@ export declare class NativeClient {
51
90
  * @throws Error if the operation fails
52
91
  */
53
92
  consumerState(): Promise<ConsumerState>
93
+ /** Builds a read-only view of a published value collection. */
94
+ publishedValue(subsystem: string, name: string, cacheMs?: number | undefined | null, cacheDisabled?: boolean | undefined | null): Promise<NativePublishedValue>
95
+ /** Builds a read-only view of a published map collection. */
96
+ publishedMap(subsystem: string, name: string, cacheMs?: number | undefined | null, cacheDisabled?: boolean | undefined | null): Promise<NativePublishedMap>
97
+ /** Builds a read-only view of a published deque collection. */
98
+ publishedDeque(subsystem: string, name: string, cacheMs?: number | undefined | null, cacheDisabled?: boolean | undefined | null): Promise<NativePublishedDeque>
54
99
  /**
55
100
  * Sends a message to a specified topic.
56
101
  *
102
+ * The payload crosses as its JSON text and is forwarded to Kafka verbatim;
103
+ * Rust never parses it. The caller supplies the event metadata, read off
104
+ * the payload object before it was serialized, so the boundary costs no
105
+ * JSON re-parse.
106
+ *
57
107
  * @param topic - The topic to send the message to
58
108
  * @param key - The key of the message
59
- * @param payload - The payload of the message (must be JSON-serializable)
109
+ * @param payload - The payload as JSON text
110
+ * @param metadata - The event metadata read off the payload object
60
111
  * @param otelContext - The OpenTelemetry context for tracing
61
112
  * @param maybeAbort - Optional promise that resolves when the operation
62
113
  * should be aborted @returns A promise that resolves when the message
63
114
  * has been sent @throws Error if the send operation fails or is
64
115
  * aborted
65
116
  */
66
- send(topic: string, key: string, payload: any, otelContext: Record<string, string>, maybeAbort?: Promise<undefined> | undefined | null): Promise<void>
117
+ send(topic: string, key: string, payload: string, metadata: EventMetadata, otelContext: Record<string, string>, maybeAbort?: Promise<undefined> | undefined | null): Promise<void>
118
+ /** Sends an excise record to a specified topic. */
119
+ excise(topic: string, key: string, otelContext: Record<string, string>, maybeAbort?: Promise<undefined> | undefined | null): Promise<void>
120
+ /** Sends one request and returns one outcome per subsystem. */
121
+ request(request: NativeRequest, otelContext: Record<string, string>, maybeAbort?: Promise<undefined> | undefined | null): Promise<Array<NativeSubsystemOutcome>>
122
+ /** Sends one excise request and returns one outcome per subsystem. */
123
+ requestExcise(request: NativeExciseRequest, otelContext: Record<string, string>, maybeAbort?: Promise<undefined> | undefined | null): Promise<Array<NativeSubsystemOutcome>>
67
124
  /**
68
125
  * Subscribes to receive messages using the provided event handler.
69
126
  *
@@ -71,7 +128,7 @@ export declare class NativeClient {
71
128
  * timers @returns A promise that resolves when the subscription is
72
129
  * established @throws Error if the subscription fails
73
130
  */
74
- subscribe(eventHandler: { onMessage: (err: null | Error, args: [Context, Message, Record<string, string>]) => Promise<void>; onTimer: (err: null | Error, args: [Context, Timer, Record<string, string>]) => Promise<void>; isPermanent: (args: [Error]) => boolean }): Promise<void>
131
+ subscribe(eventHandler: { onMessage: (err: null | Error, args: [NativeContext, Message, Record<string, string>]) => Promise<string>; onExcise: (err: null | Error, args: [NativeContext, ExciseMessage, Record<string, string>]) => Promise<string>; onTimer: (err: null | Error, args: [NativeContext, Timer, Record<string, string>]) => Promise<string>; isPermanent: (args: [Error]) => boolean }): Promise<void>
75
132
  /**
76
133
  * Gets the number of partitions assigned to the consumer.
77
134
  *
@@ -93,6 +150,13 @@ export declare class NativeClient {
93
150
  * complete @throws Error if the unsubscribe operation fails
94
151
  */
95
152
  unsubscribe(): Promise<void>
153
+ /**
154
+ * Shuts down the client and all its services.
155
+ *
156
+ * @returns A promise that resolves when shutdown is complete
157
+ * @throws Error if shutdown fails
158
+ */
159
+ shutdown(): Promise<void>
96
160
  /**
97
161
  * Gets the source system identifier configured for the client.
98
162
  *
@@ -159,6 +223,480 @@ export declare class NativeContext {
159
223
  * @throws Error if retrieval fails.
160
224
  */
161
225
  scheduled(otelContext: Record<string, string>): Promise<Array<Date>>
226
+ /**
227
+ * Vends the state handle for the named JSON value collection.
228
+ *
229
+ * Vending verifies the collection's registration (core-side); no span is
230
+ * opened here — vended handles outlive the call, and every operation opens
231
+ * its own span.
232
+ *
233
+ * @param name The registered collection name.
234
+ * @returns The value-state handle for this event's transaction.
235
+ * @throws Error (permanent) if the name is unregistered or its registered
236
+ * identity mismatches.
237
+ */
238
+ valueState(name: string): NativeJsonValueState
239
+ /**
240
+ * Vends the state handle for the named JSON map collection.
241
+ *
242
+ * Vending verifies the collection's registration (core-side); no span is
243
+ * opened here — vended handles outlive the call, and every operation opens
244
+ * its own span.
245
+ *
246
+ * @param name The registered collection name.
247
+ * @returns The map-state handle for this event's transaction.
248
+ * @throws Error (permanent) if the name is unregistered or its registered
249
+ * identity mismatches.
250
+ */
251
+ mapState(name: string): NativeJsonMapState
252
+ /**
253
+ * Vends the state handle for the named JSON deque collection.
254
+ *
255
+ * Vending verifies the collection's registration (core-side); no span is
256
+ * opened here — vended handles outlive the call, and every operation opens
257
+ * its own span.
258
+ *
259
+ * @param name The registered collection name.
260
+ * @returns The deque-state handle for this event's transaction.
261
+ * @throws Error (permanent) if the name is unregistered or its registered
262
+ * identity mismatches.
263
+ */
264
+ dequeState(name: string): NativeJsonDequeState
265
+ /**
266
+ * Vends the state handle for the named Kafka-message value collection.
267
+ *
268
+ * Items are the full `Message` the handler received, loader-resolved on
269
+ * read. Vending verifies registration (core-side); no span is opened here.
270
+ *
271
+ * @param name The registered collection name.
272
+ * @returns The message value-state handle for this event's transaction.
273
+ * @throws Error (permanent) if the name is unregistered or its registered
274
+ * identity mismatches.
275
+ */
276
+ messageValueState(name: string): NativeMessageValueState
277
+ /**
278
+ * Vends the state handle for the named Kafka-message map collection.
279
+ *
280
+ * Items are the full `Message` the handler received, loader-resolved on
281
+ * read. Vending verifies registration (core-side); no span is opened here.
282
+ *
283
+ * @param name The registered collection name.
284
+ * @returns The message map-state handle for this event's transaction.
285
+ * @throws Error (permanent) if the name is unregistered or its registered
286
+ * identity mismatches.
287
+ */
288
+ messageMapState(name: string): NativeMessageMapState
289
+ /**
290
+ * Vends the state handle for the named Kafka-message deque collection.
291
+ *
292
+ * Items are the full `Message` the handler received, loader-resolved on
293
+ * read. Vending verifies registration (core-side); no span is opened here.
294
+ *
295
+ * @param name The registered collection name.
296
+ * @returns The message deque-state handle for this event's transaction.
297
+ * @throws Error (permanent) if the name is unregistered or its registered
298
+ * identity mismatches.
299
+ */
300
+ messageDequeState(name: string): NativeMessageDequeState
301
+ }
302
+
303
+ /** Demand-driven cursor with one element type. */
304
+ export declare class NativeJsonDequeCursor {
305
+ /** Pulls the next ready chunk. */
306
+ nextChunk(otelContext: Record<string, string>): Promise<Array<string> | null>
307
+ /** Closes the cursor. */
308
+ close(): Promise<void>
309
+ }
310
+
311
+ /** JSON deque state handle for one event. */
312
+ export declare class NativeJsonDequeState {
313
+ /**
314
+ * The number of live elements.
315
+ *
316
+ * @param otelContext The OpenTelemetry context for tracing.
317
+ * @returns The element count.
318
+ * @throws Error carrying the category on `cause` if the read fails, or if
319
+ * the count exceeds the `u32` range.
320
+ */
321
+ len(otelContext: Record<string, string>): Promise<number>
322
+ /**
323
+ * Whether the deque holds no live elements.
324
+ *
325
+ * @param otelContext The OpenTelemetry context for tracing.
326
+ * @returns True when the deque is empty.
327
+ * @throws Error carrying the category on `cause` if the read fails.
328
+ */
329
+ isEmpty(otelContext: Record<string, string>): Promise<boolean>
330
+ /**
331
+ * Reads the element at front-relative position `index`.
332
+ *
333
+ * @param index The zero-based position from the front.
334
+ * @param otelContext The OpenTelemetry context for tracing.
335
+ * @returns The element, or null past the end.
336
+ * @throws Error carrying the category on `cause` if the read fails.
337
+ */
338
+ get(index: number, otelContext: Record<string, string>): Promise<string | null>
339
+ /**
340
+ * Reads the front endpoint SLOT without a length round trip — exactly
341
+ * `get(0)`.
342
+ *
343
+ * Decodes and resolves the returned element (unlike eviction). An empty
344
+ * deque, or a front endpoint slot expired under a TTL, yields null even
345
+ * when live interior elements exist — a peek never searches inward.
346
+ *
347
+ * @param otelContext The OpenTelemetry context for tracing.
348
+ * @returns The front element, or null when the endpoint slot is empty.
349
+ * @throws Error carrying the category on `cause` if the read fails.
350
+ */
351
+ peekFront(otelContext: Record<string, string>): Promise<string | null>
352
+ /**
353
+ * Reads the back endpoint SLOT without a length round trip — exactly
354
+ * `get(len − 1)`.
355
+ *
356
+ * Decodes and resolves the returned element (unlike eviction). An empty
357
+ * deque, or a back endpoint slot expired under a TTL, yields null even
358
+ * when live interior elements exist — a peek never searches inward.
359
+ *
360
+ * @param otelContext The OpenTelemetry context for tracing.
361
+ * @returns The back element, or null when the endpoint slot is empty.
362
+ * @throws Error carrying the category on `cause` if the read fails.
363
+ */
364
+ peekBack(otelContext: Record<string, string>): Promise<string | null>
365
+ /**
366
+ * Appends a JSON document at the back.
367
+ *
368
+ * JSON null is not a storable element and is rejected with a transient
369
+ * error.
370
+ *
371
+ * @param json The document's JSON text.
372
+ * @param otelContext The OpenTelemetry context for tracing.
373
+ * @throws Error carrying the category on `cause` if the write fails.
374
+ */
375
+ pushBack(json: string, otelContext: Record<string, string>): Promise<void>
376
+ /**
377
+ * Prepends a JSON document at the front.
378
+ *
379
+ * JSON null is not a storable element and is rejected with a transient
380
+ * error.
381
+ *
382
+ * @param json The document's JSON text.
383
+ * @param otelContext The OpenTelemetry context for tracing.
384
+ * @throws Error carrying the category on `cause` if the write fails.
385
+ */
386
+ pushFront(json: string, otelContext: Record<string, string>): Promise<void>
387
+ /**
388
+ * Removes and returns the front element.
389
+ *
390
+ * @param otelContext The OpenTelemetry context for tracing.
391
+ * @returns The removed front element, or null when empty.
392
+ * @throws Error carrying the category on `cause` if the operation fails.
393
+ */
394
+ popFront(otelContext: Record<string, string>): Promise<string | null>
395
+ /**
396
+ * Removes and returns the back element.
397
+ *
398
+ * @param otelContext The OpenTelemetry context for tracing.
399
+ * @returns The removed back element, or null when empty.
400
+ * @throws Error carrying the category on `cause` if the operation fails.
401
+ */
402
+ popBack(otelContext: Record<string, string>): Promise<string | null>
403
+ /**
404
+ * Removes every element.
405
+ *
406
+ * @param otelContext The OpenTelemetry context for tracing.
407
+ * @throws Error carrying the category on `cause` if the clear fails.
408
+ */
409
+ clear(otelContext: Record<string, string>): Promise<void>
410
+ /**
411
+ * Opens a demand-driven cursor over the live elements in index order.
412
+ *
413
+ * Synchronous — it performs no I/O. The extracted JavaScript context is
414
+ * active while core constructs its semantic stream span; chunk pulls do
415
+ * not create binding spans.
416
+ *
417
+ * @param direction The scan direction (`"forward"` or `"backward"`).
418
+ * @param otelContext The OpenTelemetry context for tracing.
419
+ * @returns A cursor over the deque elements.
420
+ * @throws Error if the direction token is invalid.
421
+ */
422
+ scan(direction: string, otelContext: Record<string, string>): NativeJsonDequeCursor
423
+ /** Durably commits the buffered operations. */
424
+ commit(otelContext: Record<string, string>): Promise<void>
425
+ /** Discards the buffered operations. */
426
+ rollback(otelContext: Record<string, string>): Promise<void>
427
+ }
428
+
429
+ /** Demand-driven cursor with one element type. */
430
+ export declare class NativeJsonMapCursor {
431
+ /** Pulls the next ready chunk. */
432
+ nextChunk(otelContext: Record<string, string>): Promise<Array<[string, string]> | null>
433
+ /** Closes the cursor. */
434
+ close(): Promise<void>
435
+ }
436
+
437
+ /** JSON ordered-map state handle for one event. */
438
+ export declare class NativeJsonMapState {
439
+ /**
440
+ * Reads the value for `key`.
441
+ *
442
+ * @param key The map key.
443
+ * @param otelContext The OpenTelemetry context for tracing.
444
+ * @returns The value, or null when the key is absent.
445
+ * @throws Error carrying the category on `cause` if the read fails.
446
+ */
447
+ get(key: string, otelContext: Record<string, string>): Promise<string | null>
448
+ /**
449
+ * Reads several keys in a single call.
450
+ *
451
+ * Returns one entry per key, in the same order requested: the entry at
452
+ * index `i` is the value for `keys[i]`. A key that isn't there reads as
453
+ * null, and a key listed more than once is answered at each of its spots.
454
+ * The whole read happens as one step, so no other change to this event's
455
+ * state can slip in partway through.
456
+ *
457
+ * @param keys The keys to read, in order.
458
+ * @param otelContext The OpenTelemetry context for tracing.
459
+ * @returns One result per input key; null for a key that is absent.
460
+ * @throws Error carrying the category on `cause` if the read fails.
461
+ */
462
+ getMany(keys: Array<string>, otelContext: Record<string, string>): Promise<Array<string | undefined | null>>
463
+ /**
464
+ * Reports whether a stored cell exists for `key`.
465
+ *
466
+ * Reads the event's dirty overlay (read-your-writes) and answers presence
467
+ * WITHOUT decoding the value or running the resolver — a message-backed
468
+ * map answers with zero Kafka fetches and can report `true` for a
469
+ * message that can no longer be fetched. This is NOT "no I/O": a cache
470
+ * miss can still reach Cassandra, so it is async and fallible exactly
471
+ * like `get`.
472
+ *
473
+ * @param key The map key.
474
+ * @param otelContext The OpenTelemetry context for tracing.
475
+ * @returns True when a stored cell exists for `key`.
476
+ * @throws Error carrying the category on `cause` if the read fails.
477
+ */
478
+ contains(key: string, otelContext: Record<string, string>): Promise<boolean>
479
+ /**
480
+ * Inserts or overwrites `key` with a JSON document.
481
+ *
482
+ * JSON null is rejected with a transient error naming `delete` as the way
483
+ * to remove an entry.
484
+ *
485
+ * @param key The map key.
486
+ * @param json The document's JSON text.
487
+ * @param otelContext The OpenTelemetry context for tracing.
488
+ * @throws Error carrying the category on `cause` if the write fails.
489
+ */
490
+ set(key: string, json: string, otelContext: Record<string, string>): Promise<void>
491
+ /**
492
+ * Removes `key`.
493
+ *
494
+ * @param key The map key.
495
+ * @param otelContext The OpenTelemetry context for tracing.
496
+ * @throws Error carrying the category on `cause` if the removal fails.
497
+ */
498
+ remove(key: string, otelContext: Record<string, string>): Promise<void>
499
+ /**
500
+ * Removes every entry.
501
+ *
502
+ * @param otelContext The OpenTelemetry context for tracing.
503
+ * @throws Error carrying the category on `cause` if the clear fails.
504
+ */
505
+ clear(otelContext: Record<string, string>): Promise<void>
506
+ /**
507
+ * Opens a demand-driven cursor over the live entries in key order.
508
+ *
509
+ * Synchronous — it performs no I/O. The extracted JavaScript context is
510
+ * active while core constructs its semantic stream span; chunk pulls do
511
+ * not create binding spans. Entries are yielded as `(key, value)` pairs.
512
+ *
513
+ * @param direction The scan direction (`"forward"` or `"backward"`).
514
+ * @param otelContext The OpenTelemetry context for tracing.
515
+ * @returns A cursor over the map entries.
516
+ * @throws Error if the direction token is invalid.
517
+ */
518
+ scan(direction: string, otelContext: Record<string, string>): NativeJsonMapCursor
519
+ /**
520
+ * Opens a demand-driven cursor over the live KEYS in key order.
521
+ *
522
+ * Skips the value codec and the resolver (no value decode, no Kafka
523
+ * fetch), so a message-backed map enumerates keys with zero Kafka
524
+ * fetches — but it still reads presence, so it is not zero-I/O.
525
+ * Synchronous like `scan`: the extracted JavaScript context is active
526
+ * while core constructs its semantic stream span. Yields bare keys.
527
+ *
528
+ * @param direction The scan direction (`"forward"` or `"backward"`).
529
+ * @param otelContext The OpenTelemetry context for tracing.
530
+ * @returns A cursor over the map keys.
531
+ * @throws Error if the direction token is invalid.
532
+ */
533
+ keys(direction: string, otelContext: Record<string, string>): NativeMapKeyCursor
534
+ /** Durably commits the buffered operations. */
535
+ commit(otelContext: Record<string, string>): Promise<void>
536
+ /** Discards the buffered operations. */
537
+ rollback(otelContext: Record<string, string>): Promise<void>
538
+ }
539
+
540
+ /** JSON single-value state handle for one event. */
541
+ export declare class NativeJsonValueState {
542
+ /**
543
+ * Reads the current value.
544
+ *
545
+ * @param otelContext The OpenTelemetry context for tracing.
546
+ * @returns The current value, or null when absent/cleared.
547
+ * @throws Error carrying the category on `cause` if the read fails.
548
+ */
549
+ get(otelContext: Record<string, string>): Promise<string | null>
550
+ /**
551
+ * Buffers a write of a JSON document.
552
+ *
553
+ * JSON null is rejected with a transient error naming `clear` as the way
554
+ * to delete.
555
+ *
556
+ * @param json The document's JSON text.
557
+ * @param otelContext The OpenTelemetry context for tracing.
558
+ * @throws Error carrying the category on `cause` if the write fails.
559
+ */
560
+ set(json: string, otelContext: Record<string, string>): Promise<void>
561
+ /**
562
+ * Buffers a clear of the value.
563
+ *
564
+ * @param otelContext The OpenTelemetry context for tracing.
565
+ * @throws Error carrying the category on `cause` if the clear fails.
566
+ */
567
+ clear(otelContext: Record<string, string>): Promise<void>
568
+ /** Durably commits the buffered operations. */
569
+ commit(otelContext: Record<string, string>): Promise<void>
570
+ /** Discards the buffered operations. */
571
+ rollback(otelContext: Record<string, string>): Promise<void>
572
+ }
573
+
574
+ /** Demand-driven cursor with one element type. */
575
+ export declare class NativeMapKeyCursor {
576
+ /** Pulls the next ready chunk. */
577
+ nextChunk(otelContext: Record<string, string>): Promise<Array<string> | null>
578
+ /** Closes the cursor. */
579
+ close(): Promise<void>
580
+ }
581
+
582
+ /** Demand-driven cursor with one element type. */
583
+ export declare class NativeMessageDequeCursor {
584
+ /** Pulls the next ready chunk. */
585
+ nextChunk(otelContext: Record<string, string>): Promise<Array<Message> | null>
586
+ /** Closes the cursor. */
587
+ close(): Promise<void>
588
+ }
589
+
590
+ /** Kafka-message deque state handle for one event. */
591
+ export declare class NativeMessageDequeState {
592
+ /** Returns the number of live elements. */
593
+ len(otelContext: Record<string, string>): Promise<number>
594
+ /** Reports whether the deque has no live elements. */
595
+ isEmpty(otelContext: Record<string, string>): Promise<boolean>
596
+ /** Reads one element by its position from the front. */
597
+ get(index: number, otelContext: Record<string, string>): Promise<Message | null>
598
+ /** Reads the front endpoint. */
599
+ peekFront(otelContext: Record<string, string>): Promise<Message | null>
600
+ /** Reads the back endpoint. */
601
+ peekBack(otelContext: Record<string, string>): Promise<Message | null>
602
+ /** Appends a Kafka message. */
603
+ pushBack(message: Message, otelContext: Record<string, string>): Promise<void>
604
+ /** Prepends a Kafka message. */
605
+ pushFront(message: Message, otelContext: Record<string, string>): Promise<void>
606
+ /** Removes and returns the front element. */
607
+ popFront(otelContext: Record<string, string>): Promise<Message | null>
608
+ /** Removes and returns the back element. */
609
+ popBack(otelContext: Record<string, string>): Promise<Message | null>
610
+ /** Removes every element. */
611
+ clear(otelContext: Record<string, string>): Promise<void>
612
+ /** Opens a cursor over the live elements. */
613
+ scan(direction: string, otelContext: Record<string, string>): NativeMessageDequeCursor
614
+ /** Durably commits the buffered operations. */
615
+ commit(otelContext: Record<string, string>): Promise<void>
616
+ /** Discards the buffered operations. */
617
+ rollback(otelContext: Record<string, string>): Promise<void>
618
+ }
619
+
620
+ /** Demand-driven cursor with one element type. */
621
+ export declare class NativeMessageMapCursor {
622
+ /** Pulls the next ready chunk. */
623
+ nextChunk(otelContext: Record<string, string>): Promise<Array<[string, Message]> | null>
624
+ /** Closes the cursor. */
625
+ close(): Promise<void>
626
+ }
627
+
628
+ /** Kafka-message ordered-map state handle for one event. */
629
+ export declare class NativeMessageMapState {
630
+ /** Reads the value for `key`. */
631
+ get(key: string, otelContext: Record<string, string>): Promise<Message | null>
632
+ /** Reads several keys in one operation. */
633
+ getMany(keys: Array<string>, otelContext: Record<string, string>): Promise<Array<Message | undefined | null>>
634
+ /** Reports whether `key` has a stored cell. */
635
+ contains(key: string, otelContext: Record<string, string>): Promise<boolean>
636
+ /** Inserts or overwrites `key` with a Kafka message. */
637
+ set(key: string, message: Message, otelContext: Record<string, string>): Promise<void>
638
+ /** Removes `key`. */
639
+ remove(key: string, otelContext: Record<string, string>): Promise<void>
640
+ /** Removes every entry. */
641
+ clear(otelContext: Record<string, string>): Promise<void>
642
+ /** Opens a cursor over entries in key order. */
643
+ scan(direction: string, otelContext: Record<string, string>): NativeMessageMapCursor
644
+ /** Opens a cursor over keys in key order. */
645
+ keys(direction: string, otelContext: Record<string, string>): NativeMapKeyCursor
646
+ /** Durably commits the buffered operations. */
647
+ commit(otelContext: Record<string, string>): Promise<void>
648
+ /** Discards the buffered operations. */
649
+ rollback(otelContext: Record<string, string>): Promise<void>
650
+ }
651
+
652
+ /** Kafka-message single-value state handle for one event. */
653
+ export declare class NativeMessageValueState {
654
+ /** Reads the current value. */
655
+ get(otelContext: Record<string, string>): Promise<Message | null>
656
+ /** Buffers a write of a Kafka message. */
657
+ set(message: Message, otelContext: Record<string, string>): Promise<void>
658
+ /** Buffers a clear of the value. */
659
+ clear(otelContext: Record<string, string>): Promise<void>
660
+ /** Durably commits the buffered operations. */
661
+ commit(otelContext: Record<string, string>): Promise<void>
662
+ /** Discards the buffered operations. */
663
+ rollback(otelContext: Record<string, string>): Promise<void>
664
+ }
665
+
666
+ /** A read-only published deque collection. */
667
+ export declare class NativePublishedDeque {
668
+ /** Reads one front-relative element. */
669
+ get(key: string, index: number, otelContext: Record<string, string>): Promise<string | null>
670
+ /** Returns the committed deque length. */
671
+ length(key: string, otelContext: Record<string, string>): Promise<number>
672
+ /** Reports whether the committed deque is empty. */
673
+ isEmpty(key: string, otelContext: Record<string, string>): Promise<boolean>
674
+ /** Reads the committed front element. */
675
+ peekFront(key: string, otelContext: Record<string, string>): Promise<string | null>
676
+ /** Reads the committed back element. */
677
+ peekBack(key: string, otelContext: Record<string, string>): Promise<string | null>
678
+ /** Opens an ordered element cursor. */
679
+ scan(key: string, direction: string, otelContext: Record<string, string>): Promise<NativeJsonDequeCursor>
680
+ }
681
+
682
+ /** A read-only published map collection. */
683
+ export declare class NativePublishedMap {
684
+ /** Reads one committed map entry. */
685
+ get(key: string, mapKey: string, otelContext: Record<string, string>): Promise<string | null>
686
+ /** Reads entries aligned with the supplied map keys. */
687
+ getMany(key: string, mapKeys: Array<string>, otelContext: Record<string, string>): Promise<Array<string | undefined | null>>
688
+ /** Reports whether a committed map entry exists. */
689
+ contains(key: string, mapKey: string, otelContext: Record<string, string>): Promise<boolean>
690
+ /** Opens an ordered entry cursor. */
691
+ scan(key: string, direction: string, otelContext: Record<string, string>): Promise<NativeJsonMapCursor>
692
+ /** Opens an ordered key cursor. */
693
+ keys(key: string, direction: string, otelContext: Record<string, string>): Promise<NativeMapKeyCursor>
694
+ }
695
+
696
+ /** A read-only published value collection. */
697
+ export declare class NativePublishedValue {
698
+ /** Reads the committed value for a partition key. */
699
+ get(key: string, otelContext: Record<string, string>): Promise<string | null>
162
700
  }
163
701
 
164
702
  /** Configuration options for the Prosody client. */
@@ -173,7 +711,7 @@ export interface Configuration {
173
711
  groupId?: string
174
712
  /**
175
713
  * Global shared cache capacity across all partitions for deduplicating
176
- * messages. Set to 0 to disable deduplication entirely.
714
+ * messages. Must be greater than 0.
177
715
  */
178
716
  idempotenceCacheSize?: number
179
717
  /**
@@ -232,7 +770,7 @@ export interface Configuration {
232
770
  slabSizeMs?: number
233
771
  /** Cassandra contact nodes (hostnames or IPs). */
234
772
  cassandraNodes?: string | Array<string>
235
- /** Cassandra keyspace to use for storing timer data. */
773
+ /** Cassandra keyspace used for persistent Prosody data. */
236
774
  cassandraKeyspace?: string
237
775
  /** Preferred Cassandra datacenter for query routing. */
238
776
  cassandraDatacenter?: string
@@ -243,8 +781,8 @@ export interface Configuration {
243
781
  /** Password for authenticating with Cassandra. */
244
782
  cassandraPassword?: string
245
783
  /**
246
- * Retention period for failed/unprocessed timer data in Cassandra in
247
- * seconds.
784
+ * Retention period for persistent timer and deferral data in Cassandra,
785
+ * in seconds.
248
786
  */
249
787
  cassandraRetentionSeconds?: number
250
788
  /**
@@ -306,29 +844,33 @@ export interface Configuration {
306
844
  */
307
845
  deferMaxDelayMs?: number
308
846
  /**
309
- * Failure rate threshold for enabling deferral (0.0 to 1.0).
847
+ * Failure rate threshold for disabling deferral (0.0 to 1.0).
310
848
  * When exceeded within the failure window, deferral is disabled.
311
849
  */
312
850
  deferFailureThreshold?: number
313
851
  /** Sliding window duration (in milliseconds) for failure rate tracking. */
314
852
  deferFailureWindowMs?: number
315
- /**
316
- * Cache size for defer middleware.
317
- * Controls capacity for store cache and loader cache.
318
- */
319
- deferCacheSize?: number
320
853
  /**
321
854
  * Maximum deferred store cache entries per Cassandra defer store.
322
855
  * Env: `PROSODY_DEFER_STORE_CACHE_SIZE`. Default: 8192.
323
856
  */
324
857
  deferStoreCacheSize?: number
325
- /** Timeout for Kafka seek operations in milliseconds. */
326
- deferSeekTimeoutMs?: number
858
+ /**
859
+ * Capacity of the shared Kafka message loader cache.
860
+ * Env: `PROSODY_LOADER_CACHE_SIZE`. Default: 1024.
861
+ */
862
+ loaderCacheSize?: number
863
+ /**
864
+ * Timeout for Kafka loader seek operations in milliseconds.
865
+ * Env: `PROSODY_LOADER_SEEK_TIMEOUT`. Default: 30 seconds.
866
+ */
867
+ loaderSeekTimeoutMs?: number
327
868
  /**
328
869
  * Messages to read sequentially before seeking.
329
870
  * If next offset is within this threshold, reads rather than seeks.
871
+ * Env: `PROSODY_LOADER_DISCARD_THRESHOLD`. Default: 100.
330
872
  */
331
- deferDiscardThreshold?: number
873
+ loaderDiscardThreshold?: number
332
874
  /**
333
875
  * Fixed timeout duration for handler execution in milliseconds.
334
876
  * If unset, defaults to 80% of stall threshold.
@@ -354,21 +896,117 @@ export interface Configuration {
354
896
  * or `"follows_from"`. Default: `"follows_from"`.
355
897
  */
356
898
  timerSpans?: string
899
+ /**
900
+ * Keyed-state collections to register before subscribe.
901
+ *
902
+ * Each entry declares one collection by name, kind, and payload. Duplicate
903
+ * names within this set are rejected.
904
+ */
905
+ stateCollections?: Array<StateCollectionConfig>
906
+ /**
907
+ * Disk workspace for the local keyed-state cache.
908
+ *
909
+ * Each live client needs its own directory because it is locked
910
+ * exclusively. Falls back to the `PROSODY_STATE_CACHE_DIR` environment
911
+ * variable, then a per-client temporary directory. Must not be an
912
+ * empty string when set.
913
+ */
914
+ stateCacheDir?: string
915
+ /**
916
+ * Capacity of the owning keyed-state cache. Accepts a human-readable size.
917
+ * Uses `PROSODY_STATE_OWNED_CACHE_SIZE` when omitted. Otherwise, the
918
+ * storage engine selects its default.
919
+ */
920
+ stateOwnedCacheSize?: string
921
+ /**
922
+ * Capacity of the published-state read-through cache. Uses
923
+ * `PROSODY_STATE_READ_CACHE_SIZE` when omitted. It then uses the owning
924
+ * cache size when set, or 1 MiB when both sizes are unset.
925
+ */
926
+ stateReadCacheSize?: string
927
+ /**
928
+ * Default cache policy for published-state reads. Uses
929
+ * `PROSODY_STATE_READ_CACHE_TTL` when omitted, then 5 seconds.
930
+ */
931
+ stateReadCache?: ReadCacheConfiguration
932
+ /**
933
+ * Delay in whole seconds between staging a provisional cell and the
934
+ * keyed-state recovery sweep. Every registered TTL must strictly exceed
935
+ * this. Falls back to the `PROSODY_STATE_RECOVERY_DELAY` environment
936
+ * variable (a duration string such as `30s`), then to 30 seconds. Must be
937
+ * a whole number of seconds >= 1 when set (fractional, negative, and
938
+ * non-finite values are rejected).
939
+ */
940
+ stateRecoveryDelaySeconds?: number
941
+ /**
942
+ * Subsystem under which published JSON collections are advertised.
943
+ * Uses `PROSODY_SUBSYSTEM` when omitted. Published collections require it.
944
+ */
945
+ subsystem?: string
946
+ /**
947
+ * Socket address for the peer gRPC listener. Uses
948
+ * `PROSODY_PEER_BIND_ADDRESS` when omitted.
949
+ */
950
+ peerBindAddress?: string
951
+ /**
952
+ * gRPC connect URI that remote peers use. Uses
953
+ * `PROSODY_PEER_ADVERTISED_CONNECT` when omitted.
954
+ */
955
+ peerAdvertisedConnect?: string
956
+ /**
957
+ * Network name used to select direct peer routes. Uses
958
+ * `PROSODY_PEER_NETWORK_NAME` when omitted.
959
+ */
960
+ peerNetworkName?: string
961
+ /**
962
+ * Maximum channels and peer records in each peer cache. Uses
963
+ * `PROSODY_PEER_CACHE_CAPACITY` when omitted.
964
+ */
965
+ peerCacheCapacity?: number
966
+ /**
967
+ * Peer registration lease duration in seconds. Uses
968
+ * `PROSODY_PEER_REGISTRATION_TTL` when omitted.
969
+ */
970
+ peerRegistrationTtlSeconds?: number
357
971
  }
358
972
 
359
- /**
360
- * Current state of the consumer.
361
- * Represents the lifecycle stages of a Prosody consumer.
362
- */
363
- export type ConsumerState = /** The consumer is not yet configured */
973
+ /** Current consumer state. */
974
+ export type ConsumerState = /** The client is shut down. */
975
+ 'Shutdown'|
976
+ /** The consumer is not configured. */
364
977
  'Unconfigured'|
365
- /** The consumer is configured but not running */
978
+ /** The consumer is configured but not active. */
366
979
  'Configured'|
367
- /** The consumer is actively running */
980
+ /** The consumer is active. */
368
981
  'Running'|
369
- /** The consumer configuration failed */
982
+ /** The consumer configuration failed. */
370
983
  'ConfigurationFailed';
371
984
 
985
+ /**
986
+ * Event metadata read off a payload before it was serialized.
987
+ *
988
+ * It lets the send path forward the payload without another parse.
989
+ */
990
+ export interface EventMetadata {
991
+ /** The payload's `id` field. */
992
+ eventId?: string
993
+ /** The payload's `type` field. */
994
+ eventType?: string
995
+ }
996
+
997
+ /** Type alias for excise handler arguments. */
998
+ export type ExciseHandlerArgs =
999
+ [NativeContext, ExciseMessage, Record<string, string>]
1000
+
1001
+ /**
1002
+ * Exports all pending telemetry data.
1003
+ *
1004
+ * # Errors
1005
+ *
1006
+ * Returns an error if an exporter cannot flush its pending data.
1007
+ */
1008
+ export declare function flushTelemetry(): void
1009
+
372
1010
  /**
373
1011
  * Initializes the logging system for the Prosody client.
374
1012
  *
@@ -407,27 +1045,6 @@ export interface Logger {
407
1045
  */
408
1046
  export declare function loggerIsSet(): boolean
409
1047
 
410
- /**
411
- * Represents a message consumed from a Kafka topic.
412
- *
413
- * This object contains all the relevant information about a Kafka message,
414
- * including its topic, partition, offset, timestamp, key, and payload.
415
- */
416
- export interface Message {
417
- /** The name of the topic from which the message was consumed. */
418
- topic: string
419
- /** The partition number from which the message was consumed. */
420
- partition: number
421
- /** The message offset within the partition. */
422
- offset: bigint
423
- /** The timestamp when the message was created or sent to Kafka. */
424
- timestamp: Date
425
- /** The message key. */
426
- key: string
427
- /** The message payload as a JSON-serializable value. */
428
- payload: any
429
- }
430
-
431
1048
  /** Type alias for message handler arguments. */
432
1049
  export type MessageHandlerArgs =
433
1050
  [NativeContext, Message, Record<string, string>]
@@ -443,6 +1060,18 @@ export type Mode = /** Pipeline mode for standard processing. */
443
1060
  */
444
1061
  'BestEffort';
445
1062
 
1063
+ /** One excise subsystem request. */
1064
+ export interface NativeExciseRequest {
1065
+ /** Kafka topic. */
1066
+ topic: string
1067
+ /** Message key. */
1068
+ key: string
1069
+ /** Subsystems that must respond. */
1070
+ subsystems: Array<string>
1071
+ /** Response deadline in milliseconds. */
1072
+ timeoutMs: number
1073
+ }
1074
+
446
1075
  /**
447
1076
  * Represents a native handler for processing messages and timers.
448
1077
  *
@@ -461,7 +1090,9 @@ export interface NativeHandler {
461
1090
  *
462
1091
  * Note: Error parameter is automatically added by CalleeHandled=true
463
1092
  */
464
- onMessage: (arg: MessageHandlerArgs) => Promise<undefined>
1093
+ onMessage: (arg: MessageHandlerArgs) => Promise<string>
1094
+ /** A function to call when an excise record arrives. */
1095
+ onExcise: (arg: ExciseHandlerArgs) => Promise<string>
465
1096
  /**
466
1097
  * A function to be called when a timer fires.
467
1098
  *
@@ -473,7 +1104,7 @@ export interface NativeHandler {
473
1104
  *
474
1105
  * Note: Error parameter is automatically added by CalleeHandled=true
475
1106
  */
476
- onTimer: (arg: TimerHandlerArgs) => Promise<undefined>
1107
+ onTimer: (arg: TimerHandlerArgs) => Promise<string>
477
1108
  /**
478
1109
  * Function that determines whether an error is permanent.
479
1110
  *
@@ -484,6 +1115,52 @@ export interface NativeHandler {
484
1115
  isPermanent: (arg: IsPermanentArgs) => boolean
485
1116
  }
486
1117
 
1118
+ /** One subsystem request. */
1119
+ export interface NativeRequest {
1120
+ /** Kafka topic. */
1121
+ topic: string
1122
+ /** Message key. */
1123
+ key: string
1124
+ /** JSON payload text. */
1125
+ payload: string
1126
+ /** Event metadata read before serialization. */
1127
+ metadata: EventMetadata
1128
+ /** Subsystems that must respond. */
1129
+ subsystems: Array<string>
1130
+ /** Response deadline in milliseconds. */
1131
+ timeoutMs: number
1132
+ }
1133
+
1134
+ /** One response failure. */
1135
+ export interface NativeResponseError {
1136
+ /** Failure discriminator. */
1137
+ kind: NativeResponseErrorKind
1138
+ /** Failure text. */
1139
+ message: string
1140
+ }
1141
+
1142
+ /** One response failure kind. */
1143
+ export type NativeResponseErrorKind = 'handler'|
1144
+ 'timeout'|
1145
+ 'formatMismatch'|
1146
+ 'malformedResponse';
1147
+
1148
+ /** One subsystem and its outcome. */
1149
+ export interface NativeSubsystemOutcome {
1150
+ /** Canonical subsystem name. */
1151
+ subsystem: string
1152
+ /** Encoded response or failure. */
1153
+ outcome: string | NativeResponseError
1154
+ }
1155
+
1156
+ /** Default cache policy for published-state reads. */
1157
+ export interface ReadCacheConfiguration {
1158
+ /** Cache duration in milliseconds. */
1159
+ ttlMs?: number
1160
+ /** Read durable storage on every operation. */
1161
+ disabled?: boolean
1162
+ }
1163
+
487
1164
  /**
488
1165
  * Sets a new JavaScript logger for the Prosody client.
489
1166
  *
@@ -510,6 +1187,61 @@ export declare function setLogger(logger: Logger): void
510
1187
  */
511
1188
  export declare function setLoggerIfUnset(logger: Logger): boolean
512
1189
 
1190
+ /**
1191
+ * Stops the global telemetry providers after they export pending data.
1192
+ *
1193
+ * Call this function only when the Node.js process no longer needs telemetry.
1194
+ *
1195
+ * # Errors
1196
+ *
1197
+ * Returns an error if a provider cannot stop.
1198
+ */
1199
+ export declare function shutdownTelemetry(): void
1200
+
1201
+ /** Declares one keyed-state collection to register before subscribe. */
1202
+ export interface StateCollectionConfig {
1203
+ /**
1204
+ * The collection name. Prosody requires it to be non-empty and unique
1205
+ * within the definition set.
1206
+ */
1207
+ name: string
1208
+ /** The collection kind: `"value"`, `"map"`, or `"deque"`. */
1209
+ kind: string
1210
+ /**
1211
+ * The item payload: `"json"` (JSON values) or `"message"` (the full Kafka
1212
+ * message the handler received).
1213
+ */
1214
+ payload: string
1215
+ /**
1216
+ * Optional per-write TTL in whole seconds. Must be a whole number >= 1
1217
+ * (fractional, negative, and non-finite values are rejected) and must
1218
+ * exceed the recovery delay (the latter checked at consumer build).
1219
+ */
1220
+ ttlSeconds?: number
1221
+ /**
1222
+ * Optional opt-out of transactional staging (read-uncommitted, at-least
1223
+ * once). Defaults to transactional.
1224
+ */
1225
+ readUncommitted?: boolean
1226
+ /** Whether other consumer groups may read this collection. */
1227
+ published?: boolean
1228
+ /**
1229
+ * Optional map-only keyset bound (`0..=4096`; default 128 core-side; `0`
1230
+ * disables ordered-scan tracking). The binding rejects values that cannot
1231
+ * map to an unsigned integer. Prosody enforces the semantic ceiling.
1232
+ * Invalid on value or deque collections.
1233
+ */
1234
+ keysetLimit?: number
1235
+ /**
1236
+ * Optional deque-only capacity (bounded backlog). Must be a whole number
1237
+ * >= 1 (fractional, zero, negative, and non-finite values are rejected).
1238
+ * Runtime configuration only — not persisted, not part of collection
1239
+ * identity, and freely changeable across deploys; enforced lazily on push.
1240
+ * Invalid on value or map collections.
1241
+ */
1242
+ capacity?: number
1243
+ }
1244
+
513
1245
  /**
514
1246
  * Represents a timer event.
515
1247
  *