apache-iggy 0.10.0 → 0.10.1-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 (157) hide show
  1. package/README.md +248 -28
  2. package/dist/client/client.config.d.ts +2 -0
  3. package/dist/client/client.config.js +13 -2
  4. package/dist/client/client.config.test.js +15 -2
  5. package/dist/client/client.connection-string.js +13 -1
  6. package/dist/client/client.connection-string.test.js +43 -1
  7. package/dist/client/client.connection.d.ts +33 -135
  8. package/dist/client/client.connection.js +190 -453
  9. package/dist/client/client.connection.test.js +244 -669
  10. package/dist/client/client.d.ts +4 -35
  11. package/dist/client/client.js +8 -101
  12. package/dist/client/client.operation.d.ts +120 -0
  13. package/dist/client/client.operation.js +428 -0
  14. package/dist/client/client.operation.test.d.ts +2 -0
  15. package/dist/client/client.operation.test.js +285 -0
  16. package/dist/client/client.socket.d.ts +92 -209
  17. package/dist/client/client.socket.js +1205 -981
  18. package/dist/client/client.socket.test.js +4865 -679
  19. package/dist/client/client.type.d.ts +65 -22
  20. package/dist/client/index.d.ts +1 -0
  21. package/dist/client/index.js +1 -0
  22. package/dist/client.e2e.js +3 -5
  23. package/dist/e2e/resource-options.e2e.d.ts +2 -0
  24. package/dist/{wire/stream/purge-stream.command.js → e2e/resource-options.e2e.js} +12 -20
  25. package/dist/e2e/resource-options.suite.d.ts +15 -0
  26. package/dist/e2e/resource-options.suite.js +272 -0
  27. package/dist/e2e/tcp.cluster.e2e.js +1 -0
  28. package/dist/e2e/tcp.consumer-stream.e2e.js +4 -0
  29. package/dist/e2e/tcp.parallel.e2e.js +5 -6
  30. package/dist/e2e/tcp.stream.e2e.js +0 -3
  31. package/dist/e2e/tcp.system.e2e.js +10 -1
  32. package/dist/e2e/tcp.token.e2e.js +8 -2
  33. package/dist/e2e/tcp.topic.e2e.js +0 -3
  34. package/dist/e2e/tcp.user.e2e.js +46 -3
  35. package/dist/e2e/tls.system.e2e.js +21 -12
  36. package/dist/index.d.ts +2 -1
  37. package/dist/index.js +1 -1
  38. package/dist/stream/consumer-stream.js +97 -12
  39. package/dist/wire/cluster/cluster.type.d.ts +2 -2
  40. package/dist/wire/cluster/cluster.utils.d.ts +1 -0
  41. package/dist/wire/cluster/cluster.utils.js +4 -1
  42. package/dist/wire/command-set.d.ts +8 -8
  43. package/dist/wire/command-set.js +18 -9
  44. package/dist/wire/command.code.d.ts +3 -10
  45. package/dist/wire/command.code.js +9 -11
  46. package/dist/wire/command.utils.d.ts +3 -2
  47. package/dist/wire/command.utils.js +3 -2
  48. package/dist/wire/error.code.js +17 -1
  49. package/dist/wire/error.code.test.js +28 -1
  50. package/dist/wire/error.utils.d.ts +4 -2
  51. package/dist/wire/error.utils.js +6 -3
  52. package/dist/wire/identifier.utils.d.ts +2 -0
  53. package/dist/wire/identifier.utils.js +2 -0
  54. package/dist/wire/index.d.ts +1 -0
  55. package/dist/wire/index.js +1 -0
  56. package/dist/wire/message/header.type.d.ts +1 -1
  57. package/dist/wire/message/message-batch.test.js +11 -5
  58. package/dist/wire/message/message.utils.d.ts +0 -10
  59. package/dist/wire/message/message.utils.js +1 -22
  60. package/dist/wire/message/poll-messages.command.d.ts +12 -1
  61. package/dist/wire/message/poll-messages.command.js +64 -16
  62. package/dist/wire/message/poll-messages.command.test.js +143 -5
  63. package/dist/wire/message/poll.utils.d.ts +4 -0
  64. package/dist/wire/message/poll.utils.js +6 -1
  65. package/dist/wire/message/send-messages.command.d.ts +3 -3
  66. package/dist/wire/message/send-messages.command.js +103 -3
  67. package/dist/wire/message/send-messages.command.test.js +113 -2
  68. package/dist/wire/offset/delete-offset.command.d.ts +11 -4
  69. package/dist/wire/offset/delete-offset.command.js +1 -1
  70. package/dist/wire/offset/get-offset.command.d.ts +1 -1
  71. package/dist/wire/offset/offset-write.command.test.d.ts +2 -0
  72. package/dist/wire/offset/offset-write.command.test.js +43 -0
  73. package/dist/wire/offset/offset.utils.js +10 -6
  74. package/dist/wire/offset/store-offset.command.d.ts +10 -0
  75. package/dist/wire/offset/store-offset.command.js +1 -1
  76. package/dist/wire/options.utils.d.ts +46 -0
  77. package/dist/wire/options.utils.js +57 -0
  78. package/dist/wire/partition/partition-route.d.ts +12 -0
  79. package/dist/wire/partition/partition-route.js +40 -0
  80. package/dist/wire/partition/partition-route.test.d.ts +2 -0
  81. package/dist/wire/partition/partition-route.test.js +42 -0
  82. package/dist/wire/session/login-with-token.command.d.ts +2 -2
  83. package/dist/wire/session/login-with-token.command.js +7 -2
  84. package/dist/wire/session/login.command.d.ts +2 -2
  85. package/dist/wire/session/login.command.js +7 -2
  86. package/dist/wire/stream/create-stream.command.d.ts +5 -2
  87. package/dist/wire/stream/create-stream.command.js +20 -2
  88. package/dist/wire/stream/index.d.ts +1 -1
  89. package/dist/wire/stream/index.js +1 -1
  90. package/dist/wire/stream/stream-options.d.ts +77 -0
  91. package/dist/wire/stream/stream-options.js +101 -0
  92. package/dist/wire/stream/stream-options.test.d.ts +2 -0
  93. package/dist/wire/stream/stream-options.test.js +103 -0
  94. package/dist/wire/stream/stream.utils.d.ts +9 -0
  95. package/dist/wire/stream/stream.utils.js +17 -3
  96. package/dist/wire/stream/update-stream.command.d.ts +23 -5
  97. package/dist/wire/stream/update-stream.command.js +10 -17
  98. package/dist/wire/system/describe-options.command.d.ts +23 -6
  99. package/dist/wire/system/describe-options.command.js +21 -2
  100. package/dist/wire/system/get-stats.command.d.ts +17 -0
  101. package/dist/wire/system/get-stats.command.js +69 -16
  102. package/dist/wire/system/get-stats.command.test.d.ts +2 -0
  103. package/dist/wire/system/get-stats.command.test.js +97 -0
  104. package/dist/wire/system/index.d.ts +2 -0
  105. package/dist/wire/system/index.js +2 -0
  106. package/dist/wire/system/snapshot.command.d.ts +64 -0
  107. package/dist/wire/system/snapshot.command.js +76 -0
  108. package/dist/wire/system/snapshot.command.test.d.ts +2 -0
  109. package/dist/wire/system/snapshot.command.test.js +86 -0
  110. package/dist/wire/system/update-resource.command.d.ts +53 -0
  111. package/dist/wire/system/update-resource.command.js +130 -0
  112. package/dist/wire/system/update-resource.command.test.d.ts +2 -0
  113. package/dist/wire/system/update-resource.command.test.js +497 -0
  114. package/dist/wire/token/create-token.command.d.ts +1 -1
  115. package/dist/wire/token/create-token.command.js +1 -1
  116. package/dist/wire/token/create-token.command.test.js +6 -0
  117. package/dist/wire/topic/create-topic.command.d.ts +20 -12
  118. package/dist/wire/topic/create-topic.command.js +11 -4
  119. package/dist/wire/topic/index.d.ts +1 -2
  120. package/dist/wire/topic/index.js +1 -2
  121. package/dist/wire/topic/topic.utils.d.ts +14 -5
  122. package/dist/wire/topic/topic.utils.js +26 -11
  123. package/dist/wire/topic/topic.utils.test.js +13 -13
  124. package/dist/wire/topic/update-topic.command.d.ts +22 -15
  125. package/dist/wire/topic/update-topic.command.js +12 -34
  126. package/dist/wire/user/create-user.command.d.ts +12 -2
  127. package/dist/wire/user/create-user.command.js +7 -3
  128. package/dist/wire/user/index.d.ts +1 -0
  129. package/dist/wire/user/index.js +1 -0
  130. package/dist/wire/user/update-user.command.d.ts +25 -7
  131. package/dist/wire/user/update-user.command.js +18 -31
  132. package/dist/wire/user/user.utils.d.ts +2 -0
  133. package/dist/wire/user/user.utils.js +5 -3
  134. package/dist/wire/vsr/header.d.ts +23 -8
  135. package/dist/wire/vsr/header.js +32 -10
  136. package/dist/wire/vsr/header.test.js +5 -1
  137. package/dist/wire/vsr/index.d.ts +8 -2
  138. package/dist/wire/vsr/index.js +44 -11
  139. package/dist/wire/vsr/operation.d.ts +18 -6
  140. package/dist/wire/vsr/operation.js +46 -16
  141. package/dist/wire/vsr/operation.test.js +32 -8
  142. package/dist/wire/vsr/register.d.ts +10 -6
  143. package/dist/wire/vsr/register.js +24 -7
  144. package/dist/wire/vsr/register.test.js +28 -8
  145. package/dist/wire/vsr/reply.d.ts +4 -1
  146. package/dist/wire/vsr/reply.js +42 -7
  147. package/dist/wire/vsr/reply.test.js +11 -1
  148. package/dist/wire/vsr/session.d.ts +9 -10
  149. package/dist/wire/vsr/session.js +32 -23
  150. package/dist/wire/vsr/session.test.js +33 -7
  151. package/dist/wire/vsr/vsr.test.js +57 -6
  152. package/package.json +6 -7
  153. package/dist/wire/message/flush-unsaved-buffers.command.d.ts +0 -26
  154. package/dist/wire/message/flush-unsaved-buffers.command.js +0 -36
  155. package/dist/wire/stream/purge-stream.command.d.ts +0 -22
  156. package/dist/wire/topic/purge-topic.command.d.ts +0 -24
  157. package/dist/wire/topic/purge-topic.command.js +0 -39
@@ -1,3 +1,4 @@
1
+ import { type PartitionContext } from '../vsr/header.js';
1
2
  import type { ValueOf } from '../../type.utils.js';
2
3
  import { type ParsedOptions } from '../options.utils.js';
3
4
  /**
@@ -12,11 +13,11 @@ export type BaseTopic = {
12
13
  createdAt: Date;
13
14
  /** Number of partitions */
14
15
  partitionsCount: number;
15
- /** Compression algorithm used */
16
+ /** Compression algorithm label, read from the options */
16
17
  compressionAlgorithm: number;
17
- /** Message expiry time in microseconds (0 = unlimited) */
18
+ /** Message expiry in microseconds, read from the options (u64 max = never expire) */
18
19
  messageExpiry: bigint;
19
- /** Maximum topic size in bytes (0 = unlimited) */
20
+ /** Maximum topic size in bytes, read from the options (u64 max = unlimited) */
20
21
  maxTopicSize: bigint;
21
22
  /** Total size of the topic in bytes */
22
23
  sizeBytes: bigint;
@@ -31,6 +32,8 @@ export type BaseTopic = {
31
32
  * Partition information within a topic.
32
33
  */
33
34
  export type Partition = {
35
+ /** Partition incarnation, owner generation and metadata op the reply carries */
36
+ context: PartitionContext;
34
37
  /** Partition ID */
35
38
  id: number;
36
39
  /** Partition creation timestamp */
@@ -101,8 +104,8 @@ export declare const isValidCompressionAlgorithm: (ca: number) => ca is Compress
101
104
  export declare const compressionAlgorithmName: (ca: CompressionAlgorithm) => string;
102
105
  /**
103
106
  * Deserializes a topic header from a buffer.
104
- * Layout: 50 fixed bytes, name, then two length-prefixed options blocks
105
- * (client-explicit and server-derived).
107
+ * Layout: 33 fixed bytes, name, then two length-prefixed options blocks
108
+ * (client-explicit and server-derived) holding every setting.
106
109
  *
107
110
  * @param p - Buffer containing serialized topic data
108
111
  * @param pos - Starting position in the buffer
@@ -143,5 +146,11 @@ export declare const Durability: {
143
146
  readonly Persisted: "persisted";
144
147
  };
145
148
  export type Durability = typeof Durability[keyof typeof Durability];
149
+ /** Whether a topic may add and delete partitions after create. */
150
+ export declare const PartitionResizePolicy: {
151
+ readonly Mutable: "mutable";
152
+ readonly Fixed: "fixed";
153
+ };
154
+ export type PartitionResizePolicy = typeof PartitionResizePolicy[keyof typeof PartitionResizePolicy];
146
155
  export {};
147
156
  //# sourceMappingURL=topic.utils.d.ts.map
@@ -14,8 +14,11 @@
14
14
  // KIND, either express or implied. See the License for the
15
15
  // specific language governing permissions and limitations
16
16
  // under the License.
17
+ import { deserializePartitionContext, PARTITION_CONTEXT_SIZE } from '../vsr/header.js';
17
18
  import { toDate } from '../serialize.utils.js';
18
19
  import { deserializePrefixedOptions } from '../options.utils.js';
20
+ /** Default of `message_expiry` and `max_topic_size`: never expire, no cap. */
21
+ const UNLIMITED = 0xffffffffffffffffn;
19
22
  /**
20
23
  * Compression algorithm options.
21
24
  */
@@ -41,8 +44,8 @@ export const isValidCompressionAlgorithm = (ca) => Object.values(CompressionAlgo
41
44
  export const compressionAlgorithmName = (ca) => ca === CompressionAlgorithm.Gzip ? 'gzip' : 'none';
42
45
  /**
43
46
  * Deserializes a topic header from a buffer.
44
- * Layout: 50 fixed bytes, name, then two length-prefixed options blocks
45
- * (client-explicit and server-derived).
47
+ * Layout: 33 fixed bytes, name, then two length-prefixed options blocks
48
+ * (client-explicit and server-derived) holding every setting.
46
49
  *
47
50
  * @param p - Buffer containing serialized topic data
48
51
  * @param pos - Starting position in the buffer
@@ -53,18 +56,24 @@ export const deserializeBaseTopic = (p, pos = 0) => {
53
56
  const id = p.readUInt32LE(pos);
54
57
  const createdAt = toDate(p.readBigUint64LE(pos + 4));
55
58
  const partitionsCount = p.readUInt32LE(pos + 12);
56
- const messageExpiry = p.readBigUInt64LE(pos + 16);
57
- const compressionAlgorithm = p.readUInt8(pos + 24);
58
- const maxTopicSize = p.readBigUInt64LE(pos + 25);
59
- const sizeBytes = p.readBigUInt64LE(pos + 33);
60
- const messagesCount = p.readBigUInt64LE(pos + 41);
61
- const nameLength = p.readUInt8(pos + 49);
62
- const name = p.subarray(pos + 50, pos + 50 + nameLength).toString();
63
- pos += 50 + nameLength;
59
+ const sizeBytes = p.readBigUInt64LE(pos + 16);
60
+ const messagesCount = p.readBigUInt64LE(pos + 24);
61
+ const nameLength = p.readUInt8(pos + 32);
62
+ const name = p.subarray(pos + 33, pos + 33 + nameLength).toString();
63
+ pos += 33 + nameLength;
64
64
  const explicit = deserializePrefixedOptions(p, pos);
65
65
  pos += explicit.bytesRead;
66
66
  const derived = deserializePrefixedOptions(p, pos);
67
67
  pos += derived.bytesRead;
68
+ const setting = (key) => explicit.options[key] ?? derived.options[key];
69
+ const limit = (key) => {
70
+ const value = setting(key);
71
+ return typeof value === 'bigint' ? value : UNLIMITED;
72
+ };
73
+ const compressionAlgorithm = setting('compression_algorithm') === 'gzip'
74
+ ? CompressionAlgorithm.Gzip : CompressionAlgorithm.None;
75
+ const messageExpiry = limit('message_expiry');
76
+ const maxTopicSize = limit('max_topic_size');
68
77
  return {
69
78
  bytesRead: pos - start,
70
79
  data: {
@@ -91,7 +100,7 @@ export const deserializeBaseTopic = (p, pos = 0) => {
91
100
  */
92
101
  export const deserializePartition = (p, pos = 0) => {
93
102
  return {
94
- bytesRead: 4 + 8 + 4 + 8 + 8 + 8,
103
+ bytesRead: 40 + PARTITION_CONTEXT_SIZE,
95
104
  data: {
96
105
  id: p.readUInt32LE(pos),
97
106
  createdAt: toDate(p.readBigUint64LE(pos + 4)),
@@ -99,6 +108,7 @@ export const deserializePartition = (p, pos = 0) => {
99
108
  currentOffset: p.readBigUint64LE(pos + 16),
100
109
  sizeBytes: p.readBigUint64LE(pos + 24),
101
110
  messagesCount: p.readBigUint64LE(pos + 32),
111
+ context: deserializePartitionContext(p, pos + 40),
102
112
  }
103
113
  };
104
114
  };
@@ -150,4 +160,9 @@ export const Durability = {
150
160
  Replicated: 'replicated',
151
161
  Persisted: 'persisted'
152
162
  };
163
+ /** Whether a topic may add and delete partitions after create. */
164
+ export const PartitionResizePolicy = {
165
+ Mutable: 'mutable',
166
+ Fixed: 'fixed'
167
+ };
153
168
  //# sourceMappingURL=topic.utils.js.map
@@ -20,18 +20,15 @@ import { deserializeBaseTopic } from './topic.utils.js';
20
20
  import { serializeOptions } from '../options.utils.js';
21
21
  import { HeaderValue } from '../message/header.utils.js';
22
22
  describe('deserializeBaseTopic', () => {
23
- it('uses the 50-byte fixed layout with two options blocks', () => {
24
- const fixed = Buffer.alloc(51);
23
+ it('uses the 33-byte fixed layout with settings in two options blocks', () => {
24
+ const fixed = Buffer.alloc(34);
25
25
  fixed.writeUInt32LE(7, 0);
26
26
  fixed.writeBigUInt64LE(1710000000000n, 4);
27
27
  fixed.writeUInt32LE(3, 12);
28
- fixed.writeBigUInt64LE(86400000000n, 16);
29
- fixed.writeUInt8(2, 24);
30
- fixed.writeBigUInt64LE(1000000n, 25);
31
- fixed.writeBigUInt64LE(4096n, 33);
32
- fixed.writeBigUInt64LE(12n, 41);
33
- fixed.writeUInt8(1, 49);
34
- fixed.write('t', 50);
28
+ fixed.writeBigUInt64LE(4096n, 16);
29
+ fixed.writeBigUInt64LE(12n, 24);
30
+ fixed.writeUInt8(1, 32);
31
+ fixed.write('t', 33);
35
32
  const explicit = serializeOptions([
36
33
  { key: 'message_expiry', value: HeaderValue.Uint64(86400000000n) }
37
34
  ]);
@@ -61,18 +58,21 @@ describe('deserializeBaseTopic', () => {
61
58
  max_topic_size: 1000000n
62
59
  });
63
60
  });
64
- it('skips empty options blocks', () => {
65
- const fixed = Buffer.alloc(51);
61
+ it('skips empty options blocks and falls back to the catalog defaults', () => {
62
+ const fixed = Buffer.alloc(34);
66
63
  fixed.writeUInt32LE(1, 0);
67
64
  fixed.writeUInt32LE(2, 12);
68
- fixed.writeUInt8(1, 49);
69
- fixed.write('t', 50);
65
+ fixed.writeUInt8(1, 32);
66
+ fixed.write('t', 33);
70
67
  const data = Buffer.concat([fixed, Buffer.alloc(8)]);
71
68
  const { bytesRead, data: topic } = deserializeBaseTopic(data);
72
69
  assert.equal(bytesRead, data.length);
73
70
  assert.equal(topic.partitionsCount, 2);
74
71
  assert.deepEqual(topic.options, {});
75
72
  assert.deepEqual(topic.derivedOptions, {});
73
+ assert.equal(topic.compressionAlgorithm, 1);
74
+ assert.equal(topic.messageExpiry, 0xffffffffffffffffn);
75
+ assert.equal(topic.maxTopicSize, 0xffffffffffffffffn);
76
76
  });
77
77
  });
78
78
  //# sourceMappingURL=topic.utils.test.js.map
@@ -1,8 +1,8 @@
1
- import { type Id } from '../identifier.utils.js';
2
- import { type OptionEntry } from '../options.utils.js';
3
- import { type CompressionAlgorithm as CompressionAlgorithmT } from './topic.utils.js';
1
+ import type { Id } from '../identifier.utils.js';
2
+ import type { OptionEntry, TopicOptionKey } from '../options.utils.js';
4
3
  /**
5
- * Parameters for the update topic command.
4
+ * Parameters for the update topic command. Keys left out keep their values.
5
+ * Settings fixed at create, compression among them, have no field here.
6
6
  */
7
7
  export type UpdateTopic = {
8
8
  /** Stream identifier (ID or name) */
@@ -10,34 +10,41 @@ export type UpdateTopic = {
10
10
  /** Topic identifier (ID or name) */
11
11
  topicId: Id;
12
12
  /** New topic name (1-255 bytes) */
13
- name: string;
14
- /** Compression algorithm (None or Gzip) */
15
- compressionAlgorithm?: CompressionAlgorithmT;
13
+ name?: string;
16
14
  /**
17
15
  * Message expiry time in microseconds. `0n` is not "unlimited": it omits the
18
- * key, so the topic keeps whatever expiry it currently has. Resetting a key
19
- * back to the server default is not expressible on an update.
16
+ * key, so the topic keeps whatever expiry it currently has. Reset the key to
17
+ * return to the server default.
20
18
  */
21
19
  messageExpiry?: bigint;
22
20
  /**
23
21
  * Maximum topic size in bytes. `0n` is not "unlimited": it omits the key, so
24
- * the topic keeps whatever cap it currently has. Resetting a key back to the
25
- * server default is not expressible on an update.
22
+ * the topic keeps whatever cap it currently has. Reset the key to return to
23
+ * the server default.
26
24
  */
27
25
  maxTopicSize?: bigint;
26
+ /** Keys to reset to their defaults: `message_expiry` or `max_topic_size` */
27
+ reset?: TopicOptionKey[];
28
28
  /**
29
- * Option keys with no field of their own. The server refuses any key an update
30
- * may not change, by name; a key left out keeps its current value.
29
+ * Reset names with no typed member, for a resettable key the server catalog
30
+ * gained after this build shipped. The server decides on them.
31
+ */
32
+ rawReset?: readonly string[];
33
+ /**
34
+ * Option keys with no field of their own, for an updatable key the server
35
+ * catalog gained after this build shipped. A field above wins on collision.
36
+ * The server decides on them, so a create-only or unknown key comes back as
37
+ * a server error.
31
38
  */
32
39
  options?: OptionEntry[];
33
40
  };
34
41
  /**
35
42
  * Update topic command definition.
36
- * Updates a topic's configuration.
43
+ * Changes only the keys it names, through the generic update command.
37
44
  */
38
45
  export declare const UPDATE_TOPIC: {
39
46
  code: number;
40
- serialize: ({ streamId, topicId, name, compressionAlgorithm, messageExpiry, maxTopicSize, options: extraOptions }: UpdateTopic) => Buffer<ArrayBuffer>;
47
+ serialize: ({ streamId, topicId, name, messageExpiry, maxTopicSize, reset, rawReset, options: rawOptions }: UpdateTopic) => Buffer<ArrayBuffer>;
41
48
  deserialize: (r: import("../../index.js").CommandResponse) => boolean;
42
49
  };
43
50
  /**
@@ -14,36 +14,20 @@
14
14
  // KIND, either express or implied. See the License for the
15
15
  // specific language governing permissions and limitations
16
16
  // under the License.
17
- import { serializeIdentifier } from '../identifier.utils.js';
18
- import { dedupeOptions, serializeOptions } from '../options.utils.js';
19
17
  import { HeaderValue } from '../message/header.utils.js';
20
- import { deserializeVoidResponse } from '../../client/client.utils.js';
21
18
  import { wrapCommand } from '../command.utils.js';
22
- import { COMMAND_CODE } from '../command.code.js';
23
- import { CompressionAlgorithm, compressionAlgorithmName, isValidCompressionAlgorithm } from './topic.utils.js';
19
+ import { OptionsScope } from '../system/describe-options.command.js';
20
+ import { UPDATE_RESOURCE, columnOption } from '../system/update-resource.command.js';
24
21
  /**
25
22
  * Update topic command definition.
26
- * Updates a topic's configuration.
23
+ * Changes only the keys it names, through the generic update command.
27
24
  */
28
25
  export const UPDATE_TOPIC = {
29
- code: COMMAND_CODE.UpdateTopic,
30
- serialize: ({ streamId, topicId, name, compressionAlgorithm = CompressionAlgorithm.None, messageExpiry = 0n, maxTopicSize = 0n, options: extraOptions = [] }) => {
31
- const streamIdentifier = serializeIdentifier(streamId);
32
- const topicIdentifier = serializeIdentifier(topicId);
33
- const bName = Buffer.from(name);
34
- if (bName.length < 1 || bName.length > 255)
35
- throw new Error('Topic name should be between 1 and 255 bytes');
36
- if (!isValidCompressionAlgorithm(compressionAlgorithm))
37
- throw new Error(`updateTopic: invalid compressionAlgorithm (${compressionAlgorithm})`);
38
- // Settings ride the options block. A default value means the caller did not
39
- // set the key, so it is omitted and the server leaves the current value be.
40
- // Caller keys first so a typed field below overwrites one of them.
41
- const options = [...extraOptions];
42
- if (compressionAlgorithm !== CompressionAlgorithm.None)
43
- options.push({
44
- key: 'compression_algorithm',
45
- value: HeaderValue.String(compressionAlgorithmName(compressionAlgorithm))
46
- });
26
+ code: UPDATE_RESOURCE.code,
27
+ serialize: ({ streamId, topicId, name, messageExpiry = 0n, maxTopicSize = 0n, reset, rawReset, options: rawOptions }) => {
28
+ const options = [];
29
+ if (name !== undefined)
30
+ options.push(columnOption('name', name));
47
31
  if (messageExpiry !== 0n)
48
32
  options.push({
49
33
  key: 'message_expiry',
@@ -54,17 +38,11 @@ export const UPDATE_TOPIC = {
54
38
  key: 'max_topic_size',
55
39
  value: HeaderValue.Uint64(maxTopicSize)
56
40
  });
57
- const b = Buffer.allocUnsafe(1);
58
- b.writeUInt8(bName.length, 0);
59
- return Buffer.concat([
60
- streamIdentifier,
61
- topicIdentifier,
62
- b,
63
- bName,
64
- serializeOptions(dedupeOptions(options)),
65
- ]);
41
+ return UPDATE_RESOURCE.serialize({
42
+ target: { scope: OptionsScope.Topic, streamId, topicId }, options, reset, rawOptions, rawReset
43
+ });
66
44
  },
67
- deserialize: deserializeVoidResponse
45
+ deserialize: UPDATE_RESOURCE.deserialize
68
46
  };
69
47
  /**
70
48
  * Executable update topic command function.
@@ -1,6 +1,15 @@
1
1
  import type { CommandResponse } from '../../client/client.type.js';
2
2
  import { type User, type UserStatus } from './user.utils.js';
3
3
  import { type UserPermissions } from './permissions.utils.js';
4
+ import { type OptionEntry } from '../options.utils.js';
5
+ /**
6
+ * Options a user takes at create. The server catalog has no user key yet, so
7
+ * only keys newer than this build can ride here.
8
+ */
9
+ export type UserOptions = {
10
+ /** Option keys with no field of their own */
11
+ options?: OptionEntry[];
12
+ };
4
13
  /**
5
14
  * Parameters for the create user command.
6
15
  */
@@ -13,14 +22,15 @@ export type CreateUser = {
13
22
  status: UserStatus;
14
23
  /** Optional user permissions */
15
24
  permissions?: UserPermissions;
16
- };
25
+ } & UserOptions;
17
26
  /**
18
27
  * Create user command definition.
19
28
  * Creates a new user with the specified credentials and permissions.
29
+ * The options block runs to the end of the payload.
20
30
  */
21
31
  export declare const CREATE_USER: {
22
32
  code: number;
23
- serialize: ({ username, password, status, permissions }: CreateUser) => Buffer<ArrayBuffer>;
33
+ serialize: ({ username, password, status, permissions, options }: CreateUser) => Buffer<ArrayBuffer>;
24
34
  deserialize: (r: CommandResponse) => User;
25
35
  };
26
36
  /**
@@ -19,13 +19,15 @@ import { COMMAND_CODE } from '../command.code.js';
19
19
  import { deserializeUser } from './user.utils.js';
20
20
  import { uint8ToBuf, uint32ToBuf, boolToBuf } from '../number.utils.js';
21
21
  import { serializePermissions } from './permissions.utils.js';
22
+ import { dedupeOptions, serializeOptions, sortOptions } from '../options.utils.js';
22
23
  /**
23
24
  * Create user command definition.
24
25
  * Creates a new user with the specified credentials and permissions.
26
+ * The options block runs to the end of the payload.
25
27
  */
26
28
  export const CREATE_USER = {
27
29
  code: COMMAND_CODE.CreateUser,
28
- serialize: ({ username, password, status, permissions }) => {
30
+ serialize: ({ username, password, status, permissions, options = [] }) => {
29
31
  const bUsername = Buffer.from(username);
30
32
  const bPassword = Buffer.from(password);
31
33
  if (bUsername.length < 1 || bUsername.length > 255)
@@ -39,14 +41,16 @@ export const CREATE_USER = {
39
41
  bPassword,
40
42
  uint8ToBuf(status),
41
43
  ]);
44
+ const bOptions = serializeOptions(sortOptions(dedupeOptions(options)));
42
45
  if (!permissions)
43
- return Buffer.concat([bUser, boolToBuf(false)]);
46
+ return Buffer.concat([bUser, boolToBuf(false), bOptions]);
44
47
  const bPermissions = serializePermissions(permissions);
45
48
  return Buffer.concat([
46
49
  bUser,
47
50
  boolToBuf(true),
48
51
  uint32ToBuf(bPermissions.length),
49
- bPermissions
52
+ bPermissions,
53
+ bOptions
50
54
  ]);
51
55
  },
52
56
  deserialize: (r) => deserializeUser(r.data)
@@ -5,4 +5,5 @@ export * from './get-user.command.js';
5
5
  export * from './get-users.command.js';
6
6
  export * from './update-permissions.command.js';
7
7
  export * from './update-user.command.js';
8
+ export { UserStatus } from './user.utils.js';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -21,4 +21,5 @@ export * from './get-user.command.js';
21
21
  export * from './get-users.command.js';
22
22
  export * from './update-permissions.command.js';
23
23
  export * from './update-user.command.js';
24
+ export { UserStatus } from './user.utils.js';
24
25
  //# sourceMappingURL=index.js.map
@@ -1,23 +1,41 @@
1
- import type { UserStatus } from './user.utils.js';
2
- import { type Id } from '../identifier.utils.js';
1
+ import type { Id } from '../identifier.utils.js';
2
+ import type { OptionEntry, UserOptionKey } from '../options.utils.js';
3
+ import { UserStatus } from './user.utils.js';
3
4
  /**
4
- * Parameters for the update user command.
5
+ * Parameters for the update user command. Keys left out keep their values.
5
6
  */
6
7
  export type UpdateUser = {
7
8
  /** User identifier (ID or username) */
8
9
  userId: Id;
9
- /** Optional new username (1-255 bytes) */
10
+ /** Optional new username (3-50 bytes) */
10
11
  username?: string;
11
- /** Optional new status */
12
+ /** Optional new status. Deactivating a user ends its sessions. */
12
13
  status?: UserStatus;
14
+ /**
15
+ * Keys to reset to their defaults. No user key is resettable yet, so any key
16
+ * is refused before the request is sent.
17
+ */
18
+ reset?: UserOptionKey[];
19
+ /**
20
+ * Reset names with no typed member, for a resettable key the server catalog
21
+ * gained after this build shipped. The server decides on them.
22
+ */
23
+ rawReset?: readonly string[];
24
+ /**
25
+ * Option keys with no field of their own, for an updatable key the server
26
+ * catalog gained after this build shipped. A field above wins on collision.
27
+ * The server decides on them, so a create-only or unknown key comes back as
28
+ * a server error.
29
+ */
30
+ options?: OptionEntry[];
13
31
  };
14
32
  /**
15
33
  * Update user command definition.
16
- * Updates a user's username and/or status.
34
+ * Changes only the keys it names, through the generic update command.
17
35
  */
18
36
  export declare const UPDATE_USER: {
19
37
  code: number;
20
- serialize: ({ userId, username, status }: UpdateUser) => Buffer<ArrayBuffer>;
38
+ serialize: ({ userId, username, status, reset, rawReset, options: rawOptions }: UpdateUser) => Buffer<ArrayBuffer>;
21
39
  deserialize: (r: import("../../index.js").CommandResponse) => boolean;
22
40
  };
23
41
  /**
@@ -15,42 +15,29 @@
15
15
  // specific language governing permissions and limitations
16
16
  // under the License.
17
17
  import { wrapCommand } from '../command.utils.js';
18
- import { COMMAND_CODE } from '../command.code.js';
19
- import { deserializeVoidResponse } from '../../client/client.utils.js';
20
- import { serializeIdentifier } from '../identifier.utils.js';
21
- import { uint8ToBuf } from '../number.utils.js';
18
+ import { HeaderValue } from '../message/header.utils.js';
19
+ import { OptionsScope } from '../system/describe-options.command.js';
20
+ import { UPDATE_RESOURCE, columnOption } from '../system/update-resource.command.js';
21
+ import { UserStatus } from './user.utils.js';
22
22
  /**
23
23
  * Update user command definition.
24
- * Updates a user's username and/or status.
24
+ * Changes only the keys it names, through the generic update command.
25
25
  */
26
26
  export const UPDATE_USER = {
27
- code: COMMAND_CODE.UpdateUser,
28
- serialize: ({ userId, username, status }) => {
29
- const bId = serializeIdentifier(userId);
30
- let bUsername, bStatus;
31
- if (username) {
32
- const bn = Buffer.from(username);
33
- if (bn.length < 1 || bn.length > 255)
34
- throw new Error('User username should be between 1 and 255 bytes');
35
- bUsername = Buffer.concat([
36
- uint8ToBuf(1),
37
- uint8ToBuf(bn.length),
38
- bn
39
- ]);
40
- }
41
- else
42
- bUsername = uint8ToBuf(0);
43
- if (status)
44
- bStatus = Buffer.concat([uint8ToBuf(1), uint8ToBuf(status)]);
45
- else
46
- bStatus = uint8ToBuf(0);
47
- return Buffer.concat([
48
- bId,
49
- bUsername,
50
- bStatus,
51
- ]);
27
+ code: UPDATE_RESOURCE.code,
28
+ serialize: ({ userId, username, status, reset, rawReset, options: rawOptions }) => {
29
+ const options = [];
30
+ if (username !== undefined)
31
+ options.push(columnOption('username', username));
32
+ if (status !== undefined)
33
+ options.push(status === UserStatus.Active || status === UserStatus.Inactive
34
+ ? { key: 'status', value: HeaderValue.String(status === UserStatus.Active ? 'active' : 'inactive') }
35
+ : { key: 'status', value: HeaderValue.Bool(false) });
36
+ return UPDATE_RESOURCE.serialize({
37
+ target: { scope: OptionsScope.User, userId }, options, reset, rawOptions, rawReset
38
+ });
52
39
  },
53
- deserialize: deserializeVoidResponse
40
+ deserialize: UPDATE_RESOURCE.deserialize
54
41
  };
55
42
  /**
56
43
  * Executable update user command function.
@@ -14,6 +14,8 @@ export type BaseUser = {
14
14
  userName: string;
15
15
  /** Options the client explicitly sent at create */
16
16
  options: ParsedOptions;
17
+ /** Options the server filled */
18
+ derivedOptions: ParsedOptions;
17
19
  };
18
20
  /**
19
21
  * Result of deserializing a base user.
@@ -58,15 +58,17 @@ export const deserializeBaseUser = (p, pos = 0) => {
58
58
  const status = statusString(p.readUInt8(pos + 12));
59
59
  const userNameLength = p.readUInt8(pos + 13);
60
60
  const userName = p.subarray(pos + 14, pos + 14 + userNameLength).toString();
61
- const { bytesRead: optionsBytes, options } = deserializePrefixedOptions(p, pos + 14 + userNameLength);
61
+ const explicit = deserializePrefixedOptions(p, pos + 14 + userNameLength);
62
+ const derived = deserializePrefixedOptions(p, pos + 14 + userNameLength + explicit.bytesRead);
62
63
  return {
63
- bytesRead: 14 + userNameLength + optionsBytes,
64
+ bytesRead: 14 + userNameLength + explicit.bytesRead + derived.bytesRead,
64
65
  data: {
65
66
  id,
66
67
  createdAt,
67
68
  status,
68
69
  userName,
69
- options,
70
+ options: explicit.options,
71
+ derivedOptions: derived.options,
70
72
  }
71
73
  };
72
74
  };
@@ -20,20 +20,32 @@ export declare const REQUEST_OFFSET: {
20
20
  readonly size: 48;
21
21
  readonly command: 60;
22
22
  readonly client: 128;
23
+ readonly requestChecksum: 144;
23
24
  readonly timestamp: 160;
24
25
  readonly request: 168;
25
26
  readonly operation: 176;
26
27
  readonly session: 184;
27
28
  readonly reserved: 196;
29
+ readonly partitionIncarnation: 200;
30
+ readonly ownerGeneration: 208;
31
+ readonly minimumMetadataOp: 216;
28
32
  };
29
33
  /** `ReplyHeader` field offsets the client reads. */
30
34
  export declare const REPLY_OFFSET: {
31
35
  readonly size: 48;
32
36
  readonly command: 60;
37
+ readonly requestChecksum: 128;
38
+ readonly client: 160;
39
+ readonly op: 176;
33
40
  readonly commit: 184;
41
+ readonly request: 200;
34
42
  readonly operation: 208;
35
43
  readonly status: 216;
44
+ readonly reserved: 220;
45
+ readonly partitionIncarnation: 224;
36
46
  };
47
+ export declare const COMMITTED_RESULT_MARKER = 1;
48
+ export declare const hasCommittedResult: (header: Buffer) => boolean;
37
49
  /** `EvictionHeader` field offsets the client reads. */
38
50
  export declare const EVICTION_OFFSET: {
39
51
  readonly command: 60;
@@ -70,8 +82,17 @@ export declare const EvictionReason: {
70
82
  readonly IncompatibleProtocol: 14;
71
83
  readonly MalformedLogin: 15;
72
84
  };
85
+ export declare const PARTITION_CONTEXT_SIZE = 24;
86
+ export type PartitionContext = {
87
+ readonly incarnation: bigint;
88
+ readonly ownerGeneration: bigint;
89
+ readonly metadataOp: bigint;
90
+ };
91
+ export declare const EMPTY_PARTITION_CONTEXT: PartitionContext;
92
+ export declare const deserializePartitionContext: (data: Buffer, offset?: number) => PartitionContext;
73
93
  /** Fields the client writes into a request header. */
74
94
  export type RequestHeaderFields = {
95
+ context?: PartitionContext;
75
96
  /** Header + body total, bytes. */
76
97
  size: number;
77
98
  /** Ephemeral client identifier (u128). */
@@ -85,13 +106,7 @@ export type RequestHeaderFields = {
85
106
  /** Command code for `NonReplicated`, placed in `reserved[0..4]`. */
86
107
  nonReplicatedCode?: number;
87
108
  };
88
- /**
89
- * Encodes a 256-byte request header. Only the six fields the server reads
90
- * are written. The checksums stay zero: the frame and body checksums are not
91
- * read on the client request path, and `request_checksum` treats zero as
92
- * unstamped, which opts out of the server's payload comparison. Stamping it is
93
- * optional -- the Rust SDK does for deduped ops, this SDK does not yet.
94
- */
109
+ /** Encodes one request identity and its captured partition context. */
95
110
  export declare const encodeRequestHeader: (fields: RequestHeaderFields) => Buffer;
96
111
  /**
97
112
  * Reads the frame discriminant. `command` sits at the same offset in every
@@ -100,7 +115,7 @@ export declare const encodeRequestHeader: (fields: RequestHeaderFields) => Buffe
100
115
  export declare const peekCommand: (header: Buffer) => number;
101
116
  /** Reads the total frame size from a reply or eviction header. */
102
117
  export declare const readSize: (header: Buffer) => number;
103
- /** Reads the pre-commit denial status; 0 means the reply committed. */
118
+ /** Reads the pre-commit denial status; zero alone does not prove commit. */
104
119
  export declare const readStatus: (header: Buffer) => number;
105
120
  /** Reads the `Operation` discriminant from a reply header. */
106
121
  export declare const readReplyOperation: (header: Buffer) => number;