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