@relaybus/kafka 0.2.0 → 0.3.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.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,42 @@
1
- import { RelayBusError, NonRetryableError, EventEnvelope, EventHeaders, Duration, Transport, RelayBusLogger, TransportMessageHandler } from '@relaybus/core';
1
+ import { RelayBusError, NonRetryableError, EventEnvelope, EventHeaders, Duration, RelayBusLogger } from '@relaybus/core';
2
+ import { JsonEnvelopeMapping, SubscribingTransport, TransportSubscription } from '@relaybus/core/internal';
3
+ export { fromHeader, fromPayloadField } from '@relaybus/core/internal';
4
+
5
+ /** A Kafka record that cannot be turned into an {@link EventEnvelope}. Never retried. */
6
+ declare class InvalidKafkaMessageError extends RelayBusError {
7
+ name: string;
8
+ readonly code: string;
9
+ }
10
+ /**
11
+ * An event that cannot be written to Kafka: its payload is not representable as
12
+ * JSON (`undefined`, a function, a symbol, a `BigInt`, a circular structure) or
13
+ * its `occurredAt` is not an RFC 3339 instant (invalid date, year outside 0..9999).
14
+ * Retrying cannot help, so it is a {@link NonRetryableError}.
15
+ */
16
+ declare class UnencodableEventError extends NonRetryableError {
17
+ name: string;
18
+ readonly code: string;
19
+ }
20
+ /** `publish` did not get a broker ack within `publishTimeout`. The outbox retries it. */
21
+ declare class PublishTimeoutError extends RelayBusError {
22
+ name: string;
23
+ readonly code: string;
24
+ }
25
+ /** The transport was closed: it no longer publishes or subscribes. */
26
+ declare class TransportClosedError extends RelayBusError {
27
+ name: string;
28
+ readonly code: string;
29
+ }
30
+ /** The consumer did not join its group within `startupTimeout`. */
31
+ declare class GroupJoinTimeoutError extends RelayBusError {
32
+ name: string;
33
+ readonly code: string;
34
+ }
35
+ /** A handler failure re-thrown to the Kafka client, stripped of anything that could make it fatal. */
36
+ declare class HandlerFailedError extends RelayBusError {
37
+ name: string;
38
+ readonly code: string;
39
+ }
2
40
 
3
41
  /**
4
42
  * Structural views of the Kafka client API used by this package.
@@ -97,18 +135,6 @@ interface KafkaClientLike {
97
135
  consumer(config: KafkaConsumerConfig): KafkaConsumerLike;
98
136
  }
99
137
 
100
- /** A Kafka record that cannot be turned into an {@link EventEnvelope}. Never retried. */
101
- declare class InvalidKafkaMessageError extends RelayBusError {
102
- }
103
- /**
104
- * An event that cannot be written to Kafka: its payload is not representable as
105
- * JSON (`undefined`, a function, a symbol, a `BigInt`, a circular structure) or
106
- * its `occurredAt` is not an RFC 3339 instant (invalid date, year outside 0..9999).
107
- * Retrying cannot help, so it is a {@link NonRetryableError}.
108
- */
109
- declare class UnencodableEventError extends NonRetryableError {
110
- name: string;
111
- }
112
138
  /** The wire form of one event: a Kafka record in CloudEvents binary content mode. */
113
139
  interface EncodedMessage {
114
140
  readonly key: string | null;
@@ -262,6 +288,69 @@ declare function decodeCloudEvent(record: DecodableMessage): EventEnvelope;
262
288
  */
263
289
  declare function plainJsonDecoder(options: PlainJsonDecoderOptions): KafkaMessageDecoder;
264
290
 
291
+ /** The record a codec produces for one event. `timestamp` is epoch milliseconds in a string. */
292
+ type KafkaEncodedRecord = KafkaOutgoingMessage & {
293
+ readonly timestamp?: string;
294
+ };
295
+ /**
296
+ * The wire format of a {@link KafkaTransport}: how an event becomes a record
297
+ * (`encode`, on publish) and a consumed record becomes an event (`decode`).
298
+ *
299
+ * Both must be synchronous and free of side effects. What `encode` throws
300
+ * fails the publish: the outbox retries it, unless it is a `NonRetryableError`
301
+ * such as {@link UnencodableEventError}. What `decode` throws marks the record
302
+ * as malformed: it goes to `onInvalidMessage` (dead-letter by default) and the
303
+ * consumer moves on. See {@link KafkaMessageDecoder} for the decode contract.
304
+ */
305
+ interface KafkaCodec {
306
+ readonly encode: (envelope: EventEnvelope) => KafkaEncodedRecord;
307
+ readonly decode: KafkaMessageDecoder;
308
+ }
309
+ /**
310
+ * CloudEvents 1.0 binary content mode, the default: the value is the JSON
311
+ * payload, the attributes travel as `ce_*` headers ({@link encodeEnvelope}).
312
+ * Decoding is strict: any other record is malformed ({@link decodeEnvelope}).
313
+ */
314
+ declare const cloudEventsBinary: KafkaCodec;
315
+ /**
316
+ * CloudEvents 1.0 structured content mode: the value is one
317
+ * `application/cloudevents+json` document with the attributes and `data`.
318
+ * Decoding accepts structured and binary mode ({@link decodeCloudEvent}), so a
319
+ * topic can move from one to the other while both are in flight.
320
+ */
321
+ declare const cloudEventsStructured: KafkaCodec;
322
+ /**
323
+ * Where each value of a JSON message lives, for {@link jsonEnvelope}. Besides
324
+ * `{ body }` and `{ header }`, the id may be `'record-position'`: a consumed
325
+ * record gets `kafka:<topic>:<partition>:<offset>`, stable across redeliveries
326
+ * but different for two sends of one event. Records relaybus writes carry the
327
+ * event id in a `relaybus-event-id` header, which wins on read, so an outbox
328
+ * retry that sends an event twice is still deduplicated.
329
+ */
330
+ type KafkaJsonEnvelopeMapping = JsonEnvelopeMapping<'record-position'>;
331
+ /**
332
+ * A JSON wire format declared by a mapping, in both directions: for topics
333
+ * shared with services that wrap events in their own envelope
334
+ * (`{ "eventName": ..., "data": {...} }`, MassTransit) or send the bare
335
+ * payload. The record key is always the event key; when `occurredAt` is not
336
+ * mapped, the record timestamp carries it. Event headers that are message
337
+ * headers are written as they are, so a name the mapping uses for another
338
+ * field is refused with {@link UnencodableEventError}, as are `content-type`
339
+ * and `relaybus-event-id`.
340
+ *
341
+ * ```ts
342
+ * codec: jsonEnvelope({
343
+ * type: { body: 'eventName' },
344
+ * id: { body: 'messageId' },
345
+ * payload: { body: 'data' },
346
+ * correlationId: { body: 'meta.correlationId' },
347
+ * })
348
+ * ```
349
+ *
350
+ * @throws ConfigurationError for an incomplete or self-overlapping mapping.
351
+ */
352
+ declare function jsonEnvelope(mapping: KafkaJsonEnvelopeMapping): KafkaCodec;
353
+
265
354
  /** A record the transport refused to hand to the bus because it is malformed. */
266
355
  interface InvalidKafkaMessage {
267
356
  readonly topic: string;
@@ -291,14 +380,6 @@ interface InvalidKafkaMessage {
291
380
  type InvalidMessagePolicy = 'dead-letter' | 'skip' | ((message: InvalidKafkaMessage) => void | Promise<void>) | {
292
381
  readonly deadLetterTopic: string | ((sourceTopic: string) => string);
293
382
  };
294
- /** `publish` did not get a broker ack within `publishTimeout`. The outbox retries it. */
295
- declare class PublishTimeoutError extends RelayBusError {
296
- name: string;
297
- }
298
- /** A handler failure re-thrown to the Kafka client, stripped of anything that could make it fatal. */
299
- declare class HandlerFailedError extends RelayBusError {
300
- name: string;
301
- }
302
383
  /** Bounded in-process retries around the inbound handler (the bus's `receive`). */
303
384
  interface KafkaProcessingOptions {
304
385
  /** Attempts per delivery of a record before the error is handed to the client. Default 5. */
@@ -344,24 +425,33 @@ interface KafkaTransportOptions {
344
425
  /** Handling of records that cannot be processed for good. Default `'dead-letter'`. */
345
426
  readonly onInvalidMessage?: InvalidMessagePolicy;
346
427
  /**
347
- * How consumed records become events. Default: strict CloudEvents binary
348
- * mode ({@link decodeEnvelope}), which is what relaybus producers write; any
349
- * other record is malformed and goes to `onInvalidMessage`. Set it to read
350
- * topics written by services that do not use relaybus:
351
- * {@link decodeCloudEvent} also accepts structured mode, {@link plainJsonDecoder}
352
- * maps plain JSON records, and a function of your own can do anything else
353
- * (switch on `record.topic` to decode topics differently). Whatever a custom
354
- * decoder throws marks the record as malformed, never crashes the consumer.
428
+ * The wire format, both ways: how events become records and consumed records
429
+ * become events. Default {@link cloudEventsBinary}: CloudEvents binary mode,
430
+ * strict on read, so any other record is malformed and goes to
431
+ * `onInvalidMessage`. {@link cloudEventsStructured} writes structured mode
432
+ * and reads both, {@link jsonEnvelope} maps a JSON format of your own (an
433
+ * envelope with the payload inside, or the bare payload), and an object with
434
+ * `encode` and `decode` can do anything else. Whatever a non-default codec's
435
+ * `decode` throws marks the record as malformed, never crashes the consumer.
436
+ */
437
+ readonly codec?: KafkaCodec;
438
+ /**
439
+ * How consumed records become events; events are still written in
440
+ * CloudEvents binary mode.
441
+ *
442
+ * @deprecated Use `codec`: `decode: fn` is `codec: { encode: encodeEnvelope, decode: fn }`.
443
+ * Giving both `decode` and `codec` is a configuration error.
355
444
  */
356
445
  readonly decode?: KafkaMessageDecoder;
357
446
  /** Default `console`. */
358
447
  readonly logger?: RelayBusLogger;
359
448
  }
449
+
360
450
  /**
361
451
  * Kafka {@link Transport}. Events travel as CloudEvents binary-mode records
362
452
  * (`ce_*` headers, JSON value), so any CloudEvents-aware consumer can read them.
363
- * Records from producers that do not use relaybus are read through the
364
- * `decode` option.
453
+ * The `codec` option changes the wire format, for example to read and write
454
+ * the JSON format of services that do not use relaybus.
365
455
  *
366
456
  * Publishing: idempotent producer, `acks=-1`, resolves after the broker ack and
367
457
  * rejects with {@link PublishTimeoutError} after `publishTimeout`. A timed-out
@@ -380,9 +470,10 @@ interface KafkaTransportOptions {
380
470
  * reports an unrecoverable crash anyway, the consumer run loop is restarted with
381
471
  * bounded backoff until the transport is closed.
382
472
  */
383
- declare class KafkaTransport implements Transport {
473
+ declare class KafkaTransport extends SubscribingTransport {
384
474
  #private;
385
475
  readonly name: string;
476
+ readonly system = "kafka";
386
477
  constructor(options: KafkaTransportOptions);
387
478
  /**
388
479
  * True while the consumer is joined to its group, not between a crash or
@@ -407,38 +498,9 @@ declare class KafkaTransport implements Transport {
407
498
  * @throws ConfigurationError when `groupId` is missing, `destinations` is empty
408
499
  * or the transport already subscribed (create one transport per subscription).
409
500
  */
410
- subscribe(destinations: readonly string[], onMessage: TransportMessageHandler): Promise<void>;
501
+ protected openSubscription(subscription: TransportSubscription): Promise<void>;
411
502
  /** Stops consuming and disconnects the consumer and the producer. Safe to call twice. */
412
503
  close(): Promise<void>;
413
504
  }
414
505
 
415
- /**
416
- * Reads one header of an incoming message, for the `type`, `id`, `key` or
417
- * `source` option of {@link plainJsonDecoder}. Header names are compared
418
- * exactly (Kafka header names are case-sensitive). Returns undefined when the
419
- * header is absent, so the decoder falls back to its default.
420
- *
421
- * ```ts
422
- * plainJsonDecoder({ type: fromHeader('event-type'), id: fromHeader('message-id') })
423
- * ```
424
- */
425
- declare function fromHeader(name: string): (message: {
426
- readonly headers: EventHeaders;
427
- }) => string | undefined;
428
- /**
429
- * Reads a field of the JSON payload by a dotted path (`'meta.eventType'`), for
430
- * the `type`, `id`, `key` or `source` option of {@link plainJsonDecoder}. A
431
- * string is returned as is and a safe integer as its decimal text (numeric ids
432
- * are common). Anything else returns undefined so the decoder falls back to its
433
- * default: a missing field, and also a fraction or an integer beyond 2^53, which
434
- * JSON parsing may already have rounded, so two different ids could collide.
435
- *
436
- * ```ts
437
- * plainJsonDecoder({ type: fromPayloadField('eventType'), key: fromPayloadField('order.id') })
438
- * ```
439
- */
440
- declare function fromPayloadField(path: string): (message: {
441
- readonly payload: unknown;
442
- }) => string | undefined;
443
-
444
- export { type DecodableMessage, type DecodedEvent, type EncodedMessage, HandlerFailedError, type InvalidKafkaMessage, InvalidKafkaMessageError, type InvalidMessagePolicy, type KafkaBytes, type KafkaClientLike, type KafkaConsumerConfig, type KafkaConsumerEvent, type KafkaConsumerEventNames, type KafkaConsumerLike, type KafkaEachMessagePayload, type KafkaInboundRecord, type KafkaIncomingHeaders, type KafkaIncomingMessage, type KafkaMessageDecoder, type KafkaOutgoingHeaders, type KafkaOutgoingMessage, type KafkaProcessingOptions, type KafkaProducerConfig, type KafkaProducerLike, type KafkaProducerRecord, type KafkaRestartOptions, type KafkaRunConfig, KafkaTransport, type KafkaTransportOptions, type PlainJsonDecoderOptions, type PlainJsonRecord, PublishTimeoutError, UnencodableEventError, decodeCloudEvent, decodeEnvelope, encodeEnvelope, fromHeader, fromPayloadField, plainJsonDecoder };
506
+ export { type DecodableMessage, type DecodedEvent, type EncodedMessage, GroupJoinTimeoutError, HandlerFailedError, type InvalidKafkaMessage, InvalidKafkaMessageError, type InvalidMessagePolicy, type KafkaBytes, type KafkaClientLike, type KafkaCodec, type KafkaConsumerConfig, type KafkaConsumerEvent, type KafkaConsumerEventNames, type KafkaConsumerLike, type KafkaEachMessagePayload, type KafkaEncodedRecord, type KafkaInboundRecord, type KafkaIncomingHeaders, type KafkaIncomingMessage, type KafkaJsonEnvelopeMapping, type KafkaMessageDecoder, type KafkaOutgoingHeaders, type KafkaOutgoingMessage, type KafkaProcessingOptions, type KafkaProducerConfig, type KafkaProducerLike, type KafkaProducerRecord, type KafkaRestartOptions, type KafkaRunConfig, KafkaTransport, type KafkaTransportOptions, type PlainJsonDecoderOptions, type PlainJsonRecord, PublishTimeoutError, TransportClosedError, UnencodableEventError, cloudEventsBinary, cloudEventsStructured, decodeCloudEvent, decodeEnvelope, encodeEnvelope, jsonEnvelope, plainJsonDecoder };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,42 @@
1
- import { RelayBusError, NonRetryableError, EventEnvelope, EventHeaders, Duration, Transport, RelayBusLogger, TransportMessageHandler } from '@relaybus/core';
1
+ import { RelayBusError, NonRetryableError, EventEnvelope, EventHeaders, Duration, RelayBusLogger } from '@relaybus/core';
2
+ import { JsonEnvelopeMapping, SubscribingTransport, TransportSubscription } from '@relaybus/core/internal';
3
+ export { fromHeader, fromPayloadField } from '@relaybus/core/internal';
4
+
5
+ /** A Kafka record that cannot be turned into an {@link EventEnvelope}. Never retried. */
6
+ declare class InvalidKafkaMessageError extends RelayBusError {
7
+ name: string;
8
+ readonly code: string;
9
+ }
10
+ /**
11
+ * An event that cannot be written to Kafka: its payload is not representable as
12
+ * JSON (`undefined`, a function, a symbol, a `BigInt`, a circular structure) or
13
+ * its `occurredAt` is not an RFC 3339 instant (invalid date, year outside 0..9999).
14
+ * Retrying cannot help, so it is a {@link NonRetryableError}.
15
+ */
16
+ declare class UnencodableEventError extends NonRetryableError {
17
+ name: string;
18
+ readonly code: string;
19
+ }
20
+ /** `publish` did not get a broker ack within `publishTimeout`. The outbox retries it. */
21
+ declare class PublishTimeoutError extends RelayBusError {
22
+ name: string;
23
+ readonly code: string;
24
+ }
25
+ /** The transport was closed: it no longer publishes or subscribes. */
26
+ declare class TransportClosedError extends RelayBusError {
27
+ name: string;
28
+ readonly code: string;
29
+ }
30
+ /** The consumer did not join its group within `startupTimeout`. */
31
+ declare class GroupJoinTimeoutError extends RelayBusError {
32
+ name: string;
33
+ readonly code: string;
34
+ }
35
+ /** A handler failure re-thrown to the Kafka client, stripped of anything that could make it fatal. */
36
+ declare class HandlerFailedError extends RelayBusError {
37
+ name: string;
38
+ readonly code: string;
39
+ }
2
40
 
3
41
  /**
4
42
  * Structural views of the Kafka client API used by this package.
@@ -97,18 +135,6 @@ interface KafkaClientLike {
97
135
  consumer(config: KafkaConsumerConfig): KafkaConsumerLike;
98
136
  }
99
137
 
100
- /** A Kafka record that cannot be turned into an {@link EventEnvelope}. Never retried. */
101
- declare class InvalidKafkaMessageError extends RelayBusError {
102
- }
103
- /**
104
- * An event that cannot be written to Kafka: its payload is not representable as
105
- * JSON (`undefined`, a function, a symbol, a `BigInt`, a circular structure) or
106
- * its `occurredAt` is not an RFC 3339 instant (invalid date, year outside 0..9999).
107
- * Retrying cannot help, so it is a {@link NonRetryableError}.
108
- */
109
- declare class UnencodableEventError extends NonRetryableError {
110
- name: string;
111
- }
112
138
  /** The wire form of one event: a Kafka record in CloudEvents binary content mode. */
113
139
  interface EncodedMessage {
114
140
  readonly key: string | null;
@@ -262,6 +288,69 @@ declare function decodeCloudEvent(record: DecodableMessage): EventEnvelope;
262
288
  */
263
289
  declare function plainJsonDecoder(options: PlainJsonDecoderOptions): KafkaMessageDecoder;
264
290
 
291
+ /** The record a codec produces for one event. `timestamp` is epoch milliseconds in a string. */
292
+ type KafkaEncodedRecord = KafkaOutgoingMessage & {
293
+ readonly timestamp?: string;
294
+ };
295
+ /**
296
+ * The wire format of a {@link KafkaTransport}: how an event becomes a record
297
+ * (`encode`, on publish) and a consumed record becomes an event (`decode`).
298
+ *
299
+ * Both must be synchronous and free of side effects. What `encode` throws
300
+ * fails the publish: the outbox retries it, unless it is a `NonRetryableError`
301
+ * such as {@link UnencodableEventError}. What `decode` throws marks the record
302
+ * as malformed: it goes to `onInvalidMessage` (dead-letter by default) and the
303
+ * consumer moves on. See {@link KafkaMessageDecoder} for the decode contract.
304
+ */
305
+ interface KafkaCodec {
306
+ readonly encode: (envelope: EventEnvelope) => KafkaEncodedRecord;
307
+ readonly decode: KafkaMessageDecoder;
308
+ }
309
+ /**
310
+ * CloudEvents 1.0 binary content mode, the default: the value is the JSON
311
+ * payload, the attributes travel as `ce_*` headers ({@link encodeEnvelope}).
312
+ * Decoding is strict: any other record is malformed ({@link decodeEnvelope}).
313
+ */
314
+ declare const cloudEventsBinary: KafkaCodec;
315
+ /**
316
+ * CloudEvents 1.0 structured content mode: the value is one
317
+ * `application/cloudevents+json` document with the attributes and `data`.
318
+ * Decoding accepts structured and binary mode ({@link decodeCloudEvent}), so a
319
+ * topic can move from one to the other while both are in flight.
320
+ */
321
+ declare const cloudEventsStructured: KafkaCodec;
322
+ /**
323
+ * Where each value of a JSON message lives, for {@link jsonEnvelope}. Besides
324
+ * `{ body }` and `{ header }`, the id may be `'record-position'`: a consumed
325
+ * record gets `kafka:<topic>:<partition>:<offset>`, stable across redeliveries
326
+ * but different for two sends of one event. Records relaybus writes carry the
327
+ * event id in a `relaybus-event-id` header, which wins on read, so an outbox
328
+ * retry that sends an event twice is still deduplicated.
329
+ */
330
+ type KafkaJsonEnvelopeMapping = JsonEnvelopeMapping<'record-position'>;
331
+ /**
332
+ * A JSON wire format declared by a mapping, in both directions: for topics
333
+ * shared with services that wrap events in their own envelope
334
+ * (`{ "eventName": ..., "data": {...} }`, MassTransit) or send the bare
335
+ * payload. The record key is always the event key; when `occurredAt` is not
336
+ * mapped, the record timestamp carries it. Event headers that are message
337
+ * headers are written as they are, so a name the mapping uses for another
338
+ * field is refused with {@link UnencodableEventError}, as are `content-type`
339
+ * and `relaybus-event-id`.
340
+ *
341
+ * ```ts
342
+ * codec: jsonEnvelope({
343
+ * type: { body: 'eventName' },
344
+ * id: { body: 'messageId' },
345
+ * payload: { body: 'data' },
346
+ * correlationId: { body: 'meta.correlationId' },
347
+ * })
348
+ * ```
349
+ *
350
+ * @throws ConfigurationError for an incomplete or self-overlapping mapping.
351
+ */
352
+ declare function jsonEnvelope(mapping: KafkaJsonEnvelopeMapping): KafkaCodec;
353
+
265
354
  /** A record the transport refused to hand to the bus because it is malformed. */
266
355
  interface InvalidKafkaMessage {
267
356
  readonly topic: string;
@@ -291,14 +380,6 @@ interface InvalidKafkaMessage {
291
380
  type InvalidMessagePolicy = 'dead-letter' | 'skip' | ((message: InvalidKafkaMessage) => void | Promise<void>) | {
292
381
  readonly deadLetterTopic: string | ((sourceTopic: string) => string);
293
382
  };
294
- /** `publish` did not get a broker ack within `publishTimeout`. The outbox retries it. */
295
- declare class PublishTimeoutError extends RelayBusError {
296
- name: string;
297
- }
298
- /** A handler failure re-thrown to the Kafka client, stripped of anything that could make it fatal. */
299
- declare class HandlerFailedError extends RelayBusError {
300
- name: string;
301
- }
302
383
  /** Bounded in-process retries around the inbound handler (the bus's `receive`). */
303
384
  interface KafkaProcessingOptions {
304
385
  /** Attempts per delivery of a record before the error is handed to the client. Default 5. */
@@ -344,24 +425,33 @@ interface KafkaTransportOptions {
344
425
  /** Handling of records that cannot be processed for good. Default `'dead-letter'`. */
345
426
  readonly onInvalidMessage?: InvalidMessagePolicy;
346
427
  /**
347
- * How consumed records become events. Default: strict CloudEvents binary
348
- * mode ({@link decodeEnvelope}), which is what relaybus producers write; any
349
- * other record is malformed and goes to `onInvalidMessage`. Set it to read
350
- * topics written by services that do not use relaybus:
351
- * {@link decodeCloudEvent} also accepts structured mode, {@link plainJsonDecoder}
352
- * maps plain JSON records, and a function of your own can do anything else
353
- * (switch on `record.topic` to decode topics differently). Whatever a custom
354
- * decoder throws marks the record as malformed, never crashes the consumer.
428
+ * The wire format, both ways: how events become records and consumed records
429
+ * become events. Default {@link cloudEventsBinary}: CloudEvents binary mode,
430
+ * strict on read, so any other record is malformed and goes to
431
+ * `onInvalidMessage`. {@link cloudEventsStructured} writes structured mode
432
+ * and reads both, {@link jsonEnvelope} maps a JSON format of your own (an
433
+ * envelope with the payload inside, or the bare payload), and an object with
434
+ * `encode` and `decode` can do anything else. Whatever a non-default codec's
435
+ * `decode` throws marks the record as malformed, never crashes the consumer.
436
+ */
437
+ readonly codec?: KafkaCodec;
438
+ /**
439
+ * How consumed records become events; events are still written in
440
+ * CloudEvents binary mode.
441
+ *
442
+ * @deprecated Use `codec`: `decode: fn` is `codec: { encode: encodeEnvelope, decode: fn }`.
443
+ * Giving both `decode` and `codec` is a configuration error.
355
444
  */
356
445
  readonly decode?: KafkaMessageDecoder;
357
446
  /** Default `console`. */
358
447
  readonly logger?: RelayBusLogger;
359
448
  }
449
+
360
450
  /**
361
451
  * Kafka {@link Transport}. Events travel as CloudEvents binary-mode records
362
452
  * (`ce_*` headers, JSON value), so any CloudEvents-aware consumer can read them.
363
- * Records from producers that do not use relaybus are read through the
364
- * `decode` option.
453
+ * The `codec` option changes the wire format, for example to read and write
454
+ * the JSON format of services that do not use relaybus.
365
455
  *
366
456
  * Publishing: idempotent producer, `acks=-1`, resolves after the broker ack and
367
457
  * rejects with {@link PublishTimeoutError} after `publishTimeout`. A timed-out
@@ -380,9 +470,10 @@ interface KafkaTransportOptions {
380
470
  * reports an unrecoverable crash anyway, the consumer run loop is restarted with
381
471
  * bounded backoff until the transport is closed.
382
472
  */
383
- declare class KafkaTransport implements Transport {
473
+ declare class KafkaTransport extends SubscribingTransport {
384
474
  #private;
385
475
  readonly name: string;
476
+ readonly system = "kafka";
386
477
  constructor(options: KafkaTransportOptions);
387
478
  /**
388
479
  * True while the consumer is joined to its group, not between a crash or
@@ -407,38 +498,9 @@ declare class KafkaTransport implements Transport {
407
498
  * @throws ConfigurationError when `groupId` is missing, `destinations` is empty
408
499
  * or the transport already subscribed (create one transport per subscription).
409
500
  */
410
- subscribe(destinations: readonly string[], onMessage: TransportMessageHandler): Promise<void>;
501
+ protected openSubscription(subscription: TransportSubscription): Promise<void>;
411
502
  /** Stops consuming and disconnects the consumer and the producer. Safe to call twice. */
412
503
  close(): Promise<void>;
413
504
  }
414
505
 
415
- /**
416
- * Reads one header of an incoming message, for the `type`, `id`, `key` or
417
- * `source` option of {@link plainJsonDecoder}. Header names are compared
418
- * exactly (Kafka header names are case-sensitive). Returns undefined when the
419
- * header is absent, so the decoder falls back to its default.
420
- *
421
- * ```ts
422
- * plainJsonDecoder({ type: fromHeader('event-type'), id: fromHeader('message-id') })
423
- * ```
424
- */
425
- declare function fromHeader(name: string): (message: {
426
- readonly headers: EventHeaders;
427
- }) => string | undefined;
428
- /**
429
- * Reads a field of the JSON payload by a dotted path (`'meta.eventType'`), for
430
- * the `type`, `id`, `key` or `source` option of {@link plainJsonDecoder}. A
431
- * string is returned as is and a safe integer as its decimal text (numeric ids
432
- * are common). Anything else returns undefined so the decoder falls back to its
433
- * default: a missing field, and also a fraction or an integer beyond 2^53, which
434
- * JSON parsing may already have rounded, so two different ids could collide.
435
- *
436
- * ```ts
437
- * plainJsonDecoder({ type: fromPayloadField('eventType'), key: fromPayloadField('order.id') })
438
- * ```
439
- */
440
- declare function fromPayloadField(path: string): (message: {
441
- readonly payload: unknown;
442
- }) => string | undefined;
443
-
444
- export { type DecodableMessage, type DecodedEvent, type EncodedMessage, HandlerFailedError, type InvalidKafkaMessage, InvalidKafkaMessageError, type InvalidMessagePolicy, type KafkaBytes, type KafkaClientLike, type KafkaConsumerConfig, type KafkaConsumerEvent, type KafkaConsumerEventNames, type KafkaConsumerLike, type KafkaEachMessagePayload, type KafkaInboundRecord, type KafkaIncomingHeaders, type KafkaIncomingMessage, type KafkaMessageDecoder, type KafkaOutgoingHeaders, type KafkaOutgoingMessage, type KafkaProcessingOptions, type KafkaProducerConfig, type KafkaProducerLike, type KafkaProducerRecord, type KafkaRestartOptions, type KafkaRunConfig, KafkaTransport, type KafkaTransportOptions, type PlainJsonDecoderOptions, type PlainJsonRecord, PublishTimeoutError, UnencodableEventError, decodeCloudEvent, decodeEnvelope, encodeEnvelope, fromHeader, fromPayloadField, plainJsonDecoder };
506
+ export { type DecodableMessage, type DecodedEvent, type EncodedMessage, GroupJoinTimeoutError, HandlerFailedError, type InvalidKafkaMessage, InvalidKafkaMessageError, type InvalidMessagePolicy, type KafkaBytes, type KafkaClientLike, type KafkaCodec, type KafkaConsumerConfig, type KafkaConsumerEvent, type KafkaConsumerEventNames, type KafkaConsumerLike, type KafkaEachMessagePayload, type KafkaEncodedRecord, type KafkaInboundRecord, type KafkaIncomingHeaders, type KafkaIncomingMessage, type KafkaJsonEnvelopeMapping, type KafkaMessageDecoder, type KafkaOutgoingHeaders, type KafkaOutgoingMessage, type KafkaProcessingOptions, type KafkaProducerConfig, type KafkaProducerLike, type KafkaProducerRecord, type KafkaRestartOptions, type KafkaRunConfig, KafkaTransport, type KafkaTransportOptions, type PlainJsonDecoderOptions, type PlainJsonRecord, PublishTimeoutError, TransportClosedError, UnencodableEventError, cloudEventsBinary, cloudEventsStructured, decodeCloudEvent, decodeEnvelope, encodeEnvelope, jsonEnvelope, plainJsonDecoder };