@platformatic/kafka 0.1.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 (223) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +270 -0
  3. package/dist/apis/admin/alter-client-quotas.d.ts +33 -0
  4. package/dist/apis/admin/alter-client-quotas.js +64 -0
  5. package/dist/apis/admin/alter-configs.d.ts +26 -0
  6. package/dist/apis/admin/alter-configs.js +57 -0
  7. package/dist/apis/admin/alter-partition-reassignments.d.ts +30 -0
  8. package/dist/apis/admin/alter-partition-reassignments.js +68 -0
  9. package/dist/apis/admin/alter-partition.d.ts +39 -0
  10. package/dist/apis/admin/alter-partition.js +87 -0
  11. package/dist/apis/admin/alter-replica-log-dirs.d.ts +26 -0
  12. package/dist/apis/admin/alter-replica-log-dirs.js +55 -0
  13. package/dist/apis/admin/alter-user-scram-credentials.d.ts +27 -0
  14. package/dist/apis/admin/alter-user-scram-credentials.js +60 -0
  15. package/dist/apis/admin/consumer-group-describe.d.ts +41 -0
  16. package/dist/apis/admin/consumer-group-describe.js +103 -0
  17. package/dist/apis/admin/create-acls.d.ts +24 -0
  18. package/dist/apis/admin/create-acls.js +55 -0
  19. package/dist/apis/admin/create-delegation-token.d.ts +24 -0
  20. package/dist/apis/admin/create-delegation-token.js +54 -0
  21. package/dist/apis/admin/create-partitions.d.ts +24 -0
  22. package/dist/apis/admin/create-partitions.js +54 -0
  23. package/dist/apis/admin/create-topics.d.ts +42 -0
  24. package/dist/apis/admin/create-topics.js +86 -0
  25. package/dist/apis/admin/delete-acls.d.ts +36 -0
  26. package/dist/apis/admin/delete-acls.js +82 -0
  27. package/dist/apis/admin/delete-groups.d.ts +14 -0
  28. package/dist/apis/admin/delete-groups.js +40 -0
  29. package/dist/apis/admin/delete-records.d.ts +27 -0
  30. package/dist/apis/admin/delete-records.js +59 -0
  31. package/dist/apis/admin/delete-topics.d.ts +21 -0
  32. package/dist/apis/admin/delete-topics.js +50 -0
  33. package/dist/apis/admin/describe-acls.d.ts +25 -0
  34. package/dist/apis/admin/describe-acls.js +66 -0
  35. package/dist/apis/admin/describe-client-quotas.d.ts +30 -0
  36. package/dist/apis/admin/describe-client-quotas.js +57 -0
  37. package/dist/apis/admin/describe-cluster.d.ts +23 -0
  38. package/dist/apis/admin/describe-cluster.js +50 -0
  39. package/dist/apis/admin/describe-configs.d.ts +38 -0
  40. package/dist/apis/admin/describe-configs.js +85 -0
  41. package/dist/apis/admin/describe-delegation-token.d.ts +31 -0
  42. package/dist/apis/admin/describe-delegation-token.js +62 -0
  43. package/dist/apis/admin/describe-groups.d.ts +28 -0
  44. package/dist/apis/admin/describe-groups.js +67 -0
  45. package/dist/apis/admin/describe-log-dirs.d.ts +32 -0
  46. package/dist/apis/admin/describe-log-dirs.js +75 -0
  47. package/dist/apis/admin/describe-producers.d.ts +33 -0
  48. package/dist/apis/admin/describe-producers.js +70 -0
  49. package/dist/apis/admin/describe-quorum.d.ts +50 -0
  50. package/dist/apis/admin/describe-quorum.js +116 -0
  51. package/dist/apis/admin/describe-topic-partitions.d.ts +42 -0
  52. package/dist/apis/admin/describe-topic-partitions.js +94 -0
  53. package/dist/apis/admin/describe-transactions.d.ts +24 -0
  54. package/dist/apis/admin/describe-transactions.js +59 -0
  55. package/dist/apis/admin/describe-user-scram-credentials.d.ts +26 -0
  56. package/dist/apis/admin/describe-user-scram-credentials.js +62 -0
  57. package/dist/apis/admin/envelope.d.ts +10 -0
  58. package/dist/apis/admin/envelope.js +32 -0
  59. package/dist/apis/admin/expire-delegation-token.d.ts +11 -0
  60. package/dist/apis/admin/expire-delegation-token.js +29 -0
  61. package/dist/apis/admin/incremental-alter-configs.d.ts +27 -0
  62. package/dist/apis/admin/incremental-alter-configs.js +58 -0
  63. package/dist/apis/admin/index.d.ts +37 -0
  64. package/dist/apis/admin/index.js +37 -0
  65. package/dist/apis/admin/list-groups.d.ts +18 -0
  66. package/dist/apis/admin/list-groups.js +43 -0
  67. package/dist/apis/admin/list-partition-reassignments.d.ts +27 -0
  68. package/dist/apis/admin/list-partition-reassignments.js +56 -0
  69. package/dist/apis/admin/list-transactions.d.ts +18 -0
  70. package/dist/apis/admin/list-transactions.js +45 -0
  71. package/dist/apis/admin/offset-delete.d.ts +26 -0
  72. package/dist/apis/admin/offset-delete.js +59 -0
  73. package/dist/apis/admin/renew-delegation-token.d.ts +11 -0
  74. package/dist/apis/admin/renew-delegation-token.js +29 -0
  75. package/dist/apis/admin/unregister-broker.d.ts +12 -0
  76. package/dist/apis/admin/unregister-broker.js +28 -0
  77. package/dist/apis/admin/update-features.d.ts +23 -0
  78. package/dist/apis/admin/update-features.js +60 -0
  79. package/dist/apis/consumer/consumer-group-heartbeat.d.ts +27 -0
  80. package/dist/apis/consumer/consumer-group-heartbeat.js +70 -0
  81. package/dist/apis/consumer/fetch.d.ts +46 -0
  82. package/dist/apis/consumer/fetch.js +121 -0
  83. package/dist/apis/consumer/heartbeat.d.ts +11 -0
  84. package/dist/apis/consumer/heartbeat.js +34 -0
  85. package/dist/apis/consumer/index.d.ts +9 -0
  86. package/dist/apis/consumer/index.js +9 -0
  87. package/dist/apis/consumer/join-group.d.ts +27 -0
  88. package/dist/apis/consumer/join-group.js +71 -0
  89. package/dist/apis/consumer/leave-group.d.ts +22 -0
  90. package/dist/apis/consumer/leave-group.js +57 -0
  91. package/dist/apis/consumer/list-offsets.d.ts +30 -0
  92. package/dist/apis/consumer/list-offsets.js +68 -0
  93. package/dist/apis/consumer/offset-commit.d.ts +29 -0
  94. package/dist/apis/consumer/offset-commit.js +68 -0
  95. package/dist/apis/consumer/offset-fetch.d.ts +37 -0
  96. package/dist/apis/consumer/offset-fetch.js +81 -0
  97. package/dist/apis/consumer/sync-group.d.ts +18 -0
  98. package/dist/apis/consumer/sync-group.js +49 -0
  99. package/dist/apis/definitions.d.ts +16 -0
  100. package/dist/apis/definitions.js +12 -0
  101. package/dist/apis/enumerations.d.ts +114 -0
  102. package/dist/apis/enumerations.js +78 -0
  103. package/dist/apis/index.d.ts +8 -0
  104. package/dist/apis/index.js +10 -0
  105. package/dist/apis/metadata/api-versions.d.ts +17 -0
  106. package/dist/apis/metadata/api-versions.js +41 -0
  107. package/dist/apis/metadata/find-coordinator.d.ts +19 -0
  108. package/dist/apis/metadata/find-coordinator.js +50 -0
  109. package/dist/apis/metadata/index.d.ts +3 -0
  110. package/dist/apis/metadata/index.js +3 -0
  111. package/dist/apis/metadata/metadata.d.ts +37 -0
  112. package/dist/apis/metadata/metadata.js +92 -0
  113. package/dist/apis/producer/add-offsets-to-txn.d.ts +10 -0
  114. package/dist/apis/producer/add-offsets-to-txn.js +34 -0
  115. package/dist/apis/producer/add-partitions-to-txn.d.ts +34 -0
  116. package/dist/apis/producer/add-partitions-to-txn.js +79 -0
  117. package/dist/apis/producer/end-txn.d.ts +10 -0
  118. package/dist/apis/producer/end-txn.js +34 -0
  119. package/dist/apis/producer/index.d.ts +6 -0
  120. package/dist/apis/producer/index.js +6 -0
  121. package/dist/apis/producer/init-producer-id.d.ts +21 -0
  122. package/dist/apis/producer/init-producer-id.js +38 -0
  123. package/dist/apis/producer/produce.d.ts +29 -0
  124. package/dist/apis/producer/produce.js +104 -0
  125. package/dist/apis/producer/txn-offset-commit.d.ts +29 -0
  126. package/dist/apis/producer/txn-offset-commit.js +77 -0
  127. package/dist/apis/security/index.d.ts +2 -0
  128. package/dist/apis/security/index.js +2 -0
  129. package/dist/apis/security/sasl-authenticate.d.ts +15 -0
  130. package/dist/apis/security/sasl-authenticate.js +30 -0
  131. package/dist/apis/security/sasl-handshake.d.ts +10 -0
  132. package/dist/apis/security/sasl-handshake.js +28 -0
  133. package/dist/apis/telemetry/get-telemetry-subscriptions.d.ts +18 -0
  134. package/dist/apis/telemetry/get-telemetry-subscriptions.js +46 -0
  135. package/dist/apis/telemetry/index.d.ts +3 -0
  136. package/dist/apis/telemetry/index.js +3 -0
  137. package/dist/apis/telemetry/list-client-metrics-resources.d.ts +14 -0
  138. package/dist/apis/telemetry/list-client-metrics-resources.js +32 -0
  139. package/dist/apis/telemetry/push-telemetry.d.ts +10 -0
  140. package/dist/apis/telemetry/push-telemetry.js +36 -0
  141. package/dist/clients/admin/admin.d.ts +18 -0
  142. package/dist/clients/admin/admin.js +322 -0
  143. package/dist/clients/admin/index.d.ts +3 -0
  144. package/dist/clients/admin/index.js +3 -0
  145. package/dist/clients/admin/options.d.ts +135 -0
  146. package/dist/clients/admin/options.js +81 -0
  147. package/dist/clients/admin/types.d.ts +56 -0
  148. package/dist/clients/admin/types.js +1 -0
  149. package/dist/clients/base/base.d.ts +48 -0
  150. package/dist/clients/base/base.js +242 -0
  151. package/dist/clients/base/index.d.ts +3 -0
  152. package/dist/clients/base/index.js +3 -0
  153. package/dist/clients/base/options.d.ts +115 -0
  154. package/dist/clients/base/options.js +59 -0
  155. package/dist/clients/base/types.d.ts +38 -0
  156. package/dist/clients/base/types.js +1 -0
  157. package/dist/clients/callbacks.d.ts +8 -0
  158. package/dist/clients/callbacks.js +42 -0
  159. package/dist/clients/consumer/consumer.d.ts +33 -0
  160. package/dist/clients/consumer/consumer.js +767 -0
  161. package/dist/clients/consumer/index.d.ts +5 -0
  162. package/dist/clients/consumer/index.js +5 -0
  163. package/dist/clients/consumer/messages-stream.d.ts +56 -0
  164. package/dist/clients/consumer/messages-stream.js +404 -0
  165. package/dist/clients/consumer/options.d.ts +521 -0
  166. package/dist/clients/consumer/options.js +177 -0
  167. package/dist/clients/consumer/topics-map.d.ts +8 -0
  168. package/dist/clients/consumer/topics-map.js +48 -0
  169. package/dist/clients/consumer/types.d.ts +74 -0
  170. package/dist/clients/consumer/types.js +11 -0
  171. package/dist/clients/index.d.ts +6 -0
  172. package/dist/clients/index.js +6 -0
  173. package/dist/clients/producer/index.d.ts +3 -0
  174. package/dist/clients/producer/index.js +3 -0
  175. package/dist/clients/producer/options.d.ts +122 -0
  176. package/dist/clients/producer/options.js +47 -0
  177. package/dist/clients/producer/producer.d.ts +13 -0
  178. package/dist/clients/producer/producer.js +272 -0
  179. package/dist/clients/producer/types.d.ts +29 -0
  180. package/dist/clients/producer/types.js +1 -0
  181. package/dist/clients/serde.d.ts +40 -0
  182. package/dist/clients/serde.js +49 -0
  183. package/dist/errors.d.ts +67 -0
  184. package/dist/errors.js +160 -0
  185. package/dist/index.d.ts +6 -0
  186. package/dist/index.js +10 -0
  187. package/dist/network/connection-pool.d.ts +11 -0
  188. package/dist/network/connection-pool.js +101 -0
  189. package/dist/network/connection.d.ts +49 -0
  190. package/dist/network/connection.js +319 -0
  191. package/dist/network/index.d.ts +2 -0
  192. package/dist/network/index.js +2 -0
  193. package/dist/protocol/apis.d.ts +2 -0
  194. package/dist/protocol/apis.js +191 -0
  195. package/dist/protocol/compression.d.ts +70 -0
  196. package/dist/protocol/compression.js +114 -0
  197. package/dist/protocol/crc32c.d.ts +2 -0
  198. package/dist/protocol/crc32c.js +83 -0
  199. package/dist/protocol/definitions.d.ts +12 -0
  200. package/dist/protocol/definitions.js +11 -0
  201. package/dist/protocol/dynamic-buffer.d.ts +65 -0
  202. package/dist/protocol/dynamic-buffer.js +557 -0
  203. package/dist/protocol/errors.d.ts +8 -0
  204. package/dist/protocol/errors.js +908 -0
  205. package/dist/protocol/index.d.ts +14 -0
  206. package/dist/protocol/index.js +14 -0
  207. package/dist/protocol/murmur2.d.ts +1 -0
  208. package/dist/protocol/murmur2.js +55 -0
  209. package/dist/protocol/reader.d.ts +58 -0
  210. package/dist/protocol/reader.js +296 -0
  211. package/dist/protocol/records.d.ts +110 -0
  212. package/dist/protocol/records.js +149 -0
  213. package/dist/protocol/sasl/plain.d.ts +3 -0
  214. package/dist/protocol/sasl/plain.js +3 -0
  215. package/dist/protocol/sasl/scram-sha.d.ts +28 -0
  216. package/dist/protocol/sasl/scram-sha.js +104 -0
  217. package/dist/protocol/varint.d.ts +12 -0
  218. package/dist/protocol/varint.js +36 -0
  219. package/dist/protocol/writer.d.ts +48 -0
  220. package/dist/protocol/writer.js +223 -0
  221. package/dist/utils.d.ts +20 -0
  222. package/dist/utils.js +127 -0
  223. package/package.json +75 -0
@@ -0,0 +1,14 @@
1
+ export * from './apis.ts';
2
+ export * from './compression.ts';
3
+ export * from './crc32c.ts';
4
+ export * from './definitions.ts';
5
+ export * from './dynamic-buffer.ts';
6
+ export * from './errors.ts';
7
+ export * from './index.ts';
8
+ export * from './murmur2.ts';
9
+ export * from './reader.ts';
10
+ export * from './records.ts';
11
+ export * as saslPlain from './sasl/plain.ts';
12
+ export * as saslScramSha from './sasl/scram-sha.ts';
13
+ export * from './varint.ts';
14
+ export * from './writer.ts';
@@ -0,0 +1,14 @@
1
+ export * from "./apis.js";
2
+ export * from "./compression.js";
3
+ export * from "./crc32c.js";
4
+ export * from "./definitions.js";
5
+ export * from "./dynamic-buffer.js";
6
+ export * from "./errors.js";
7
+ export * from "./index.js";
8
+ export * from "./murmur2.js";
9
+ export * from "./reader.js";
10
+ export * from "./records.js";
11
+ export * as saslPlain from "./sasl/plain.js";
12
+ export * as saslScramSha from "./sasl/scram-sha.js";
13
+ export * from "./varint.js";
14
+ export * from "./writer.js";
@@ -0,0 +1 @@
1
+ export declare function murmur2(data: string | Buffer, useCache?: boolean): number;
@@ -0,0 +1,55 @@
1
+ import { LRUCache } from 'mnemonist';
2
+ // This is a Javascript port of
3
+ // https://github.com/apache/kafka/blob/trunk/clients/src/main/java/org/apache/kafka/common/utils/Utils.java#L492
4
+ // 'm' and 'r' are mixing constants generated offline. They're not really 'magic', they just happen to work well.
5
+ const seed = 0x9747b28cn;
6
+ const m = 0x5bd1e995n;
7
+ const r = 24;
8
+ const cache = new LRUCache(1000);
9
+ const tail = Buffer.alloc(4);
10
+ function tripleRightShift(num, bits) {
11
+ return BigInt(Number(BigInt.asIntN(32, num)) >>> bits);
12
+ }
13
+ export function murmur2(data, useCache = false) {
14
+ let key;
15
+ if (typeof data === 'string') {
16
+ if (useCache) {
17
+ key = data;
18
+ const existing = key ? cache.get(key) : undefined;
19
+ if (existing) {
20
+ return existing;
21
+ }
22
+ }
23
+ data = Buffer.from(data);
24
+ }
25
+ const length = data.length;
26
+ // Initialize the hash to a random value
27
+ let h = seed ^ BigInt(length);
28
+ let i = 0;
29
+ while (i < length - 3) {
30
+ let k = BigInt(data.readInt32LE(i));
31
+ i += 4;
32
+ k *= m;
33
+ k ^= tripleRightShift(k, r);
34
+ k *= m;
35
+ h *= m;
36
+ h ^= k;
37
+ }
38
+ // Read the last few bytes of the input array
39
+ // If this becomes an hot-path, consider to optimize it further and avoid copying
40
+ if (length % 4 > 0) {
41
+ data.copy(tail, 0, length - (length % 4));
42
+ h ^= BigInt(tail.readInt32LE(0));
43
+ tail.fill(0);
44
+ h *= m;
45
+ }
46
+ // Perform the final mixing
47
+ h ^= tripleRightShift(h, 13);
48
+ h *= m;
49
+ h ^= tripleRightShift(h, 15);
50
+ const hash = Number(BigInt.asIntN(32, h));
51
+ if (key !== undefined) {
52
+ cache.set(key, hash);
53
+ }
54
+ return hash;
55
+ }
@@ -0,0 +1,58 @@
1
+ import { DynamicBuffer } from './dynamic-buffer.ts';
2
+ import { Writer } from './writer.ts';
3
+ export type EntryReader<OutputType> = (reader: Reader, index: number) => OutputType;
4
+ declare const instanceIdentifier: unique symbol;
5
+ export declare class Reader {
6
+ buffer: DynamicBuffer;
7
+ position: number;
8
+ [instanceIdentifier]: boolean;
9
+ static isReader(target: any): boolean;
10
+ static from(buffer: Buffer | DynamicBuffer | Writer): Reader;
11
+ constructor(buffer: DynamicBuffer);
12
+ reset(buffer?: Buffer | DynamicBuffer): void;
13
+ inspect(): string;
14
+ skip(length: number): this;
15
+ peekUnsignedInt8(): number;
16
+ peekUnsignedInt16(): number;
17
+ peekUnsignedInt32(): number;
18
+ peekUnsignedInt64(): bigint;
19
+ peekUnsignedVarInt(): number;
20
+ peekUnsignedVarInt64(): bigint;
21
+ peekInt8(): number;
22
+ peekInt16(): number;
23
+ peekInt32(): number;
24
+ peekInt64(): bigint;
25
+ peekFloat64(): number;
26
+ peekVarInt(): number;
27
+ peekVarInt64(): bigint;
28
+ peekBoolean(): boolean;
29
+ peekUUID(): string;
30
+ readUnsignedInt8(): number;
31
+ readUnsignedInt16(): number;
32
+ readUnsignedInt32(): number;
33
+ readUnsignedInt64(): bigint;
34
+ readUnsignedVarInt(): number;
35
+ readUnsignedVarInt64(): bigint;
36
+ readInt8(): number;
37
+ readInt16(): number;
38
+ readInt32(): number;
39
+ readInt64(): bigint;
40
+ readFloat64(): number;
41
+ readVarInt(): number;
42
+ readVarInt64(): bigint;
43
+ readBoolean(): boolean;
44
+ readNullableString(compact?: boolean, encoding?: BufferEncoding): string | null;
45
+ readString(compact?: boolean, encoding?: BufferEncoding): string;
46
+ readUUID(): string;
47
+ readNullableBytes(compact?: boolean): Buffer | null;
48
+ readBytes(compact?: boolean): Buffer;
49
+ readVarIntBytes(): Buffer;
50
+ readNullableArray<OutputType>(reader: EntryReader<OutputType>, compact?: boolean, discardTrailingTaggedFields?: boolean): OutputType[] | null;
51
+ readNullableMap<Key, Value>(reader: EntryReader<[Key, Value]>, compact?: boolean, discardTrailingTaggedFields?: boolean): Map<Key, Value> | null;
52
+ readArray<OutputType>(reader: EntryReader<OutputType>, compact?: boolean, discardTrailingTaggedFields?: boolean): OutputType[];
53
+ readMap<Key, Value>(reader: EntryReader<[Key, Value]>, compact?: boolean, discardTrailingTaggedFields?: boolean): Map<Key, Value>;
54
+ readVarIntArray<OutputType>(reader: EntryReader<OutputType>): OutputType[];
55
+ readVarIntMap<Key, Value>(reader: EntryReader<[Key, Value]>): Map<Key, Value>;
56
+ readTaggedFields(): void;
57
+ }
58
+ export {};
@@ -0,0 +1,296 @@
1
+ import { EMPTY_BUFFER, INT16_SIZE, INT32_SIZE, INT64_SIZE, INT8_SIZE, UUID_SIZE } from "./definitions.js";
2
+ import { DynamicBuffer } from "./dynamic-buffer.js";
3
+ import { Writer } from "./writer.js";
4
+ const instanceIdentifier = Symbol('plt.kafka.reader.instanceIdentifier');
5
+ export class Reader {
6
+ buffer;
7
+ position;
8
+ [instanceIdentifier];
9
+ static isReader(target) {
10
+ return target?.[instanceIdentifier] === true;
11
+ }
12
+ static from(buffer) {
13
+ if (Writer.isWriter(buffer)) {
14
+ return new Reader(buffer.dynamicBuffer);
15
+ }
16
+ else if (Buffer.isBuffer(buffer)) {
17
+ buffer = new DynamicBuffer(buffer);
18
+ }
19
+ return new Reader(buffer);
20
+ }
21
+ constructor(buffer) {
22
+ this.buffer = buffer;
23
+ this.position = 0;
24
+ this[instanceIdentifier] = true;
25
+ }
26
+ reset(buffer) {
27
+ if (buffer) {
28
+ if (Buffer.isBuffer(buffer)) {
29
+ buffer = new DynamicBuffer(buffer);
30
+ }
31
+ this.buffer = buffer;
32
+ }
33
+ this.position = 0;
34
+ }
35
+ inspect() {
36
+ return this.buffer
37
+ .subarray(this.position)
38
+ .toString('hex')
39
+ .replaceAll(/(.{4})/g, '$1 ')
40
+ .trim();
41
+ }
42
+ skip(length) {
43
+ this.position += length;
44
+ return this;
45
+ }
46
+ peekUnsignedInt8() {
47
+ return this.buffer.readUInt8(this.position);
48
+ }
49
+ peekUnsignedInt16() {
50
+ return this.buffer.readUInt16BE(this.position);
51
+ }
52
+ peekUnsignedInt32() {
53
+ return this.buffer.readUInt32BE(this.position);
54
+ }
55
+ peekUnsignedInt64() {
56
+ return this.buffer.readBigUInt64BE(this.position);
57
+ }
58
+ peekUnsignedVarInt() {
59
+ return this.buffer.readUnsignedVarInt(this.position)[0];
60
+ }
61
+ peekUnsignedVarInt64() {
62
+ return this.buffer.readUnsignedVarInt64(this.position)[0];
63
+ }
64
+ peekInt8() {
65
+ return this.buffer.readInt8(this.position);
66
+ }
67
+ peekInt16() {
68
+ return this.buffer.readInt16BE(this.position);
69
+ }
70
+ peekInt32() {
71
+ return this.buffer.readInt32BE(this.position);
72
+ }
73
+ peekInt64() {
74
+ return this.buffer.readBigInt64BE(this.position);
75
+ }
76
+ peekFloat64() {
77
+ return this.buffer.readDoubleBE(this.position);
78
+ }
79
+ peekVarInt() {
80
+ return this.buffer.readVarInt(this.position)[0];
81
+ }
82
+ peekVarInt64() {
83
+ return this.buffer.readVarInt64(this.position)[0];
84
+ }
85
+ peekBoolean() {
86
+ return this.buffer.readInt8(this.position) === 1;
87
+ }
88
+ peekUUID() {
89
+ return this.buffer.toString('hex', this.position, this.position + UUID_SIZE);
90
+ }
91
+ readUnsignedInt8() {
92
+ const value = this.peekUnsignedInt8();
93
+ this.position += INT8_SIZE;
94
+ return value;
95
+ }
96
+ readUnsignedInt16() {
97
+ const value = this.peekUnsignedInt16();
98
+ this.position += INT16_SIZE;
99
+ return value;
100
+ }
101
+ readUnsignedInt32() {
102
+ const value = this.peekUnsignedInt32();
103
+ this.position += INT32_SIZE;
104
+ return value;
105
+ }
106
+ readUnsignedInt64() {
107
+ const value = this.peekUnsignedInt64();
108
+ this.position += INT64_SIZE;
109
+ return value;
110
+ }
111
+ readUnsignedVarInt() {
112
+ const [value, read] = this.buffer.readUnsignedVarInt(this.position);
113
+ this.position += read;
114
+ return value;
115
+ }
116
+ readUnsignedVarInt64() {
117
+ const [value, read] = this.buffer.readUnsignedVarInt64(this.position);
118
+ this.position += read;
119
+ return value;
120
+ }
121
+ readInt8() {
122
+ const value = this.peekInt8();
123
+ this.position += INT8_SIZE;
124
+ return value;
125
+ }
126
+ readInt16() {
127
+ const value = this.peekInt16();
128
+ this.position += INT16_SIZE;
129
+ return value;
130
+ }
131
+ readInt32() {
132
+ const value = this.peekInt32();
133
+ this.position += INT32_SIZE;
134
+ return value;
135
+ }
136
+ readInt64() {
137
+ const value = this.peekInt64();
138
+ this.position += INT64_SIZE;
139
+ return value;
140
+ }
141
+ readFloat64() {
142
+ const value = this.peekFloat64();
143
+ this.position += INT64_SIZE;
144
+ return value;
145
+ }
146
+ readVarInt() {
147
+ const [value, read] = this.buffer.readVarInt(this.position);
148
+ this.position += read;
149
+ return value;
150
+ }
151
+ readVarInt64() {
152
+ const [value, read] = this.buffer.readVarInt64(this.position);
153
+ this.position += read;
154
+ return value;
155
+ }
156
+ readBoolean() {
157
+ const value = this.peekUnsignedInt8();
158
+ this.position += INT8_SIZE;
159
+ return value === 1;
160
+ }
161
+ readNullableString(compact = true, encoding = 'utf-8') {
162
+ let length;
163
+ if (compact) {
164
+ length = this.readUnsignedVarInt();
165
+ if (length === 0) {
166
+ return null;
167
+ }
168
+ length--;
169
+ }
170
+ else {
171
+ length = this.readInt16();
172
+ if (length === -1) {
173
+ return null;
174
+ }
175
+ }
176
+ const value = this.buffer.toString(encoding, this.position, this.position + length);
177
+ this.position += length;
178
+ return value;
179
+ }
180
+ readString(compact = true, encoding = 'utf-8') {
181
+ return this.readNullableString(compact, encoding) || '';
182
+ }
183
+ readUUID() {
184
+ const value = this.peekUUID();
185
+ this.position += UUID_SIZE;
186
+ return value.replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, '$1-$2-$3-$4-$5');
187
+ }
188
+ readNullableBytes(compact = true) {
189
+ let length;
190
+ if (compact) {
191
+ length = this.readUnsignedVarInt();
192
+ if (length === 0) {
193
+ return null;
194
+ }
195
+ length--;
196
+ }
197
+ else {
198
+ length = this.readInt32();
199
+ if (length === -1) {
200
+ return null;
201
+ }
202
+ }
203
+ const value = this.buffer.slice(this.position, this.position + length);
204
+ this.position += length;
205
+ return value;
206
+ }
207
+ readBytes(compact = true) {
208
+ /* c8 ignore next */
209
+ return this.readNullableBytes(compact) || EMPTY_BUFFER;
210
+ }
211
+ readVarIntBytes() {
212
+ const length = this.readVarInt();
213
+ const value = this.buffer.slice(this.position, this.position + length);
214
+ this.position += length;
215
+ return value;
216
+ }
217
+ readNullableArray(reader, compact = true, discardTrailingTaggedFields = true) {
218
+ let length;
219
+ if (compact) {
220
+ length = this.readUnsignedVarInt();
221
+ if (length === 0) {
222
+ return null;
223
+ }
224
+ length--;
225
+ }
226
+ else {
227
+ length = this.readInt32();
228
+ if (length === -1) {
229
+ return null;
230
+ }
231
+ }
232
+ const value = [];
233
+ for (let i = 0; i < length; i++) {
234
+ value.push(reader(this, i));
235
+ if (discardTrailingTaggedFields) {
236
+ this.readTaggedFields();
237
+ }
238
+ }
239
+ return value;
240
+ }
241
+ readNullableMap(reader, compact = true, discardTrailingTaggedFields = true) {
242
+ let length;
243
+ if (compact) {
244
+ length = this.readUnsignedVarInt();
245
+ if (length === 0) {
246
+ return null;
247
+ }
248
+ length--;
249
+ }
250
+ else {
251
+ length = this.readInt32();
252
+ if (length === -1) {
253
+ return null;
254
+ }
255
+ }
256
+ const map = new Map();
257
+ for (let i = 0; i < length; i++) {
258
+ const [key, value] = reader(this, i);
259
+ map.set(key, value);
260
+ if (discardTrailingTaggedFields) {
261
+ this.readTaggedFields();
262
+ }
263
+ }
264
+ return map;
265
+ }
266
+ readArray(reader, compact = true, discardTrailingTaggedFields = true) {
267
+ return this.readNullableArray(reader, compact, discardTrailingTaggedFields) || [];
268
+ }
269
+ readMap(reader, compact = true, discardTrailingTaggedFields = true) {
270
+ return this.readNullableMap(reader, compact, discardTrailingTaggedFields) ?? new Map();
271
+ }
272
+ readVarIntArray(reader) {
273
+ const length = this.readVarInt();
274
+ const value = [];
275
+ for (let i = 0; i < length; i++) {
276
+ value.push(reader(this, i));
277
+ }
278
+ return value;
279
+ }
280
+ readVarIntMap(reader) {
281
+ const length = this.readVarInt();
282
+ const map = new Map();
283
+ for (let i = 0; i < length; i++) {
284
+ const [key, value] = reader(this, i);
285
+ map.set(key, value);
286
+ }
287
+ return map;
288
+ }
289
+ // TODO(ShogunPanda): Tagged fields are not supported yet
290
+ readTaggedFields() {
291
+ const length = this.readVarInt();
292
+ if (length > 0) {
293
+ this.skip(length);
294
+ }
295
+ }
296
+ }
@@ -0,0 +1,110 @@
1
+ import { type NumericMap } from '../utils.ts';
2
+ import { type CompressionAlgorithms } from './compression.ts';
3
+ import { type NullableString } from './definitions.ts';
4
+ import { Reader } from './reader.ts';
5
+ import { Writer } from './writer.ts';
6
+ export interface MessageBase<Key = Buffer, Value = Buffer> {
7
+ key?: Key;
8
+ value?: Value;
9
+ topic: string;
10
+ partition?: number;
11
+ timestamp?: bigint;
12
+ }
13
+ export interface MessageToProduce<Key = Buffer, Value = Buffer, HeaderKey = Buffer, HeaderValue = Buffer> extends MessageBase<Key, Value> {
14
+ headers?: Map<HeaderKey, HeaderValue> | Record<string, HeaderValue>;
15
+ }
16
+ export interface Message<Key = Buffer, Value = Buffer, HeaderKey = Buffer, HeaderValue = Buffer> extends Required<MessageBase<Key, Value>> {
17
+ headers: Map<HeaderKey, HeaderValue>;
18
+ offset: bigint;
19
+ commit(callback?: (error?: Error) => void): void | Promise<void>;
20
+ }
21
+ export interface MessageRecord {
22
+ key?: Buffer;
23
+ value: Buffer;
24
+ headers?: Map<Buffer, Buffer>;
25
+ topic: string;
26
+ partition?: number;
27
+ timestamp?: bigint;
28
+ }
29
+ export interface CreateRecordsBatchOptions {
30
+ transactionalId?: NullableString;
31
+ compression: CompressionAlgorithms;
32
+ firstSequence?: number;
33
+ producerId: bigint;
34
+ producerEpoch: number;
35
+ sequences: NumericMap;
36
+ partitionLeaderEpoch: number;
37
+ }
38
+ export interface KafkaRecord {
39
+ length: number;
40
+ attributes: number;
41
+ timestampDelta: bigint;
42
+ offsetDelta: number;
43
+ key: Buffer;
44
+ value: Buffer;
45
+ headers: [Buffer, Buffer][];
46
+ }
47
+ export interface RecordsBatch {
48
+ firstOffset: bigint;
49
+ length: number;
50
+ partitionLeaderEpoch: number;
51
+ magic: number;
52
+ crc: number;
53
+ attributes: number;
54
+ lastOffsetDelta: number;
55
+ firstTimestamp: bigint;
56
+ maxTimestamp: bigint;
57
+ producerId: bigint;
58
+ producerEpoch: number;
59
+ firstSequence: number;
60
+ records: KafkaRecord[];
61
+ }
62
+ export declare const messageSchema: {
63
+ type: string;
64
+ properties: {
65
+ key: {
66
+ oneOf: ({
67
+ type: string;
68
+ buffer?: undefined;
69
+ } | {
70
+ buffer: boolean;
71
+ type?: undefined;
72
+ })[];
73
+ };
74
+ value: {
75
+ oneOf: ({
76
+ type: string;
77
+ buffer?: undefined;
78
+ } | {
79
+ buffer: boolean;
80
+ type?: undefined;
81
+ })[];
82
+ };
83
+ headers: {
84
+ anyOf: ({
85
+ map: boolean;
86
+ type?: undefined;
87
+ additionalProperties?: undefined;
88
+ } | {
89
+ type: string;
90
+ additionalProperties: boolean;
91
+ map?: undefined;
92
+ })[];
93
+ };
94
+ topic: {
95
+ type: string;
96
+ };
97
+ partition: {
98
+ type: string;
99
+ };
100
+ timestamp: {
101
+ bigint: boolean;
102
+ };
103
+ };
104
+ required: string[];
105
+ additionalProperties: boolean;
106
+ };
107
+ export declare function createRecord(message: MessageRecord, offsetDelta: number, firstTimestamp: bigint): Writer;
108
+ export declare function readRecord(reader: Reader): KafkaRecord;
109
+ export declare function createRecordsBatch(messages: MessageRecord[], options?: Partial<CreateRecordsBatchOptions>): Writer;
110
+ export declare function readRecordsBatch(reader: Reader): RecordsBatch;
@@ -0,0 +1,149 @@
1
+ import { UnsupportedCompressionError } from "../errors.js";
2
+ import { compressionsAlgorithms, compressionsAlgorithmsByBitmask } from "./compression.js";
3
+ import { crc32c } from "./crc32c.js";
4
+ import { DynamicBuffer } from "./dynamic-buffer.js";
5
+ import { Reader } from "./reader.js";
6
+ import { Writer } from "./writer.js";
7
+ const CURRENT_RECORD_VERSION = 2;
8
+ const IS_TRANSACTIONAL = 0b10000; // Bit 4 set
9
+ const IS_COMPRESSED = 0b111; // Bits 0, 1 and/or 2 set
10
+ export const messageSchema = {
11
+ type: 'object',
12
+ properties: {
13
+ key: {
14
+ oneOf: [{ type: 'string' }, { buffer: true }]
15
+ },
16
+ value: {
17
+ oneOf: [{ type: 'string' }, { buffer: true }]
18
+ },
19
+ headers: {
20
+ // Note: we can't use oneOf here since a Map is also a 'object'. Thanks JS.
21
+ anyOf: [
22
+ {
23
+ map: true
24
+ },
25
+ {
26
+ type: 'object',
27
+ additionalProperties: true
28
+ }
29
+ ]
30
+ },
31
+ topic: { type: 'string' },
32
+ partition: { type: 'integer' },
33
+ timestamp: { bigint: true }
34
+ },
35
+ required: ['value', 'topic'],
36
+ additionalProperties: true
37
+ };
38
+ export function createRecord(message, offsetDelta, firstTimestamp) {
39
+ return Writer.create()
40
+ .appendInt8(0) // Attributes are unused for now
41
+ .appendVarInt64((message.timestamp ?? BigInt(Date.now())) - firstTimestamp)
42
+ .appendVarInt(offsetDelta)
43
+ .appendVarIntBytes(message.key)
44
+ .appendVarIntBytes(message.value)
45
+ .appendVarIntMap(message.headers, (w, [key, value]) => {
46
+ w.appendVarIntBytes(key).appendVarIntBytes(value);
47
+ })
48
+ .prependVarIntLength();
49
+ }
50
+ export function readRecord(reader) {
51
+ return {
52
+ length: reader.readVarInt(),
53
+ attributes: reader.readInt8(),
54
+ timestampDelta: reader.readVarInt64(),
55
+ offsetDelta: reader.readVarInt(),
56
+ key: reader.readVarIntBytes(),
57
+ value: reader.readVarIntBytes(),
58
+ headers: reader.readVarIntArray(r => [r.readVarIntBytes(), r.readVarIntBytes()])
59
+ };
60
+ }
61
+ export function createRecordsBatch(messages, options = {}) {
62
+ const now = BigInt(Date.now());
63
+ const timestamps = [];
64
+ for (let i = 0; i < messages.length; i++) {
65
+ timestamps.push(messages[i].timestamp ?? now);
66
+ }
67
+ messages.sort();
68
+ const firstTimestamp = timestamps[0];
69
+ const maxTimestamp = timestamps[timestamps.length - 1];
70
+ let buffer = new DynamicBuffer();
71
+ for (let i = 0; i < messages.length; i++) {
72
+ const record = createRecord(messages[i], i, firstTimestamp);
73
+ buffer.appendFrom(record.dynamicBuffer);
74
+ }
75
+ let attributes = 0;
76
+ let firstSequence = 0;
77
+ if (options.sequences) {
78
+ const firstMessage = messages[0];
79
+ firstSequence = options.sequences.getWithDefault(`${firstMessage.topic}:${firstMessage.partition}`, 0);
80
+ }
81
+ // Set the transaction
82
+ if (options.transactionalId) {
83
+ attributes |= IS_TRANSACTIONAL;
84
+ }
85
+ // Set the compression, if any
86
+ /* c8 ignore next */
87
+ if ((options.compression ?? 'none') !== 'none') {
88
+ const algorithm = compressionsAlgorithms[options.compression];
89
+ if (!algorithm) {
90
+ throw new UnsupportedCompressionError(`Unsupported compression algorithm ${options.compression}`);
91
+ }
92
+ attributes |= algorithm.bitmask;
93
+ const compressed = algorithm.compressSync(buffer.buffer);
94
+ buffer = new DynamicBuffer(compressed);
95
+ }
96
+ const writer = Writer.create()
97
+ // Phase 1: Prepare the message from Attributes (included) to the end
98
+ .appendInt16(attributes)
99
+ // LastOffsetDelta, FirstTimestamp and MaxTimestamp are extracted from the messages
100
+ .appendInt32(messages.length - 1)
101
+ .appendInt64(BigInt(firstTimestamp))
102
+ .appendInt64(BigInt(maxTimestamp))
103
+ /* c8 ignore next */
104
+ .appendInt64(options.producerId ?? -1n)
105
+ /* c8 ignore next */
106
+ .appendInt16(options.producerEpoch ?? 0)
107
+ .appendInt32(firstSequence)
108
+ .appendInt32(messages.length) // Number of records
109
+ .appendFrom(buffer);
110
+ // Phase 2: Prepend the PartitionLeaderEpoch, Magic and CRC, then the Length and firstOffset, in reverse order
111
+ return (writer
112
+ .appendUnsignedInt32(crc32c(writer.dynamicBuffer), false)
113
+ .appendInt8(CURRENT_RECORD_VERSION, false)
114
+ .appendInt32(options.partitionLeaderEpoch ?? 0, false)
115
+ .prependLength()
116
+ // FirstOffset is 0
117
+ .appendInt64(0n, false));
118
+ }
119
+ export function readRecordsBatch(reader) {
120
+ const batch = {
121
+ firstOffset: reader.readInt64(),
122
+ length: reader.readInt32(),
123
+ partitionLeaderEpoch: reader.readInt32(),
124
+ magic: reader.readInt8(),
125
+ crc: reader.readUnsignedInt32(),
126
+ attributes: reader.readInt16(),
127
+ lastOffsetDelta: reader.readInt32(),
128
+ firstTimestamp: reader.readInt64(),
129
+ maxTimestamp: reader.readInt64(),
130
+ producerId: reader.readInt64(),
131
+ producerEpoch: reader.readInt16(),
132
+ firstSequence: reader.readInt32(),
133
+ records: []
134
+ };
135
+ const recordsLength = reader.readInt32();
136
+ const compression = batch.attributes & IS_COMPRESSED;
137
+ if (compression !== 0) {
138
+ const algorithm = compressionsAlgorithmsByBitmask[compression];
139
+ if (!algorithm) {
140
+ throw new UnsupportedCompressionError(`Unsupported compression algorithm with bitmask ${compression}`);
141
+ }
142
+ const buffer = algorithm.decompressSync(reader.buffer.slice(reader.position, reader.buffer.length));
143
+ reader = Reader.from(buffer);
144
+ }
145
+ for (let i = 0; i < recordsLength; i++) {
146
+ batch.records.push(readRecord(reader));
147
+ }
148
+ return batch;
149
+ }