@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,465 @@
|
|
|
1
|
+
// @generated by scripts/ts-ser-gen.ts — DO NOT EDIT
|
|
2
|
+
import * as flatbuffers from "flatbuffers";
|
|
3
|
+
import {
|
|
4
|
+
QuoteT,
|
|
5
|
+
TradeT,
|
|
6
|
+
PortfolioSnapshotT,
|
|
7
|
+
PortfolioPositionT,
|
|
8
|
+
ComplexT,
|
|
9
|
+
OrderT,
|
|
10
|
+
CustomerT,
|
|
11
|
+
OrderLineT,
|
|
12
|
+
OrderBillingT,
|
|
13
|
+
BigValT,
|
|
14
|
+
HelloT,
|
|
15
|
+
WelcomeT,
|
|
16
|
+
SubscribeT,
|
|
17
|
+
UnsubscribeT,
|
|
18
|
+
JoinGroupT,
|
|
19
|
+
LeaveGroupT,
|
|
20
|
+
SnapshotRequestT,
|
|
21
|
+
PingT,
|
|
22
|
+
PongT,
|
|
23
|
+
} from "./ts/backend";
|
|
24
|
+
import { anyEventNameToId, WIRE_HEADER_LEN, WIRE_VERSION } from "./registry";
|
|
25
|
+
import type { AnyEventName, ControlEvents, Events } from "../schema";
|
|
26
|
+
|
|
27
|
+
/** string → flatc numeric enum value lookups */
|
|
28
|
+
const SIDE = { buy: 0, sell: 1 } as const;
|
|
29
|
+
const TAGS = { hot: 0, new: 1, sale: 2 } as const;
|
|
30
|
+
|
|
31
|
+
/** pooled builder — each encode clears it (safe because encodeEventFrame copies). */
|
|
32
|
+
let shared: flatbuffers.Builder | null = null;
|
|
33
|
+
function getBuilder(): flatbuffers.Builder {
|
|
34
|
+
if (!shared) shared = new flatbuffers.Builder(1024);
|
|
35
|
+
return shared;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
type QuotePlain = {
|
|
39
|
+
symbol: string;
|
|
40
|
+
bid: number;
|
|
41
|
+
ask: number;
|
|
42
|
+
bidSize: number;
|
|
43
|
+
askSize: number;
|
|
44
|
+
ts: number;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
type TradePlain = {
|
|
48
|
+
symbol: string;
|
|
49
|
+
price: number;
|
|
50
|
+
volume: number;
|
|
51
|
+
side: "buy" | "sell";
|
|
52
|
+
ts: number;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
type PortfolioSnapshotPlain = {
|
|
56
|
+
accountId: string;
|
|
57
|
+
positions: PortfolioPositionPlain[];
|
|
58
|
+
totalValue: number;
|
|
59
|
+
cash: number;
|
|
60
|
+
ts: number;
|
|
61
|
+
updatedBy?: string | undefined;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
type PortfolioPositionPlain = {
|
|
65
|
+
symbol: string;
|
|
66
|
+
quantity: number;
|
|
67
|
+
avgPrice: number;
|
|
68
|
+
pnl: number;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
type ComplexPlain = {
|
|
72
|
+
id: string;
|
|
73
|
+
names: string[];
|
|
74
|
+
prices: number[];
|
|
75
|
+
counts: number[];
|
|
76
|
+
flags: boolean[];
|
|
77
|
+
tags: ("hot" | "new" | "sale")[];
|
|
78
|
+
active: boolean;
|
|
79
|
+
total: number;
|
|
80
|
+
ts: number;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
type OrderPlain = {
|
|
84
|
+
orderId: string;
|
|
85
|
+
customer: CustomerPlain;
|
|
86
|
+
lines: OrderLinePlain[];
|
|
87
|
+
notes: string[];
|
|
88
|
+
discounts: number[];
|
|
89
|
+
active: boolean;
|
|
90
|
+
createdAt: number;
|
|
91
|
+
billing?: OrderBillingPlain | undefined;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
type CustomerPlain = {
|
|
95
|
+
id: string;
|
|
96
|
+
name: string;
|
|
97
|
+
vip: boolean;
|
|
98
|
+
loyaltyPoints: number;
|
|
99
|
+
rating: number;
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
type OrderLinePlain = {
|
|
103
|
+
sku: string;
|
|
104
|
+
qty: number;
|
|
105
|
+
unitPrice: number;
|
|
106
|
+
tags: ("hot" | "new" | "sale")[];
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
type OrderBillingPlain = {
|
|
110
|
+
id: string;
|
|
111
|
+
name: string;
|
|
112
|
+
vip: boolean;
|
|
113
|
+
loyaltyPoints: number;
|
|
114
|
+
rating: number;
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
type BigValPlain = {
|
|
118
|
+
id: string;
|
|
119
|
+
seq: bigint;
|
|
120
|
+
when: number;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
type HelloPlain = {
|
|
124
|
+
version: number;
|
|
125
|
+
caps: string[];
|
|
126
|
+
lastSeq: number;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
type WelcomePlain = {
|
|
130
|
+
clientId: string;
|
|
131
|
+
groups: string[];
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
type SubscribePlain = {
|
|
135
|
+
topic: string;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
type UnsubscribePlain = {
|
|
139
|
+
topic: string;
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
type JoinGroupPlain = {
|
|
143
|
+
group: string;
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
type LeaveGroupPlain = {
|
|
147
|
+
group: string;
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
type SnapshotRequestPlain = {
|
|
151
|
+
topic: string;
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
type PingPlain = {
|
|
155
|
+
ts: number;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
type PongPlain = {
|
|
159
|
+
ts: number;
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
function buildQuoteT(o: QuotePlain): QuoteT {
|
|
163
|
+
return new QuoteT(
|
|
164
|
+
o.symbol,
|
|
165
|
+
o.bid,
|
|
166
|
+
o.ask,
|
|
167
|
+
o.bidSize === undefined ? 0n : BigInt(o.bidSize),
|
|
168
|
+
o.askSize === undefined ? 0n : BigInt(o.askSize),
|
|
169
|
+
o.ts === undefined ? 0n : BigInt(o.ts),
|
|
170
|
+
);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function buildTradeT(o: TradePlain): TradeT {
|
|
174
|
+
return new TradeT(
|
|
175
|
+
o.symbol,
|
|
176
|
+
o.price,
|
|
177
|
+
o.volume === undefined ? 0n : BigInt(o.volume),
|
|
178
|
+
SIDE[o.side],
|
|
179
|
+
o.ts === undefined ? 0n : BigInt(o.ts),
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function buildPortfolioSnapshotT(o: PortfolioSnapshotPlain): PortfolioSnapshotT {
|
|
184
|
+
return new PortfolioSnapshotT(
|
|
185
|
+
o.accountId,
|
|
186
|
+
(o.positions ?? []).map((v) => buildPortfolioPositionT(v)),
|
|
187
|
+
o.totalValue,
|
|
188
|
+
o.cash,
|
|
189
|
+
o.ts === undefined ? 0n : BigInt(o.ts),
|
|
190
|
+
o.updatedBy ?? null,
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function buildPortfolioPositionT(o: PortfolioPositionPlain): PortfolioPositionT {
|
|
195
|
+
return new PortfolioPositionT(
|
|
196
|
+
o.symbol,
|
|
197
|
+
o.quantity === undefined ? 0n : BigInt(o.quantity),
|
|
198
|
+
o.avgPrice,
|
|
199
|
+
o.pnl,
|
|
200
|
+
);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
function buildComplexT(o: ComplexPlain): ComplexT {
|
|
204
|
+
return new ComplexT(
|
|
205
|
+
o.id,
|
|
206
|
+
(o.names ?? []),
|
|
207
|
+
(o.prices ?? []),
|
|
208
|
+
(o.counts ?? []).map((v) => BigInt(v)),
|
|
209
|
+
(o.flags ?? []),
|
|
210
|
+
(o.tags ?? []).map((v) => TAGS[v]),
|
|
211
|
+
o.active,
|
|
212
|
+
o.total,
|
|
213
|
+
o.ts === undefined ? 0n : BigInt(o.ts),
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function buildOrderT(o: OrderPlain): OrderT {
|
|
218
|
+
return new OrderT(
|
|
219
|
+
o.orderId,
|
|
220
|
+
buildCustomerT(o.customer),
|
|
221
|
+
(o.lines ?? []).map((v) => buildOrderLineT(v)),
|
|
222
|
+
(o.notes ?? []),
|
|
223
|
+
(o.discounts ?? []),
|
|
224
|
+
o.active,
|
|
225
|
+
o.createdAt === undefined ? 0n : BigInt(o.createdAt),
|
|
226
|
+
o.billing ? buildOrderBillingT(o.billing) : null,
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function buildCustomerT(o: CustomerPlain): CustomerT {
|
|
231
|
+
return new CustomerT(
|
|
232
|
+
o.id,
|
|
233
|
+
o.name,
|
|
234
|
+
o.vip,
|
|
235
|
+
o.loyaltyPoints === undefined ? 0n : BigInt(o.loyaltyPoints),
|
|
236
|
+
o.rating,
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function buildOrderLineT(o: OrderLinePlain): OrderLineT {
|
|
241
|
+
return new OrderLineT(
|
|
242
|
+
o.sku,
|
|
243
|
+
o.qty === undefined ? 0n : BigInt(o.qty),
|
|
244
|
+
o.unitPrice,
|
|
245
|
+
(o.tags ?? []).map((v) => TAGS[v]),
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
function buildOrderBillingT(o: OrderBillingPlain): OrderBillingT {
|
|
250
|
+
return new OrderBillingT(
|
|
251
|
+
o.id,
|
|
252
|
+
o.name,
|
|
253
|
+
o.vip,
|
|
254
|
+
o.loyaltyPoints === undefined ? 0n : BigInt(o.loyaltyPoints),
|
|
255
|
+
o.rating,
|
|
256
|
+
);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function buildBigValT(o: BigValPlain): BigValT {
|
|
260
|
+
return new BigValT(
|
|
261
|
+
o.id,
|
|
262
|
+
o.seq,
|
|
263
|
+
o.when === undefined ? 0n : BigInt(o.when),
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function buildHelloT(o: HelloPlain): HelloT {
|
|
268
|
+
return new HelloT(
|
|
269
|
+
o.version === undefined ? 0n : BigInt(o.version),
|
|
270
|
+
(o.caps ?? []),
|
|
271
|
+
o.lastSeq === undefined ? 0n : BigInt(o.lastSeq),
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function buildWelcomeT(o: WelcomePlain): WelcomeT {
|
|
276
|
+
return new WelcomeT(
|
|
277
|
+
o.clientId,
|
|
278
|
+
(o.groups ?? []),
|
|
279
|
+
);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function buildSubscribeT(o: SubscribePlain): SubscribeT {
|
|
283
|
+
return new SubscribeT(
|
|
284
|
+
o.topic,
|
|
285
|
+
);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function buildUnsubscribeT(o: UnsubscribePlain): UnsubscribeT {
|
|
289
|
+
return new UnsubscribeT(
|
|
290
|
+
o.topic,
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
function buildJoinGroupT(o: JoinGroupPlain): JoinGroupT {
|
|
295
|
+
return new JoinGroupT(
|
|
296
|
+
o.group,
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function buildLeaveGroupT(o: LeaveGroupPlain): LeaveGroupT {
|
|
301
|
+
return new LeaveGroupT(
|
|
302
|
+
o.group,
|
|
303
|
+
);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function buildSnapshotRequestT(o: SnapshotRequestPlain): SnapshotRequestT {
|
|
307
|
+
return new SnapshotRequestT(
|
|
308
|
+
o.topic,
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
function buildPingT(o: PingPlain): PingT {
|
|
313
|
+
return new PingT(
|
|
314
|
+
o.ts === undefined ? 0n : BigInt(o.ts),
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function buildPongT(o: PongPlain): PongT {
|
|
319
|
+
return new PongT(
|
|
320
|
+
o.ts === undefined ? 0n : BigInt(o.ts),
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
/** payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
325
|
+
export function encodeQuotePayload(o: Events["quote"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
326
|
+
b.clear();
|
|
327
|
+
b.finishSizePrefixed(buildQuoteT(o).pack(b));
|
|
328
|
+
return b.asUint8Array();
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
/** payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
332
|
+
export function encodeTradePayload(o: Events["trade"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
333
|
+
b.clear();
|
|
334
|
+
b.finishSizePrefixed(buildTradeT(o).pack(b));
|
|
335
|
+
return b.asUint8Array();
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/** payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
339
|
+
export function encodePortfolioPayload(o: Events["portfolio"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
340
|
+
b.clear();
|
|
341
|
+
b.finishSizePrefixed(buildPortfolioSnapshotT(o).pack(b));
|
|
342
|
+
return b.asUint8Array();
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/** payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
346
|
+
export function encodeComplexPayload(o: Events["complex"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
347
|
+
b.clear();
|
|
348
|
+
b.finishSizePrefixed(buildComplexT(o).pack(b));
|
|
349
|
+
return b.asUint8Array();
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/** payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
353
|
+
export function encodeOrderPayload(o: Events["order"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
354
|
+
b.clear();
|
|
355
|
+
b.finishSizePrefixed(buildOrderT(o).pack(b));
|
|
356
|
+
return b.asUint8Array();
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/** payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
360
|
+
export function encodeBigValPayload(o: Events["bigVal"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
361
|
+
b.clear();
|
|
362
|
+
b.finishSizePrefixed(buildBigValT(o).pack(b));
|
|
363
|
+
return b.asUint8Array();
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
/** control payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
367
|
+
export function encodeHelloPayload(o: ControlEvents["hello"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
368
|
+
b.clear();
|
|
369
|
+
b.finishSizePrefixed(buildHelloT(o).pack(b));
|
|
370
|
+
return b.asUint8Array();
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/** control payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
374
|
+
export function encodeWelcomePayload(o: ControlEvents["welcome"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
375
|
+
b.clear();
|
|
376
|
+
b.finishSizePrefixed(buildWelcomeT(o).pack(b));
|
|
377
|
+
return b.asUint8Array();
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/** control payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
381
|
+
export function encodeSubscribePayload(o: ControlEvents["subscribe"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
382
|
+
b.clear();
|
|
383
|
+
b.finishSizePrefixed(buildSubscribeT(o).pack(b));
|
|
384
|
+
return b.asUint8Array();
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/** control payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
388
|
+
export function encodeUnsubscribePayload(o: ControlEvents["unsubscribe"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
389
|
+
b.clear();
|
|
390
|
+
b.finishSizePrefixed(buildUnsubscribeT(o).pack(b));
|
|
391
|
+
return b.asUint8Array();
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
/** control payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
395
|
+
export function encodeJoinGroupPayload(o: ControlEvents["joinGroup"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
396
|
+
b.clear();
|
|
397
|
+
b.finishSizePrefixed(buildJoinGroupT(o).pack(b));
|
|
398
|
+
return b.asUint8Array();
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/** control payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
402
|
+
export function encodeLeaveGroupPayload(o: ControlEvents["leaveGroup"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
403
|
+
b.clear();
|
|
404
|
+
b.finishSizePrefixed(buildLeaveGroupT(o).pack(b));
|
|
405
|
+
return b.asUint8Array();
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/** control payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
409
|
+
export function encodeSnapshotRequestPayload(o: ControlEvents["snapshotRequest"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
410
|
+
b.clear();
|
|
411
|
+
b.finishSizePrefixed(buildSnapshotRequestT(o).pack(b));
|
|
412
|
+
return b.asUint8Array();
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/** control payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
416
|
+
export function encodePingPayload(o: ControlEvents["ping"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
417
|
+
b.clear();
|
|
418
|
+
b.finishSizePrefixed(buildPingT(o).pack(b));
|
|
419
|
+
return b.asUint8Array();
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/** control payload encoder: plain object → size-prefixed FlatBuffer. */
|
|
423
|
+
export function encodePongPayload(o: ControlEvents["pong"], b: flatbuffers.Builder = getBuilder()): Uint8Array {
|
|
424
|
+
b.clear();
|
|
425
|
+
b.finishSizePrefixed(buildPongT(o).pack(b));
|
|
426
|
+
return b.asUint8Array();
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
export type JsEncoder = (o: unknown, b?: flatbuffers.Builder) => Uint8Array;
|
|
430
|
+
|
|
431
|
+
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,
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
/** Encode a payload (app or control event) → size-prefixed FlatBuffer. */
|
|
450
|
+
export function encodeJsPayload(name: AnyEventName, o: unknown, b?: flatbuffers.Builder): Uint8Array {
|
|
451
|
+
const enc = jsEncoders[name];
|
|
452
|
+
if (!enc) throw new Error(`ignex: no JS encoder for "${name}" — regenerate`);
|
|
453
|
+
return enc(o, b);
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
/** Encode a payload into a full wire frame `[version][event_id:u32][size-prefixed FB]`. */
|
|
457
|
+
export function encodeEventFrame(name: AnyEventName, o: unknown, b?: flatbuffers.Builder): Uint8Array {
|
|
458
|
+
const payload = encodeJsPayload(name, o, b);
|
|
459
|
+
const id = anyEventNameToId[name]!;
|
|
460
|
+
const frame = new Uint8Array(WIRE_HEADER_LEN + payload.byteLength);
|
|
461
|
+
frame[0] = WIRE_VERSION;
|
|
462
|
+
new DataView(frame.buffer).setUint32(1, id, true);
|
|
463
|
+
frame.set(payload, WIRE_HEADER_LEN);
|
|
464
|
+
return frame;
|
|
465
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"events": {
|
|
4
|
+
"quote": 2995289047,
|
|
5
|
+
"trade": 1362521689,
|
|
6
|
+
"portfolio": 464274147,
|
|
7
|
+
"complex": 2318166199,
|
|
8
|
+
"order": 1932267671,
|
|
9
|
+
"bigVal": 3211729064,
|
|
10
|
+
"hello": 1335831723,
|
|
11
|
+
"welcome": 669089267,
|
|
12
|
+
"subscribe": 2946386435,
|
|
13
|
+
"unsubscribe": 4190043798,
|
|
14
|
+
"joinGroup": 3026600144,
|
|
15
|
+
"leaveGroup": 3755061443,
|
|
16
|
+
"snapshotRequest": 1249175018,
|
|
17
|
+
"ping": 375255177,
|
|
18
|
+
"pong": 2061178551
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Zero-allocation UTF-8 helpers (Bun, server-side). Used by the generated
|
|
3
|
+
* direct fast-path encoders to turn JS strings into pre-encoded byte buffers
|
|
4
|
+
* WITHOUT allocating: write into a reusable scratch via a cached `Buffer` view
|
|
5
|
+
* (castrum's `encodeUtf8Into` pattern).
|
|
6
|
+
*/
|
|
7
|
+
import { Buffer } from "node:buffer";
|
|
8
|
+
|
|
9
|
+
const viewCache = new WeakMap<ArrayBuffer, Buffer>();
|
|
10
|
+
|
|
11
|
+
function bufView(ab: ArrayBuffer): Buffer {
|
|
12
|
+
let b = viewCache.get(ab);
|
|
13
|
+
if (!b) {
|
|
14
|
+
b = Buffer.from(ab);
|
|
15
|
+
viewCache.set(ab, b);
|
|
16
|
+
}
|
|
17
|
+
return b;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** UTF-8 byte length of `s` — no allocation. */
|
|
21
|
+
export function utf8Len(s: string): number {
|
|
22
|
+
return Buffer.byteLength(s, "utf8");
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Write `s` as UTF-8 into `dest` at `offset`; returns bytes written. */
|
|
26
|
+
export function encodeUtf8Into(s: string, dest: Uint8Array, offset = 0): number {
|
|
27
|
+
return bufView(dest.buffer as ArrayBuffer).write(s, offset, "utf8");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Grow a scratch in place (returns a new buffer) if it can't hold `needed`. */
|
|
31
|
+
export function ensureCapacity(current: Uint8Array, needed: number, minGrow = 64): Uint8Array {
|
|
32
|
+
if (current.byteLength >= needed) return current;
|
|
33
|
+
const cap = Math.max(current.byteLength * 2, needed, minGrow);
|
|
34
|
+
return new Uint8Array(cap);
|
|
35
|
+
}
|