@arbitro/client 0.5.0 → 0.5.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.
- package/README.md +9 -0
- package/dist/{chunk-C2QLJBAC.mjs → chunk-3EHQPPLU.mjs} +2 -1
- package/dist/chunk-3EHQPPLU.mjs.map +1 -0
- package/dist/{chunk-GW36GP2C.mjs → chunk-BSPQZJHF.mjs} +2 -2
- package/dist/{constants-57DO6N3H.mjs → constants-LWTWKOBZ.mjs} +2 -2
- package/dist/index.d.mts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +26 -4
- package/dist/index.mjs.map +1 -1
- package/dist/{publish-BSVUMN7T.mjs → publish-NKAK5BOA.mjs} +3 -3
- package/package.json +1 -1
- package/dist/chunk-C2QLJBAC.mjs.map +0 -1
- /package/dist/{chunk-GW36GP2C.mjs.map → chunk-BSPQZJHF.mjs.map} +0 -0
- /package/dist/{constants-57DO6N3H.mjs.map → constants-LWTWKOBZ.mjs.map} +0 -0
- /package/dist/{publish-BSVUMN7T.mjs.map → publish-NKAK5BOA.mjs.map} +0 -0
package/README.md
CHANGED
|
@@ -111,6 +111,11 @@ await client.upsertConsumer('orders', { name: 'workers', filter: 'orders.>' })
|
|
|
111
111
|
await client.deleteConsumer('workers')
|
|
112
112
|
await client.deleteStream('orders') // default: delete metadata + data
|
|
113
113
|
await client.deleteStream('orders', { deleteData: false }) // preserve journal bytes
|
|
114
|
+
|
|
115
|
+
// Per-message deletion (tombstones a single message by sequence number)
|
|
116
|
+
await client.deleteMessage('orders', 42n) // true if deleted, false if not found/already deleted
|
|
117
|
+
await stream.deleteMessage(42n) // convenience — delegates to client.deleteMessage
|
|
118
|
+
await consumer.deleteMessage(42n) // convenience — delegates to client.deleteMessage
|
|
114
119
|
```
|
|
115
120
|
|
|
116
121
|
## Stream / consumer sugar
|
|
@@ -339,6 +344,10 @@ npm run test:integration # requires Docker
|
|
|
339
344
|
- `.agent/rules/*.md` — internal coding rules (hot-path discipline, wire protocol, etc.).
|
|
340
345
|
- `CLAUDE.md` — index pointing at the rule files.
|
|
341
346
|
|
|
347
|
+
## Replication
|
|
348
|
+
|
|
349
|
+
Replication is transparent to the client -- `replicas` is set at `create_stream` time. The client publishes normally; the broker handles replication internally.
|
|
350
|
+
|
|
342
351
|
## License
|
|
343
352
|
|
|
344
353
|
MIT — see [LICENSE](./LICENSE).
|
|
@@ -62,6 +62,7 @@ var Action = /* @__PURE__ */ ((Action2) => {
|
|
|
62
62
|
Action2[Action2["ListStreams"] = 1028] = "ListStreams";
|
|
63
63
|
Action2[Action2["PurgeStream"] = 1029] = "PurgeStream";
|
|
64
64
|
Action2[Action2["DrainSubject"] = 1030] = "DrainSubject";
|
|
65
|
+
Action2[Action2["DeleteMessage"] = 1031] = "DeleteMessage";
|
|
65
66
|
Action2[Action2["CreateConsumer"] = 1281] = "CreateConsumer";
|
|
66
67
|
Action2[Action2["DeleteConsumer"] = 1282] = "DeleteConsumer";
|
|
67
68
|
Action2[Action2["GetConsumer"] = 1283] = "GetConsumer";
|
|
@@ -99,4 +100,4 @@ export {
|
|
|
99
100
|
EntryFlag,
|
|
100
101
|
Action
|
|
101
102
|
};
|
|
102
|
-
//# sourceMappingURL=chunk-
|
|
103
|
+
//# sourceMappingURL=chunk-3EHQPPLU.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/proto/constants.ts"],"sourcesContent":["// V2 wire protocol constants — must match arbitro-proto/src/action.rs exactly.\n\n// ── Hello handshake (only frame without a Header) ───────────────────────\nexport const MAGIC_V2 = 0x32425241 // \"ARB2\" as u32 LE\nexport const HELLO_SIZE = 8\nexport const CURRENT_VERSION = 2\n\nexport const enum Role {\n Client = 0,\n Server = 1,\n}\n\nexport const enum Cap {\n Headers = 1 << 0,\n Reply = 1 << 1,\n BatchHeaders = 1 << 2,\n CompressedPayload = 1 << 3,\n}\n\n// ── Header (16 bytes, every frame after Hello) ──────────────────────────\nexport const HEADER_SIZE = 16\n\n// Byte offsets within the 16-byte header\nexport const OFF_ACTION = 0 // u16 LE\nexport const OFF_FLAGS = 2 // u8\nexport const OFF_ENTRY_FLAGS = 3 // u8\nexport const OFF_MSG_LEN = 4 // u32 LE\nexport const OFF_SEQ = 8 // u64 LE\n\n// ── Transport flags (header.flags, offset 2) ────────────────────────────\nexport const enum Flag {\n None = 0x00,\n AckReq = 0x01,\n Dup = 0x02,\n PriorityHigh = 0x04,\n}\n\n// ── Per-message flags (header.entry_flags, offset 3) ────────────────────\nexport const enum EntryFlag {\n None = 0x00,\n Retain = 0x01,\n Compressed = 0x02,\n NoBackpressure = 0x04,\n}\n\n// ── Action codes (0xFFGG: FF=family, GG=variant) ────────────────────────\nexport const enum Action {\n // 0x00xx — Handshake / control\n Hello = 0x0001,\n Auth = 0x0002,\n\n // 0x01xx — Publish family\n Publish = 0x0101,\n PublishAccumulate = 0x0102,\n PublishBatch = 0x0103,\n PublishWithReply = 0x0104,\n PublishWithHeaders = 0x0105,\n PublishBatchWithHeaders = 0x0106,\n\n // 0x02xx — Delivery / Ack\n Deliver = 0x0200,\n Ack = 0x0201,\n Nack = 0x0202,\n RepOk = 0x0203,\n RepError = 0x0204,\n RepBatch = 0x0205,\n BatchAck = 0x0206,\n FanoutBatch = 0x0207,\n AckSync = 0x0208,\n BatchAckSync = 0x0209,\n BatchNack = 0x020A,\n\n // 0x03xx — Subscription\n Subscribe = 0x0301,\n Unsubscribe = 0x0302,\n\n // 0x04xx — Stream management\n CreateStream = 0x0401,\n DeleteStream = 0x0402,\n GetStream = 0x0403,\n ListStreams = 0x0404,\n PurgeStream = 0x0405,\n DrainSubject = 0x0406,\n DeleteMessage = 0x0407,\n\n // 0x05xx — Consumer management\n CreateConsumer = 0x0501,\n DeleteConsumer = 0x0502,\n GetConsumer = 0x0503,\n ListConsumers = 0x0504,\n ConsumerStats = 0x0505,\n PauseConsumer = 0x0506,\n ResumeConsumer = 0x0507,\n\n // 0x08xx — Delayed publish\n PublishDelayed = 0x0801,\n\n // 0x06xx — System\n Ping = 0x0601,\n Pong = 0x0602,\n Connect = 0x0603,\n Connected = 0x0604,\n Disconnect = 0x0605,\n\n // 0x07xx — Cron scheduling\n CreateCron = 0x0701,\n DeleteCron = 0x0702,\n ListCrons = 0x0703,\n CronFire = 0x0704,\n CronAck = 0x0705,\n\n // 0x09xx reserved (workflow removed — now a client-side library).\n}\n"],"mappings":";AAGO,IAAM,WAAiB;AACvB,IAAM,aAAiB;AACvB,IAAM,kBAAkB;AAExB,IAAW,OAAX,kBAAWA,UAAX;AACL,EAAAA,YAAA,YAAS,KAAT;AACA,EAAAA,YAAA,YAAS,KAAT;AAFgB,SAAAA;AAAA,GAAA;AAKX,IAAW,MAAX,kBAAWC,SAAX;AACL,EAAAA,UAAA,aAAmB,KAAnB;AACA,EAAAA,UAAA,WAAmB,KAAnB;AACA,EAAAA,UAAA,kBAAmB,KAAnB;AACA,EAAAA,UAAA,uBAAoB,KAApB;AAJgB,SAAAA;AAAA,GAAA;AAQX,IAAM,cAAkB;AAGxB,IAAM,aAAkB;AACxB,IAAM,YAAkB;AACxB,IAAM,kBAAkB;AACxB,IAAM,cAAkB;AACxB,IAAM,UAAkB;AAGxB,IAAW,OAAX,kBAAWC,UAAX;AACL,EAAAA,YAAA,UAAe,KAAf;AACA,EAAAA,YAAA,YAAe,KAAf;AACA,EAAAA,YAAA,SAAe,KAAf;AACA,EAAAA,YAAA,kBAAe,KAAf;AAJgB,SAAAA;AAAA,GAAA;AAQX,IAAW,YAAX,kBAAWC,eAAX;AACL,EAAAA,sBAAA,UAAiB,KAAjB;AACA,EAAAA,sBAAA,YAAiB,KAAjB;AACA,EAAAA,sBAAA,gBAAiB,KAAjB;AACA,EAAAA,sBAAA,oBAAiB,KAAjB;AAJgB,SAAAA;AAAA,GAAA;AAQX,IAAW,SAAX,kBAAWC,YAAX;AAEL,EAAAA,gBAAA,WAAkB,KAAlB;AACA,EAAAA,gBAAA,UAAkB,KAAlB;AAGA,EAAAA,gBAAA,aAA0B,OAA1B;AACA,EAAAA,gBAAA,uBAA0B,OAA1B;AACA,EAAAA,gBAAA,kBAA0B,OAA1B;AACA,EAAAA,gBAAA,sBAA0B,OAA1B;AACA,EAAAA,gBAAA,wBAA0B,OAA1B;AACA,EAAAA,gBAAA,6BAA0B,OAA1B;AAGA,EAAAA,gBAAA,aAAe,OAAf;AACA,EAAAA,gBAAA,SAAe,OAAf;AACA,EAAAA,gBAAA,UAAe,OAAf;AACA,EAAAA,gBAAA,WAAe,OAAf;AACA,EAAAA,gBAAA,cAAe,OAAf;AACA,EAAAA,gBAAA,cAAe,OAAf;AACA,EAAAA,gBAAA,cAAe,OAAf;AACA,EAAAA,gBAAA,iBAAe,OAAf;AACA,EAAAA,gBAAA,aAAe,OAAf;AACA,EAAAA,gBAAA,kBAAe,OAAf;AACA,EAAAA,gBAAA,eAAe,OAAf;AAGA,EAAAA,gBAAA,eAAc,OAAd;AACA,EAAAA,gBAAA,iBAAc,OAAd;AAGA,EAAAA,gBAAA,kBAAgB,QAAhB;AACA,EAAAA,gBAAA,kBAAgB,QAAhB;AACA,EAAAA,gBAAA,eAAgB,QAAhB;AACA,EAAAA,gBAAA,iBAAgB,QAAhB;AACA,EAAAA,gBAAA,iBAAgB,QAAhB;AACA,EAAAA,gBAAA,kBAAgB,QAAhB;AACA,EAAAA,gBAAA,mBAAgB,QAAhB;AAGA,EAAAA,gBAAA,oBAAiB,QAAjB;AACA,EAAAA,gBAAA,oBAAiB,QAAjB;AACA,EAAAA,gBAAA,iBAAiB,QAAjB;AACA,EAAAA,gBAAA,mBAAiB,QAAjB;AACA,EAAAA,gBAAA,mBAAiB,QAAjB;AACA,EAAAA,gBAAA,mBAAiB,QAAjB;AACA,EAAAA,gBAAA,oBAAiB,QAAjB;AAGA,EAAAA,gBAAA,oBAAiB,QAAjB;AAGA,EAAAA,gBAAA,UAAa,QAAb;AACA,EAAAA,gBAAA,UAAa,QAAb;AACA,EAAAA,gBAAA,aAAa,QAAb;AACA,EAAAA,gBAAA,eAAa,QAAb;AACA,EAAAA,gBAAA,gBAAa,QAAb;AAGA,EAAAA,gBAAA,gBAAa,QAAb;AACA,EAAAA,gBAAA,gBAAa,QAAb;AACA,EAAAA,gBAAA,eAAa,QAAb;AACA,EAAAA,gBAAA,cAAa,QAAb;AACA,EAAAA,gBAAA,aAAa,QAAb;AA/DgB,SAAAA;AAAA,GAAA;","names":["Role","Cap","Flag","EntryFlag","Action"]}
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
OFF_FLAGS,
|
|
9
9
|
OFF_MSG_LEN,
|
|
10
10
|
OFF_SEQ
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-3EHQPPLU.mjs";
|
|
12
12
|
|
|
13
13
|
// src/proto/frame.ts
|
|
14
14
|
function frame(action, seq, bodyLen, flags = 0, entryFlags = 0) {
|
|
@@ -121,4 +121,4 @@ export {
|
|
|
121
121
|
packPublishDelayed,
|
|
122
122
|
packPublishBatch
|
|
123
123
|
};
|
|
124
|
-
//# sourceMappingURL=chunk-
|
|
124
|
+
//# sourceMappingURL=chunk-BSPQZJHF.mjs.map
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
OFF_MSG_LEN,
|
|
14
14
|
OFF_SEQ,
|
|
15
15
|
Role
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-3EHQPPLU.mjs";
|
|
17
17
|
export {
|
|
18
18
|
Action,
|
|
19
19
|
CURRENT_VERSION,
|
|
@@ -30,4 +30,4 @@ export {
|
|
|
30
30
|
OFF_SEQ,
|
|
31
31
|
Role
|
|
32
32
|
};
|
|
33
|
-
//# sourceMappingURL=constants-
|
|
33
|
+
//# sourceMappingURL=constants-LWTWKOBZ.mjs.map
|
package/dist/index.d.mts
CHANGED
|
@@ -463,6 +463,8 @@ declare class Consumer {
|
|
|
463
463
|
* from `streamName + name`. Equivalent of NATS `num_ack_pending`.
|
|
464
464
|
*/
|
|
465
465
|
getPendings(): Promise<number>;
|
|
466
|
+
/** Tombstone a single message by seq. Returns true if found. */
|
|
467
|
+
deleteMessage(seq: bigint): Promise<boolean>;
|
|
466
468
|
subscribe(cb?: RawCallback, opts?: SubscribeOptions): Promise<Subscription>;
|
|
467
469
|
subscribe<T extends Record<string, unknown>>(codec: Encoding<T>, cb: (msg: LazyMessage<T>) => void, opts?: SubscribeOptions): Promise<Subscription>;
|
|
468
470
|
}
|
|
@@ -574,6 +576,14 @@ declare class ArbitroClient {
|
|
|
574
576
|
streamExists(name: string): Promise<boolean>;
|
|
575
577
|
purgeStream(name: string): Promise<number>;
|
|
576
578
|
drainSubject(streamName: string, subject: string): Promise<number>;
|
|
579
|
+
/**
|
|
580
|
+
* Tombstone a single message by sequence number.
|
|
581
|
+
*
|
|
582
|
+
* The broker marks the entry as deleted — it will never be delivered
|
|
583
|
+
* to any consumer. Returns `true` if the message was found and
|
|
584
|
+
* tombstoned, `false` if not found or already tombstoned.
|
|
585
|
+
*/
|
|
586
|
+
deleteMessage(streamName: string, seq: bigint): Promise<boolean>;
|
|
577
587
|
createConsumer(streamName: string, config: ConsumerConfig): Promise<Consumer>;
|
|
578
588
|
private createConsumerRaw;
|
|
579
589
|
upsertConsumer(streamName: string, config: ConsumerConfig): Promise<Consumer>;
|
|
@@ -638,6 +648,8 @@ declare class Stream {
|
|
|
638
648
|
* with the broker; the caller decides whether to wait via `await`. */
|
|
639
649
|
publishBatch(messages: BatchPublishEntry[]): Promise<bigint>;
|
|
640
650
|
request(subject: string, data: Buffer, timeoutMs?: number): Promise<Buffer>;
|
|
651
|
+
/** Tombstone a single message by seq. Returns true if found. */
|
|
652
|
+
deleteMessage(seq: bigint): Promise<boolean>;
|
|
641
653
|
consumer(overrides?: Partial<ConsumerConfig>): Consumer;
|
|
642
654
|
topic<T extends Record<string, unknown>>(subject: string, codec: Encoding<T>): Topic<T>;
|
|
643
655
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -463,6 +463,8 @@ declare class Consumer {
|
|
|
463
463
|
* from `streamName + name`. Equivalent of NATS `num_ack_pending`.
|
|
464
464
|
*/
|
|
465
465
|
getPendings(): Promise<number>;
|
|
466
|
+
/** Tombstone a single message by seq. Returns true if found. */
|
|
467
|
+
deleteMessage(seq: bigint): Promise<boolean>;
|
|
466
468
|
subscribe(cb?: RawCallback, opts?: SubscribeOptions): Promise<Subscription>;
|
|
467
469
|
subscribe<T extends Record<string, unknown>>(codec: Encoding<T>, cb: (msg: LazyMessage<T>) => void, opts?: SubscribeOptions): Promise<Subscription>;
|
|
468
470
|
}
|
|
@@ -574,6 +576,14 @@ declare class ArbitroClient {
|
|
|
574
576
|
streamExists(name: string): Promise<boolean>;
|
|
575
577
|
purgeStream(name: string): Promise<number>;
|
|
576
578
|
drainSubject(streamName: string, subject: string): Promise<number>;
|
|
579
|
+
/**
|
|
580
|
+
* Tombstone a single message by sequence number.
|
|
581
|
+
*
|
|
582
|
+
* The broker marks the entry as deleted — it will never be delivered
|
|
583
|
+
* to any consumer. Returns `true` if the message was found and
|
|
584
|
+
* tombstoned, `false` if not found or already tombstoned.
|
|
585
|
+
*/
|
|
586
|
+
deleteMessage(streamName: string, seq: bigint): Promise<boolean>;
|
|
577
587
|
createConsumer(streamName: string, config: ConsumerConfig): Promise<Consumer>;
|
|
578
588
|
private createConsumerRaw;
|
|
579
589
|
upsertConsumer(streamName: string, config: ConsumerConfig): Promise<Consumer>;
|
|
@@ -638,6 +648,8 @@ declare class Stream {
|
|
|
638
648
|
* with the broker; the caller decides whether to wait via `await`. */
|
|
639
649
|
publishBatch(messages: BatchPublishEntry[]): Promise<bigint>;
|
|
640
650
|
request(subject: string, data: Buffer, timeoutMs?: number): Promise<Buffer>;
|
|
651
|
+
/** Tombstone a single message by seq. Returns true if found. */
|
|
652
|
+
deleteMessage(seq: bigint): Promise<boolean>;
|
|
641
653
|
consumer(overrides?: Partial<ConsumerConfig>): Consumer;
|
|
642
654
|
topic<T extends Record<string, unknown>>(subject: string, codec: Encoding<T>): Topic<T>;
|
|
643
655
|
}
|
package/dist/index.js
CHANGED
|
@@ -115,6 +115,7 @@ var init_constants = __esm({
|
|
|
115
115
|
Action2[Action2["ListStreams"] = 1028] = "ListStreams";
|
|
116
116
|
Action2[Action2["PurgeStream"] = 1029] = "PurgeStream";
|
|
117
117
|
Action2[Action2["DrainSubject"] = 1030] = "DrainSubject";
|
|
118
|
+
Action2[Action2["DeleteMessage"] = 1031] = "DeleteMessage";
|
|
118
119
|
Action2[Action2["CreateConsumer"] = 1281] = "CreateConsumer";
|
|
119
120
|
Action2[Action2["DeleteConsumer"] = 1282] = "DeleteConsumer";
|
|
120
121
|
Action2[Action2["GetConsumer"] = 1283] = "GetConsumer";
|
|
@@ -562,6 +563,7 @@ var packDrainSubject = (seq, name, subject) => packCold2(1030 /* DrainSubject */
|
|
|
562
563
|
name: bytesArr(name),
|
|
563
564
|
subject: bytesArr(subject)
|
|
564
565
|
});
|
|
566
|
+
var packDeleteMessage = (seq, name, msgSeq) => packCold2(1031 /* DeleteMessage */, seq, { name: bytesArr(name), seq: Number(msgSeq) });
|
|
565
567
|
var packListStreams = (seq, offset = 0, limit = 1e3) => packCold2(1028 /* ListStreams */, seq, { offset: offset >>> 0, limit: limit >>> 0 });
|
|
566
568
|
function packCreateConsumer(seq, opts) {
|
|
567
569
|
const limits = (opts.subjectLimits ?? []).map((l) => ({
|
|
@@ -1225,6 +1227,10 @@ var Consumer = class {
|
|
|
1225
1227
|
}
|
|
1226
1228
|
return this.client.getPending(this.streamName, this.name);
|
|
1227
1229
|
}
|
|
1230
|
+
/** Tombstone a single message by seq. Returns true if found. */
|
|
1231
|
+
deleteMessage(seq) {
|
|
1232
|
+
return this.client.deleteMessage(this.streamName, seq);
|
|
1233
|
+
}
|
|
1228
1234
|
subscribe(codecOrCb, cbOrOpts, opts) {
|
|
1229
1235
|
if (!codecOrCb || typeof codecOrCb === "function") {
|
|
1230
1236
|
return this.client.subscribe(
|
|
@@ -1314,6 +1320,10 @@ var Stream = class {
|
|
|
1314
1320
|
request(subject, data, timeoutMs) {
|
|
1315
1321
|
return this.client.request(this.name, subject, data, timeoutMs);
|
|
1316
1322
|
}
|
|
1323
|
+
/** Tombstone a single message by seq. Returns true if found. */
|
|
1324
|
+
deleteMessage(seq) {
|
|
1325
|
+
return this.client.deleteMessage(this.name, seq);
|
|
1326
|
+
}
|
|
1317
1327
|
// ── Context factories ───────────────────────────────────────────────────
|
|
1318
1328
|
consumer(overrides) {
|
|
1319
1329
|
const config = {
|
|
@@ -1701,6 +1711,19 @@ var ArbitroClient = class {
|
|
|
1701
1711
|
);
|
|
1702
1712
|
return Number(refSeq);
|
|
1703
1713
|
}
|
|
1714
|
+
/**
|
|
1715
|
+
* Tombstone a single message by sequence number.
|
|
1716
|
+
*
|
|
1717
|
+
* The broker marks the entry as deleted — it will never be delivered
|
|
1718
|
+
* to any consumer. Returns `true` if the message was found and
|
|
1719
|
+
* tombstoned, `false` if not found or already tombstoned.
|
|
1720
|
+
*/
|
|
1721
|
+
async deleteMessage(streamName, seq) {
|
|
1722
|
+
const refSeq = await this.conn.sendExpectReply(
|
|
1723
|
+
packDeleteMessage(this.conn.nextSeq(), Buffer.from(streamName), seq)
|
|
1724
|
+
);
|
|
1725
|
+
return refSeq > 0n;
|
|
1726
|
+
}
|
|
1704
1727
|
// ── Consumer management ───────────────────────────────────────────────────
|
|
1705
1728
|
async createConsumer(streamName, config) {
|
|
1706
1729
|
const consumerId = await this.createConsumerRaw(streamName, config);
|