@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.
- package/README.md +136 -33
- package/docs/ai/LOCAL_DEV.md +81 -0
- package/docs/ai/TREE.md +292 -0
- package/docs/architecture.md +101 -28
- package/docs/events.md +252 -0
- package/docs/generic-bindings.md +207 -0
- package/docs/publishing.md +2 -2
- package/docs/wire-format.md +74 -20
- package/index.ts +75 -27
- package/package.json +13 -2
- package/prebuilds/linux-x64/libignex_ffi.so +0 -0
- package/public/bindings.ts +24 -0
- package/public/client.ts +5 -1
- package/public/events.ts +71 -0
- package/public/generate.ts +510 -0
- package/public/internal.ts +16 -0
- package/public/nats.ts +9 -5
- package/public/server.ts +52 -16
- package/rust/src/ffi.rs +10 -0
- package/rust/src/generated/backend.rs +503 -0
- package/rust/src/transcode/generated.rs +377 -17
- package/src/bindings/assemble.ts +73 -0
- package/src/bindings/default.ts +65 -0
- package/src/bindings/types.ts +113 -0
- package/src/bridge/nats/inbound.ts +46 -0
- package/src/bridge/nats/index.ts +131 -0
- package/src/bridge/nats/real-transport.ts +133 -0
- package/src/bridge/nats/types.ts +80 -0
- package/src/bridge/subjects.ts +3 -0
- package/src/codegen/constants.ts +28 -0
- package/src/codegen/direct-gen.ts +564 -0
- package/src/codegen/fingerprint.ts +44 -0
- package/src/codegen/hash.ts +25 -0
- package/src/codegen/registry-gen.ts +246 -0
- package/src/codegen/rust-glue-gen.ts +552 -0
- package/src/codegen/schema-model.ts +363 -0
- package/src/codegen/ts-ser-gen.ts +230 -0
- package/src/codegen/typebox-to-fbs.ts +60 -0
- package/src/core/auth.ts +67 -5
- package/src/core/client-heartbeat.ts +2 -1
- package/src/core/client-reconnect.ts +9 -2
- package/src/core/client-rpc.ts +75 -0
- package/src/core/client-state.ts +63 -8
- package/src/core/client-wire.ts +148 -15
- package/src/core/client.ts +105 -31
- package/src/core/groups.ts +8 -0
- package/src/core/metrics.ts +42 -21
- package/src/core/outbound.ts +62 -11
- package/src/core/rate-limit.ts +69 -0
- package/src/core/replay.ts +41 -1
- package/src/core/resume.ts +181 -0
- package/src/core/rooms.ts +10 -3
- package/src/core/routing.ts +144 -12
- package/src/core/server/client-info.ts +37 -0
- package/src/core/server/http-routes.ts +59 -0
- package/src/core/server/index.ts +360 -0
- package/src/core/server/metrics-view.ts +53 -0
- package/src/core/server/socket-lifecycle.ts +57 -0
- package/src/core/state.ts +124 -14
- package/src/core/topic-log.ts +86 -0
- package/src/events/clients.ts +174 -0
- package/src/events/cluster/dedupe.ts +43 -0
- package/src/events/cluster/envelope.ts +149 -0
- package/src/events/cluster/index.ts +50 -0
- package/src/events/cluster/keys.ts +33 -0
- package/src/events/cluster/kinds.ts +32 -0
- package/src/events/cluster/presence-table.ts +99 -0
- package/src/events/cluster/presence.ts +53 -0
- package/src/events/cluster/redis-client.ts +50 -0
- package/src/events/cluster/store-memory.ts +67 -0
- package/src/events/cluster/store-redis.ts +44 -0
- package/src/events/cluster/subjects.ts +30 -0
- package/src/events/cluster/sync.ts +476 -0
- package/src/events/cluster/transport-nats.ts +24 -0
- package/src/events/cluster/transport-redis.ts +120 -0
- package/src/events/cluster-rpc.ts +196 -0
- package/src/events/data.ts +38 -0
- package/src/events/delivery.ts +83 -0
- package/src/events/emit.ts +173 -0
- package/src/events/global.ts +117 -0
- package/src/events/groups.ts +118 -0
- package/src/events/hub/context-factory.ts +79 -0
- package/src/events/hub/dispatch.ts +86 -0
- package/src/events/hub/index.ts +536 -0
- package/src/events/hub/internal.ts +31 -0
- package/src/events/hub/metrics-snapshot.ts +84 -0
- package/src/events/hub/resolve-cluster.ts +49 -0
- package/src/events/index.ts +61 -0
- package/src/events/queue.ts +123 -0
- package/src/events/registry.ts +214 -0
- package/src/events/schedule.ts +73 -0
- package/src/events/trace.ts +283 -0
- package/src/events/types/client.ts +68 -0
- package/src/events/types/cluster.ts +40 -0
- package/src/events/types/context.ts +50 -0
- package/src/events/types/emit-target.ts +29 -0
- package/src/events/types/groups.ts +35 -0
- package/src/events/types/hub.ts +124 -0
- package/src/events/types/index.ts +30 -0
- package/src/events/types/metrics.ts +52 -0
- package/src/events/types/options.ts +62 -0
- package/src/generated/direct-ser.ts +148 -60
- package/src/generated/fbs/backend.fbs +24 -1
- package/src/generated/registry.ts +94 -33
- package/src/generated/rust/backend_generated.rs +503 -0
- package/src/generated/ts/backend.ts +4 -0
- package/src/generated/ts/resume.ts +74 -0
- package/src/generated/ts/resumed.ts +88 -0
- package/src/generated/ts/rpc-call.ts +112 -0
- package/src/generated/ts/rpc-result.ts +126 -0
- package/src/generated/ts/snapshot-request.ts +19 -5
- package/src/generated/ts-ser.ts +110 -17
- package/src/generated/wire-registry.json +7 -2
- package/src/native/ffi.ts +85 -28
- package/src/schema/index.ts +49 -2
- package/src/server.ts +7 -3
- package/src/transport/transport.ts +200 -79
- package/src/bridge/nats.ts +0 -269
- package/src/core/server.ts +0 -294
- 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
|
|
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
|
-
|
|
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
|
|
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
|
|
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 =
|
|
48
|
-
export const WIRE_HEADER_LEN =
|
|
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
|
+
}
|