@ignex/nova 0.1.1 → 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 (120) hide show
  1. package/README.md +136 -33
  2. package/docs/ai/LOCAL_DEV.md +81 -0
  3. package/docs/ai/TREE.md +292 -0
  4. package/docs/architecture.md +101 -28
  5. package/docs/events.md +252 -0
  6. package/docs/generic-bindings.md +207 -0
  7. package/docs/publishing.md +2 -2
  8. package/docs/wire-format.md +74 -20
  9. package/index.ts +75 -27
  10. package/package.json +13 -2
  11. package/prebuilds/linux-x64/libignex_ffi.so +0 -0
  12. package/public/bindings.ts +24 -0
  13. package/public/client.ts +5 -1
  14. package/public/events.ts +71 -0
  15. package/public/generate.ts +510 -0
  16. package/public/internal.ts +16 -0
  17. package/public/nats.ts +9 -5
  18. package/public/server.ts +52 -16
  19. package/rust/src/ffi.rs +10 -0
  20. package/rust/src/generated/backend.rs +503 -0
  21. package/rust/src/transcode/generated.rs +377 -17
  22. package/src/bindings/assemble.ts +73 -0
  23. package/src/bindings/default.ts +65 -0
  24. package/src/bindings/types.ts +113 -0
  25. package/src/bridge/nats/inbound.ts +46 -0
  26. package/src/bridge/nats/index.ts +131 -0
  27. package/src/bridge/nats/real-transport.ts +133 -0
  28. package/src/bridge/nats/types.ts +80 -0
  29. package/src/bridge/subjects.ts +3 -0
  30. package/src/codegen/constants.ts +28 -0
  31. package/src/codegen/direct-gen.ts +564 -0
  32. package/src/codegen/fingerprint.ts +44 -0
  33. package/src/codegen/hash.ts +25 -0
  34. package/src/codegen/registry-gen.ts +246 -0
  35. package/src/codegen/rust-glue-gen.ts +552 -0
  36. package/src/codegen/schema-model.ts +363 -0
  37. package/src/codegen/ts-ser-gen.ts +230 -0
  38. package/src/codegen/typebox-to-fbs.ts +60 -0
  39. package/src/core/auth.ts +67 -5
  40. package/src/core/client-heartbeat.ts +2 -1
  41. package/src/core/client-reconnect.ts +9 -2
  42. package/src/core/client-rpc.ts +75 -0
  43. package/src/core/client-state.ts +63 -8
  44. package/src/core/client-wire.ts +148 -15
  45. package/src/core/client.ts +105 -31
  46. package/src/core/groups.ts +8 -0
  47. package/src/core/metrics.ts +42 -21
  48. package/src/core/outbound.ts +62 -11
  49. package/src/core/rate-limit.ts +69 -0
  50. package/src/core/replay.ts +41 -1
  51. package/src/core/resume.ts +181 -0
  52. package/src/core/rooms.ts +10 -3
  53. package/src/core/routing.ts +144 -12
  54. package/src/core/server/client-info.ts +37 -0
  55. package/src/core/server/http-routes.ts +59 -0
  56. package/src/core/server/index.ts +360 -0
  57. package/src/core/server/metrics-view.ts +53 -0
  58. package/src/core/server/socket-lifecycle.ts +57 -0
  59. package/src/core/state.ts +124 -14
  60. package/src/core/topic-log.ts +86 -0
  61. package/src/events/clients.ts +174 -0
  62. package/src/events/cluster/dedupe.ts +43 -0
  63. package/src/events/cluster/envelope.ts +149 -0
  64. package/src/events/cluster/index.ts +50 -0
  65. package/src/events/cluster/keys.ts +33 -0
  66. package/src/events/cluster/kinds.ts +32 -0
  67. package/src/events/cluster/presence-table.ts +99 -0
  68. package/src/events/cluster/presence.ts +53 -0
  69. package/src/events/cluster/redis-client.ts +50 -0
  70. package/src/events/cluster/store-memory.ts +67 -0
  71. package/src/events/cluster/store-redis.ts +44 -0
  72. package/src/events/cluster/subjects.ts +30 -0
  73. package/src/events/cluster/sync.ts +476 -0
  74. package/src/events/cluster/transport-nats.ts +24 -0
  75. package/src/events/cluster/transport-redis.ts +120 -0
  76. package/src/events/cluster-rpc.ts +196 -0
  77. package/src/events/data.ts +38 -0
  78. package/src/events/delivery.ts +83 -0
  79. package/src/events/emit.ts +173 -0
  80. package/src/events/global.ts +117 -0
  81. package/src/events/groups.ts +118 -0
  82. package/src/events/hub/context-factory.ts +79 -0
  83. package/src/events/hub/dispatch.ts +86 -0
  84. package/src/events/hub/index.ts +536 -0
  85. package/src/events/hub/internal.ts +31 -0
  86. package/src/events/hub/metrics-snapshot.ts +84 -0
  87. package/src/events/hub/resolve-cluster.ts +49 -0
  88. package/src/events/index.ts +61 -0
  89. package/src/events/queue.ts +123 -0
  90. package/src/events/registry.ts +214 -0
  91. package/src/events/schedule.ts +73 -0
  92. package/src/events/trace.ts +283 -0
  93. package/src/events/types/client.ts +68 -0
  94. package/src/events/types/cluster.ts +40 -0
  95. package/src/events/types/context.ts +50 -0
  96. package/src/events/types/emit-target.ts +29 -0
  97. package/src/events/types/groups.ts +35 -0
  98. package/src/events/types/hub.ts +124 -0
  99. package/src/events/types/index.ts +30 -0
  100. package/src/events/types/metrics.ts +52 -0
  101. package/src/events/types/options.ts +62 -0
  102. package/src/generated/direct-ser.ts +148 -60
  103. package/src/generated/fbs/backend.fbs +24 -1
  104. package/src/generated/registry.ts +94 -33
  105. package/src/generated/rust/backend_generated.rs +503 -0
  106. package/src/generated/ts/backend.ts +4 -0
  107. package/src/generated/ts/resume.ts +74 -0
  108. package/src/generated/ts/resumed.ts +88 -0
  109. package/src/generated/ts/rpc-call.ts +112 -0
  110. package/src/generated/ts/rpc-result.ts +126 -0
  111. package/src/generated/ts/snapshot-request.ts +19 -5
  112. package/src/generated/ts-ser.ts +110 -17
  113. package/src/generated/wire-registry.json +7 -2
  114. package/src/native/ffi.ts +85 -28
  115. package/src/schema/index.ts +49 -2
  116. package/src/server.ts +7 -3
  117. package/src/transport/transport.ts +200 -79
  118. package/src/bridge/nats.ts +0 -269
  119. package/src/core/server.ts +0 -294
  120. package/src/transport/stats.ts +0 -44
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Events-layer metrics snapshot type (folded into `server.getMetrics().events`).
3
+ *
4
+ * Type-only module (part of the `src/events/types` barrel). The assembly
5
+ * runtime lives in `src/events/hub/metrics-snapshot.ts`.
6
+ */
7
+ import type { EmitTargetKind } from "./emit-target";
8
+
9
+ /** Events-layer counters (folded into `server.getMetrics().events`). */
10
+ export interface EventsMetricsSnapshot {
11
+ /** emit calls (all targets) */
12
+ emitted: number;
13
+ emittedByTarget: Record<EmitTargetKind, number>;
14
+ /** frames written to local sockets by the events layer */
15
+ deliveredLocal: number;
16
+ /** frames handed to the cluster transport */
17
+ clusterPublished: number;
18
+ /** frames received from other instances */
19
+ clusterReceived: number;
20
+ /** frames dropped because they originated on this instance */
21
+ clusterDroppedSelf: number;
22
+ /** duplicate cluster messages dropped (broker redelivery dedupe window) */
23
+ clusterDroppedDupe: number;
24
+ /** targeted emits routed ONLY to owning instances instead of the full mesh */
25
+ clusterRouted: number;
26
+ /** cluster transport / decode failures */
27
+ clusterErrors: number;
28
+ /** offload-queue: tasks accepted */
29
+ queueQueued: number;
30
+ /** offload-queue: tasks dropped (overflow) */
31
+ queueDropped: number;
32
+ /** offload-queue: task failures */
33
+ queueErrors: number;
34
+ /** handler exceptions (caught + isolated) */
35
+ handlerErrors: number;
36
+ /** handler retries scheduled by the reliability layer (`handlers.retries`) */
37
+ handlerRetries: number;
38
+ /** events dead-lettered after exhausting the retry budget */
39
+ dlqCount: number;
40
+ /** emits currently scheduled via `hub.schedule` */
41
+ scheduledActive: number;
42
+ /** cross-instance rpc calls sent / received */
43
+ rpcSent: number;
44
+ rpcReceived: number;
45
+ /** local connected clients */
46
+ connectedClients: number;
47
+ /** remote clients known via cluster presence */
48
+ remoteClients: number;
49
+ /** active client groups / user groups */
50
+ clientGroups: number;
51
+ userGroups: number;
52
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Events-layer option types — `createServer({ events })` input.
3
+ *
4
+ * Type-only module (part of the `src/events/types` barrel). Resolved by
5
+ * `createEventsHub` (`src/events/hub/index.ts`).
6
+ */
7
+ import type { Bindings, DefaultBindings, EventNameOf } from "../../bindings/types";
8
+ import type { NatsBridgeOptions, NatsBridge } from "../../bridge/nats";
9
+ import type { ClusterTransport, ClusterStateStore, RedisConnectionOptions } from "./cluster";
10
+ import type { EventClient } from "./client";
11
+ import type { DeliveryPolicy } from "../delivery";
12
+
13
+ /**
14
+ * `createServer({ events: EventsOptions })` — enables the events layer and
15
+ * exposes it as `server.events`. The module-global `emit` / `on` singleton is
16
+ * bound by default (`global: false` to opt out).
17
+ */
18
+ export interface EventsOptions<B extends Bindings = DefaultBindings> {
19
+ /**
20
+ * App events clients are allowed to send to the hub. Default: every event
21
+ * registered via `hub.on(...)` is auto-allowed on first use.
22
+ */
23
+ inbound?: EventNameOf<B>[];
24
+ /** bind the module-global `emit`/`on` singleton (default true) */
25
+ global?: boolean;
26
+ /** called after a connection's client record is attached (seed `data`, …) */
27
+ onConnect?: (client: EventClient) => void;
28
+ /** called after a connection's client record is detached (cleanup) */
29
+ onDisconnect?: (client: EventClient) => void;
30
+ /** handler reliability: retries with backoff + dead-letter sink (default off) */
31
+ handlers?: DeliveryPolicy;
32
+ /** horizontal-scaling sync (server ⇄ server) */
33
+ cluster?: EventsClusterOptions;
34
+ /** offload-queue limits (the queue keeps cluster/state work off hot paths) */
35
+ queue?: { workers?: number; maxPending?: number };
36
+ }
37
+
38
+ export interface EventsClusterOptions {
39
+ /** stable id of this instance (default: random UUID) — self-dedupe */
40
+ instanceId?: string;
41
+ /** subject prefix (default: bindings subject prefix or "ignex") */
42
+ prefix?: string;
43
+ /**
44
+ * NATS-based cluster messaging. `true` reuses the server's NATS bridge
45
+ * connection (set `options.nats` too); pass `NatsBridgeOptions` to create a
46
+ * dedicated bridge; pass a `NatsBridge` to reuse an existing one.
47
+ */
48
+ nats?: boolean | NatsBridgeOptions | NatsBridge;
49
+ /** Redis pub/sub cluster messaging (lazy `ioredis`; subjects mirror NATS) */
50
+ redis?: RedisConnectionOptions;
51
+ /** pluggable messaging transport (tests / custom brokers) */
52
+ transport?: ClusterTransport;
53
+ /**
54
+ * Shared-state store for presence / cluster group membership / client data.
55
+ * Default: per-instance memory. Production: `createRedisStateStore(...)`.
56
+ */
57
+ state?: ClusterStateStore;
58
+ /** presence re-announce + prune cadence (ms, default 15_000) */
59
+ heartbeatMs?: number;
60
+ /** remote presence TTL (ms, default 60_000) */
61
+ presenceTtlMs?: number;
62
+ }
@@ -1,4 +1,5 @@
1
- // @generated by scripts/direct-gen.ts DO NOT EDIT
1
+ // @ts-nocheck — generated file: not subject to hand-typed strictness gates
2
+ // @generated by src/codegen/direct-gen.ts — DO NOT EDIT
2
3
  import { encodeUtf8Into, ensureCapacity, utf8Len } from "../native/codec";
3
4
  import { checkInt64 } from "../core/int64-guard";
4
5
  import { anyEventNameToId, WIRE_VERSION, WIRE_HEADER_LEN } from "./registry";
@@ -10,62 +11,78 @@ export type DirectCall = (...args: unknown[]) => number;
10
11
  * output tail `(ptr, usize)` is upgraded to `(buffer, buffer_length)` by
11
12
  * the `abi()` transformer in `src/native/ffi.ts` when supported). */
12
13
  export const directSymbols = {
13
- fb_quote_serialize: {
14
+ "fb_quote_serialize": {
14
15
  args: ["cstring", "f64", "f64", "i64", "i64", "i64", "ptr", "usize"],
15
16
  returns: "u64_fast",
16
17
  },
17
- fb_trade_serialize: {
18
+ "fb_trade_serialize": {
18
19
  args: ["cstring", "f64", "i64", "u32", "i64", "ptr", "usize"],
19
20
  returns: "u64_fast",
20
21
  },
21
- fb_portfolio_serialize: {
22
+ "fb_portfolio_serialize": {
22
23
  args: ["cstring", "buffer", "usize", "f64", "f64", "i64", "cstring", "ptr", "usize"],
23
24
  returns: "u64_fast",
24
25
  },
25
- fb_complex_serialize: {
26
+ "fb_complex_serialize": {
26
27
  args: ["cstring", "buffer", "usize", "buffer", "usize", "buffer", "usize", "buffer", "usize", "buffer", "usize", "u8", "f64", "i64", "ptr", "usize"],
27
28
  returns: "u64_fast",
28
29
  },
29
- fb_big_val_serialize: {
30
+ "fb_big_val_serialize": {
30
31
  args: ["cstring", "i64", "i64", "ptr", "usize"],
31
32
  returns: "u64_fast",
32
33
  },
33
- fb_hello_serialize: {
34
+ "fb_hello_serialize": {
34
35
  args: ["i64", "buffer", "usize", "i64", "ptr", "usize"],
35
36
  returns: "u64_fast",
36
37
  },
37
- fb_welcome_serialize: {
38
+ "fb_welcome_serialize": {
38
39
  args: ["cstring", "buffer", "usize", "ptr", "usize"],
39
40
  returns: "u64_fast",
40
41
  },
41
- fb_subscribe_serialize: {
42
+ "fb_subscribe_serialize": {
42
43
  args: ["cstring", "ptr", "usize"],
43
44
  returns: "u64_fast",
44
45
  },
45
- fb_unsubscribe_serialize: {
46
+ "fb_unsubscribe_serialize": {
46
47
  args: ["cstring", "ptr", "usize"],
47
48
  returns: "u64_fast",
48
49
  },
49
- fb_join_group_serialize: {
50
+ "fb_join_group_serialize": {
50
51
  args: ["cstring", "ptr", "usize"],
51
52
  returns: "u64_fast",
52
53
  },
53
- fb_leave_group_serialize: {
54
+ "fb_leave_group_serialize": {
54
55
  args: ["cstring", "ptr", "usize"],
55
56
  returns: "u64_fast",
56
57
  },
57
- fb_snapshot_request_serialize: {
58
- args: ["cstring", "ptr", "usize"],
58
+ "fb_snapshot_request_serialize": {
59
+ args: ["cstring", "i64", "ptr", "usize"],
59
60
  returns: "u64_fast",
60
61
  },
61
- fb_ping_serialize: {
62
+ "fb_ping_serialize": {
62
63
  args: ["i64", "ptr", "usize"],
63
64
  returns: "u64_fast",
64
65
  },
65
- fb_pong_serialize: {
66
+ "fb_pong_serialize": {
66
67
  args: ["i64", "ptr", "usize"],
67
68
  returns: "u64_fast",
68
69
  },
70
+ "fb_resume_serialize": {
71
+ args: ["i64", "ptr", "usize"],
72
+ returns: "u64_fast",
73
+ },
74
+ "fb_resumed_serialize": {
75
+ args: ["u8", "i64", "ptr", "usize"],
76
+ returns: "u64_fast",
77
+ },
78
+ "fb_rpc_call_serialize": {
79
+ args: ["cstring", "cstring", "cstring", "ptr", "usize"],
80
+ returns: "u64_fast",
81
+ },
82
+ "fb_rpc_result_serialize": {
83
+ args: ["cstring", "u8", "cstring", "cstring", "ptr", "usize"],
84
+ returns: "u64_fast",
85
+ },
69
86
  } as const;
70
87
 
71
88
  /** sample objects for the bind-time self-test (representative values). */
@@ -81,9 +98,13 @@ const directSamples: Record<string, unknown> = {
81
98
  "unsubscribe": { "topic": "SELFTEST" },
82
99
  "joinGroup": { "group": "SELFTEST" },
83
100
  "leaveGroup": { "group": "SELFTEST" },
84
- "snapshotRequest": { "topic": "SELFTEST" },
101
+ "snapshotRequest": { "topic": "SELFTEST", "fromSeq": 123456 },
85
102
  "ping": { "ts": 123456 },
86
103
  "pong": { "ts": 123456 },
104
+ "resume": { "lastSeq": 123456 },
105
+ "resumed": { "ok": true, "from": 123456 },
106
+ "rpcCall": { "id": "SELFTEST", "name": "SELFTEST", "payloadB64": "SELFTEST" },
107
+ "rpcResult": { "id": "SELFTEST", "ok": true, "err": "SELFTEST", "payloadB64": "SELFTEST" },
87
108
  } as const;
88
109
 
89
110
  /** grow the packer scratch, write the u32 count, return the DataView. */
@@ -291,7 +312,8 @@ export function encodeLeaveGroup(call: DirectCall, o: unknown, out: Uint8Array):
291
312
  /** zero-alloc encoder: fields straight into the (reusable) out buffer. */
292
313
  export function encodeSnapshotRequest(call: DirectCall, o: unknown, out: Uint8Array): number {
293
314
  const p = o as ControlEvents["snapshotRequest"];
294
- return call(p.topic, out, out) as number;
315
+ checkInt64("snapshotRequest.fromSeq", p.fromSeq);
316
+ return call(p.topic, p.fromSeq, out, out) as number;
295
317
  }
296
318
 
297
319
  /** zero-alloc encoder: fields straight into the (reusable) out buffer. */
@@ -308,6 +330,32 @@ export function encodePong(call: DirectCall, o: unknown, out: Uint8Array): numbe
308
330
  return call(p.ts, out, out) as number;
309
331
  }
310
332
 
333
+ /** zero-alloc encoder: fields straight into the (reusable) out buffer. */
334
+ export function encodeResume(call: DirectCall, o: unknown, out: Uint8Array): number {
335
+ const p = o as ControlEvents["resume"];
336
+ checkInt64("resume.lastSeq", p.lastSeq);
337
+ return call(p.lastSeq, out, out) as number;
338
+ }
339
+
340
+ /** zero-alloc encoder: fields straight into the (reusable) out buffer. */
341
+ export function encodeResumed(call: DirectCall, o: unknown, out: Uint8Array): number {
342
+ const p = o as ControlEvents["resumed"];
343
+ checkInt64("resumed.from", p.from);
344
+ return call(p.ok ? 1 : 0, p.from, out, out) as number;
345
+ }
346
+
347
+ /** zero-alloc encoder: fields straight into the (reusable) out buffer. */
348
+ export function encodeRpcCall(call: DirectCall, o: unknown, out: Uint8Array): number {
349
+ const p = o as ControlEvents["rpcCall"];
350
+ return call(p.id, p.name, p.payloadB64, out, out) as number;
351
+ }
352
+
353
+ /** zero-alloc encoder: fields straight into the (reusable) out buffer. */
354
+ export function encodeRpcResult(call: DirectCall, o: unknown, out: Uint8Array): number {
355
+ const p = o as ControlEvents["rpcResult"];
356
+ return call(p.id, p.ok ? 1 : 0, p.err, p.payloadB64, out, out) as number;
357
+ }
358
+
311
359
  function hasNulQuote(o: unknown): boolean {
312
360
  const p = o as Events["quote"];
313
361
  return (
@@ -406,58 +454,98 @@ function hasNulPong(o: unknown): boolean {
406
454
  return false;
407
455
  }
408
456
 
457
+ function hasNulResume(o: unknown): boolean {
458
+ const p = o as ControlEvents["resume"];
459
+ return false;
460
+ }
461
+
462
+ function hasNulResumed(o: unknown): boolean {
463
+ const p = o as ControlEvents["resumed"];
464
+ return false;
465
+ }
466
+
467
+ function hasNulRpcCall(o: unknown): boolean {
468
+ const p = o as ControlEvents["rpcCall"];
469
+ return (
470
+ (typeof p.id === "string" && p.id.includes("\0")) ||
471
+ (typeof p.name === "string" && p.name.includes("\0")) ||
472
+ (typeof p.payloadB64 === "string" && p.payloadB64.includes("\0"))
473
+ );
474
+ }
475
+
476
+ function hasNulRpcResult(o: unknown): boolean {
477
+ const p = o as ControlEvents["rpcResult"];
478
+ return (
479
+ (typeof p.id === "string" && p.id.includes("\0")) ||
480
+ (typeof p.err === "string" && p.err.includes("\0")) ||
481
+ (typeof p.payloadB64 === "string" && p.payloadB64.includes("\0"))
482
+ );
483
+ }
484
+
409
485
  /** per-event NUL pre-scan — true routes the payload to the JSON path (cstring truncates `\0`). */
410
486
  export const hasNulEncoders: Partial<Record<AnyEventName, (o: unknown) => boolean>> = {
411
- quote: hasNulQuote,
412
- trade: hasNulTrade,
413
- portfolio: hasNulPortfolio,
414
- complex: hasNulComplex,
415
- bigVal: hasNulBigVal,
416
- hello: hasNulHello,
417
- welcome: hasNulWelcome,
418
- subscribe: hasNulSubscribe,
419
- unsubscribe: hasNulUnsubscribe,
420
- joinGroup: hasNulJoinGroup,
421
- leaveGroup: hasNulLeaveGroup,
422
- snapshotRequest: hasNulSnapshotRequest,
423
- ping: hasNulPing,
424
- pong: hasNulPong,
487
+ "quote": hasNulQuote,
488
+ "trade": hasNulTrade,
489
+ "portfolio": hasNulPortfolio,
490
+ "complex": hasNulComplex,
491
+ "bigVal": hasNulBigVal,
492
+ "hello": hasNulHello,
493
+ "welcome": hasNulWelcome,
494
+ "subscribe": hasNulSubscribe,
495
+ "unsubscribe": hasNulUnsubscribe,
496
+ "joinGroup": hasNulJoinGroup,
497
+ "leaveGroup": hasNulLeaveGroup,
498
+ "snapshotRequest": hasNulSnapshotRequest,
499
+ "ping": hasNulPing,
500
+ "pong": hasNulPong,
501
+ "resume": hasNulResume,
502
+ "resumed": hasNulResumed,
503
+ "rpcCall": hasNulRpcCall,
504
+ "rpcResult": hasNulRpcResult,
425
505
  };
426
506
 
427
507
  export const directSymbolNames: Partial<Record<AnyEventName, string>> = {
428
- quote: "fb_quote_serialize",
429
- trade: "fb_trade_serialize",
430
- portfolio: "fb_portfolio_serialize",
431
- complex: "fb_complex_serialize",
432
- bigVal: "fb_big_val_serialize",
433
- hello: "fb_hello_serialize",
434
- welcome: "fb_welcome_serialize",
435
- subscribe: "fb_subscribe_serialize",
436
- unsubscribe: "fb_unsubscribe_serialize",
437
- joinGroup: "fb_join_group_serialize",
438
- leaveGroup: "fb_leave_group_serialize",
439
- snapshotRequest: "fb_snapshot_request_serialize",
440
- ping: "fb_ping_serialize",
441
- pong: "fb_pong_serialize",
508
+ "quote": "fb_quote_serialize",
509
+ "trade": "fb_trade_serialize",
510
+ "portfolio": "fb_portfolio_serialize",
511
+ "complex": "fb_complex_serialize",
512
+ "bigVal": "fb_big_val_serialize",
513
+ "hello": "fb_hello_serialize",
514
+ "welcome": "fb_welcome_serialize",
515
+ "subscribe": "fb_subscribe_serialize",
516
+ "unsubscribe": "fb_unsubscribe_serialize",
517
+ "joinGroup": "fb_join_group_serialize",
518
+ "leaveGroup": "fb_leave_group_serialize",
519
+ "snapshotRequest": "fb_snapshot_request_serialize",
520
+ "ping": "fb_ping_serialize",
521
+ "pong": "fb_pong_serialize",
522
+ "resume": "fb_resume_serialize",
523
+ "resumed": "fb_resumed_serialize",
524
+ "rpcCall": "fb_rpc_call_serialize",
525
+ "rpcResult": "fb_rpc_result_serialize",
442
526
  };
443
527
 
444
528
  export type DirectEncoder = (call: DirectCall, o: unknown, out: Uint8Array) => number;
445
529
 
446
530
  export const directEncoders: Partial<Record<AnyEventName, DirectEncoder>> = {
447
- quote: encodeQuote,
448
- trade: encodeTrade,
449
- portfolio: encodePortfolio,
450
- complex: encodeComplex,
451
- bigVal: encodeBigVal,
452
- hello: encodeHello,
453
- welcome: encodeWelcome,
454
- subscribe: encodeSubscribe,
455
- unsubscribe: encodeUnsubscribe,
456
- joinGroup: encodeJoinGroup,
457
- leaveGroup: encodeLeaveGroup,
458
- snapshotRequest: encodeSnapshotRequest,
459
- ping: encodePing,
460
- pong: encodePong,
531
+ "quote": encodeQuote,
532
+ "trade": encodeTrade,
533
+ "portfolio": encodePortfolio,
534
+ "complex": encodeComplex,
535
+ "bigVal": encodeBigVal,
536
+ "hello": encodeHello,
537
+ "welcome": encodeWelcome,
538
+ "subscribe": encodeSubscribe,
539
+ "unsubscribe": encodeUnsubscribe,
540
+ "joinGroup": encodeJoinGroup,
541
+ "leaveGroup": encodeLeaveGroup,
542
+ "snapshotRequest": encodeSnapshotRequest,
543
+ "ping": encodePing,
544
+ "pong": encodePong,
545
+ "resume": encodeResume,
546
+ "resumed": encodeResumed,
547
+ "rpcCall": encodeRpcCall,
548
+ "rpcResult": encodeRpcResult,
461
549
  };
462
550
 
463
551
  /**
@@ -1,4 +1,4 @@
1
- // @generated by scripts/typebox-to-fbs.ts — DO NOT EDIT
1
+ // @generated by src/codegen/typebox-to-fbs.ts — DO NOT EDIT
2
2
  // FlatBuffers schema derived from the TypeBox events registry (schema/index.ts).
3
3
 
4
4
  file_identifier "IGNX";
@@ -128,6 +128,7 @@ table LeaveGroup {
128
128
 
129
129
  table SnapshotRequest {
130
130
  topic:string;
131
+ from_seq:int64;
131
132
  }
132
133
 
133
134
  table Ping {
@@ -137,3 +138,25 @@ table Ping {
137
138
  table Pong {
138
139
  ts:int64;
139
140
  }
141
+
142
+ table Resume {
143
+ last_seq:int64;
144
+ }
145
+
146
+ table Resumed {
147
+ ok:bool;
148
+ from:int64;
149
+ }
150
+
151
+ table RpcCall {
152
+ id:string;
153
+ name:string;
154
+ payload_b64:string;
155
+ }
156
+
157
+ table RpcResult {
158
+ id:string;
159
+ ok:bool;
160
+ err:string;
161
+ payload_b64:string;
162
+ }
@@ -1,4 +1,5 @@
1
- // @generated by scripts/registry-gen.ts DO NOT EDIT
1
+ // @ts-nocheck — generated file: not subject to hand-typed strictness gates
2
+ // @generated by src/codegen/registry-gen.ts — DO NOT EDIT
2
3
  import * as flatbuffers from "flatbuffers";
3
4
  import { pooledByteBuffer } from "../transport/byte-buffer-pool";
4
5
 
@@ -22,6 +23,10 @@ import {
22
23
  SnapshotRequest,
23
24
  Ping,
24
25
  Pong,
26
+ Resume,
27
+ Resumed,
28
+ RpcCall,
29
+ RpcResult,
25
30
  type QuoteT,
26
31
  type TradeT,
27
32
  type PortfolioSnapshotT,
@@ -41,50 +46,63 @@ import {
41
46
  type SnapshotRequestT,
42
47
  type PingT,
43
48
  type PongT,
49
+ type ResumeT,
50
+ type ResumedT,
51
+ type RpcCallT,
52
+ type RpcResultT,
44
53
  } from "./ts/backend";
45
54
  import type { AnyEventName, ControlEventName, ControlEvents, Events, EventName } from "../schema";
46
55
 
47
- export const WIRE_VERSION = 1;
48
- export const WIRE_HEADER_LEN = 5; // [version:1][event_id:u32 LE]
56
+ export const WIRE_VERSION = 2;
57
+ export const WIRE_HEADER_LEN = 14; // [version:1][event_id:u32 LE]
58
+ export const SCHEMA_FINGERPRINT = 3647747841; // fnv1a32(canonical model)
49
59
 
50
60
  export const eventNameToId: Record<EventName, number> = {
51
- quote: 2995289047, // fnv1a32("quote")
52
- trade: 1362521689, // fnv1a32("trade")
53
- portfolio: 464274147, // fnv1a32("portfolio")
54
- complex: 2318166199, // fnv1a32("complex")
55
- order: 1932267671, // fnv1a32("order")
56
- bigVal: 3211729064, // fnv1a32("bigVal")
61
+ "quote": 2995289047, // fnv1a32("quote")
62
+ "trade": 1362521689, // fnv1a32("trade")
63
+ "portfolio": 464274147, // fnv1a32("portfolio")
64
+ "complex": 2318166199, // fnv1a32("complex")
65
+ "order": 1932267671, // fnv1a32("order")
66
+ "bigVal": 3211729064, // fnv1a32("bigVal")
57
67
  };
58
68
 
59
69
  export const controlEventNameToId: Record<ControlEventName, number> = {
60
- hello: 1335831723, // fnv1a32("hello")
61
- welcome: 669089267, // fnv1a32("welcome")
62
- subscribe: 2946386435, // fnv1a32("subscribe")
63
- unsubscribe: 4190043798, // fnv1a32("unsubscribe")
64
- joinGroup: 3026600144, // fnv1a32("joinGroup")
65
- leaveGroup: 3755061443, // fnv1a32("leaveGroup")
66
- snapshotRequest: 1249175018, // fnv1a32("snapshotRequest")
67
- ping: 375255177, // fnv1a32("ping")
68
- pong: 2061178551, // fnv1a32("pong")
70
+ "hello": 1335831723, // fnv1a32("hello")
71
+ "welcome": 669089267, // fnv1a32("welcome")
72
+ "subscribe": 2946386435, // fnv1a32("subscribe")
73
+ "unsubscribe": 4190043798, // fnv1a32("unsubscribe")
74
+ "joinGroup": 3026600144, // fnv1a32("joinGroup")
75
+ "leaveGroup": 3755061443, // fnv1a32("leaveGroup")
76
+ "snapshotRequest": 1249175018, // fnv1a32("snapshotRequest")
77
+ "ping": 375255177, // fnv1a32("ping")
78
+ "pong": 2061178551, // fnv1a32("pong")
79
+ "resume": 4281967466, // fnv1a32("resume")
80
+ "resumed": 3585847050, // fnv1a32("resumed")
81
+ "rpcCall": 986404564, // fnv1a32("rpcCall")
82
+ "rpcResult": 648609069, // fnv1a32("rpcResult")
69
83
  };
70
84
 
71
85
  /** merged app + control registry (used by encodeToScratch / JS encoder). */
72
86
  export const anyEventNameToId: Record<string, number> = {
73
- quote: 2995289047,
74
- trade: 1362521689,
75
- portfolio: 464274147,
76
- complex: 2318166199,
77
- order: 1932267671,
78
- bigVal: 3211729064,
79
- hello: 1335831723,
80
- welcome: 669089267,
81
- subscribe: 2946386435,
82
- unsubscribe: 4190043798,
83
- joinGroup: 3026600144,
84
- leaveGroup: 3755061443,
85
- snapshotRequest: 1249175018,
86
- ping: 375255177,
87
- pong: 2061178551,
87
+ "quote": 2995289047,
88
+ "trade": 1362521689,
89
+ "portfolio": 464274147,
90
+ "complex": 2318166199,
91
+ "order": 1932267671,
92
+ "bigVal": 3211729064,
93
+ "hello": 1335831723,
94
+ "welcome": 669089267,
95
+ "subscribe": 2946386435,
96
+ "unsubscribe": 4190043798,
97
+ "joinGroup": 3026600144,
98
+ "leaveGroup": 3755061443,
99
+ "snapshotRequest": 1249175018,
100
+ "ping": 375255177,
101
+ "pong": 2061178551,
102
+ "resume": 4281967466,
103
+ "resumed": 3585847050,
104
+ "rpcCall": 986404564,
105
+ "rpcResult": 648609069,
88
106
  };
89
107
 
90
108
  export const idToEventName: Record<number, EventName> = {
@@ -113,6 +131,10 @@ export const idToAnyEventName: Record<number, AnyEventName> = {
113
131
  1249175018: "snapshotRequest",
114
132
  375255177: "ping",
115
133
  2061178551: "pong",
134
+ 4281967466: "resume",
135
+ 3585847050: "resumed",
136
+ 986404564: "rpcCall",
137
+ 648609069: "rpcResult",
116
138
  };
117
139
 
118
140
  export type DecodeFn = (bb: flatbuffers.ByteBuffer) => unknown;
@@ -133,6 +155,10 @@ export const eventIdToDecoder: Record<number, DecodeFn> = {
133
155
  1249175018: (bb) => snapshot_requestToPlain(SnapshotRequest.getSizePrefixedRootAsSnapshotRequest(bb).unpack()),
134
156
  375255177: (bb) => pingToPlain(Ping.getSizePrefixedRootAsPing(bb).unpack()),
135
157
  2061178551: (bb) => pongToPlain(Pong.getSizePrefixedRootAsPong(bb).unpack()),
158
+ 4281967466: (bb) => resumeToPlain(Resume.getSizePrefixedRootAsResume(bb).unpack()),
159
+ 3585847050: (bb) => resumedToPlain(Resumed.getSizePrefixedRootAsResumed(bb).unpack()),
160
+ 986404564: (bb) => rpc_callToPlain(RpcCall.getSizePrefixedRootAsRpcCall(bb).unpack()),
161
+ 648609069: (bb) => rpc_resultToPlain(RpcResult.getSizePrefixedRootAsRpcResult(bb).unpack()),
136
162
  };
137
163
 
138
164
  const controlIds = new Set<number>([
@@ -145,6 +171,10 @@ const controlIds = new Set<number>([
145
171
  1249175018,
146
172
  375255177,
147
173
  2061178551,
174
+ 4281967466,
175
+ 3585847050,
176
+ 986404564,
177
+ 648609069,
148
178
  ]);
149
179
  export function isControlId(id: number): boolean { return controlIds.has(id); }
150
180
 
@@ -325,6 +355,7 @@ function leave_groupToPlain(o: LeaveGroupT): ControlEvents["leaveGroup"] {
325
355
  function snapshot_requestToPlain(o: SnapshotRequestT): ControlEvents["snapshotRequest"] {
326
356
  return {
327
357
  topic: str(o.topic),
358
+ fromSeq: Number(o.fromSeq),
328
359
  };
329
360
  }
330
361
 
@@ -339,3 +370,33 @@ function pongToPlain(o: PongT): ControlEvents["pong"] {
339
370
  ts: Number(o.ts),
340
371
  };
341
372
  }
373
+
374
+ function resumeToPlain(o: ResumeT): ControlEvents["resume"] {
375
+ return {
376
+ lastSeq: Number(o.lastSeq),
377
+ };
378
+ }
379
+
380
+ function resumedToPlain(o: ResumedT): ControlEvents["resumed"] {
381
+ return {
382
+ ok: o.ok,
383
+ from: Number(o.from),
384
+ };
385
+ }
386
+
387
+ function rpc_callToPlain(o: RpcCallT): ControlEvents["rpcCall"] {
388
+ return {
389
+ id: str(o.id),
390
+ name: str(o.name),
391
+ payloadB64: str(o.payloadB64),
392
+ };
393
+ }
394
+
395
+ function rpc_resultToPlain(o: RpcResultT): ControlEvents["rpcResult"] {
396
+ return {
397
+ id: str(o.id),
398
+ ok: o.ok,
399
+ err: str(o.err),
400
+ payloadB64: str(o.payloadB64),
401
+ };
402
+ }