apache-iggy 0.5.2 → 0.6.0-edge.2

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 (75) hide show
  1. package/dist/client/client.connection.js +30 -34
  2. package/dist/client/client.socket.js +1 -1
  3. package/dist/debug-send.js +14 -16
  4. package/dist/debug.js +13 -15
  5. package/dist/e2e/tcp.cluster.e2e.d.ts +20 -0
  6. package/dist/e2e/tcp.cluster.e2e.js +55 -0
  7. package/dist/e2e/tcp.consumer-group.e2e.js +41 -29
  8. package/dist/e2e/tcp.consumer-stream.e2e.js +11 -12
  9. package/dist/e2e/tcp.send-message.e2e.js +60 -23
  10. package/dist/e2e/tcp.stream.e2e.js +5 -6
  11. package/dist/e2e/tcp.system.e2e.js +1 -1
  12. package/dist/e2e/tcp.topic.e2e.js +18 -23
  13. package/dist/e2e/tcp.user.e2e.js +5 -0
  14. package/dist/stream/consumer-stream.d.ts +2 -2
  15. package/dist/stream/consumer-stream.js +4 -14
  16. package/dist/tcp.e2e.js +2 -0
  17. package/dist/wire/client/get-client.command.d.ts +2 -2
  18. package/dist/wire/client/get-client.command.js +5 -1
  19. package/dist/wire/cluster/cluster.type.d.ts +54 -0
  20. package/dist/wire/cluster/cluster.type.js +62 -0
  21. package/dist/wire/cluster/cluster.utils.d.ts +40 -0
  22. package/dist/wire/cluster/cluster.utils.js +85 -0
  23. package/dist/wire/cluster/get-cluster-metadata.command.d.ts +27 -0
  24. package/dist/wire/cluster/get-cluster-metadata.command.js +30 -0
  25. package/dist/wire/cluster/index.d.ts +21 -0
  26. package/dist/wire/cluster/index.js +21 -0
  27. package/dist/wire/command-set.d.ts +15 -6
  28. package/dist/wire/command-set.js +14 -2
  29. package/dist/wire/command.code.d.ts +1 -0
  30. package/dist/wire/command.code.js +1 -0
  31. package/dist/wire/command.utils.js +0 -6
  32. package/dist/wire/consumer-group/create-group.command.d.ts +1 -2
  33. package/dist/wire/consumer-group/create-group.command.js +4 -4
  34. package/dist/wire/consumer-group/create-group.command.test.js +1 -2
  35. package/dist/wire/consumer-group/ensure-group.virtual.command.d.ts +23 -0
  36. package/dist/wire/consumer-group/ensure-group.virtual.command.js +33 -0
  37. package/dist/wire/consumer-group/get-group.command.d.ts +2 -2
  38. package/dist/wire/consumer-group/get-group.command.js +2 -0
  39. package/dist/wire/consumer-group/index.d.ts +1 -0
  40. package/dist/wire/consumer-group/index.js +1 -0
  41. package/dist/wire/error.utils.d.ts +4 -0
  42. package/dist/wire/error.utils.js +10 -0
  43. package/dist/wire/message/header.type.d.ts +1 -1
  44. package/dist/wire/message/poll-messages.command.d.ts +1 -1
  45. package/dist/wire/message/poll.utils.d.ts +1 -1
  46. package/dist/wire/message/poll.utils.js +1 -2
  47. package/dist/wire/offset/delete-offset.command.js +1 -1
  48. package/dist/wire/offset/get-offset.command.d.ts +7 -3
  49. package/dist/wire/offset/get-offset.command.js +3 -3
  50. package/dist/wire/offset/offset.utils.d.ts +2 -2
  51. package/dist/wire/offset/offset.utils.js +13 -4
  52. package/dist/wire/offset/store-offset.command.d.ts +1 -1
  53. package/dist/wire/stream/create-stream.command.d.ts +2 -2
  54. package/dist/wire/stream/create-stream.command.js +4 -4
  55. package/dist/wire/stream/create-stream.command.test.js +2 -3
  56. package/dist/wire/stream/ensure-stream.virtual.command.d.ts +21 -0
  57. package/dist/wire/stream/ensure-stream.virtual.command.js +26 -0
  58. package/dist/wire/stream/get-stream.command.d.ts +2 -2
  59. package/dist/wire/stream/get-stream.command.js +2 -0
  60. package/dist/wire/stream/index.d.ts +1 -0
  61. package/dist/wire/stream/index.js +1 -0
  62. package/dist/wire/system/get-stats.command.d.ts +1 -1
  63. package/dist/wire/topic/create-topic.command.d.ts +1 -2
  64. package/dist/wire/topic/create-topic.command.js +9 -9
  65. package/dist/wire/topic/create-topic.command.test.js +2 -3
  66. package/dist/wire/topic/ensure-topic.virtual.command.d.ts +22 -0
  67. package/dist/wire/topic/ensure-topic.virtual.command.js +28 -0
  68. package/dist/wire/topic/get-topic.command.d.ts +2 -2
  69. package/dist/wire/topic/get-topic.command.js +2 -0
  70. package/dist/wire/topic/index.d.ts +1 -0
  71. package/dist/wire/topic/index.js +1 -0
  72. package/dist/wire/topic/topic.utils.js +1 -1
  73. package/dist/wire/user/get-user.command.d.ts +2 -2
  74. package/dist/wire/user/get-user.command.js +5 -1
  75. package/package.json +1 -1
@@ -28,12 +28,14 @@ import { getGroup } from './consumer-group/get-group.command.js';
28
28
  import { getGroups } from './consumer-group/get-groups.command.js';
29
29
  import { leaveGroup } from './consumer-group/leave-group.command.js';
30
30
  import { deleteGroup } from './consumer-group/delete-group.command.js';
31
+ import { ensureConsumerGroup, ensureConsumerGroupAndJoin } from './consumer-group/ensure-group.virtual.command.js';
31
32
  import { purgeTopic } from './topic/purge-topic.command.js';
32
33
  import { createTopic } from './topic/create-topic.command.js';
33
34
  import { updateTopic } from './topic/update-topic.command.js';
34
35
  import { getTopic } from './topic/get-topic.command.js';
35
36
  import { getTopics } from './topic/get-topics.command.js';
36
37
  import { deleteTopic } from './topic/delete-topic.command.js';
38
+ import { ensureTopic } from './topic/ensure-topic.virtual.command.js';
37
39
  import { getOffset } from './offset/get-offset.command.js';
38
40
  import { storeOffset } from './offset/store-offset.command.js';
39
41
  import { deleteOffset } from './offset/delete-offset.command.js';
@@ -46,11 +48,13 @@ import { getStream } from './stream/get-stream.command.js';
46
48
  import { getStreams } from './stream/get-streams.command.js';
47
49
  import { deleteStream } from './stream/delete-stream.command.js';
48
50
  import { purgeStream } from './stream/purge-stream.command.js';
51
+ import { ensureStream } from './stream/ensure-stream.virtual.command.js';
49
52
  import { createPartition } from './partition/create-partition.command.js';
50
53
  import { deletePartition } from './partition/delete-partition.command.js';
51
54
  import { deleteSegments } from './segment/delete-segments.command.js';
52
55
  import { getStats } from './system/get-stats.command.js';
53
56
  import { ping } from './system/ping.command.js';
57
+ import { getClusterMetadata } from './cluster/get-cluster-metadata.command.js';
54
58
  import { getTokens } from './token/get-tokens.command.js';
55
59
  import { createToken } from './token/create-token.command.js';
56
60
  import { deleteToken } from './token/delete-token.command.js';
@@ -91,7 +95,8 @@ const streamAPI = (c) => ({
91
95
  create: createStream(c),
92
96
  update: updateStream(c),
93
97
  delete: deleteStream(c),
94
- purge: purgeStream(c)
98
+ purge: purgeStream(c),
99
+ ensure: ensureStream(c)
95
100
  });
96
101
  const topicAPI = (c) => ({
97
102
  get: getTopic(c),
@@ -99,7 +104,8 @@ const topicAPI = (c) => ({
99
104
  create: createTopic(c),
100
105
  update: updateTopic(c),
101
106
  delete: deleteTopic(c),
102
- purge: purgeTopic(c)
107
+ purge: purgeTopic(c),
108
+ ensure: ensureTopic(c)
103
109
  });
104
110
  const partitionAPI = (c) => ({
105
111
  create: createPartition(c),
@@ -115,6 +121,8 @@ const groupAPI = (c) => ({
115
121
  join: joinGroup(c),
116
122
  leave: leaveGroup(c),
117
123
  delete: deleteGroup(c),
124
+ ensure: ensureConsumerGroup(c),
125
+ ensureAndJoin: ensureConsumerGroupAndJoin(c)
118
126
  });
119
127
  const offsetAPI = (c) => ({
120
128
  get: getOffset(c),
@@ -130,6 +138,9 @@ const systemAPI = (c) => ({
130
138
  ping: ping(c),
131
139
  getStats: getStats(c)
132
140
  });
141
+ const clusterAPI = (c) => ({
142
+ getClusterMetadata: getClusterMetadata(c)
143
+ });
133
144
  export class AbstractAPI {
134
145
  clientProvider;
135
146
  constructor(getClient) {
@@ -149,6 +160,7 @@ export class CommandAPI extends AbstractAPI {
149
160
  offset = offsetAPI(this.clientProvider);
150
161
  message = messageAPI(this.clientProvider);
151
162
  system = systemAPI(this.clientProvider);
163
+ cluster = clusterAPI(this.clientProvider);
152
164
  constructor(c) {
153
165
  super(c);
154
166
  }
@@ -20,6 +20,7 @@ export declare const COMMAND_CODE: {
20
20
  Ping: number;
21
21
  GetStats: number;
22
22
  GetSnapshot: number;
23
+ GetClusterMetadata: number;
23
24
  GetMe: number;
24
25
  GetClient: number;
25
26
  GetClients: number;
@@ -21,6 +21,7 @@ export const COMMAND_CODE = {
21
21
  Ping: 1,
22
22
  GetStats: 10,
23
23
  GetSnapshot: 11, // @TODO GET_SNAPSHOT_FILE_CODE: u32 = 11
24
+ GetClusterMetadata: 12, // GET_CLUSTER_METADATA_CODE: u32 = 12
24
25
  GetMe: 20,
25
26
  GetClient: 21,
26
27
  GetClients: 22,
@@ -16,12 +16,6 @@
16
16
  * specific language governing permissions and limitations
17
17
  * under the License.
18
18
  */
19
- // export function wrapCommand<I, O>(cmd: Command<I, O>) {
20
- // return (client: RawClient) =>
21
- // async (arg: I) => cmd.deserialize(
22
- // await client.sendCommand(cmd.code, cmd.serialize(arg))
23
- // );
24
- // };
25
19
  export function wrapCommand(cmd) {
26
20
  return (getClient) => async (arg) => cmd.deserialize(await (await getClient()).sendCommand(cmd.code, cmd.serialize(arg)));
27
21
  }
@@ -22,12 +22,11 @@ import { type ConsumerGroup } from './group.utils.js';
22
22
  export type CreateGroup = {
23
23
  streamId: Id;
24
24
  topicId: Id;
25
- groupId: number;
26
25
  name: string;
27
26
  };
28
27
  export declare const CREATE_GROUP: {
29
28
  code: number;
30
- serialize: ({ streamId, topicId, groupId, name }: CreateGroup) => Buffer<ArrayBuffer>;
29
+ serialize: ({ streamId, topicId, name }: CreateGroup) => Buffer<ArrayBuffer>;
31
30
  deserialize: (r: CommandResponse) => ConsumerGroup;
32
31
  };
33
32
  export declare const createGroup: (getClient: import("../../client/client.type.js").ClientProvider) => (arg: CreateGroup) => Promise<ConsumerGroup>;
@@ -22,13 +22,13 @@ import { COMMAND_CODE } from '../command.code.js';
22
22
  import { deserializeConsumerGroup } from './group.utils.js';
23
23
  export const CREATE_GROUP = {
24
24
  code: COMMAND_CODE.CreateGroup,
25
- serialize: ({ streamId, topicId, groupId, name }) => {
25
+ serialize: ({ streamId, topicId, name }) => {
26
+ // Consumer group ID is now auto-assigned by the server, not sent in the protocol
26
27
  const bName = Buffer.from(name);
27
28
  if (bName.length < 1 || bName.length > 255)
28
29
  throw new Error('Consumer group name should be between 1 and 255 bytes');
29
- const b = Buffer.allocUnsafe(5);
30
- b.writeUInt32LE(groupId);
31
- b.writeUInt8(bName.length, 4);
30
+ const b = Buffer.allocUnsafe(1);
31
+ b.writeUInt8(bName.length, 0);
32
32
  return Buffer.concat([
33
33
  serializeIdentifier(streamId),
34
34
  serializeIdentifier(topicId),
@@ -24,11 +24,10 @@ describe('CreateGroup', () => {
24
24
  const s1 = {
25
25
  streamId: 5,
26
26
  topicId: 2,
27
- groupId: 1,
28
27
  name: 'test-group'
29
28
  };
30
29
  it('serialize group id & name into buffer', () => {
31
- assert.deepEqual(CREATE_GROUP.serialize(s1).length, 6 + 6 + 5 + s1.name.length);
30
+ assert.deepEqual(CREATE_GROUP.serialize(s1).length, 6 + 6 + 1 + s1.name.length);
32
31
  });
33
32
  it('throw on name < 1', () => {
34
33
  const s2 = { ...s1, name: '' };
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+ import type { Id } from '../identifier.utils.js';
20
+ import { ClientProvider } from '../../client/index.js';
21
+ export declare const ensureConsumerGroup: (c: ClientProvider) => (streamId: Id, topicId: Id, groupName: string) => Promise<import("./group.utils.js").ConsumerGroup>;
22
+ export declare const ensureConsumerGroupAndJoin: (c: ClientProvider) => (streamId: Id, topicId: Id, groupName: string) => Promise<import("./group.utils.js").ConsumerGroup>;
23
+ //# sourceMappingURL=ensure-group.virtual.command.d.ts.map
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+ import { createGroup } from './create-group.command.js';
20
+ import { getGroup } from './get-group.command.js';
21
+ import { joinGroup } from './join-group.command.js';
22
+ export const ensureConsumerGroup = (c) => async function ensureConsumerGroup(streamId, topicId, groupName) {
23
+ const group = await getGroup(c)({ streamId, topicId, groupId: groupName });
24
+ if (!group)
25
+ return await createGroup(c)({ streamId, topicId, name: groupName });
26
+ return group;
27
+ };
28
+ export const ensureConsumerGroupAndJoin = (c) => async function ensureConsumerGroupAndJoin(streamId, topicId, groupName) {
29
+ const group = await ensureConsumerGroup(c)(streamId, topicId, groupName);
30
+ await joinGroup(c)({ streamId, topicId, groupId: group.id });
31
+ return group;
32
+ };
33
+ //# sourceMappingURL=ensure-group.virtual.command.js.map
@@ -27,7 +27,7 @@ export type GetGroup = {
27
27
  export declare const GET_GROUP: {
28
28
  code: number;
29
29
  serialize: ({ streamId, topicId, groupId }: GetGroup) => Buffer<ArrayBuffer>;
30
- deserialize: (r: CommandResponse) => ConsumerGroup;
30
+ deserialize: (r: CommandResponse) => ConsumerGroup | null;
31
31
  };
32
- export declare const getGroup: (getClient: import("../../client/client.type.js").ClientProvider) => (arg: GetGroup) => Promise<ConsumerGroup>;
32
+ export declare const getGroup: (getClient: import("../../client/client.type.js").ClientProvider) => (arg: GetGroup) => Promise<ConsumerGroup | null>;
33
33
  //# sourceMappingURL=get-group.command.d.ts.map
@@ -25,6 +25,8 @@ export const GET_GROUP = {
25
25
  return serializeTargetGroup(streamId, topicId, groupId);
26
26
  },
27
27
  deserialize: (r) => {
28
+ if (r.status === 0 && r.length === 0)
29
+ return null;
28
30
  return deserializeConsumerGroup(r.data).data;
29
31
  }
30
32
  };
@@ -22,4 +22,5 @@ export * from './get-group.command.js';
22
22
  export * from './get-groups.command.js';
23
23
  export * from './join-group.command.js';
24
24
  export * from './leave-group.command.js';
25
+ export * from './ensure-group.virtual.command.js';
25
26
  //# sourceMappingURL=index.d.ts.map
@@ -22,4 +22,5 @@ export * from './get-group.command.js';
22
22
  export * from './get-groups.command.js';
23
23
  export * from './join-group.command.js';
24
24
  export * from './leave-group.command.js';
25
+ export * from './ensure-group.virtual.command.js';
25
26
  //# sourceMappingURL=index.js.map
@@ -17,4 +17,8 @@
17
17
  * under the License.
18
18
  */
19
19
  export declare const responseError: (cmdCode: number, errCode: number) => Error;
20
+ export declare class DeserializeError extends Error {
21
+ constructor(message: string, cause?: Record<string, unknown>);
22
+ }
23
+ export declare const deserializeError: (name: string, position: number, buffer_size: number, lookup?: number, read?: Record<string, unknown>) => never;
20
24
  //# sourceMappingURL=error.utils.d.ts.map
@@ -20,4 +20,14 @@ import { translateCommandCode } from './command.code.js';
20
20
  import { translateErrorCode } from './error.code.js';
21
21
  export const responseError = (cmdCode, errCode) => new Error(`command: { code: ${cmdCode}, name: ${translateCommandCode(cmdCode)} } ` +
22
22
  `error: {code: ${errCode}, message: ${translateErrorCode(errCode)} }`);
23
+ export class DeserializeError extends Error {
24
+ constructor(message, cause) {
25
+ super(message, cause);
26
+ this.name = "DeserializeError";
27
+ Object.setPrototypeOf(this, DeserializeError.prototype);
28
+ }
29
+ }
30
+ export const deserializeError = (name, position, buffer_size, lookup, read) => {
31
+ throw new DeserializeError(`cannot deserialize ${name}: buffer too small`, { cause: { position, buffer_size, lookup, read } });
32
+ };
23
33
  //# sourceMappingURL=error.utils.js.map
@@ -37,7 +37,7 @@ export declare const HeaderKind: {
37
37
  export type HeaderKind = typeof HeaderKind;
38
38
  export type HeaderKindId = keyof HeaderKind;
39
39
  export type HeaderKindValue = ValueOf<HeaderKind>;
40
- export declare const ReverseHeaderKind: Record<1 | 2 | 10 | 11 | 4 | 8 | 3 | 5 | 12 | 9 | 13 | 6 | 7 | 14 | 15, "Raw" | "String" | "Bool" | "Int8" | "Int16" | "Int32" | "Int64" | "Int128" | "Uint8" | "Uint16" | "Uint32" | "Uint64" | "Uint128" | "Float" | "Double">;
40
+ export declare const ReverseHeaderKind: Record<1 | 2 | 10 | 11 | 12 | 4 | 8 | 3 | 5 | 9 | 13 | 6 | 7 | 14 | 15, "Raw" | "String" | "Bool" | "Int8" | "Int16" | "Int32" | "Int64" | "Int128" | "Uint8" | "Uint16" | "Uint32" | "Uint64" | "Uint128" | "Float" | "Double">;
41
41
  export type HeaderValueRaw = {
42
42
  kind: HeaderKind['Raw'];
43
43
  value: Buffer;
@@ -24,7 +24,7 @@ export type PollMessages = {
24
24
  streamId: Id;
25
25
  topicId: Id;
26
26
  consumer: Consumer;
27
- partitionId: number;
27
+ partitionId: number | null;
28
28
  pollingStrategy: PollingStrategy;
29
29
  count: number;
30
30
  autocommit: boolean;
@@ -60,7 +60,7 @@ export declare const PollingStrategy: {
60
60
  Offset: (n: bigint) => OffsetPollingStrategy;
61
61
  Timestamp: (n: bigint) => TimestampPollingStrategy;
62
62
  };
63
- export declare const serializePollMessages: (streamId: Id, topicId: Id, consumer: Consumer, partitionId: number, pollingStrategy: PollingStrategy, count?: number, autocommit?: boolean) => Buffer<ArrayBuffer>;
63
+ export declare const serializePollMessages: (streamId: Id, topicId: Id, consumer: Consumer, partitionId: number | null, pollingStrategy: PollingStrategy, count?: number, autocommit?: boolean) => Buffer<ArrayBuffer>;
64
64
  export declare const MessageState: {
65
65
  Available: number;
66
66
  Unavailable: number;
@@ -56,8 +56,7 @@ export const PollingStrategy = {
56
56
  Offset,
57
57
  Timestamp
58
58
  };
59
- export const serializePollMessages = (streamId, topicId, consumer, partitionId, // default to 1
60
- pollingStrategy, // default to OffsetPollingStrategy
59
+ export const serializePollMessages = (streamId, topicId, consumer, partitionId, pollingStrategy, // default to OffsetPollingStrategy
61
60
  count = 10, autocommit = false) => {
62
61
  const b = Buffer.allocUnsafe(14);
63
62
  b.writeUInt8(pollingStrategy.kind, 0);
@@ -22,7 +22,7 @@ import { serializeGetOffset } from './offset.utils.js';
22
22
  import { COMMAND_CODE } from '../command.code.js';
23
23
  export const DELETE_OFFSET = {
24
24
  code: COMMAND_CODE.DeleteConsumerOffset,
25
- serialize: ({ streamId, topicId, consumer, partitionId = 1 }) => {
25
+ serialize: ({ streamId, topicId, consumer, partitionId = 0 }) => {
26
26
  return serializeGetOffset(streamId, topicId, consumer, partitionId);
27
27
  },
28
28
  deserialize: deserializeVoidResponse
@@ -23,12 +23,16 @@ export type GetOffset = {
23
23
  streamId: Id;
24
24
  topicId: Id;
25
25
  consumer: Consumer;
26
- partitionId?: number;
26
+ partitionId: number | null;
27
27
  };
28
28
  export declare const GET_OFFSET: {
29
29
  code: number;
30
30
  serialize: ({ streamId, topicId, consumer, partitionId }: GetOffset) => Buffer<ArrayBuffer>;
31
- deserialize: (r: CommandResponse) => OffsetResponse;
31
+ deserialize: (r: CommandResponse) => {
32
+ partitionId: number;
33
+ currentOffset: bigint;
34
+ storedOffset: bigint;
35
+ } | null;
32
36
  };
33
- export declare const getOffset: (getClient: import("../../client/client.type.js").ClientProvider) => (arg: GetOffset) => Promise<OffsetResponse>;
37
+ export declare const getOffset: (getClient: import("../../client/client.type.js").ClientProvider) => (arg: GetOffset) => Promise<OffsetResponse | null>;
34
38
  //# sourceMappingURL=get-offset.command.d.ts.map
@@ -21,12 +21,12 @@ import { COMMAND_CODE } from '../command.code.js';
21
21
  import { serializeGetOffset } from './offset.utils.js';
22
22
  export const GET_OFFSET = {
23
23
  code: COMMAND_CODE.GetOffset,
24
- serialize: ({ streamId, topicId, consumer, partitionId = 1 }) => {
24
+ serialize: ({ streamId, topicId, consumer, partitionId = 0 }) => {
25
25
  return serializeGetOffset(streamId, topicId, consumer, partitionId);
26
26
  },
27
27
  deserialize: (r) => {
28
- if (r.data.length < 20)
29
- throw new Error('Offset not found');
28
+ if (r.status === 0 && r.length === 0)
29
+ return null;
30
30
  const partitionId = r.data.readUInt32LE(0);
31
31
  const currentOffset = r.data.readBigUInt64LE(4);
32
32
  const storedOffset = r.data.readBigUInt64LE(12);
@@ -49,6 +49,6 @@ export type OffsetResponse = {
49
49
  currentOffset: bigint;
50
50
  storedOffset: bigint;
51
51
  };
52
- export declare const serializeGetOffset: (streamId: Id, topicId: Id, consumer: Consumer, partitionId?: number) => Buffer<ArrayBuffer>;
53
- export declare const serializeStoreOffset: (streamId: Id, topicId: Id, consumer: Consumer, partitionId: number, offset: bigint) => Buffer<ArrayBuffer>;
52
+ export declare const serializeGetOffset: (streamId: Id, topicId: Id, consumer: Consumer, partitionId: number | null) => Buffer<ArrayBuffer>;
53
+ export declare const serializeStoreOffset: (streamId: Id, topicId: Id, consumer: Consumer, partitionId: number | null, offset: bigint) => Buffer<ArrayBuffer>;
54
54
  //# sourceMappingURL=offset.utils.d.ts.map
@@ -17,7 +17,7 @@
17
17
  * under the License.
18
18
  */
19
19
  import { serializeIdentifier } from '../identifier.utils.js';
20
- import { uint32ToBuf, uint8ToBuf } from '../number.utils.js';
20
+ import { uint8ToBuf } from '../number.utils.js';
21
21
  export const ConsumerKind = {
22
22
  Single: 1,
23
23
  Group: 2
@@ -34,13 +34,22 @@ export const Consumer = {
34
34
  })
35
35
  };
36
36
  export const serializeGetOffset = (streamId, topicId, consumer, partitionId) => {
37
- if (consumer.kind === ConsumerKind.Single && (!partitionId || partitionId < 1))
38
- throw new Error('getOffset error: partitionId must be > 0 for single consumer kind');
37
+ if (consumer.kind === ConsumerKind.Single && partitionId === null)
38
+ throw new Error('getOffset error: partitionId must be provided for single consumer kind');
39
39
  const streamIdentifier = serializeIdentifier(streamId);
40
40
  const topicIdentifier = serializeIdentifier(topicId);
41
41
  const consumerIdentifier = serializeIdentifier(consumer.id);
42
42
  const b1 = uint8ToBuf(consumer.kind);
43
- const b2 = uint32ToBuf(partitionId || 0);
43
+ // Encode partition_id with a flag byte: 1 = Some, 0 = None
44
+ const b2 = Buffer.allocUnsafe(5);
45
+ if (partitionId !== null) {
46
+ b2.writeUInt8(1, 0); // Flag byte: partition_id is Some
47
+ b2.writeUInt32LE(partitionId, 1);
48
+ }
49
+ else {
50
+ b2.writeUInt8(0, 0); // Flag byte: partition_id is None
51
+ b2.writeUInt32LE(0, 1); // Padding
52
+ }
44
53
  return Buffer.concat([
45
54
  b1,
46
55
  consumerIdentifier,
@@ -22,7 +22,7 @@ export type StoreOffset = {
22
22
  streamId: Id;
23
23
  topicId: Id;
24
24
  consumer: Consumer;
25
- partitionId: number;
25
+ partitionId: number | null;
26
26
  offset: bigint;
27
27
  };
28
28
  export declare const STORE_OFFSET: {
@@ -19,12 +19,12 @@
19
19
  import type { CommandResponse } from '../../client/client.type.js';
20
20
  import { type Stream } from './stream.utils.js';
21
21
  export type CreateStream = {
22
- streamId: number;
22
+ streamId?: number;
23
23
  name: string;
24
24
  };
25
25
  export declare const CREATE_STREAM: {
26
26
  code: number;
27
- serialize: ({ streamId, name }: CreateStream) => Buffer<ArrayBuffer>;
27
+ serialize: ({ name }: CreateStream) => Buffer<ArrayBuffer>;
28
28
  deserialize: (r: CommandResponse) => Stream;
29
29
  };
30
30
  export declare const createStream: (getClient: import("../../client/client.type.js").ClientProvider) => (arg: CreateStream) => Promise<Stream>;
@@ -21,13 +21,13 @@ import { COMMAND_CODE } from '../command.code.js';
21
21
  import { deserializeToStream } from './stream.utils.js';
22
22
  export const CREATE_STREAM = {
23
23
  code: COMMAND_CODE.CreateStream,
24
- serialize: ({ streamId, name }) => {
24
+ serialize: ({ name }) => {
25
+ // Stream ID is now auto-assigned by the server, not sent in the protocol
25
26
  const bName = Buffer.from(name);
26
27
  if (bName.length < 1 || bName.length > 255)
27
28
  throw new Error('Stream name should be between 1 and 255 bytes');
28
- const b = Buffer.allocUnsafe(4 + 1);
29
- b.writeUInt32LE(streamId, 0);
30
- b.writeUInt8(bName.length, 4);
29
+ const b = Buffer.allocUnsafe(1);
30
+ b.writeUInt8(bName.length, 0);
31
31
  return Buffer.concat([
32
32
  b,
33
33
  bName
@@ -22,11 +22,10 @@ import { CREATE_STREAM } from './create-stream.command.js';
22
22
  describe('CreateStream', () => {
23
23
  describe('serialize', () => {
24
24
  const s1 = {
25
- streamId: 1,
26
25
  name: 'test-stream'
27
26
  };
28
- it('serialize 1 numeric id & 1 name into buffer', () => {
29
- assert.deepEqual(CREATE_STREAM.serialize(s1).length, 4 + 1 + s1.name.length);
27
+ it('serialize 1 name into buffer', () => {
28
+ assert.deepEqual(CREATE_STREAM.serialize(s1).length, 1 + s1.name.length);
30
29
  });
31
30
  it('throw on name < 1', () => {
32
31
  const s2 = { ...s1, name: '' };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+ import { ClientProvider } from '../../client/index.js';
20
+ export declare const ensureStream: (c: ClientProvider) => (streamName: string) => Promise<import("./stream.utils.js").Stream>;
21
+ //# sourceMappingURL=ensure-stream.virtual.command.d.ts.map
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Licensed to the Apache Software Foundation (ASF) under one
3
+ * or more contributor license agreements. See the NOTICE file
4
+ * distributed with this work for additional information
5
+ * regarding copyright ownership. The ASF licenses this file
6
+ * to you under the Apache License, Version 2.0 (the
7
+ * "License"); you may not use this file except in compliance
8
+ * with the License. You may obtain a copy of the License at
9
+ *
10
+ * http://www.apache.org/licenses/LICENSE-2.0
11
+ *
12
+ * Unless required by applicable law or agreed to in writing,
13
+ * software distributed under the License is distributed on an
14
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ * KIND, either express or implied. See the License for the
16
+ * specific language governing permissions and limitations
17
+ * under the License.
18
+ */
19
+ import { createStream } from './create-stream.command.js';
20
+ import { getStream } from './get-stream.command.js';
21
+ export const ensureStream = (c) => async function ensureStream(streamName) {
22
+ const stream = await getStream(c)({ streamId: streamName });
23
+ return stream === null ?
24
+ createStream(c)({ name: streamName }) : stream;
25
+ };
26
+ //# sourceMappingURL=ensure-stream.virtual.command.js.map
@@ -25,7 +25,7 @@ export type GetStream = {
25
25
  export declare const GET_STREAM: {
26
26
  code: number;
27
27
  serialize: ({ streamId }: GetStream) => Buffer<ArrayBufferLike>;
28
- deserialize: (r: CommandResponse) => Stream;
28
+ deserialize: (r: CommandResponse) => Stream | null;
29
29
  };
30
- export declare const getStream: (getClient: import("../../client/client.type.js").ClientProvider) => (arg: GetStream) => Promise<Stream>;
30
+ export declare const getStream: (getClient: import("../../client/client.type.js").ClientProvider) => (arg: GetStream) => Promise<Stream | null>;
31
31
  //# sourceMappingURL=get-stream.command.d.ts.map
@@ -26,6 +26,8 @@ export const GET_STREAM = {
26
26
  return serializeIdentifier(streamId);
27
27
  },
28
28
  deserialize: (r) => {
29
+ if (r.status === 0 && r.length === 0)
30
+ return null;
29
31
  return deserializeToStream(r.data, 0).data;
30
32
  }
31
33
  };
@@ -22,4 +22,5 @@ export * from './get-stream.command.js';
22
22
  export * from './get-streams.command.js';
23
23
  export * from './purge-stream.command.js';
24
24
  export * from './update-stream.command.js';
25
+ export * from './ensure-stream.virtual.command.js';
25
26
  //# sourceMappingURL=index.d.ts.map
@@ -22,4 +22,5 @@ export * from './get-stream.command.js';
22
22
  export * from './get-streams.command.js';
23
23
  export * from './purge-stream.command.js';
24
24
  export * from './update-stream.command.js';
25
+ export * from './ensure-stream.virtual.command.js';
25
26
  //# sourceMappingURL=index.js.map
@@ -16,7 +16,7 @@
16
16
  * specific language governing permissions and limitations
17
17
  * under the License.
18
18
  */
19
- import type { CommandResponse } from '../../client/client.type.js';
19
+ import type { CommandResponse } from '../../client/index.js';
20
20
  export type Stats = {
21
21
  processId: number;
22
22
  cpuUsage: number;
@@ -21,7 +21,6 @@ import { type Id } from '../identifier.utils.js';
21
21
  import { type Topic, type CompressionAlgorithm as CompressionAlgorithmT } from './topic.utils.js';
22
22
  export type CreateTopic = {
23
23
  streamId: Id;
24
- topicId: number;
25
24
  name: string;
26
25
  partitionCount: number;
27
26
  compressionAlgorithm: CompressionAlgorithmT;
@@ -31,7 +30,7 @@ export type CreateTopic = {
31
30
  };
32
31
  export declare const CREATE_TOPIC: {
33
32
  code: number;
34
- serialize: ({ streamId, topicId, name, partitionCount, compressionAlgorithm, messageExpiry, maxTopicSize, replicationFactor }: CreateTopic) => Buffer<ArrayBuffer>;
33
+ serialize: ({ streamId, name, partitionCount, compressionAlgorithm, messageExpiry, maxTopicSize, replicationFactor }: CreateTopic) => Buffer<ArrayBuffer>;
35
34
  deserialize: (r: CommandResponse) => Topic;
36
35
  };
37
36
  export declare const createTopic: (getClient: import("../../client/client.type.js").ClientProvider) => (arg: CreateTopic) => Promise<Topic>;
@@ -22,7 +22,8 @@ import { COMMAND_CODE } from '../command.code.js';
22
22
  import { isValidCompressionAlgorithm, CompressionAlgorithm, deserializeTopic } from './topic.utils.js';
23
23
  export const CREATE_TOPIC = {
24
24
  code: COMMAND_CODE.CreateTopic,
25
- serialize: ({ streamId, topicId, name, partitionCount, compressionAlgorithm = CompressionAlgorithm.None, messageExpiry = 0n, maxTopicSize = 0n, replicationFactor = 1 }) => {
25
+ serialize: ({ streamId, name, partitionCount, compressionAlgorithm = CompressionAlgorithm.None, messageExpiry = 0n, maxTopicSize = 0n, replicationFactor = 1 }) => {
26
+ // Topic ID is now auto-assigned by the server, not sent in the protocol
26
27
  const streamIdentifier = serializeIdentifier(streamId);
27
28
  const bName = Buffer.from(name);
28
29
  if (replicationFactor < 1 || replicationFactor > 255)
@@ -31,14 +32,13 @@ export const CREATE_TOPIC = {
31
32
  throw new Error('Topic name should be between 1 and 255 bytes');
32
33
  if (!isValidCompressionAlgorithm(compressionAlgorithm))
33
34
  throw new Error(`createTopic: invalid compressionAlgorithm (${compressionAlgorithm})`);
34
- const b = Buffer.allocUnsafe(4 + 4 + 1 + 8 + 8 + 1 + 1);
35
- b.writeUInt32LE(topicId, 0);
36
- b.writeUInt32LE(partitionCount, 4);
37
- b.writeUInt8(compressionAlgorithm, 8);
38
- b.writeBigUInt64LE(messageExpiry, 9); // 0 is unlimited
39
- b.writeBigUInt64LE(maxTopicSize, 17); // optional, 0 is null
40
- b.writeUInt8(replicationFactor, 25); // must be > 0
41
- b.writeUInt8(bName.length, 26);
35
+ const b = Buffer.allocUnsafe(4 + 1 + 8 + 8 + 1 + 1);
36
+ b.writeUInt32LE(partitionCount, 0);
37
+ b.writeUInt8(compressionAlgorithm, 4);
38
+ b.writeBigUInt64LE(messageExpiry, 5); // 0 is unlimited
39
+ b.writeBigUInt64LE(maxTopicSize, 13); // optional, 0 is null
40
+ b.writeUInt8(replicationFactor, 21); // must be > 0
41
+ b.writeUInt8(bName.length, 22);
42
42
  return Buffer.concat([
43
43
  streamIdentifier,
44
44
  b,