@ignex/nova 0.1.3 → 0.1.5

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 (98) hide show
  1. package/README.md +4 -1
  2. package/docs/ai/TREE.md +69 -9
  3. package/docs/architecture.md +75 -27
  4. package/docs/events.md +83 -1
  5. package/docs/generic-bindings.md +10 -0
  6. package/docs/wire-format.md +65 -18
  7. package/package.json +2 -1
  8. package/prebuilds/linux-x64/libignex_ffi.so +0 -0
  9. package/public/generate.ts +97 -3
  10. package/public/server.ts +10 -0
  11. package/rust/src/generated/backend.rs +503 -0
  12. package/rust/src/transcode/generated.rs +376 -17
  13. package/src/bridge/nats/inbound.ts +46 -0
  14. package/src/bridge/nats/index.ts +131 -0
  15. package/src/bridge/nats/real-transport.ts +133 -0
  16. package/src/bridge/nats/types.ts +80 -0
  17. package/src/codegen/constants.ts +14 -4
  18. package/src/codegen/direct-gen.ts +20 -6
  19. package/src/codegen/registry-gen.ts +10 -6
  20. package/src/codegen/rust-glue-gen.ts +10 -3
  21. package/src/codegen/schema-model.ts +28 -3
  22. package/src/codegen/ts-ser-gen.ts +12 -3
  23. package/src/core/auth.ts +65 -4
  24. package/src/core/client-rpc.ts +75 -0
  25. package/src/core/client-state.ts +42 -0
  26. package/src/core/client-wire.ts +142 -8
  27. package/src/core/client.ts +72 -3
  28. package/src/core/groups.ts +5 -0
  29. package/src/core/metrics.ts +38 -21
  30. package/src/core/outbound.ts +50 -6
  31. package/src/core/rate-limit.ts +69 -0
  32. package/src/core/replay.ts +41 -1
  33. package/src/core/resume.ts +181 -0
  34. package/src/core/rooms.ts +10 -3
  35. package/src/core/routing.ts +128 -5
  36. package/src/core/server/client-info.ts +37 -0
  37. package/src/core/server/http-routes.ts +59 -0
  38. package/src/core/{server.ts → server/index.ts} +112 -120
  39. package/src/core/server/metrics-view.ts +53 -0
  40. package/src/core/server/socket-lifecycle.ts +57 -0
  41. package/src/core/state.ts +73 -1
  42. package/src/core/topic-log.ts +86 -0
  43. package/src/events/clients.ts +18 -0
  44. package/src/events/cluster/dedupe.ts +43 -0
  45. package/src/events/cluster/envelope.ts +149 -0
  46. package/src/events/cluster/index.ts +50 -0
  47. package/src/events/cluster/keys.ts +33 -0
  48. package/src/events/cluster/kinds.ts +32 -0
  49. package/src/events/cluster/presence-table.ts +99 -0
  50. package/src/events/cluster/presence.ts +53 -0
  51. package/src/events/cluster/redis-client.ts +50 -0
  52. package/src/events/cluster/store-memory.ts +67 -0
  53. package/src/events/cluster/store-redis.ts +44 -0
  54. package/src/events/cluster/subjects.ts +30 -0
  55. package/src/events/cluster/sync.ts +476 -0
  56. package/src/events/cluster/transport-nats.ts +24 -0
  57. package/src/events/cluster/transport-redis.ts +120 -0
  58. package/src/events/cluster-rpc.ts +196 -0
  59. package/src/events/delivery.ts +83 -0
  60. package/src/events/emit.ts +57 -11
  61. package/src/events/hub/context-factory.ts +79 -0
  62. package/src/events/hub/dispatch.ts +86 -0
  63. package/src/events/hub/index.ts +536 -0
  64. package/src/events/hub/internal.ts +31 -0
  65. package/src/events/hub/metrics-snapshot.ts +84 -0
  66. package/src/events/hub/resolve-cluster.ts +49 -0
  67. package/src/events/queue.ts +36 -9
  68. package/src/events/registry.ts +90 -54
  69. package/src/events/schedule.ts +73 -0
  70. package/src/events/trace.ts +283 -0
  71. package/src/events/types/client.ts +68 -0
  72. package/src/events/types/cluster.ts +40 -0
  73. package/src/events/types/context.ts +50 -0
  74. package/src/events/types/emit-target.ts +29 -0
  75. package/src/events/types/groups.ts +35 -0
  76. package/src/events/types/hub.ts +124 -0
  77. package/src/events/types/index.ts +30 -0
  78. package/src/events/types/metrics.ts +52 -0
  79. package/src/events/types/options.ts +62 -0
  80. package/src/generated/direct-ser.ts +146 -59
  81. package/src/generated/fbs/backend.fbs +23 -0
  82. package/src/generated/registry.ts +92 -33
  83. package/src/generated/rust/backend_generated.rs +503 -0
  84. package/src/generated/ts/backend.ts +4 -0
  85. package/src/generated/ts/resume.ts +74 -0
  86. package/src/generated/ts/resumed.ts +88 -0
  87. package/src/generated/ts/rpc-call.ts +112 -0
  88. package/src/generated/ts/rpc-result.ts +126 -0
  89. package/src/generated/ts/snapshot-request.ts +19 -5
  90. package/src/generated/ts-ser.ts +109 -16
  91. package/src/generated/wire-registry.json +7 -3
  92. package/src/schema/index.ts +45 -1
  93. package/src/transport/transport.ts +117 -77
  94. package/src/bridge/nats.ts +0 -309
  95. package/src/events/cluster.ts +0 -732
  96. package/src/events/hub.ts +0 -481
  97. package/src/events/types.ts +0 -378
  98. package/src/transport/stats.ts +0 -48
@@ -0,0 +1,88 @@
1
+ // automatically generated by the FlatBuffers compiler, do not modify
2
+
3
+ /* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
4
+
5
+ import * as flatbuffers from 'flatbuffers';
6
+
7
+
8
+
9
+ export class Resumed implements flatbuffers.IUnpackableObject<ResumedT> {
10
+ bb: flatbuffers.ByteBuffer|null = null;
11
+ bb_pos = 0;
12
+ __init(i:number, bb:flatbuffers.ByteBuffer):Resumed {
13
+ this.bb_pos = i;
14
+ this.bb = bb;
15
+ return this;
16
+ }
17
+
18
+ static getRootAsResumed(bb:flatbuffers.ByteBuffer, obj?:Resumed):Resumed {
19
+ return (obj || new Resumed()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
20
+ }
21
+
22
+ static getSizePrefixedRootAsResumed(bb:flatbuffers.ByteBuffer, obj?:Resumed):Resumed {
23
+ bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
24
+ return (obj || new Resumed()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
25
+ }
26
+
27
+ ok():boolean {
28
+ const offset = this.bb!.__offset(this.bb_pos, 4);
29
+ return offset ? !!this.bb!.readInt8(this.bb_pos + offset) : false;
30
+ }
31
+
32
+ from():bigint {
33
+ const offset = this.bb!.__offset(this.bb_pos, 6);
34
+ return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
35
+ }
36
+
37
+ static startResumed(builder:flatbuffers.Builder) {
38
+ builder.startObject(2);
39
+ }
40
+
41
+ static addOk(builder:flatbuffers.Builder, ok:boolean) {
42
+ builder.addFieldInt8(0, +ok, +false);
43
+ }
44
+
45
+ static addFrom(builder:flatbuffers.Builder, from:bigint) {
46
+ builder.addFieldInt64(1, from, BigInt('0'));
47
+ }
48
+
49
+ static endResumed(builder:flatbuffers.Builder):flatbuffers.Offset {
50
+ const offset = builder.endObject();
51
+ return offset;
52
+ }
53
+
54
+ static createResumed(builder:flatbuffers.Builder, ok:boolean, from:bigint):flatbuffers.Offset {
55
+ Resumed.startResumed(builder);
56
+ Resumed.addOk(builder, ok);
57
+ Resumed.addFrom(builder, from);
58
+ return Resumed.endResumed(builder);
59
+ }
60
+
61
+ unpack(): ResumedT {
62
+ return new ResumedT(
63
+ this.ok(),
64
+ this.from()
65
+ );
66
+ }
67
+
68
+
69
+ unpackTo(_o: ResumedT): void {
70
+ _o.ok = this.ok();
71
+ _o.from = this.from();
72
+ }
73
+ }
74
+
75
+ export class ResumedT implements flatbuffers.IGeneratedObject {
76
+ constructor(
77
+ public ok: boolean = false,
78
+ public from: bigint = BigInt('0')
79
+ ){}
80
+
81
+
82
+ pack(builder:flatbuffers.Builder): flatbuffers.Offset {
83
+ return Resumed.createResumed(builder,
84
+ this.ok,
85
+ this.from
86
+ );
87
+ }
88
+ }
@@ -0,0 +1,112 @@
1
+ // automatically generated by the FlatBuffers compiler, do not modify
2
+
3
+ /* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
4
+
5
+ import * as flatbuffers from 'flatbuffers';
6
+
7
+
8
+
9
+ export class RpcCall implements flatbuffers.IUnpackableObject<RpcCallT> {
10
+ bb: flatbuffers.ByteBuffer|null = null;
11
+ bb_pos = 0;
12
+ __init(i:number, bb:flatbuffers.ByteBuffer):RpcCall {
13
+ this.bb_pos = i;
14
+ this.bb = bb;
15
+ return this;
16
+ }
17
+
18
+ static getRootAsRpcCall(bb:flatbuffers.ByteBuffer, obj?:RpcCall):RpcCall {
19
+ return (obj || new RpcCall()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
20
+ }
21
+
22
+ static getSizePrefixedRootAsRpcCall(bb:flatbuffers.ByteBuffer, obj?:RpcCall):RpcCall {
23
+ bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
24
+ return (obj || new RpcCall()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
25
+ }
26
+
27
+ id():string|null
28
+ id(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
29
+ id(optionalEncoding?:any):string|Uint8Array|null {
30
+ const offset = this.bb!.__offset(this.bb_pos, 4);
31
+ return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
32
+ }
33
+
34
+ name():string|null
35
+ name(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
36
+ name(optionalEncoding?:any):string|Uint8Array|null {
37
+ const offset = this.bb!.__offset(this.bb_pos, 6);
38
+ return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
39
+ }
40
+
41
+ payloadB64():string|null
42
+ payloadB64(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
43
+ payloadB64(optionalEncoding?:any):string|Uint8Array|null {
44
+ const offset = this.bb!.__offset(this.bb_pos, 8);
45
+ return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
46
+ }
47
+
48
+ static startRpcCall(builder:flatbuffers.Builder) {
49
+ builder.startObject(3);
50
+ }
51
+
52
+ static addId(builder:flatbuffers.Builder, idOffset:flatbuffers.Offset) {
53
+ builder.addFieldOffset(0, idOffset, 0);
54
+ }
55
+
56
+ static addName(builder:flatbuffers.Builder, nameOffset:flatbuffers.Offset) {
57
+ builder.addFieldOffset(1, nameOffset, 0);
58
+ }
59
+
60
+ static addPayloadB64(builder:flatbuffers.Builder, payloadB64Offset:flatbuffers.Offset) {
61
+ builder.addFieldOffset(2, payloadB64Offset, 0);
62
+ }
63
+
64
+ static endRpcCall(builder:flatbuffers.Builder):flatbuffers.Offset {
65
+ const offset = builder.endObject();
66
+ return offset;
67
+ }
68
+
69
+ static createRpcCall(builder:flatbuffers.Builder, idOffset:flatbuffers.Offset, nameOffset:flatbuffers.Offset, payloadB64Offset:flatbuffers.Offset):flatbuffers.Offset {
70
+ RpcCall.startRpcCall(builder);
71
+ RpcCall.addId(builder, idOffset);
72
+ RpcCall.addName(builder, nameOffset);
73
+ RpcCall.addPayloadB64(builder, payloadB64Offset);
74
+ return RpcCall.endRpcCall(builder);
75
+ }
76
+
77
+ unpack(): RpcCallT {
78
+ return new RpcCallT(
79
+ this.id(),
80
+ this.name(),
81
+ this.payloadB64()
82
+ );
83
+ }
84
+
85
+
86
+ unpackTo(_o: RpcCallT): void {
87
+ _o.id = this.id();
88
+ _o.name = this.name();
89
+ _o.payloadB64 = this.payloadB64();
90
+ }
91
+ }
92
+
93
+ export class RpcCallT implements flatbuffers.IGeneratedObject {
94
+ constructor(
95
+ public id: string|Uint8Array|null = null,
96
+ public name: string|Uint8Array|null = null,
97
+ public payloadB64: string|Uint8Array|null = null
98
+ ){}
99
+
100
+
101
+ pack(builder:flatbuffers.Builder): flatbuffers.Offset {
102
+ const id = (this.id !== null ? builder.createString(this.id!) : 0);
103
+ const name = (this.name !== null ? builder.createString(this.name!) : 0);
104
+ const payloadB64 = (this.payloadB64 !== null ? builder.createString(this.payloadB64!) : 0);
105
+
106
+ return RpcCall.createRpcCall(builder,
107
+ id,
108
+ name,
109
+ payloadB64
110
+ );
111
+ }
112
+ }
@@ -0,0 +1,126 @@
1
+ // automatically generated by the FlatBuffers compiler, do not modify
2
+
3
+ /* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, @typescript-eslint/no-non-null-assertion */
4
+
5
+ import * as flatbuffers from 'flatbuffers';
6
+
7
+
8
+
9
+ export class RpcResult implements flatbuffers.IUnpackableObject<RpcResultT> {
10
+ bb: flatbuffers.ByteBuffer|null = null;
11
+ bb_pos = 0;
12
+ __init(i:number, bb:flatbuffers.ByteBuffer):RpcResult {
13
+ this.bb_pos = i;
14
+ this.bb = bb;
15
+ return this;
16
+ }
17
+
18
+ static getRootAsRpcResult(bb:flatbuffers.ByteBuffer, obj?:RpcResult):RpcResult {
19
+ return (obj || new RpcResult()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
20
+ }
21
+
22
+ static getSizePrefixedRootAsRpcResult(bb:flatbuffers.ByteBuffer, obj?:RpcResult):RpcResult {
23
+ bb.setPosition(bb.position() + flatbuffers.SIZE_PREFIX_LENGTH);
24
+ return (obj || new RpcResult()).__init(bb.readInt32(bb.position()) + bb.position(), bb);
25
+ }
26
+
27
+ id():string|null
28
+ id(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
29
+ id(optionalEncoding?:any):string|Uint8Array|null {
30
+ const offset = this.bb!.__offset(this.bb_pos, 4);
31
+ return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
32
+ }
33
+
34
+ ok():boolean {
35
+ const offset = this.bb!.__offset(this.bb_pos, 6);
36
+ return offset ? !!this.bb!.readInt8(this.bb_pos + offset) : false;
37
+ }
38
+
39
+ err():string|null
40
+ err(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
41
+ err(optionalEncoding?:any):string|Uint8Array|null {
42
+ const offset = this.bb!.__offset(this.bb_pos, 8);
43
+ return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
44
+ }
45
+
46
+ payloadB64():string|null
47
+ payloadB64(optionalEncoding:flatbuffers.Encoding):string|Uint8Array|null
48
+ payloadB64(optionalEncoding?:any):string|Uint8Array|null {
49
+ const offset = this.bb!.__offset(this.bb_pos, 10);
50
+ return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
51
+ }
52
+
53
+ static startRpcResult(builder:flatbuffers.Builder) {
54
+ builder.startObject(4);
55
+ }
56
+
57
+ static addId(builder:flatbuffers.Builder, idOffset:flatbuffers.Offset) {
58
+ builder.addFieldOffset(0, idOffset, 0);
59
+ }
60
+
61
+ static addOk(builder:flatbuffers.Builder, ok:boolean) {
62
+ builder.addFieldInt8(1, +ok, +false);
63
+ }
64
+
65
+ static addErr(builder:flatbuffers.Builder, errOffset:flatbuffers.Offset) {
66
+ builder.addFieldOffset(2, errOffset, 0);
67
+ }
68
+
69
+ static addPayloadB64(builder:flatbuffers.Builder, payloadB64Offset:flatbuffers.Offset) {
70
+ builder.addFieldOffset(3, payloadB64Offset, 0);
71
+ }
72
+
73
+ static endRpcResult(builder:flatbuffers.Builder):flatbuffers.Offset {
74
+ const offset = builder.endObject();
75
+ return offset;
76
+ }
77
+
78
+ static createRpcResult(builder:flatbuffers.Builder, idOffset:flatbuffers.Offset, ok:boolean, errOffset:flatbuffers.Offset, payloadB64Offset:flatbuffers.Offset):flatbuffers.Offset {
79
+ RpcResult.startRpcResult(builder);
80
+ RpcResult.addId(builder, idOffset);
81
+ RpcResult.addOk(builder, ok);
82
+ RpcResult.addErr(builder, errOffset);
83
+ RpcResult.addPayloadB64(builder, payloadB64Offset);
84
+ return RpcResult.endRpcResult(builder);
85
+ }
86
+
87
+ unpack(): RpcResultT {
88
+ return new RpcResultT(
89
+ this.id(),
90
+ this.ok(),
91
+ this.err(),
92
+ this.payloadB64()
93
+ );
94
+ }
95
+
96
+
97
+ unpackTo(_o: RpcResultT): void {
98
+ _o.id = this.id();
99
+ _o.ok = this.ok();
100
+ _o.err = this.err();
101
+ _o.payloadB64 = this.payloadB64();
102
+ }
103
+ }
104
+
105
+ export class RpcResultT implements flatbuffers.IGeneratedObject {
106
+ constructor(
107
+ public id: string|Uint8Array|null = null,
108
+ public ok: boolean = false,
109
+ public err: string|Uint8Array|null = null,
110
+ public payloadB64: string|Uint8Array|null = null
111
+ ){}
112
+
113
+
114
+ pack(builder:flatbuffers.Builder): flatbuffers.Offset {
115
+ const id = (this.id !== null ? builder.createString(this.id!) : 0);
116
+ const err = (this.err !== null ? builder.createString(this.err!) : 0);
117
+ const payloadB64 = (this.payloadB64 !== null ? builder.createString(this.payloadB64!) : 0);
118
+
119
+ return RpcResult.createRpcResult(builder,
120
+ id,
121
+ this.ok,
122
+ err,
123
+ payloadB64
124
+ );
125
+ }
126
+ }
@@ -31,40 +31,53 @@ topic(optionalEncoding?:any):string|Uint8Array|null {
31
31
  return offset ? this.bb!.__string(this.bb_pos + offset, optionalEncoding) : null;
32
32
  }
33
33
 
34
+ fromSeq():bigint {
35
+ const offset = this.bb!.__offset(this.bb_pos, 6);
36
+ return offset ? this.bb!.readInt64(this.bb_pos + offset) : BigInt('0');
37
+ }
38
+
34
39
  static startSnapshotRequest(builder:flatbuffers.Builder) {
35
- builder.startObject(1);
40
+ builder.startObject(2);
36
41
  }
37
42
 
38
43
  static addTopic(builder:flatbuffers.Builder, topicOffset:flatbuffers.Offset) {
39
44
  builder.addFieldOffset(0, topicOffset, 0);
40
45
  }
41
46
 
47
+ static addFromSeq(builder:flatbuffers.Builder, fromSeq:bigint) {
48
+ builder.addFieldInt64(1, fromSeq, BigInt('0'));
49
+ }
50
+
42
51
  static endSnapshotRequest(builder:flatbuffers.Builder):flatbuffers.Offset {
43
52
  const offset = builder.endObject();
44
53
  return offset;
45
54
  }
46
55
 
47
- static createSnapshotRequest(builder:flatbuffers.Builder, topicOffset:flatbuffers.Offset):flatbuffers.Offset {
56
+ static createSnapshotRequest(builder:flatbuffers.Builder, topicOffset:flatbuffers.Offset, fromSeq:bigint):flatbuffers.Offset {
48
57
  SnapshotRequest.startSnapshotRequest(builder);
49
58
  SnapshotRequest.addTopic(builder, topicOffset);
59
+ SnapshotRequest.addFromSeq(builder, fromSeq);
50
60
  return SnapshotRequest.endSnapshotRequest(builder);
51
61
  }
52
62
 
53
63
  unpack(): SnapshotRequestT {
54
64
  return new SnapshotRequestT(
55
- this.topic()
65
+ this.topic(),
66
+ this.fromSeq()
56
67
  );
57
68
  }
58
69
 
59
70
 
60
71
  unpackTo(_o: SnapshotRequestT): void {
61
72
  _o.topic = this.topic();
73
+ _o.fromSeq = this.fromSeq();
62
74
  }
63
75
  }
64
76
 
65
77
  export class SnapshotRequestT implements flatbuffers.IGeneratedObject {
66
78
  constructor(
67
- public topic: string|Uint8Array|null = null
79
+ public topic: string|Uint8Array|null = null,
80
+ public fromSeq: bigint = BigInt('0')
68
81
  ){}
69
82
 
70
83
 
@@ -72,7 +85,8 @@ pack(builder:flatbuffers.Builder): flatbuffers.Offset {
72
85
  const topic = (this.topic !== null ? builder.createString(this.topic!) : 0);
73
86
 
74
87
  return SnapshotRequest.createSnapshotRequest(builder,
75
- topic
88
+ topic,
89
+ this.fromSeq
76
90
  );
77
91
  }
78
92
  }
@@ -20,6 +20,10 @@ import {
20
20
  SnapshotRequestT,
21
21
  PingT,
22
22
  PongT,
23
+ ResumeT,
24
+ ResumedT,
25
+ RpcCallT,
26
+ RpcResultT,
23
27
  } from "./ts/backend";
24
28
  import { anyEventNameToId, WIRE_HEADER_LEN, WIRE_VERSION } from "./registry";
25
29
  import type { AnyEventName, ControlEvents, Events } from "../schema";
@@ -149,6 +153,7 @@ type LeaveGroupPlain = {
149
153
 
150
154
  type SnapshotRequestPlain = {
151
155
  topic: string;
156
+ fromSeq: number;
152
157
  };
153
158
 
154
159
  type PingPlain = {
@@ -159,6 +164,28 @@ type PongPlain = {
159
164
  ts: number;
160
165
  };
161
166
 
167
+ type ResumePlain = {
168
+ lastSeq: number;
169
+ };
170
+
171
+ type ResumedPlain = {
172
+ ok: boolean;
173
+ from: number;
174
+ };
175
+
176
+ type RpcCallPlain = {
177
+ id: string;
178
+ name: string;
179
+ payloadB64: string;
180
+ };
181
+
182
+ type RpcResultPlain = {
183
+ id: string;
184
+ ok: boolean;
185
+ err: string;
186
+ payloadB64: string;
187
+ };
188
+
162
189
  function buildQuoteT(o: QuotePlain): QuoteT {
163
190
  return new QuoteT(
164
191
  o.symbol,
@@ -306,6 +333,7 @@ function buildLeaveGroupT(o: LeaveGroupPlain): LeaveGroupT {
306
333
  function buildSnapshotRequestT(o: SnapshotRequestPlain): SnapshotRequestT {
307
334
  return new SnapshotRequestT(
308
335
  o.topic,
336
+ o.fromSeq === undefined ? 0n : BigInt(o.fromSeq),
309
337
  );
310
338
  }
311
339
 
@@ -321,6 +349,36 @@ function buildPongT(o: PongPlain): PongT {
321
349
  );
322
350
  }
323
351
 
352
+ function buildResumeT(o: ResumePlain): ResumeT {
353
+ return new ResumeT(
354
+ o.lastSeq === undefined ? 0n : BigInt(o.lastSeq),
355
+ );
356
+ }
357
+
358
+ function buildResumedT(o: ResumedPlain): ResumedT {
359
+ return new ResumedT(
360
+ o.ok,
361
+ o.from === undefined ? 0n : BigInt(o.from),
362
+ );
363
+ }
364
+
365
+ function buildRpcCallT(o: RpcCallPlain): RpcCallT {
366
+ return new RpcCallT(
367
+ o.id,
368
+ o.name,
369
+ o.payloadB64,
370
+ );
371
+ }
372
+
373
+ function buildRpcResultT(o: RpcResultPlain): RpcResultT {
374
+ return new RpcResultT(
375
+ o.id,
376
+ o.ok,
377
+ o.err,
378
+ o.payloadB64,
379
+ );
380
+ }
381
+
324
382
  /** payload encoder: plain object → size-prefixed FlatBuffer. */
325
383
  export function encodeQuotePayload(o: Events["quote"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
326
384
  b.clear();
@@ -426,24 +484,56 @@ export function encodePongPayload(o: ControlEvents["pong"], b: flatbuffers.Build
426
484
  return b.asUint8Array();
427
485
  }
428
486
 
487
+ /** control payload encoder: plain object → size-prefixed FlatBuffer. */
488
+ export function encodeResumePayload(o: ControlEvents["resume"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
489
+ b.clear();
490
+ b.finishSizePrefixed(buildResumeT(o).pack(b));
491
+ return b.asUint8Array();
492
+ }
493
+
494
+ /** control payload encoder: plain object → size-prefixed FlatBuffer. */
495
+ export function encodeResumedPayload(o: ControlEvents["resumed"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
496
+ b.clear();
497
+ b.finishSizePrefixed(buildResumedT(o).pack(b));
498
+ return b.asUint8Array();
499
+ }
500
+
501
+ /** control payload encoder: plain object → size-prefixed FlatBuffer. */
502
+ export function encodeRpcCallPayload(o: ControlEvents["rpcCall"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
503
+ b.clear();
504
+ b.finishSizePrefixed(buildRpcCallT(o).pack(b));
505
+ return b.asUint8Array();
506
+ }
507
+
508
+ /** control payload encoder: plain object → size-prefixed FlatBuffer. */
509
+ export function encodeRpcResultPayload(o: ControlEvents["rpcResult"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
510
+ b.clear();
511
+ b.finishSizePrefixed(buildRpcResultT(o).pack(b));
512
+ return b.asUint8Array();
513
+ }
514
+
429
515
  export type JsEncoder = (o: unknown, b?: flatbuffers.Builder) => Uint8Array;
430
516
 
431
517
  export const jsEncoders: Record<string, JsEncoder> = {
432
- quote: encodeQuotePayload as JsEncoder,
433
- trade: encodeTradePayload as JsEncoder,
434
- portfolio: encodePortfolioPayload as JsEncoder,
435
- complex: encodeComplexPayload as JsEncoder,
436
- order: encodeOrderPayload as JsEncoder,
437
- bigVal: encodeBigValPayload as JsEncoder,
438
- hello: encodeHelloPayload as JsEncoder,
439
- welcome: encodeWelcomePayload as JsEncoder,
440
- subscribe: encodeSubscribePayload as JsEncoder,
441
- unsubscribe: encodeUnsubscribePayload as JsEncoder,
442
- joinGroup: encodeJoinGroupPayload as JsEncoder,
443
- leaveGroup: encodeLeaveGroupPayload as JsEncoder,
444
- snapshotRequest: encodeSnapshotRequestPayload as JsEncoder,
445
- ping: encodePingPayload as JsEncoder,
446
- pong: encodePongPayload as JsEncoder,
518
+ "quote": encodeQuotePayload as JsEncoder,
519
+ "trade": encodeTradePayload as JsEncoder,
520
+ "portfolio": encodePortfolioPayload as JsEncoder,
521
+ "complex": encodeComplexPayload as JsEncoder,
522
+ "order": encodeOrderPayload as JsEncoder,
523
+ "bigVal": encodeBigValPayload as JsEncoder,
524
+ "hello": encodeHelloPayload as JsEncoder,
525
+ "welcome": encodeWelcomePayload as JsEncoder,
526
+ "subscribe": encodeSubscribePayload as JsEncoder,
527
+ "unsubscribe": encodeUnsubscribePayload as JsEncoder,
528
+ "joinGroup": encodeJoinGroupPayload as JsEncoder,
529
+ "leaveGroup": encodeLeaveGroupPayload as JsEncoder,
530
+ "snapshotRequest": encodeSnapshotRequestPayload as JsEncoder,
531
+ "ping": encodePingPayload as JsEncoder,
532
+ "pong": encodePongPayload as JsEncoder,
533
+ "resume": encodeResumePayload as JsEncoder,
534
+ "resumed": encodeResumedPayload as JsEncoder,
535
+ "rpcCall": encodeRpcCallPayload as JsEncoder,
536
+ "rpcResult": encodeRpcResultPayload as JsEncoder,
447
537
  };
448
538
 
449
539
  /** Encode a payload (app or control event) → size-prefixed FlatBuffer. */
@@ -453,13 +543,16 @@ export function encodeJsPayload(name: AnyEventName, o: unknown, b?: flatbuffers.
453
543
  return enc(o, b);
454
544
  }
455
545
 
456
- /** Encode a payload into a full wire frame `[version][event_id:u32][size-prefixed FB]`. */
546
+ /** Encode a payload into a full wire frame `[version][event_id:u32][flags:1][seq:u64 LE][size-prefixed FB]`. */
457
547
  export function encodeEventFrame(name: AnyEventName, o: unknown, b?: flatbuffers.Builder): Uint8Array {
458
548
  const payload = encodeJsPayload(name, o, b);
459
549
  const id = anyEventNameToId[name]!;
460
550
  const frame = new Uint8Array(WIRE_HEADER_LEN + payload.byteLength);
461
551
  frame[0] = WIRE_VERSION;
462
552
  new DataView(frame.buffer).setUint32(1, id, true);
553
+ // pristine delivery header (flags=0, seq=0) — client-sent frames are not stamped
554
+ frame[WIRE_HEADER_LEN - 9] = 0;
555
+ new DataView(frame.buffer).setBigUint64(WIRE_HEADER_LEN - 8, 0n, true);
463
556
  frame.set(payload, WIRE_HEADER_LEN);
464
557
  return frame;
465
558
  }
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": 1,
3
- "fingerprint": 1656642724,
2
+ "version": 2,
3
+ "fingerprint": 3647747841,
4
4
  "events": {
5
5
  "quote": 2995289047,
6
6
  "trade": 1362521689,
@@ -16,6 +16,10 @@
16
16
  "leaveGroup": 3755061443,
17
17
  "snapshotRequest": 1249175018,
18
18
  "ping": 375255177,
19
- "pong": 2061178551
19
+ "pong": 2061178551,
20
+ "resume": 4281967466,
21
+ "resumed": 3585847050,
22
+ "rpcCall": 986404564,
23
+ "rpcResult": 648609069
20
24
  }
21
25
  }
@@ -183,7 +183,14 @@ export const JoinGroup = Type.Object({ group: Type.String() }, { additionalPrope
183
183
  export const LeaveGroup = Type.Object({ group: Type.String() }, { additionalProperties: false });
184
184
 
185
185
  export const SnapshotRequest = Type.Object(
186
- { topic: Type.String() },
186
+ {
187
+ topic: Type.String(),
188
+ /**
189
+ * Resume point: serve recorded history STRICTLY AFTER this topic seq
190
+ * (0 = from the beginning of retained history — the v1 behavior).
191
+ */
192
+ fromSeq: Type.Integer(),
193
+ },
187
194
  { additionalProperties: false },
188
195
  );
189
196
 
@@ -191,6 +198,39 @@ export const Ping = Type.Object({ ts: Type.Integer() }, { additionalProperties:
191
198
 
192
199
  export const Pong = Type.Object({ ts: Type.Integer() }, { additionalProperties: false });
193
200
 
201
+ /**
202
+ * Client → server: resume missed delivery-seq frames after a gap or
203
+ * reconnect. The server replays everything it still holds strictly after
204
+ * `lastSeq` from the per-connection history ring, prefixed by a `resumed`
205
+ * control frame (`ok:false` when the hole is older than the ring).
206
+ */
207
+ export const Resume = Type.Object(
208
+ { lastSeq: Type.Integer() }, // last CONTIGUOUS delivery seq the client has
209
+ { additionalProperties: false },
210
+ );
211
+
212
+ /** Server → client: ack before replayed frames (`ok:false` → resubscribe topics). */
213
+ export const Resumed = Type.Object(
214
+ { ok: Type.Boolean(), from: Type.Integer() }, // first seq being replayed
215
+ { additionalProperties: false },
216
+ );
217
+
218
+ /**
219
+ * Request/response over the event wire (correlation id + timeout live on the
220
+ * caller side). `name` is the app-event name being requested; `payload` is the
221
+ * base64 of a full wire frame encoded with that same event's schema — the
222
+ * response reuses the SAME event schema both directions.
223
+ */
224
+ export const RpcCall = Type.Object(
225
+ { id: Type.String(), name: Type.String(), payloadB64: Type.String() },
226
+ { additionalProperties: false },
227
+ );
228
+
229
+ export const RpcResult = Type.Object(
230
+ { id: Type.String(), ok: Type.Boolean(), err: Type.String(), payloadB64: Type.String() },
231
+ { additionalProperties: false },
232
+ );
233
+
194
234
  /** Server→client identity assignment (sent right after `hello` on open). */
195
235
  export const Welcome = Type.Object(
196
236
  {
@@ -211,6 +251,10 @@ export const controlEvents = {
211
251
  snapshotRequest: SnapshotRequest,
212
252
  ping: Ping,
213
253
  pong: Pong,
254
+ resume: Resume,
255
+ resumed: Resumed,
256
+ rpcCall: RpcCall,
257
+ rpcResult: RpcResult,
214
258
  } as const;
215
259
 
216
260
  export type EventName = keyof typeof events;