@platformatic/kafka 1.13.0 → 1.14.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.
@@ -1,5 +1,12 @@
1
- export declare const SASLMechanisms: readonly ["PLAIN", "SCRAM-SHA-256", "SCRAM-SHA-512", "OAUTHBEARER"];
2
- export type SASLMechanism = (typeof SASLMechanisms)[number];
1
+ export declare const SASLMechanisms: {
2
+ readonly PLAIN: "PLAIN";
3
+ readonly SCRAM_SHA_256: "SCRAM-SHA-256";
4
+ readonly SCRAM_SHA_512: "SCRAM-SHA-512";
5
+ readonly OAUTHBEARER: "OAUTHBEARER";
6
+ };
7
+ export declare const allowedSASLMechanisms: SASLMechanismValue[];
8
+ export type SASLMechanism = keyof typeof SASLMechanisms;
9
+ export type SASLMechanismValue = (typeof SASLMechanisms)[keyof typeof SASLMechanisms];
3
10
  export declare const FindCoordinatorKeyTypes: {
4
11
  readonly GROUP: 0;
5
12
  readonly TRANSACTION: 1;
@@ -11,11 +18,13 @@ export declare const ProduceAcks: {
11
18
  readonly NO_RESPONSE: 0;
12
19
  readonly LEADER: 1;
13
20
  };
21
+ export declare const allowedProduceAcks: number[];
14
22
  export type ProduceAck = keyof typeof ProduceAcks;
15
23
  export declare const FetchIsolationLevels: {
16
24
  READ_UNCOMMITTED: number;
17
25
  READ_COMMITTED: number;
18
26
  };
27
+ export declare const allowedFetchIsolationLevels: number[];
19
28
  export type FetchIsolationLevel = keyof typeof FetchIsolationLevels;
20
29
  export declare const ListOffsetTimestamps: {
21
30
  LATEST: bigint;
@@ -1,5 +1,11 @@
1
1
  // SASL Authentication
2
- export const SASLMechanisms = ['PLAIN', 'SCRAM-SHA-256', 'SCRAM-SHA-512', 'OAUTHBEARER'];
2
+ export const SASLMechanisms = {
3
+ PLAIN: 'PLAIN',
4
+ SCRAM_SHA_256: 'SCRAM-SHA-256',
5
+ SCRAM_SHA_512: 'SCRAM-SHA-512',
6
+ OAUTHBEARER: 'OAUTHBEARER'
7
+ };
8
+ export const allowedSASLMechanisms = Object.values(SASLMechanisms);
3
9
  // Metadata API
4
10
  // ./metadata/find-coordinator.ts
5
11
  export const FindCoordinatorKeyTypes = { GROUP: 0, TRANSACTION: 1, SHARE: 2 };
@@ -9,9 +15,11 @@ export const ProduceAcks = {
9
15
  NO_RESPONSE: 0,
10
16
  LEADER: 1
11
17
  };
18
+ export const allowedProduceAcks = Object.values(ProduceAcks);
12
19
  // Consumer API
13
20
  // ./consumer/fetch.ts
14
21
  export const FetchIsolationLevels = { READ_UNCOMMITTED: 0, READ_COMMITTED: 1 };
22
+ export const allowedFetchIsolationLevels = Object.values(FetchIsolationLevels);
15
23
  export const ListOffsetTimestamps = { LATEST: -1n, EARLIEST: -2n };
16
24
  // Admin API
17
25
  // ./admin/*-acls.ts - See: https://cwiki.apache.org/confluence/display/KAFKA/KIP-140%3A+Add+administrative+RPCs+for+adding%2C+deleting%2C+and+listing+ACLs
@@ -88,7 +88,7 @@ export declare const baseOptionsSchema: {
88
88
  properties: {
89
89
  mechanism: {
90
90
  type: string;
91
- enum: readonly ["PLAIN", "SCRAM-SHA-256", "SCRAM-SHA-512", "OAUTHBEARER"];
91
+ enum: import("../../apis/enumerations.ts").SASLMechanismValue[];
92
92
  };
93
93
  username: {
94
94
  oneOf: ({
@@ -1,4 +1,4 @@
1
- import { SASLMechanisms } from "../../apis/enumerations.js";
1
+ import { allowedSASLMechanisms } from "../../apis/enumerations.js";
2
2
  import { ajv } from "../../utils.js";
3
3
  import { version } from "../../version.js";
4
4
  // Note: clientSoftwareName can only contain alphanumeric characters, hyphens and dots
@@ -36,7 +36,7 @@ export const baseOptionsSchema = {
36
36
  sasl: {
37
37
  type: 'object',
38
38
  properties: {
39
- mechanism: { type: 'string', enum: SASLMechanisms },
39
+ mechanism: { type: 'string', enum: allowedSASLMechanisms },
40
40
  username: { oneOf: [{ type: 'string' }, { function: true }] },
41
41
  password: { oneOf: [{ type: 'string' }, { function: true }] },
42
42
  token: { oneOf: [{ type: 'string' }, { function: true }] },
@@ -39,7 +39,9 @@ export class MessagesStream extends Readable {
39
39
  #metricsConsumedMessages;
40
40
  #corruptedMessageHandler;
41
41
  constructor(consumer, options) {
42
- const { autocommit, mode, fallbackMode, maxFetches, offsets, deserializers, onCorruptedMessage, ...otherOptions } = options;
42
+ const { autocommit, mode, fallbackMode, maxFetches, offsets, deserializers, onCorruptedMessage,
43
+ // The options below are only destructured to avoid being part of structuredClone below
44
+ partitionAssigner: _partitionAssigner, ...otherOptions } = options;
43
45
  if (offsets && mode !== MessagesStreamModes.MANUAL) {
44
46
  throw new UserError('Cannot specify offsets when the stream mode is not MANUAL.');
45
47
  }
@@ -93,7 +93,7 @@ export declare const consumeOptionsProperties: {
93
93
  };
94
94
  isolationLevel: {
95
95
  type: string;
96
- enum: string[];
96
+ enum: number[];
97
97
  };
98
98
  deserializers: {
99
99
  type: string;
@@ -196,7 +196,7 @@ export declare const consumeOptionsSchema: {
196
196
  };
197
197
  isolationLevel: {
198
198
  type: string;
199
- enum: string[];
199
+ enum: number[];
200
200
  };
201
201
  deserializers: {
202
202
  type: string;
@@ -275,11 +275,11 @@ export declare const consumeOptionsSchema: {
275
275
  };
276
276
  mode: {
277
277
  type: string;
278
- enum: ("latest" | "earliest" | "committed" | "manual")[];
278
+ enum: import("./types.ts").MessagesStreamModeValue[];
279
279
  };
280
280
  fallbackMode: {
281
281
  type: string;
282
- enum: ("latest" | "earliest" | "fail")[];
282
+ enum: import("./types.ts").MessagesStreamFallbackModeValue[];
283
283
  };
284
284
  maxFetches: {
285
285
  type: string;
@@ -340,7 +340,7 @@ export declare const consumerOptionsSchema: {
340
340
  };
341
341
  isolationLevel: {
342
342
  type: string;
343
- enum: string[];
343
+ enum: number[];
344
344
  };
345
345
  deserializers: {
346
346
  type: string;
@@ -444,7 +444,7 @@ export declare const fetchOptionsSchema: {
444
444
  };
445
445
  isolationLevel: {
446
446
  type: string;
447
- enum: string[];
447
+ enum: number[];
448
448
  };
449
449
  deserializers: {
450
450
  type: string;
@@ -639,7 +639,7 @@ export declare const listOffsetsOptionsSchema: {
639
639
  };
640
640
  isolationLevel: {
641
641
  type: string;
642
- enum: string[];
642
+ enum: number[];
643
643
  };
644
644
  timestamp: {
645
645
  bigint: boolean;
@@ -1,8 +1,8 @@
1
- import { FetchIsolationLevels } from "../../apis/enumerations.js";
1
+ import { allowedFetchIsolationLevels } from "../../apis/enumerations.js";
2
2
  import { ajv } from "../../utils.js";
3
3
  import { idProperty, topicWithPartitionAndOffsetProperties } from "../base/options.js";
4
4
  import { serdeProperties } from "../serde.js";
5
- import { MessagesStreamFallbackModes, MessagesStreamModes } from "./types.js";
5
+ import { allowedMessagesStreamFallbackModes, allowedMessagesStreamModes } from "./types.js";
6
6
  export const groupOptionsProperties = {
7
7
  sessionTimeout: { type: 'number', minimum: 0 },
8
8
  rebalanceTimeout: { type: 'number', minimum: 0 },
@@ -56,7 +56,7 @@ export const consumeOptionsProperties = {
56
56
  minBytes: { type: 'number', minimum: 0 },
57
57
  maxBytes: { type: 'number', minimum: 0 },
58
58
  maxWaitTime: { type: 'number', minimum: 0 },
59
- isolationLevel: { type: 'string', enum: Object.keys(FetchIsolationLevels) },
59
+ isolationLevel: { type: 'string', enum: allowedFetchIsolationLevels },
60
60
  deserializers: serdeProperties,
61
61
  highWaterMark: { type: 'number', minimum: 1 }
62
62
  };
@@ -69,8 +69,8 @@ export const consumeOptionsSchema = {
69
69
  type: 'object',
70
70
  properties: {
71
71
  topics: { type: 'array', items: idProperty },
72
- mode: { type: 'string', enum: Object.values(MessagesStreamModes) },
73
- fallbackMode: { type: 'string', enum: Object.values(MessagesStreamFallbackModes) },
72
+ mode: { type: 'string', enum: allowedMessagesStreamModes },
73
+ fallbackMode: { type: 'string', enum: allowedMessagesStreamFallbackModes },
74
74
  maxFetches: { type: 'number', minimum: 0, default: 0 },
75
75
  offsets: {
76
76
  type: 'array',
@@ -187,7 +187,7 @@ export const listOffsetsOptionsSchema = {
187
187
  items: { type: 'number', minimum: 0 }
188
188
  }
189
189
  },
190
- isolationLevel: { type: 'string', enum: Object.keys(FetchIsolationLevels) },
190
+ isolationLevel: { type: 'string', enum: allowedFetchIsolationLevels },
191
191
  timestamp: { bigint: true }
192
192
  },
193
193
  required: ['topics'],
@@ -33,6 +33,7 @@ export declare const MessagesStreamModes: {
33
33
  readonly COMMITTED: "committed";
34
34
  readonly MANUAL: "manual";
35
35
  };
36
+ export declare const allowedMessagesStreamModes: MessagesStreamModeValue[];
36
37
  export type MessagesStreamMode = keyof typeof MessagesStreamModes;
37
38
  export type MessagesStreamModeValue = (typeof MessagesStreamModes)[keyof typeof MessagesStreamModes];
38
39
  export declare const MessagesStreamFallbackModes: {
@@ -40,6 +41,7 @@ export declare const MessagesStreamFallbackModes: {
40
41
  readonly EARLIEST: "earliest";
41
42
  readonly FAIL: "fail";
42
43
  };
44
+ export declare const allowedMessagesStreamFallbackModes: MessagesStreamFallbackModeValue[];
43
45
  export type MessagesStreamFallbackMode = keyof typeof MessagesStreamFallbackModes;
44
46
  export type MessagesStreamFallbackModeValue = (typeof MessagesStreamFallbackModes)[keyof typeof MessagesStreamFallbackModes];
45
47
  export interface GroupOptions {
@@ -4,8 +4,10 @@ export const MessagesStreamModes = {
4
4
  COMMITTED: 'committed',
5
5
  MANUAL: 'manual'
6
6
  };
7
+ export const allowedMessagesStreamModes = Object.values(MessagesStreamModes);
7
8
  export const MessagesStreamFallbackModes = {
8
9
  LATEST: 'latest',
9
10
  EARLIEST: 'earliest',
10
11
  FAIL: 'fail'
11
12
  };
13
+ export const allowedMessagesStreamFallbackModes = Object.values(MessagesStreamFallbackModes);
@@ -11,14 +11,14 @@ export declare const produceOptionsProperties: {
11
11
  acks: {
12
12
  type: string;
13
13
  enumeration: {
14
- allowed: (0 | 1 | -1)[];
14
+ allowed: number[];
15
15
  errorMessage: string;
16
16
  };
17
17
  };
18
18
  compression: {
19
19
  type: string;
20
20
  enumeration: {
21
- allowed: string[];
21
+ allowed: import("../../protocol/compression.ts").CompressionAlgorithmValue[];
22
22
  errorMessage: string;
23
23
  };
24
24
  };
@@ -47,14 +47,14 @@ export declare const produceOptionsSchema: {
47
47
  acks: {
48
48
  type: string;
49
49
  enumeration: {
50
- allowed: (0 | 1 | -1)[];
50
+ allowed: number[];
51
51
  errorMessage: string;
52
52
  };
53
53
  };
54
54
  compression: {
55
55
  type: string;
56
56
  enumeration: {
57
- allowed: string[];
57
+ allowed: import("../../protocol/compression.ts").CompressionAlgorithmValue[];
58
58
  errorMessage: string;
59
59
  };
60
60
  };
@@ -87,14 +87,14 @@ export declare const sendOptionsSchema: {
87
87
  acks: {
88
88
  type: string;
89
89
  enumeration: {
90
- allowed: (0 | 1 | -1)[];
90
+ allowed: number[];
91
91
  errorMessage: string;
92
92
  };
93
93
  };
94
94
  compression: {
95
95
  type: string;
96
96
  enumeration: {
97
- allowed: string[];
97
+ allowed: import("../../protocol/compression.ts").CompressionAlgorithmValue[];
98
98
  errorMessage: string;
99
99
  };
100
100
  };
@@ -1,5 +1,5 @@
1
- import { ProduceAcks } from "../../apis/enumerations.js";
2
- import { compressionsAlgorithms } from "../../protocol/compression.js";
1
+ import { allowedProduceAcks, ProduceAcks } from "../../apis/enumerations.js";
2
+ import { allowedCompressionsAlgorithms, compressionsAlgorithms } from "../../protocol/compression.js";
3
3
  import { messageSchema } from "../../protocol/records.js";
4
4
  import { ajv, enumErrorMessage } from "../../utils.js";
5
5
  import { serdeProperties } from "../serde.js";
@@ -10,15 +10,15 @@ export const produceOptionsProperties = {
10
10
  acks: {
11
11
  type: 'number',
12
12
  enumeration: {
13
- allowed: Object.values(ProduceAcks),
13
+ allowed: allowedProduceAcks,
14
14
  errorMessage: enumErrorMessage(ProduceAcks)
15
15
  }
16
16
  },
17
17
  compression: {
18
18
  type: 'string',
19
19
  enumeration: {
20
- allowed: Object.keys(compressionsAlgorithms),
21
- errorMessage: enumErrorMessage(compressionsAlgorithms, true)
20
+ allowed: allowedCompressionsAlgorithms,
21
+ errorMessage: enumErrorMessage(compressionsAlgorithms)
22
22
  }
23
23
  },
24
24
  partitioner: { function: true },
@@ -3,7 +3,7 @@ import { type Socket } from 'node:net';
3
3
  import { type ConnectionOptions as TLSConnectionOptions } from 'node:tls';
4
4
  import { type CallbackWithPromise } from '../apis/callbacks.ts';
5
5
  import { type Callback, type ResponseParser } from '../apis/definitions.ts';
6
- import { type SASLMechanism } from '../apis/enumerations.ts';
6
+ import { type SASLMechanismValue } from '../apis/enumerations.ts';
7
7
  import { Writer } from '../protocol/writer.ts';
8
8
  export type SASLCredentialProvider = () => string | Promise<string>;
9
9
  export interface Broker {
@@ -11,7 +11,7 @@ export interface Broker {
11
11
  port: number;
12
12
  }
13
13
  export interface SASLOptions {
14
- mechanism: SASLMechanism;
14
+ mechanism: SASLMechanismValue;
15
15
  username?: string | SASLCredentialProvider;
16
16
  password?: string | SASLCredentialProvider;
17
17
  token?: string | SASLCredentialProvider;
@@ -3,7 +3,7 @@ import EventEmitter from 'node:events';
3
3
  import { createConnection } from 'node:net';
4
4
  import { connect as createTLSConnection } from 'node:tls';
5
5
  import { createPromisifiedCallback, kCallbackPromise } from "../apis/callbacks.js";
6
- import { SASLMechanisms } from "../apis/enumerations.js";
6
+ import { allowedSASLMechanisms, SASLMechanisms } from "../apis/enumerations.js";
7
7
  import { saslAuthenticateV2, saslHandshakeV1 } from "../apis/index.js";
8
8
  import { connectionsApiChannel, connectionsConnectsChannel, createDiagnosticContext, notifyCreation } from "../diagnostic.js";
9
9
  import { AuthenticationError, NetworkError, TimeoutError, UnexpectedCorrelationIdError, UserError } from "../errors.js";
@@ -237,7 +237,7 @@ export class Connection extends EventEmitter {
237
237
  this.#status = ConnectionStatuses.AUTHENTICATING;
238
238
  }
239
239
  const { mechanism, username, password, token } = this.#options.sasl;
240
- if (!SASLMechanisms.includes(mechanism)) {
240
+ if (!allowedSASLMechanisms.includes(mechanism)) {
241
241
  this.#onConnectionError(host, port, diagnosticContext, new UserError(`SASL mechanism ${mechanism} not supported.`));
242
242
  return;
243
243
  }
@@ -248,10 +248,10 @@ export class Connection extends EventEmitter {
248
248
  }
249
249
  this.emit('sasl:handshake', response.mechanisms);
250
250
  const callback = this.#onSaslAuthenticate.bind(this, host, port, diagnosticContext);
251
- if (mechanism === 'PLAIN') {
251
+ if (mechanism === SASLMechanisms.PLAIN) {
252
252
  saslPlain.authenticate(saslAuthenticateV2.api, this, username, password, callback);
253
253
  }
254
- else if (mechanism === 'OAUTHBEARER') {
254
+ else if (mechanism === SASLMechanisms.OAUTHBEARER) {
255
255
  saslOAuthBearer.authenticate(saslAuthenticateV2.api, this, token, callback);
256
256
  }
257
257
  else {
@@ -345,7 +345,7 @@ export class Connection extends EventEmitter {
345
345
  }
346
346
  #onSaslAuthenticationValidation(host, port, diagnosticContext, sessionLifetimeMs, error, authBytes) {
347
347
  if (error) {
348
- this.#onConnectionError(host, port, diagnosticContext, error);
348
+ this.#onConnectionError(host, port, diagnosticContext, new AuthenticationError('SASL authentication failed.', { cause: error }));
349
349
  return;
350
350
  }
351
351
  if (sessionLifetimeMs > 0) {
@@ -14,6 +14,7 @@ export declare const CompressionAlgorithms: {
14
14
  readonly LZ4: "lz4";
15
15
  readonly ZSTD: "zstd";
16
16
  };
17
+ export declare const allowedCompressionsAlgorithms: CompressionAlgorithmValue[];
17
18
  export type CompressionAlgorithm = keyof typeof CompressionAlgorithms;
18
19
  export type CompressionAlgorithmValue = (typeof CompressionAlgorithms)[keyof typeof CompressionAlgorithms];
19
20
  export declare const compressionsAlgorithms: {
@@ -11,6 +11,7 @@ export const CompressionAlgorithms = {
11
11
  LZ4: 'lz4',
12
12
  ZSTD: 'zstd'
13
13
  };
14
+ export const allowedCompressionsAlgorithms = Object.values(CompressionAlgorithms);
14
15
  function ensureBuffer(data) {
15
16
  return DynamicBuffer.isDynamicBuffer(data) ? data.slice() : data;
16
17
  }
@@ -2,9 +2,12 @@ import { createPromisifiedCallback, kCallbackPromise } from "../../apis/callback
2
2
  import { AuthenticationError } from "../../errors.js";
3
3
  import { getCredential } from "./credential-provider.js";
4
4
  export function jwtValidateAuthenticationBytes(authBytes, callback) {
5
- let authData;
5
+ let authData = {};
6
6
  try {
7
- authData = authBytes.length > 0 ? JSON.parse(authBytes.toString('utf-8')) : {};
7
+ if (authBytes.length > 0) {
8
+ authData = JSON.parse(authBytes.toString('utf-8'));
9
+ }
10
+ /* c8 ignore next 8 - Hard to test */
8
11
  }
9
12
  catch (e) {
10
13
  callback(new AuthenticationError('Invalid authBytes in SASL/OAUTHBEARER response', { authBytes }), undefined);
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  export const name = "@platformatic/kafka";
2
- export const version = "1.13.0";
2
+ export const version = "1.14.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/kafka",
3
- "version": "1.13.0",
3
+ "version": "1.14.0",
4
4
  "description": "Modern and performant client for Apache Kafka",
5
5
  "homepage": "https://github.com/platformatic/kafka",
6
6
  "author": "Platformatic Inc. <oss@platformatic.dev> (https://platformatic.dev)",
@@ -69,12 +69,12 @@
69
69
  "lint": "eslint --cache",
70
70
  "typecheck": "tsc -p . --noEmit",
71
71
  "format": "prettier -w benchmarks playground src test",
72
- "test": "c8 -c test/config/c8-local.json node --env-file=test/config/env --no-warnings --test --test-timeout=300000 'test/**/*.test.ts'",
73
- "test:ci": "c8 -c test/config/c8-ci.json node --env-file=test/config/env --no-warnings --test --test-timeout=300000 'test/**/*.test.ts'",
72
+ "test": "c8 -c test/config/c8-local.json node --env-file=test/config/env --no-warnings --test --test-timeout=600000 'test/**/*.test.ts'",
73
+ "test:ci": "c8 -c test/config/c8-ci.json node --env-file=test/config/env --no-warnings --test --test-timeout=600000 'test/**/*.test.ts'",
74
74
  "test:docker:up": "node scripts/docker.ts up -d --wait",
75
75
  "test:docker:down": "node scripts/docker.ts down",
76
76
  "ci": "npm run build && npm run lint && npm run test:ci",
77
- "ci:v20": "npm run lint && rm -rf dist && tsc -p tsconfig.json && node dist/scripts/postbuild.js && cd dist && c8 -c ../test/config/c8-ci.json node --env-file=../test/config/env --no-warnings --test --test-timeout=300000",
77
+ "ci:v20": "npm run lint && rm -rf dist && tsc -p tsconfig.json && node dist/scripts/postbuild.js && cd dist && c8 -c ../test/config/c8-ci.json node --env-file=../test/config/env --no-warnings --test --test-timeout=600000",
78
78
  "generate:apis": "node scripts/generate-apis.ts",
79
79
  "generate:errors": "node scripts/generate-errors.ts",
80
80
  "create:api": "node scripts/create-api.ts"