@ignex/nova 0.1.1
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/LICENSE +21 -0
- package/README.md +313 -0
- package/docs/architecture.md +146 -0
- package/docs/publishing.md +119 -0
- package/docs/wire-format.md +170 -0
- package/index.ts +61 -0
- package/package.json +89 -0
- package/prebuilds/linux-x64/libignex_ffi.so +0 -0
- package/public/client.ts +23 -0
- package/public/nats.ts +19 -0
- package/public/server.ts +35 -0
- package/rust/Cargo.toml +19 -0
- package/rust/src/ffi.rs +135 -0
- package/rust/src/generated/backend.rs +2817 -0
- package/rust/src/generated/mod.rs +2 -0
- package/rust/src/lib.rs +9 -0
- package/rust/src/transcode/generated.rs +1352 -0
- package/rust/src/transcode/mod.rs +2 -0
- package/src/bridge/nats.ts +269 -0
- package/src/bridge/subjects.ts +30 -0
- package/src/core/auth.ts +56 -0
- package/src/core/backpressure.ts +39 -0
- package/src/core/client-heartbeat.ts +27 -0
- package/src/core/client-reconnect.ts +35 -0
- package/src/core/client-state.ts +76 -0
- package/src/core/client-wire.ts +72 -0
- package/src/core/client.ts +176 -0
- package/src/core/groups.ts +52 -0
- package/src/core/int64-guard.ts +44 -0
- package/src/core/metrics.ts +105 -0
- package/src/core/outbound.ts +76 -0
- package/src/core/replay.ts +31 -0
- package/src/core/ring.ts +85 -0
- package/src/core/rooms.ts +44 -0
- package/src/core/routing.ts +94 -0
- package/src/core/server.ts +294 -0
- package/src/core/state.ts +179 -0
- package/src/generated/direct-ser.ts +495 -0
- package/src/generated/fbs/backend.fbs +139 -0
- package/src/generated/registry.ts +341 -0
- package/src/generated/rust/backend_generated.rs +2817 -0
- package/src/generated/ts/backend.ts +25 -0
- package/src/generated/ts/big-val.ts +106 -0
- package/src/generated/ts/complex.ts +303 -0
- package/src/generated/ts/customer.ts +137 -0
- package/src/generated/ts/hello.ts +123 -0
- package/src/generated/ts/join-group.ts +78 -0
- package/src/generated/ts/leave-group.ts +78 -0
- package/src/generated/ts/order-billing.ts +137 -0
- package/src/generated/ts/order-line.ts +144 -0
- package/src/generated/ts/order.ts +236 -0
- package/src/generated/ts/ping.ts +74 -0
- package/src/generated/ts/pong.ts +74 -0
- package/src/generated/ts/portfolio-position.ts +120 -0
- package/src/generated/ts/portfolio-snapshot.ts +170 -0
- package/src/generated/ts/quote.ts +148 -0
- package/src/generated/ts/side.ts +8 -0
- package/src/generated/ts/snapshot-request.ts +78 -0
- package/src/generated/ts/subscribe.ts +78 -0
- package/src/generated/ts/tags.ts +9 -0
- package/src/generated/ts/trade.ts +135 -0
- package/src/generated/ts/unsubscribe.ts +78 -0
- package/src/generated/ts/welcome.ts +112 -0
- package/src/generated/ts-ser.ts +465 -0
- package/src/generated/wire-registry.json +20 -0
- package/src/native/codec.ts +35 -0
- package/src/native/ffi.ts +214 -0
- package/src/native/loader.ts +55 -0
- package/src/schema/index.ts +217 -0
- package/src/server.ts +87 -0
- package/src/transport/byte-buffer-pool.ts +63 -0
- package/src/transport/scratch.ts +48 -0
- package/src/transport/stats.ts +44 -0
- package/src/transport/transport.ts +106 -0
|
@@ -0,0 +1,341 @@
|
|
|
1
|
+
// @generated by scripts/registry-gen.ts — DO NOT EDIT
|
|
2
|
+
import * as flatbuffers from "flatbuffers";
|
|
3
|
+
import { pooledByteBuffer } from "../transport/byte-buffer-pool";
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
Quote,
|
|
7
|
+
Trade,
|
|
8
|
+
PortfolioSnapshot,
|
|
9
|
+
PortfolioPosition,
|
|
10
|
+
Complex,
|
|
11
|
+
Order,
|
|
12
|
+
Customer,
|
|
13
|
+
OrderLine,
|
|
14
|
+
OrderBilling,
|
|
15
|
+
BigVal,
|
|
16
|
+
Hello,
|
|
17
|
+
Welcome,
|
|
18
|
+
Subscribe,
|
|
19
|
+
Unsubscribe,
|
|
20
|
+
JoinGroup,
|
|
21
|
+
LeaveGroup,
|
|
22
|
+
SnapshotRequest,
|
|
23
|
+
Ping,
|
|
24
|
+
Pong,
|
|
25
|
+
type QuoteT,
|
|
26
|
+
type TradeT,
|
|
27
|
+
type PortfolioSnapshotT,
|
|
28
|
+
type PortfolioPositionT,
|
|
29
|
+
type ComplexT,
|
|
30
|
+
type OrderT,
|
|
31
|
+
type CustomerT,
|
|
32
|
+
type OrderLineT,
|
|
33
|
+
type OrderBillingT,
|
|
34
|
+
type BigValT,
|
|
35
|
+
type HelloT,
|
|
36
|
+
type WelcomeT,
|
|
37
|
+
type SubscribeT,
|
|
38
|
+
type UnsubscribeT,
|
|
39
|
+
type JoinGroupT,
|
|
40
|
+
type LeaveGroupT,
|
|
41
|
+
type SnapshotRequestT,
|
|
42
|
+
type PingT,
|
|
43
|
+
type PongT,
|
|
44
|
+
} from "./ts/backend";
|
|
45
|
+
import type { AnyEventName, ControlEventName, ControlEvents, Events, EventName } from "../schema";
|
|
46
|
+
|
|
47
|
+
export const WIRE_VERSION = 1;
|
|
48
|
+
export const WIRE_HEADER_LEN = 5; // [version:1][event_id:u32 LE]
|
|
49
|
+
|
|
50
|
+
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")
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
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")
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
/** merged app + control registry (used by encodeToScratch / JS encoder). */
|
|
72
|
+
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,
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const idToEventName: Record<number, EventName> = {
|
|
91
|
+
2995289047: "quote",
|
|
92
|
+
1362521689: "trade",
|
|
93
|
+
464274147: "portfolio",
|
|
94
|
+
2318166199: "complex",
|
|
95
|
+
1932267671: "order",
|
|
96
|
+
3211729064: "bigVal",
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
/** merged app + control id → name lookup (decode dispatch). */
|
|
100
|
+
export const idToAnyEventName: Record<number, AnyEventName> = {
|
|
101
|
+
2995289047: "quote",
|
|
102
|
+
1362521689: "trade",
|
|
103
|
+
464274147: "portfolio",
|
|
104
|
+
2318166199: "complex",
|
|
105
|
+
1932267671: "order",
|
|
106
|
+
3211729064: "bigVal",
|
|
107
|
+
1335831723: "hello",
|
|
108
|
+
669089267: "welcome",
|
|
109
|
+
2946386435: "subscribe",
|
|
110
|
+
4190043798: "unsubscribe",
|
|
111
|
+
3026600144: "joinGroup",
|
|
112
|
+
3755061443: "leaveGroup",
|
|
113
|
+
1249175018: "snapshotRequest",
|
|
114
|
+
375255177: "ping",
|
|
115
|
+
2061178551: "pong",
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export type DecodeFn = (bb: flatbuffers.ByteBuffer) => unknown;
|
|
119
|
+
|
|
120
|
+
export const eventIdToDecoder: Record<number, DecodeFn> = {
|
|
121
|
+
2995289047: (bb) => quoteToPlain(Quote.getSizePrefixedRootAsQuote(bb).unpack()),
|
|
122
|
+
1362521689: (bb) => tradeToPlain(Trade.getSizePrefixedRootAsTrade(bb).unpack()),
|
|
123
|
+
464274147: (bb) => portfolio_snapshotToPlain(PortfolioSnapshot.getSizePrefixedRootAsPortfolioSnapshot(bb).unpack()),
|
|
124
|
+
2318166199: (bb) => complexToPlain(Complex.getSizePrefixedRootAsComplex(bb).unpack()),
|
|
125
|
+
1932267671: (bb) => orderToPlain(Order.getSizePrefixedRootAsOrder(bb).unpack()),
|
|
126
|
+
3211729064: (bb) => big_valToPlain(BigVal.getSizePrefixedRootAsBigVal(bb).unpack()),
|
|
127
|
+
1335831723: (bb) => helloToPlain(Hello.getSizePrefixedRootAsHello(bb).unpack()),
|
|
128
|
+
669089267: (bb) => welcomeToPlain(Welcome.getSizePrefixedRootAsWelcome(bb).unpack()),
|
|
129
|
+
2946386435: (bb) => subscribeToPlain(Subscribe.getSizePrefixedRootAsSubscribe(bb).unpack()),
|
|
130
|
+
4190043798: (bb) => unsubscribeToPlain(Unsubscribe.getSizePrefixedRootAsUnsubscribe(bb).unpack()),
|
|
131
|
+
3026600144: (bb) => join_groupToPlain(JoinGroup.getSizePrefixedRootAsJoinGroup(bb).unpack()),
|
|
132
|
+
3755061443: (bb) => leave_groupToPlain(LeaveGroup.getSizePrefixedRootAsLeaveGroup(bb).unpack()),
|
|
133
|
+
1249175018: (bb) => snapshot_requestToPlain(SnapshotRequest.getSizePrefixedRootAsSnapshotRequest(bb).unpack()),
|
|
134
|
+
375255177: (bb) => pingToPlain(Ping.getSizePrefixedRootAsPing(bb).unpack()),
|
|
135
|
+
2061178551: (bb) => pongToPlain(Pong.getSizePrefixedRootAsPong(bb).unpack()),
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const controlIds = new Set<number>([
|
|
139
|
+
1335831723,
|
|
140
|
+
669089267,
|
|
141
|
+
2946386435,
|
|
142
|
+
4190043798,
|
|
143
|
+
3026600144,
|
|
144
|
+
3755061443,
|
|
145
|
+
1249175018,
|
|
146
|
+
375255177,
|
|
147
|
+
2061178551,
|
|
148
|
+
]);
|
|
149
|
+
export function isControlId(id: number): boolean { return controlIds.has(id); }
|
|
150
|
+
|
|
151
|
+
export function readFrameHeader(bytes: Uint8Array): { name: AnyEventName; id: number } | null {
|
|
152
|
+
if (bytes.byteLength < WIRE_HEADER_LEN) return null;
|
|
153
|
+
if (bytes[0] !== WIRE_VERSION) return null; // version mismatch — reject
|
|
154
|
+
const id = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength).getUint32(1, true);
|
|
155
|
+
const name = idToAnyEventName[id];
|
|
156
|
+
if (name === undefined) return null;
|
|
157
|
+
return { name, id };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** Decode a frame's payload given a validated id (no envelope re-parse). */
|
|
161
|
+
export function decodePayload(id: number, bytes: Uint8Array): unknown {
|
|
162
|
+
const decoder = eventIdToDecoder[id];
|
|
163
|
+
if (!decoder) return null;
|
|
164
|
+
// Reuse the pooled ByteBuffer (no per-frame ByteBuffer + TextDecoder
|
|
165
|
+
// allocation); position it at the payload start (relative to the view).
|
|
166
|
+
return decoder(pooledByteBuffer(bytes, WIRE_HEADER_LEN));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
export function decodeFrame(bytes: Uint8Array): { name: AnyEventName; id: number; payload: unknown } | null {
|
|
170
|
+
const h = readFrameHeader(bytes);
|
|
171
|
+
if (!h) return null;
|
|
172
|
+
return { name: h.name, id: h.id, payload: decodePayload(h.id, bytes) };
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// reused for every string decode (flatc object-API strings are Uint8Array)
|
|
176
|
+
const textDecoder = new TextDecoder();
|
|
177
|
+
function str(v: string | Uint8Array | null | undefined, dflt = ""): string {
|
|
178
|
+
return v == null ? dflt : typeof v === "string" ? v : textDecoder.decode(v);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function quoteToPlain(o: QuoteT): Events["quote"] {
|
|
182
|
+
return {
|
|
183
|
+
symbol: str(o.symbol),
|
|
184
|
+
bid: o.bid,
|
|
185
|
+
ask: o.ask,
|
|
186
|
+
bidSize: Number(o.bidSize),
|
|
187
|
+
askSize: Number(o.askSize),
|
|
188
|
+
ts: Number(o.ts),
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function tradeToPlain(o: TradeT): Events["trade"] {
|
|
193
|
+
return {
|
|
194
|
+
symbol: str(o.symbol),
|
|
195
|
+
price: o.price,
|
|
196
|
+
volume: Number(o.volume),
|
|
197
|
+
side: (["buy", "sell"] as const)[o.side] ?? "buy",
|
|
198
|
+
ts: Number(o.ts),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function portfolio_snapshotToPlain(o: PortfolioSnapshotT): Events["portfolio"] {
|
|
203
|
+
return {
|
|
204
|
+
accountId: str(o.accountId),
|
|
205
|
+
positions: o.positions.map((c) => portfolio_positionToPlain(c)),
|
|
206
|
+
totalValue: o.totalValue,
|
|
207
|
+
cash: o.cash,
|
|
208
|
+
ts: Number(o.ts),
|
|
209
|
+
updatedBy: o.updatedBy == null ? undefined : str(o.updatedBy),
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function portfolio_positionToPlain(o: PortfolioPositionT) {
|
|
214
|
+
return {
|
|
215
|
+
symbol: str(o.symbol),
|
|
216
|
+
quantity: Number(o.quantity),
|
|
217
|
+
avgPrice: o.avgPrice,
|
|
218
|
+
pnl: o.pnl,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function complexToPlain(o: ComplexT): Events["complex"] {
|
|
223
|
+
return {
|
|
224
|
+
id: str(o.id),
|
|
225
|
+
names: o.names.map((s) => str(s)),
|
|
226
|
+
prices: o.prices.map((n) => n),
|
|
227
|
+
counts: o.counts.map((n) => Number(n)),
|
|
228
|
+
flags: o.flags.map((n) => n),
|
|
229
|
+
tags: o.tags.map((n) => (["hot", "new", "sale"] as const)[n] ?? "hot"),
|
|
230
|
+
active: o.active,
|
|
231
|
+
total: o.total,
|
|
232
|
+
ts: Number(o.ts),
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function orderToPlain(o: OrderT): Events["order"] {
|
|
237
|
+
return {
|
|
238
|
+
orderId: str(o.orderId),
|
|
239
|
+
customer: customerToPlain(o.customer!),
|
|
240
|
+
lines: o.lines.map((c) => order_lineToPlain(c)),
|
|
241
|
+
notes: o.notes.map((s) => str(s)),
|
|
242
|
+
discounts: o.discounts.map((n) => n),
|
|
243
|
+
active: o.active,
|
|
244
|
+
createdAt: Number(o.createdAt),
|
|
245
|
+
billing: o.billing === null || o.billing === undefined ? undefined : order_billingToPlain(o.billing),
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function customerToPlain(o: CustomerT) {
|
|
250
|
+
return {
|
|
251
|
+
id: str(o.id),
|
|
252
|
+
name: str(o.name),
|
|
253
|
+
vip: o.vip,
|
|
254
|
+
loyaltyPoints: Number(o.loyaltyPoints),
|
|
255
|
+
rating: o.rating,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function order_lineToPlain(o: OrderLineT) {
|
|
260
|
+
return {
|
|
261
|
+
sku: str(o.sku),
|
|
262
|
+
qty: Number(o.qty),
|
|
263
|
+
unitPrice: o.unitPrice,
|
|
264
|
+
tags: o.tags.map((n) => (["hot", "new", "sale"] as const)[n] ?? "hot"),
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function order_billingToPlain(o: OrderBillingT) {
|
|
269
|
+
return {
|
|
270
|
+
id: str(o.id),
|
|
271
|
+
name: str(o.name),
|
|
272
|
+
vip: o.vip,
|
|
273
|
+
loyaltyPoints: Number(o.loyaltyPoints),
|
|
274
|
+
rating: o.rating,
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function big_valToPlain(o: BigValT): Events["bigVal"] {
|
|
279
|
+
return {
|
|
280
|
+
id: str(o.id),
|
|
281
|
+
seq: o.seq,
|
|
282
|
+
when: Number(o.when),
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function helloToPlain(o: HelloT): ControlEvents["hello"] {
|
|
287
|
+
return {
|
|
288
|
+
version: Number(o.version),
|
|
289
|
+
caps: o.caps.map((s) => str(s)),
|
|
290
|
+
lastSeq: Number(o.lastSeq),
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function welcomeToPlain(o: WelcomeT): ControlEvents["welcome"] {
|
|
295
|
+
return {
|
|
296
|
+
clientId: str(o.clientId),
|
|
297
|
+
groups: o.groups.map((s) => str(s)),
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function subscribeToPlain(o: SubscribeT): ControlEvents["subscribe"] {
|
|
302
|
+
return {
|
|
303
|
+
topic: str(o.topic),
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function unsubscribeToPlain(o: UnsubscribeT): ControlEvents["unsubscribe"] {
|
|
308
|
+
return {
|
|
309
|
+
topic: str(o.topic),
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
function join_groupToPlain(o: JoinGroupT): ControlEvents["joinGroup"] {
|
|
314
|
+
return {
|
|
315
|
+
group: str(o.group),
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
function leave_groupToPlain(o: LeaveGroupT): ControlEvents["leaveGroup"] {
|
|
320
|
+
return {
|
|
321
|
+
group: str(o.group),
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function snapshot_requestToPlain(o: SnapshotRequestT): ControlEvents["snapshotRequest"] {
|
|
326
|
+
return {
|
|
327
|
+
topic: str(o.topic),
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
function pingToPlain(o: PingT): ControlEvents["ping"] {
|
|
332
|
+
return {
|
|
333
|
+
ts: Number(o.ts),
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function pongToPlain(o: PongT): ControlEvents["pong"] {
|
|
338
|
+
return {
|
|
339
|
+
ts: Number(o.ts),
|
|
340
|
+
};
|
|
341
|
+
}
|