@prosody-events/prosody 0.4.0 → 0.5.1

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 +346 -239
  2. package/bindings.d.ts +430 -174
  3. package/bindings.js +211 -83
  4. package/index.d.ts +231 -34
  5. package/index.js +699 -246
  6. package/package.json +21 -21
package/index.d.ts CHANGED
@@ -5,14 +5,30 @@
5
5
  */
6
6
 
7
7
  import type {
8
+ AdminClient,
8
9
  Configuration,
9
10
  ConsumerState,
11
+ ExciseMessage as NativeExciseMessage,
10
12
  Message as NativeMessage,
11
13
  Mode,
14
+ ReadCacheConfiguration,
12
15
  Timer,
13
16
  } from "./bindings";
14
17
 
15
- export { Configuration, ConsumerState, Timer, Mode };
18
+ export {
19
+ AdminClient,
20
+ Configuration,
21
+ ConsumerState,
22
+ ReadCacheConfiguration,
23
+ Timer,
24
+ Mode,
25
+ };
26
+
27
+ /** Exports all pending telemetry data. */
28
+ export function flushTelemetry(): void;
29
+
30
+ /** Stops the global telemetry providers after they export pending data. */
31
+ export function shutdownTelemetry(): void;
16
32
 
17
33
  /** A primitive value representable in JSON. */
18
34
  export type JsonPrimitive = null | boolean | number | string;
@@ -33,7 +49,7 @@ export type JsonValue =
33
49
  */
34
50
  export type JsonCompatible<T> = T extends JsonPrimitive
35
51
  ? T
36
- : T extends bigint | symbol | undefined | ((...args: any[]) => unknown)
52
+ : T extends bigint | symbol | undefined | ((...args: never[]) => unknown)
37
53
  ? never
38
54
  : T extends readonly (infer Item)[]
39
55
  ? readonly JsonCompatible<Item>[]
@@ -41,6 +57,9 @@ export type JsonCompatible<T> = T extends JsonPrimitive
41
57
  ? { readonly [Key in keyof T]: JsonCompatible<T[Key]> }
42
58
  : never;
43
59
 
60
+ /** A value that a handler can return now or through a promise. */
61
+ export type MaybePromise<T> = T | PromiseLike<T>;
62
+
44
63
  /**
45
64
  * Represents a message consumed from a Kafka topic.
46
65
  *
@@ -48,12 +67,19 @@ export type JsonCompatible<T> = T extends JsonPrimitive
48
67
  * payload is unchanged. An unparameterized `Message` uses {@link JsonValue};
49
68
  * provide an application payload type for precise field-level checking.
50
69
  * Message-backed keyed-state collections vend their items as `Message<P>`.
70
+ *
71
+ * A message can be stored into a message collection, whether it arrived from the
72
+ * topic or was read back out of a collection. What is stored is the message
73
+ * itself, so mutating its parsed `payload` does not change what is written.
51
74
  */
52
75
  export interface Message<P = JsonValue> extends Omit<NativeMessage, "payload"> {
53
76
  /** The message payload as a JSON-serializable value. */
54
77
  payload: P;
55
78
  }
56
79
 
80
+ /** An excise record with Kafka metadata and no payload. */
81
+ export type ExciseMessage = NativeExciseMessage;
82
+
57
83
  /**
58
84
  * Wrapper around `MessageContext` for use in Node.js bindings.
59
85
  * Automatically injects OpenTelemetry context for all operations.
@@ -185,8 +211,16 @@ export interface StateDefinitionOptions {
185
211
  readUncommitted?: boolean;
186
212
  }
187
213
 
214
+ /** Options accepted by JSON collections that may be published. */
215
+ export interface PublishedStateDefinitionOptions extends StateDefinitionOptions {
216
+ /** Allow read-only access from other consumer groups. */
217
+ published?: boolean;
218
+ /** Override caching when this descriptor opens a published reader. */
219
+ readCache?: ReadCacheOptions | false;
220
+ }
221
+
188
222
  /** Options accepted by the map definition constructors. */
189
- export interface MapDefinitionOptions extends StateDefinitionOptions {
223
+ export interface MapDefinitionOptions extends PublishedStateDefinitionOptions {
190
224
  /**
191
225
  * Keyset bound for ordered scans (`0..=4096`; default 128 core-side; `0`
192
226
  * disables ordered-scan tracking). Map collections only.
@@ -195,7 +229,7 @@ export interface MapDefinitionOptions extends StateDefinitionOptions {
195
229
  }
196
230
 
197
231
  /** Options accepted by the deque definition constructors. */
198
- export interface DequeDefinitionOptions extends StateDefinitionOptions {
232
+ export interface DequeDefinitionOptions extends PublishedStateDefinitionOptions {
199
233
  /**
200
234
  * Optional maximum element count (bounded backlog). Must be a whole number
201
235
  * >= 1. Runtime-only: not persisted, not part of collection identity, and
@@ -206,47 +240,70 @@ export interface DequeDefinitionOptions extends StateDefinitionOptions {
206
240
  capacity?: number;
207
241
  }
208
242
 
243
+ /** Options accepted by message-map definitions, which cannot be published. */
244
+ export interface MessageMapDefinitionOptions extends StateDefinitionOptions {
245
+ /** Keyset bound for ordered scans (`0..=4096`; default 128 core-side). */
246
+ keysetLimit?: number;
247
+ }
248
+
249
+ /** Options accepted by message-deque definitions, which cannot be published. */
250
+ export interface MessageDequeDefinitionOptions extends StateDefinitionOptions {
251
+ /** Optional maximum element count. Must be a whole number >= 1. */
252
+ capacity?: number;
253
+ }
254
+
209
255
  /**
210
256
  * Phantom brand carrying a definition's item type. Never present at runtime —
211
257
  * it exists only so the item type survives on the frozen definition object and
212
258
  * flows into the vended handle.
213
259
  */
214
260
  declare const StateItem: unique symbol;
261
+ declare const StateDescriptor: unique symbol;
262
+
263
+ interface DefinitionBrand {
264
+ readonly [StateDescriptor]: true;
265
+ }
215
266
 
216
267
  /** A frozen single-value JSON collection definition. */
217
- export interface ValueDefinition<T = JsonValue> {
268
+ export interface ValueDefinition<T = JsonValue> extends DefinitionBrand {
218
269
  readonly name: string;
219
270
  readonly kind: "value";
220
271
  readonly payload: "json";
221
272
  readonly ttlSeconds?: number;
222
273
  readonly readUncommitted?: boolean;
274
+ readonly published?: boolean;
275
+ readonly readCache?: ReadCacheOptions | false;
223
276
  readonly [StateItem]?: T;
224
277
  }
225
278
 
226
279
  /** A frozen ordered-map JSON collection definition (string keys). */
227
- export interface MapDefinition<V = JsonValue> {
280
+ export interface MapDefinition<V = JsonValue> extends DefinitionBrand {
228
281
  readonly name: string;
229
282
  readonly kind: "map";
230
283
  readonly payload: "json";
231
284
  readonly ttlSeconds?: number;
232
285
  readonly readUncommitted?: boolean;
286
+ readonly published?: boolean;
287
+ readonly readCache?: ReadCacheOptions | false;
233
288
  readonly keysetLimit?: number;
234
289
  readonly [StateItem]?: V;
235
290
  }
236
291
 
237
292
  /** A frozen deque JSON collection definition. */
238
- export interface DequeDefinition<T = JsonValue> {
293
+ export interface DequeDefinition<T = JsonValue> extends DefinitionBrand {
239
294
  readonly name: string;
240
295
  readonly kind: "deque";
241
296
  readonly payload: "json";
242
297
  readonly ttlSeconds?: number;
243
298
  readonly readUncommitted?: boolean;
299
+ readonly published?: boolean;
300
+ readonly readCache?: ReadCacheOptions | false;
244
301
  readonly capacity?: number;
245
302
  readonly [StateItem]?: T;
246
303
  }
247
304
 
248
305
  /** A frozen single-value message collection definition (items are `Message<P>`). */
249
- export interface MessageValueDefinition<P = JsonValue> {
306
+ export interface MessageValueDefinition<P = JsonValue> extends DefinitionBrand {
250
307
  readonly name: string;
251
308
  readonly kind: "value";
252
309
  readonly payload: "message";
@@ -256,7 +313,7 @@ export interface MessageValueDefinition<P = JsonValue> {
256
313
  }
257
314
 
258
315
  /** A frozen ordered-map message collection definition (values are `Message<P>`). */
259
- export interface MessageMapDefinition<P = JsonValue> {
316
+ export interface MessageMapDefinition<P = JsonValue> extends DefinitionBrand {
260
317
  readonly name: string;
261
318
  readonly kind: "map";
262
319
  readonly payload: "message";
@@ -267,7 +324,7 @@ export interface MessageMapDefinition<P = JsonValue> {
267
324
  }
268
325
 
269
326
  /** A frozen deque message collection definition (elements are `Message<P>`). */
270
- export interface MessageDequeDefinition<P = JsonValue> {
327
+ export interface MessageDequeDefinition<P = JsonValue> extends DefinitionBrand {
271
328
  readonly name: string;
272
329
  readonly kind: "deque";
273
330
  readonly payload: "message";
@@ -284,11 +341,12 @@ export interface MessageDequeDefinition<P = JsonValue> {
284
341
  * handle. The type parameter annotates the stored value and is compile-time
285
342
  * only — payloads cross as plain JSON with no runtime validation.
286
343
  * @param name - The collection name (unique per client).
287
- * @param options - Optional `ttlSeconds` (whole seconds) and `readUncommitted`.
344
+ * @param options - Optional retention, transaction, publication, and read-cache
345
+ * settings.
288
346
  */
289
347
  export function value<T = JsonValue>(
290
348
  name: string,
291
- options?: StateDefinitionOptions,
349
+ options?: PublishedStateDefinitionOptions,
292
350
  ): ValueDefinition<T>;
293
351
 
294
352
  /**
@@ -297,7 +355,8 @@ export function value<T = JsonValue>(
297
355
  * and with `Context.state()`. The type parameter annotates the stored value
298
356
  * (compile-time only).
299
357
  * @param name - The collection name (unique per client).
300
- * @param options - Optional `ttlSeconds`, `readUncommitted`, and `keysetLimit`.
358
+ * @param options - Optional retention, transaction, publication, read-cache,
359
+ * and `keysetLimit` settings.
301
360
  */
302
361
  export function map<V = JsonValue>(
303
362
  name: string,
@@ -309,8 +368,8 @@ export function map<V = JsonValue>(
309
368
  * is used both in `Configuration.stateCollections` and with `Context.state()`.
310
369
  * The type parameter annotates the stored element (compile-time only).
311
370
  * @param name - The collection name (unique per client).
312
- * @param options - Optional `ttlSeconds` (whole seconds), `readUncommitted`, and
313
- * `capacity` (bounded backlog; enforced lazily on push).
371
+ * @param options - Optional retention, transaction, publication, read-cache,
372
+ * and `capacity` settings.
314
373
  */
315
374
  export function deque<T = JsonValue>(
316
375
  name: string,
@@ -338,7 +397,7 @@ export function messageValue<P = JsonValue>(
338
397
  */
339
398
  export function messageMap<P = JsonValue>(
340
399
  name: string,
341
- options?: MapDefinitionOptions,
400
+ options?: MessageMapDefinitionOptions,
342
401
  ): MessageMapDefinition<P>;
343
402
 
344
403
  /**
@@ -351,7 +410,7 @@ export function messageMap<P = JsonValue>(
351
410
  */
352
411
  export function messageDeque<P = JsonValue>(
353
412
  name: string,
354
- options?: DequeDefinitionOptions,
413
+ options?: MessageDequeDefinitionOptions,
355
414
  ): MessageDequeDefinition<P>;
356
415
 
357
416
  /**
@@ -538,31 +597,52 @@ export declare class DequeState<T = JsonValue> {
538
597
  */
539
598
  export interface Logger {
540
599
  /** Logs error-level messages. */
541
- error: (message: string | undefined | null, metadata?: any) => void;
600
+ error: (
601
+ message: string | undefined | null,
602
+ metadata?: Record<string, unknown>,
603
+ ) => void;
542
604
  /** Logs warning-level messages. */
543
- warn: (message: string | undefined | null, metadata?: any) => void;
605
+ warn: (
606
+ message: string | undefined | null,
607
+ metadata?: Record<string, unknown>,
608
+ ) => void;
544
609
  /** Logs info-level messages. */
545
- info: (message: string | undefined | null, metadata?: any) => void;
610
+ info: (
611
+ message: string | undefined | null,
612
+ metadata?: Record<string, unknown>,
613
+ ) => void;
546
614
  /** Logs debug-level messages. */
547
- debug: (message: string | undefined | null, metadata?: any) => void;
615
+ debug: (
616
+ message: string | undefined | null,
617
+ metadata?: Record<string, unknown>,
618
+ ) => void;
548
619
  /** Logs trace-level messages. */
549
- trace: (message: string | undefined | null, metadata?: any) => void;
620
+ trace: (
621
+ message: string | undefined | null,
622
+ metadata?: Record<string, unknown>,
623
+ ) => void;
550
624
  }
551
625
 
552
- export interface EventHandler<P = JsonValue> {
626
+ export interface EventHandler<P = JsonValue, R = JsonValue> {
627
+ /** Handles an excise record. */
628
+ onExcise: (
629
+ context: Context,
630
+ message: ExciseMessage,
631
+ signal: AbortSignal,
632
+ ) => MaybePromise<R & JsonCompatible<R>>;
553
633
  /**
554
634
  * Callback function to handle incoming messages.
555
635
  *
556
636
  * @param context - The context of the message processing.
557
637
  * @param message - The received Kafka message.
558
638
  * @param signal - An AbortSignal that can be used to cancel the message processing.
559
- * @returns A promise that resolves when the message has been processed.
639
+ * @returns A JSON response for subsystem requests. JSON null is valid.
560
640
  */
561
- onMessage?: (
641
+ onMessage: (
562
642
  context: Context,
563
643
  message: Message<P>,
564
644
  signal: AbortSignal,
565
- ) => Promise<void>;
645
+ ) => MaybePromise<R & JsonCompatible<R>>;
566
646
 
567
647
  /**
568
648
  * Callback function to handle timers.
@@ -570,22 +650,56 @@ export interface EventHandler<P = JsonValue> {
570
650
  * @param context - The context of the message processing.
571
651
  * @param timer - The triggered timer.
572
652
  * @param signal - An AbortSignal that can be used to cancel the message processing.
573
- * @returns A promise that resolves when the timer has been processed.
653
+ * @returns No value.
574
654
  */
575
- onTimer?: (
655
+ onTimer: (
576
656
  context: Context,
577
657
  timer: Timer,
578
658
  signal: AbortSignal,
579
- ) => Promise<void>;
659
+ ) => MaybePromise<void>;
660
+ }
661
+
662
+ /** One successful subsystem outcome. */
663
+ export interface Success<T> {
664
+ readonly ok: true;
665
+ readonly value: T;
666
+ }
667
+
668
+ /** One failed subsystem outcome. */
669
+ export interface Failure {
670
+ readonly ok: false;
671
+ readonly error: ResponseError;
672
+ }
673
+
674
+ /** One subsystem outcome. */
675
+ export type Outcome<T> = Success<T> | Failure;
676
+
677
+ /** One subsystem failure. */
678
+ export type ResponseError =
679
+ | { readonly kind: "handler"; readonly message: string }
680
+ | { readonly kind: "timeout"; readonly message: string }
681
+ | { readonly kind: "formatMismatch"; readonly message: string }
682
+ | { readonly kind: "malformedResponse"; readonly message: string };
683
+
684
+ /** Request targets, deadline, and cancellation. */
685
+ export interface RequestOptions {
686
+ /** The subsystems that must respond. */
687
+ readonly subsystems: readonly string[];
688
+ /** The response deadline in milliseconds. */
689
+ readonly timeoutMs: number;
690
+ /** Cancels the local wait. */
691
+ readonly signal?: AbortSignal;
580
692
  }
581
693
 
582
694
  export declare class ProsodyClient {
695
+ private constructor();
696
+
583
697
  /**
584
- * Creates a new ProsodyClient instance.
698
+ * Creates a Prosody client without blocking the Node.js event loop.
585
699
  *
586
700
  * @param config - The configuration options for the client.
587
701
  */
588
- constructor(config: Configuration);
702
+ static create(config: Configuration): Promise<ProsodyClient>;
589
703
 
590
704
  /**
591
705
  * Gets the current state of the consumer.
@@ -611,6 +725,22 @@ export declare class ProsodyClient {
611
725
  */
612
726
  isStalled(): Promise<boolean>;
613
727
 
728
+ /** Opens a read-only view of a published JSON value collection. */
729
+ state<T>(
730
+ subsystem: string,
731
+ definition: ValueDefinition<T>,
732
+ ): Promise<PublishedValue<T>>;
733
+ /** Opens a read-only view of a published JSON map collection. */
734
+ state<V>(
735
+ subsystem: string,
736
+ definition: MapDefinition<V>,
737
+ ): Promise<PublishedMap<V>>;
738
+ /** Opens a read-only view of a published JSON deque collection. */
739
+ state<T>(
740
+ subsystem: string,
741
+ definition: DequeDefinition<T>,
742
+ ): Promise<PublishedDeque<T>>;
743
+
614
744
  /**
615
745
  * Gets the source system identifier configured for the client.
616
746
  *
@@ -635,22 +765,89 @@ export declare class ProsodyClient {
635
765
  signal?: AbortSignal,
636
766
  ): Promise<void>;
637
767
 
768
+ /** Sends an excise record for a key. */
769
+ excise(topic: string, key: string, signal?: AbortSignal): Promise<void>;
770
+
771
+ /**
772
+ * Sends a request and returns one outcome for each subsystem.
773
+ *
774
+ * The map contains every selected subsystem. A missing response has a timeout outcome.
775
+ * @throws Error if the input is invalid, sending fails, shutdown starts, or the signal aborts.
776
+ */
777
+ request<R = JsonValue>(
778
+ topic: string,
779
+ key: string,
780
+ payload: JsonValue,
781
+ options: RequestOptions,
782
+ ): Promise<ReadonlyMap<string, Outcome<R>>>;
783
+
784
+ /** Sends an excise request and returns one outcome for each subsystem. */
785
+ requestExcise<R = JsonValue>(
786
+ topic: string,
787
+ key: string,
788
+ options: RequestOptions,
789
+ ): Promise<ReadonlyMap<string, Outcome<R>>>;
790
+
638
791
  /**
639
792
  * Subscribes to receive messages using the provided event handler.
640
793
  *
641
794
  * @param eventHandler - The event handler to process received messages and timers.
642
795
  * @returns A promise that resolves when the subscription is successfully established and the consumer is ready to receive messages.
796
+ * @throws TypeError if any required handler method is missing.
643
797
  * @throws Error if the subscription fails to establish.
644
798
  */
645
- subscribe<P = JsonValue>(eventHandler: EventHandler<P>): Promise<void>;
799
+ subscribe<P = JsonValue, R = JsonValue>(
800
+ eventHandler: EventHandler<P, R>,
801
+ ): Promise<void>;
646
802
 
647
803
  /**
648
- * Unsubscribes from receiving messages and shuts down the consumer.
804
+ * Stops the consumer. You can subscribe again later.
649
805
  *
650
806
  * @returns A promise that resolves when the unsubscribe operation is complete.
651
807
  * @throws Error if the unsubscribe operation fails.
652
808
  */
653
809
  unsubscribe(): Promise<void>;
810
+
811
+ /**
812
+ * Shuts down the client and all its services.
813
+ * Concurrent and repeated calls await the same shutdown operation.
814
+ *
815
+ * @returns A promise that resolves when shutdown is complete.
816
+ * @throws Error if shutdown fails.
817
+ */
818
+ shutdown(): Promise<void>;
819
+ }
820
+
821
+ /** Per-collection cache override for published reads. */
822
+ export interface ReadCacheOptions {
823
+ /** Cache duration in milliseconds. */
824
+ ttlMs: number;
825
+ }
826
+
827
+ /** Read-only published value collection. */
828
+ export declare class PublishedValue<T = JsonValue> {
829
+ get(key: string): Promise<T | null>;
830
+ }
831
+
832
+ /** Read-only published map collection. */
833
+ export declare class PublishedMap<V = JsonValue> {
834
+ get(key: string, mapKey: string): Promise<V | null>;
835
+ getMany(key: string, mapKeys: string[]): Promise<Array<V | null>>;
836
+ has(key: string, mapKey: string): Promise<boolean>;
837
+ entries(
838
+ key: string,
839
+ direction?: ScanDirection,
840
+ ): AsyncIterableIterator<[string, V]>;
841
+ keys(key: string, direction?: ScanDirection): AsyncIterableIterator<string>;
842
+ values(key: string, direction?: ScanDirection): AsyncIterableIterator<V>;
843
+ }
844
+
845
+ /** Read-only published deque collection. */
846
+ export declare class PublishedDeque<T = JsonValue> {
847
+ length(key: string): Promise<number>;
848
+ isEmpty(key: string): Promise<boolean>;
849
+ at(key: string, index: number): Promise<T | null>;
850
+ values(key: string, direction?: ScanDirection): AsyncIterableIterator<T>;
654
851
  }
655
852
 
656
853
  /**
@@ -765,7 +962,7 @@ export function isStateError(
765
962
  ): error is PermanentStateError | TransientStateError;
766
963
 
767
964
  /** Type alias for a constructor of an Error subclass. */
768
- type ErrorClass<T extends Error> = new (...args: any[]) => T;
965
+ type ErrorClass<T extends Error> = new (...args: never[]) => T;
769
966
 
770
967
  /**
771
968
  * Type for a decorator function that can be applied to both methods and standalone functions.