@moqtap/trace 0.1.0 → 0.1.2
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 -21
- package/README.md +33 -33
- package/dist/index.cjs +26 -22
- package/dist/index.d.cts +13 -11
- package/dist/index.d.ts +13 -11
- package/dist/index.js +27 -23
- package/package.json +3 -3
- package/src/binary.ts +117 -120
- package/src/index.ts +19 -20
- package/src/json.ts +16 -10
- package/src/recorder.ts +96 -79
- package/src/types.ts +60 -60
package/src/binary.ts
CHANGED
|
@@ -1,27 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Perspective,
|
|
8
|
-
} from './types.js';
|
|
9
|
-
|
|
10
|
-
const MAGIC = new Uint8Array([0x4d, 0x4f, 0x51, 0x54, 0x52, 0x41, 0x43, 0x45]); // "MOQTRACE"
|
|
11
|
-
const FORMAT_VERSION = 1;
|
|
12
|
-
const PREAMBLE_SIZE = 16; // 8 magic + 4 version + 4 header length
|
|
1
|
+
import { decode, decodeMultiple, encode } from 'cbor-x'
|
|
2
|
+
import type { DetailLevel, Perspective, Trace, TraceEvent, TraceHeader } from './types.js'
|
|
3
|
+
|
|
4
|
+
const MAGIC = new Uint8Array([0x4d, 0x4f, 0x51, 0x54, 0x52, 0x41, 0x43, 0x45]) // "MOQTRACE"
|
|
5
|
+
const FORMAT_VERSION = 1
|
|
6
|
+
const PREAMBLE_SIZE = 16 // 8 magic + 4 version + 4 header length
|
|
13
7
|
|
|
14
8
|
// Event type string ↔ integer mapping
|
|
15
9
|
const EVENT_TYPE_TO_INT: Record<TraceEvent['type'], number> = {
|
|
16
|
-
|
|
10
|
+
control: 0,
|
|
17
11
|
'stream-opened': 1,
|
|
18
12
|
'stream-closed': 2,
|
|
19
13
|
'object-header': 3,
|
|
20
14
|
'object-payload': 4,
|
|
21
15
|
'state-change': 5,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
16
|
+
error: 6,
|
|
17
|
+
annotation: 7,
|
|
18
|
+
}
|
|
25
19
|
|
|
26
20
|
const INT_TO_EVENT_TYPE: Record<number, TraceEvent['type']> = {
|
|
27
21
|
0: 'control',
|
|
@@ -32,7 +26,7 @@ const INT_TO_EVENT_TYPE: Record<number, TraceEvent['type']> = {
|
|
|
32
26
|
5: 'state-change',
|
|
33
27
|
6: 'error',
|
|
34
28
|
7: 'annotation',
|
|
35
|
-
}
|
|
29
|
+
}
|
|
36
30
|
|
|
37
31
|
// --- Header serialization ---
|
|
38
32
|
|
|
@@ -42,14 +36,14 @@ function headerToCbor(header: TraceHeader): Record<string, unknown> {
|
|
|
42
36
|
perspective: header.perspective,
|
|
43
37
|
detail: header.detail,
|
|
44
38
|
startTime: header.startTime,
|
|
45
|
-
}
|
|
46
|
-
if (header.endTime != null) map.endTime = header.endTime
|
|
47
|
-
if (header.transport != null) map.transport = header.transport
|
|
48
|
-
if (header.source != null) map.source = header.source
|
|
49
|
-
if (header.endpoint != null) map.endpoint = header.endpoint
|
|
50
|
-
if (header.sessionId != null) map.sessionId = header.sessionId
|
|
51
|
-
if (header.custom != null) map.custom = header.custom
|
|
52
|
-
return map
|
|
39
|
+
}
|
|
40
|
+
if (header.endTime != null) map.endTime = header.endTime
|
|
41
|
+
if (header.transport != null) map.transport = header.transport
|
|
42
|
+
if (header.source != null) map.source = header.source
|
|
43
|
+
if (header.endpoint != null) map.endpoint = header.endpoint
|
|
44
|
+
if (header.sessionId != null) map.sessionId = header.sessionId
|
|
45
|
+
if (header.custom != null) map.custom = header.custom
|
|
46
|
+
return map
|
|
53
47
|
}
|
|
54
48
|
|
|
55
49
|
function cborToHeader(obj: Record<string, unknown>): TraceHeader {
|
|
@@ -64,7 +58,7 @@ function cborToHeader(obj: Record<string, unknown>): TraceHeader {
|
|
|
64
58
|
...(obj.endpoint != null ? { endpoint: obj.endpoint as string } : {}),
|
|
65
59
|
...(obj.sessionId != null ? { sessionId: obj.sessionId as string } : {}),
|
|
66
60
|
...(obj.custom != null ? { custom: obj.custom as Record<string, unknown> } : {}),
|
|
67
|
-
}
|
|
61
|
+
}
|
|
68
62
|
}
|
|
69
63
|
|
|
70
64
|
// --- Event serialization ---
|
|
@@ -74,65 +68,65 @@ function eventToCbor(event: TraceEvent): Record<string, unknown> {
|
|
|
74
68
|
n: event.seq,
|
|
75
69
|
t: event.timestamp,
|
|
76
70
|
e: EVENT_TYPE_TO_INT[event.type],
|
|
77
|
-
}
|
|
71
|
+
}
|
|
78
72
|
|
|
79
73
|
switch (event.type) {
|
|
80
74
|
case 'control': {
|
|
81
|
-
base.d = event.direction
|
|
82
|
-
base.mt = event.messageType
|
|
83
|
-
base.msg = event.message
|
|
84
|
-
if (event.raw != null) base.raw = event.raw
|
|
85
|
-
break
|
|
75
|
+
base.d = event.direction
|
|
76
|
+
base.mt = event.messageType
|
|
77
|
+
base.msg = event.message
|
|
78
|
+
if (event.raw != null) base.raw = event.raw
|
|
79
|
+
break
|
|
86
80
|
}
|
|
87
81
|
case 'stream-opened': {
|
|
88
|
-
base.sid = event.streamId
|
|
89
|
-
base.d = event.direction
|
|
90
|
-
base.st = event.streamType
|
|
91
|
-
break
|
|
82
|
+
base.sid = event.streamId
|
|
83
|
+
base.d = event.direction
|
|
84
|
+
base.st = event.streamType
|
|
85
|
+
break
|
|
92
86
|
}
|
|
93
87
|
case 'stream-closed': {
|
|
94
|
-
base.sid = event.streamId
|
|
95
|
-
base.ec = event.errorCode
|
|
96
|
-
break
|
|
88
|
+
base.sid = event.streamId
|
|
89
|
+
base.ec = event.errorCode
|
|
90
|
+
break
|
|
97
91
|
}
|
|
98
92
|
case 'object-header': {
|
|
99
|
-
base.sid = event.streamId
|
|
100
|
-
base.g = event.groupId
|
|
101
|
-
base.o = event.objectId
|
|
102
|
-
base.pp = event.publisherPriority
|
|
103
|
-
base.os = event.objectStatus
|
|
104
|
-
break
|
|
93
|
+
base.sid = event.streamId
|
|
94
|
+
base.g = event.groupId
|
|
95
|
+
base.o = event.objectId
|
|
96
|
+
base.pp = event.publisherPriority
|
|
97
|
+
base.os = event.objectStatus
|
|
98
|
+
break
|
|
105
99
|
}
|
|
106
100
|
case 'object-payload': {
|
|
107
|
-
base.sid = event.streamId
|
|
108
|
-
base.g = event.groupId
|
|
109
|
-
base.o = event.objectId
|
|
110
|
-
base.sz = event.size
|
|
111
|
-
if (event.payload != null) base.pl = event.payload
|
|
112
|
-
break
|
|
101
|
+
base.sid = event.streamId
|
|
102
|
+
base.g = event.groupId
|
|
103
|
+
base.o = event.objectId
|
|
104
|
+
base.sz = event.size
|
|
105
|
+
if (event.payload != null) base.pl = event.payload
|
|
106
|
+
break
|
|
113
107
|
}
|
|
114
108
|
case 'state-change': {
|
|
115
|
-
base.from = event.from
|
|
116
|
-
base.to = event.to
|
|
117
|
-
break
|
|
109
|
+
base.from = event.from
|
|
110
|
+
base.to = event.to
|
|
111
|
+
break
|
|
118
112
|
}
|
|
119
113
|
case 'error': {
|
|
120
|
-
base.ec = event.errorCode
|
|
121
|
-
base.reason = event.reason
|
|
122
|
-
break
|
|
114
|
+
base.ec = event.errorCode
|
|
115
|
+
base.reason = event.reason
|
|
116
|
+
break
|
|
123
117
|
}
|
|
124
118
|
case 'annotation': {
|
|
125
|
-
base.label = event.label
|
|
126
|
-
if (event.data !== undefined) base.data = event.data
|
|
127
|
-
break
|
|
119
|
+
base.label = event.label
|
|
120
|
+
if (event.data !== undefined) base.data = event.data
|
|
121
|
+
break
|
|
128
122
|
}
|
|
129
123
|
}
|
|
130
124
|
|
|
131
|
-
return base
|
|
125
|
+
return base
|
|
132
126
|
}
|
|
133
127
|
|
|
134
128
|
function cborToEvent(obj: Record<string, unknown>): TraceEvent {
|
|
135
|
-
const eventType = INT_TO_EVENT_TYPE[obj.e as number]
|
|
129
|
+
const eventType = INT_TO_EVENT_TYPE[obj.e as number]
|
|
136
130
|
if (eventType == null) {
|
|
137
131
|
// Unknown event type — skip per spec (return annotation as fallback)
|
|
138
132
|
return {
|
|
@@ -141,11 +135,11 @@ function cborToEvent(obj: Record<string, unknown>): TraceEvent {
|
|
|
141
135
|
timestamp: Number(obj.t ?? 0),
|
|
142
136
|
label: `unknown-event-${obj.e}`,
|
|
143
137
|
data: obj,
|
|
144
|
-
}
|
|
138
|
+
}
|
|
145
139
|
}
|
|
146
140
|
|
|
147
|
-
const seq = Number(obj.n ?? 0)
|
|
148
|
-
const timestamp = Number(obj.t ?? 0)
|
|
141
|
+
const seq = Number(obj.n ?? 0)
|
|
142
|
+
const timestamp = Number(obj.t ?? 0)
|
|
149
143
|
|
|
150
144
|
switch (eventType) {
|
|
151
145
|
case 'control':
|
|
@@ -157,7 +151,7 @@ function cborToEvent(obj: Record<string, unknown>): TraceEvent {
|
|
|
157
151
|
messageType: Number(obj.mt ?? 0),
|
|
158
152
|
message: (obj.msg ?? {}) as Record<string, unknown>,
|
|
159
153
|
...(obj.raw != null ? { raw: obj.raw as Uint8Array } : {}),
|
|
160
|
-
}
|
|
154
|
+
}
|
|
161
155
|
|
|
162
156
|
case 'stream-opened':
|
|
163
157
|
return {
|
|
@@ -167,7 +161,7 @@ function cborToEvent(obj: Record<string, unknown>): TraceEvent {
|
|
|
167
161
|
streamId: BigInt(obj.sid as bigint | number),
|
|
168
162
|
direction: obj.d as 0 | 1,
|
|
169
163
|
streamType: obj.st as 0 | 1 | 2,
|
|
170
|
-
}
|
|
164
|
+
}
|
|
171
165
|
|
|
172
166
|
case 'stream-closed':
|
|
173
167
|
return {
|
|
@@ -176,7 +170,7 @@ function cborToEvent(obj: Record<string, unknown>): TraceEvent {
|
|
|
176
170
|
timestamp,
|
|
177
171
|
streamId: BigInt(obj.sid as bigint | number),
|
|
178
172
|
errorCode: Number(obj.ec ?? 0),
|
|
179
|
-
}
|
|
173
|
+
}
|
|
180
174
|
|
|
181
175
|
case 'object-header':
|
|
182
176
|
return {
|
|
@@ -188,7 +182,7 @@ function cborToEvent(obj: Record<string, unknown>): TraceEvent {
|
|
|
188
182
|
objectId: BigInt(obj.o as bigint | number),
|
|
189
183
|
publisherPriority: Number(obj.pp ?? 0),
|
|
190
184
|
objectStatus: Number(obj.os ?? 0),
|
|
191
|
-
}
|
|
185
|
+
}
|
|
192
186
|
|
|
193
187
|
case 'object-payload':
|
|
194
188
|
return {
|
|
@@ -200,7 +194,7 @@ function cborToEvent(obj: Record<string, unknown>): TraceEvent {
|
|
|
200
194
|
objectId: BigInt(obj.o as bigint | number),
|
|
201
195
|
size: Number(obj.sz ?? 0),
|
|
202
196
|
...(obj.pl != null ? { payload: obj.pl as Uint8Array } : {}),
|
|
203
|
-
}
|
|
197
|
+
}
|
|
204
198
|
|
|
205
199
|
case 'state-change':
|
|
206
200
|
return {
|
|
@@ -209,7 +203,7 @@ function cborToEvent(obj: Record<string, unknown>): TraceEvent {
|
|
|
209
203
|
timestamp,
|
|
210
204
|
from: obj.from as string,
|
|
211
205
|
to: obj.to as string,
|
|
212
|
-
}
|
|
206
|
+
}
|
|
213
207
|
|
|
214
208
|
case 'error':
|
|
215
209
|
return {
|
|
@@ -218,7 +212,7 @@ function cborToEvent(obj: Record<string, unknown>): TraceEvent {
|
|
|
218
212
|
timestamp,
|
|
219
213
|
errorCode: Number(obj.ec ?? 0),
|
|
220
214
|
reason: (obj.reason ?? '') as string,
|
|
221
|
-
}
|
|
215
|
+
}
|
|
222
216
|
|
|
223
217
|
case 'annotation':
|
|
224
218
|
return {
|
|
@@ -227,45 +221,48 @@ function cborToEvent(obj: Record<string, unknown>): TraceEvent {
|
|
|
227
221
|
timestamp,
|
|
228
222
|
label: (obj.label ?? '') as string,
|
|
229
223
|
data: obj.data,
|
|
230
|
-
}
|
|
224
|
+
}
|
|
231
225
|
}
|
|
232
226
|
}
|
|
233
227
|
|
|
234
228
|
// --- Preamble helpers ---
|
|
235
229
|
|
|
236
230
|
function writePreamble(headerCbor: Uint8Array): Uint8Array {
|
|
237
|
-
const buf = new Uint8Array(PREAMBLE_SIZE + headerCbor.length)
|
|
238
|
-
buf.set(MAGIC, 0)
|
|
239
|
-
const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength)
|
|
240
|
-
view.setUint32(8, FORMAT_VERSION, true)
|
|
241
|
-
view.setUint32(12, headerCbor.length, true)
|
|
242
|
-
buf.set(headerCbor, PREAMBLE_SIZE)
|
|
243
|
-
return buf
|
|
231
|
+
const buf = new Uint8Array(PREAMBLE_SIZE + headerCbor.length)
|
|
232
|
+
buf.set(MAGIC, 0)
|
|
233
|
+
const view = new DataView(buf.buffer, buf.byteOffset, buf.byteLength)
|
|
234
|
+
view.setUint32(8, FORMAT_VERSION, true)
|
|
235
|
+
view.setUint32(12, headerCbor.length, true)
|
|
236
|
+
buf.set(headerCbor, PREAMBLE_SIZE)
|
|
237
|
+
return buf
|
|
244
238
|
}
|
|
245
239
|
|
|
246
|
-
function validatePreamble(bytes: Uint8Array): {
|
|
240
|
+
function validatePreamble(bytes: Uint8Array): {
|
|
241
|
+
version: number
|
|
242
|
+
headerLength: number
|
|
243
|
+
} {
|
|
247
244
|
if (bytes.length < PREAMBLE_SIZE) {
|
|
248
|
-
throw new Error('File too short: expected at least 16 bytes')
|
|
245
|
+
throw new Error('File too short: expected at least 16 bytes')
|
|
249
246
|
}
|
|
250
247
|
|
|
251
248
|
for (let i = 0; i < 8; i++) {
|
|
252
249
|
if (bytes[i] !== MAGIC[i]) {
|
|
253
|
-
throw new Error('Invalid magic bytes: not a .moqtrace file')
|
|
250
|
+
throw new Error('Invalid magic bytes: not a .moqtrace file')
|
|
254
251
|
}
|
|
255
252
|
}
|
|
256
253
|
|
|
257
|
-
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)
|
|
258
|
-
const version = view.getUint32(8, true)
|
|
254
|
+
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength)
|
|
255
|
+
const version = view.getUint32(8, true)
|
|
259
256
|
if (version !== FORMAT_VERSION) {
|
|
260
|
-
throw new Error(`Unsupported format version: ${version} (expected ${FORMAT_VERSION})`)
|
|
257
|
+
throw new Error(`Unsupported format version: ${version} (expected ${FORMAT_VERSION})`)
|
|
261
258
|
}
|
|
262
259
|
|
|
263
|
-
const headerLength = view.getUint32(12, true)
|
|
260
|
+
const headerLength = view.getUint32(12, true)
|
|
264
261
|
if (PREAMBLE_SIZE + headerLength > bytes.length) {
|
|
265
|
-
throw new Error('File truncated: header extends beyond file')
|
|
262
|
+
throw new Error('File truncated: header extends beyond file')
|
|
266
263
|
}
|
|
267
264
|
|
|
268
|
-
return { version, headerLength }
|
|
265
|
+
return { version, headerLength }
|
|
269
266
|
}
|
|
270
267
|
|
|
271
268
|
// --- Public API ---
|
|
@@ -274,56 +271,56 @@ function validatePreamble(bytes: Uint8Array): { version: number; headerLength: n
|
|
|
274
271
|
* Write a complete trace to .moqtrace binary format.
|
|
275
272
|
*/
|
|
276
273
|
export function writeMoqtrace(trace: Trace): Uint8Array {
|
|
277
|
-
const headerCbor = encode(headerToCbor(trace.header))
|
|
278
|
-
const preamble = writePreamble(headerCbor)
|
|
274
|
+
const headerCbor = encode(headerToCbor(trace.header))
|
|
275
|
+
const preamble = writePreamble(headerCbor)
|
|
279
276
|
|
|
280
|
-
const eventChunks: Uint8Array[] = []
|
|
281
|
-
let totalEventBytes = 0
|
|
277
|
+
const eventChunks: Uint8Array[] = []
|
|
278
|
+
let totalEventBytes = 0
|
|
282
279
|
for (const event of trace.events) {
|
|
283
|
-
const chunk = encode(eventToCbor(event))
|
|
284
|
-
eventChunks.push(chunk)
|
|
285
|
-
totalEventBytes += chunk.length
|
|
280
|
+
const chunk = encode(eventToCbor(event))
|
|
281
|
+
eventChunks.push(chunk)
|
|
282
|
+
totalEventBytes += chunk.length
|
|
286
283
|
}
|
|
287
284
|
|
|
288
|
-
const result = new Uint8Array(preamble.length + totalEventBytes)
|
|
289
|
-
result.set(preamble, 0)
|
|
290
|
-
let offset = preamble.length
|
|
285
|
+
const result = new Uint8Array(preamble.length + totalEventBytes)
|
|
286
|
+
result.set(preamble, 0)
|
|
287
|
+
let offset = preamble.length
|
|
291
288
|
for (const chunk of eventChunks) {
|
|
292
|
-
result.set(chunk, offset)
|
|
293
|
-
offset += chunk.length
|
|
289
|
+
result.set(chunk, offset)
|
|
290
|
+
offset += chunk.length
|
|
294
291
|
}
|
|
295
292
|
|
|
296
|
-
return result
|
|
293
|
+
return result
|
|
297
294
|
}
|
|
298
295
|
|
|
299
296
|
/**
|
|
300
297
|
* Read a complete .moqtrace file from bytes.
|
|
301
298
|
*/
|
|
302
299
|
export function readMoqtrace(bytes: Uint8Array): Trace {
|
|
303
|
-
const { headerLength } = validatePreamble(bytes)
|
|
300
|
+
const { headerLength } = validatePreamble(bytes)
|
|
304
301
|
|
|
305
|
-
const headerBytes = bytes.slice(PREAMBLE_SIZE, PREAMBLE_SIZE + headerLength)
|
|
306
|
-
const header = cborToHeader(decode(headerBytes) as Record<string, unknown>)
|
|
302
|
+
const headerBytes = bytes.slice(PREAMBLE_SIZE, PREAMBLE_SIZE + headerLength)
|
|
303
|
+
const header = cborToHeader(decode(headerBytes) as Record<string, unknown>)
|
|
307
304
|
|
|
308
|
-
const eventBytes = bytes.slice(PREAMBLE_SIZE + headerLength)
|
|
309
|
-
const events: TraceEvent[] = []
|
|
305
|
+
const eventBytes = bytes.slice(PREAMBLE_SIZE + headerLength)
|
|
306
|
+
const events: TraceEvent[] = []
|
|
310
307
|
|
|
311
308
|
if (eventBytes.length > 0) {
|
|
312
309
|
decodeMultiple(eventBytes, (obj: unknown) => {
|
|
313
|
-
events.push(cborToEvent(obj as Record<string, unknown>))
|
|
314
|
-
})
|
|
310
|
+
events.push(cborToEvent(obj as Record<string, unknown>))
|
|
311
|
+
})
|
|
315
312
|
}
|
|
316
313
|
|
|
317
|
-
return { header, events }
|
|
314
|
+
return { header, events }
|
|
318
315
|
}
|
|
319
316
|
|
|
320
317
|
/**
|
|
321
318
|
* Read only the header from a .moqtrace file (fast metadata peek).
|
|
322
319
|
*/
|
|
323
320
|
export function readMoqtraceHeader(bytes: Uint8Array): TraceHeader {
|
|
324
|
-
const { headerLength } = validatePreamble(bytes)
|
|
325
|
-
const headerBytes = bytes.slice(PREAMBLE_SIZE, PREAMBLE_SIZE + headerLength)
|
|
326
|
-
return cborToHeader(decode(headerBytes) as Record<string, unknown>)
|
|
321
|
+
const { headerLength } = validatePreamble(bytes)
|
|
322
|
+
const headerBytes = bytes.slice(PREAMBLE_SIZE, PREAMBLE_SIZE + headerLength)
|
|
323
|
+
return cborToHeader(decode(headerBytes) as Record<string, unknown>)
|
|
327
324
|
}
|
|
328
325
|
|
|
329
326
|
/**
|
|
@@ -331,21 +328,21 @@ export function readMoqtraceHeader(bytes: Uint8Array): TraceHeader {
|
|
|
331
328
|
*/
|
|
332
329
|
export interface MoqtraceWriter {
|
|
333
330
|
/** Returns the file preamble (magic + version + header). Write this first. */
|
|
334
|
-
preamble(): Uint8Array
|
|
331
|
+
preamble(): Uint8Array
|
|
335
332
|
/** Encode a single event. Append the returned bytes after the preamble. */
|
|
336
|
-
writeEvent(event: TraceEvent): Uint8Array
|
|
333
|
+
writeEvent(event: TraceEvent): Uint8Array
|
|
337
334
|
}
|
|
338
335
|
|
|
339
336
|
export function createMoqtraceWriter(header: TraceHeader): MoqtraceWriter {
|
|
340
|
-
const headerCbor = encode(headerToCbor(header))
|
|
341
|
-
const preambleBytes = writePreamble(headerCbor)
|
|
337
|
+
const headerCbor = encode(headerToCbor(header))
|
|
338
|
+
const preambleBytes = writePreamble(headerCbor)
|
|
342
339
|
|
|
343
340
|
return {
|
|
344
341
|
preamble(): Uint8Array {
|
|
345
|
-
return preambleBytes
|
|
342
|
+
return preambleBytes
|
|
346
343
|
},
|
|
347
344
|
writeEvent(event: TraceEvent): Uint8Array {
|
|
348
|
-
return encode(eventToCbor(event))
|
|
345
|
+
return encode(eventToCbor(event))
|
|
349
346
|
},
|
|
350
|
-
}
|
|
347
|
+
}
|
|
351
348
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,33 +1,32 @@
|
|
|
1
1
|
// Binary .moqtrace format
|
|
2
|
+
|
|
3
|
+
export type { MoqtraceWriter } from './binary.js'
|
|
2
4
|
export {
|
|
3
|
-
|
|
5
|
+
createMoqtraceWriter,
|
|
4
6
|
readMoqtrace,
|
|
5
7
|
readMoqtraceHeader,
|
|
6
|
-
|
|
7
|
-
} from './binary.js'
|
|
8
|
-
export type { MoqtraceWriter } from './binary.js';
|
|
9
|
-
|
|
10
|
-
// Recorder
|
|
11
|
-
export { createRecorder } from './recorder.js';
|
|
12
|
-
export type { TraceRecorder } from './recorder.js';
|
|
13
|
-
|
|
8
|
+
writeMoqtrace,
|
|
9
|
+
} from './binary.js'
|
|
14
10
|
// JSON (convenience)
|
|
15
|
-
export { traceToJSON } from './json.js'
|
|
11
|
+
export { traceToJSON } from './json.js'
|
|
12
|
+
export type { TraceRecorder } from './recorder.js'
|
|
13
|
+
// Recorder
|
|
14
|
+
export { createRecorder } from './recorder.js'
|
|
16
15
|
|
|
17
16
|
// Types
|
|
18
17
|
export type {
|
|
19
|
-
|
|
20
|
-
TraceHeader,
|
|
21
|
-
TraceEvent,
|
|
18
|
+
AnnotationEvent,
|
|
22
19
|
ControlMessageEvent,
|
|
23
|
-
|
|
24
|
-
StreamClosedEvent,
|
|
20
|
+
DetailLevel,
|
|
25
21
|
ObjectHeaderEvent,
|
|
26
22
|
ObjectPayloadEvent,
|
|
27
|
-
StateChangeEvent,
|
|
28
|
-
TraceErrorEvent,
|
|
29
|
-
AnnotationEvent,
|
|
30
|
-
DetailLevel,
|
|
31
23
|
Perspective,
|
|
32
24
|
RecorderOptions,
|
|
33
|
-
|
|
25
|
+
StateChangeEvent,
|
|
26
|
+
StreamClosedEvent,
|
|
27
|
+
StreamOpenedEvent,
|
|
28
|
+
Trace,
|
|
29
|
+
TraceErrorEvent,
|
|
30
|
+
TraceEvent,
|
|
31
|
+
TraceHeader,
|
|
32
|
+
} from './types.js'
|
package/src/json.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Trace } from './types.js'
|
|
1
|
+
import type { Trace } from './types.js'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Serialize a trace to human-readable JSON.
|
|
@@ -9,13 +9,19 @@ import type { Trace } from './types.js';
|
|
|
9
9
|
* (`writeMoqtrace` / `readMoqtrace`).
|
|
10
10
|
*/
|
|
11
11
|
export function traceToJSON(trace: Trace): string {
|
|
12
|
-
return JSON.stringify(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
12
|
+
return JSON.stringify(
|
|
13
|
+
trace,
|
|
14
|
+
(_key, value) => {
|
|
15
|
+
if (typeof value === 'bigint') {
|
|
16
|
+
return `0x${value.toString(16)}`
|
|
17
|
+
}
|
|
18
|
+
if (value instanceof Uint8Array) {
|
|
19
|
+
return Array.from(value)
|
|
20
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
21
|
+
.join('')
|
|
22
|
+
}
|
|
23
|
+
return value
|
|
24
|
+
},
|
|
25
|
+
2,
|
|
26
|
+
)
|
|
21
27
|
}
|