@moqtap/codec 0.11.0 → 0.12.0

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.
Files changed (132) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +3 -2
  3. package/dist/{auth-redaction-DsdLq4Qs.d.cts → auth-redaction-B9JJOlIY.d.cts} +0 -2
  4. package/dist/{auth-redaction-DsdLq4Qs.d.ts → auth-redaction-B9JJOlIY.d.ts} +0 -2
  5. package/dist/chunk-OBATJBNL.cjs +868 -0
  6. package/dist/chunk-T2TCLZZV.js +2304 -0
  7. package/dist/chunk-WB65UG7G.cjs +2304 -0
  8. package/dist/chunk-XPCBPACE.js +868 -0
  9. package/dist/{codec-c0YEwwWn.d.ts → codec-B-oUU-cp.d.ts} +2 -2
  10. package/dist/{codec-DHzKAUCa.d.cts → codec-B3RpCI9k.d.cts} +2 -2
  11. package/dist/{codec-Clu_skx8.d.cts → codec-B5pcOS3m.d.cts} +2 -2
  12. package/dist/{codec-DxtgPxJS.d.ts → codec-BLjxwK2f.d.ts} +2 -2
  13. package/dist/{codec-BkheTXO7.d.ts → codec-BV3CL_3m.d.ts} +2 -2
  14. package/dist/{codec-Bb6GKTrv.d.ts → codec-BYCDWgED.d.ts} +2 -2
  15. package/dist/{codec-ejDu-va6.d.ts → codec-Bwqq7ZQT.d.ts} +2 -2
  16. package/dist/{codec-76xzrLTL.d.cts → codec-BzWxOFby.d.cts} +2 -2
  17. package/dist/{codec-CM5yd6n3.d.ts → codec-C-nJhNNl.d.ts} +2 -2
  18. package/dist/{codec-BgpfHoAd.d.cts → codec-C11VEPbQ.d.cts} +2 -2
  19. package/dist/codec-C9U0Vzy9.d.cts +68 -0
  20. package/dist/{codec-yYKGOipj.d.ts → codec-CCx22jnd.d.ts} +2 -2
  21. package/dist/{codec-mVYqkIUF.d.ts → codec-CP3zkfTv.d.ts} +2 -2
  22. package/dist/{codec-qSbO5nOa.d.ts → codec-CRmOLDpt.d.ts} +2 -2
  23. package/dist/{codec-CpOpemR8.d.cts → codec-CUu56DDU.d.cts} +2 -2
  24. package/dist/codec-Cb8mUre3.d.ts +68 -0
  25. package/dist/{codec-DELe00w_.d.cts → codec-CemqAQdR.d.cts} +2 -2
  26. package/dist/{codec-8p40WdLg.d.ts → codec-CxMvsVMS.d.ts} +2 -2
  27. package/dist/{codec-zfzg9uiy.d.cts → codec-DIgMVTi4.d.cts} +2 -2
  28. package/dist/{codec-DdVBtvx7.d.ts → codec-DYzozF68.d.ts} +2 -2
  29. package/dist/{codec-kaBUzdpV.d.ts → codec-D_O9zxax.d.ts} +2 -2
  30. package/dist/{codec-XLrnreeu.d.cts → codec-Ddc-QxV6.d.cts} +2 -2
  31. package/dist/{codec-C5s1eBJX.d.cts → codec-DoojMl2z.d.cts} +2 -2
  32. package/dist/{codec-DlxGuYMv.d.ts → codec-DqdjiOQF.d.ts} +2 -2
  33. package/dist/{codec-Cshdl9Tt.d.cts → codec-Dstemwrq.d.cts} +2 -2
  34. package/dist/{codec-BN2Bu0KI.d.ts → codec-Dt6nuejp.d.ts} +2 -2
  35. package/dist/{codec-BwVDkokh.d.cts → codec-DuYhd8fP.d.cts} +2 -2
  36. package/dist/{codec-I8u2pfS4.d.cts → codec-DwNOFgPU.d.cts} +2 -2
  37. package/dist/{codec-GAY4lybi.d.cts → codec-l01BpNhF.d.cts} +2 -2
  38. package/dist/{codec-Cb8HC3XV.d.cts → codec-psN2vB6I.d.cts} +2 -2
  39. package/dist/draft07-session.d.cts +3 -3
  40. package/dist/draft07-session.d.ts +3 -3
  41. package/dist/draft07.d.cts +4 -4
  42. package/dist/draft07.d.ts +4 -4
  43. package/dist/draft08-session.d.cts +3 -3
  44. package/dist/draft08-session.d.ts +3 -3
  45. package/dist/draft08.d.cts +5 -5
  46. package/dist/draft08.d.ts +5 -5
  47. package/dist/draft09-session.d.cts +3 -3
  48. package/dist/draft09-session.d.ts +3 -3
  49. package/dist/draft09.d.cts +5 -5
  50. package/dist/draft09.d.ts +5 -5
  51. package/dist/draft10-session.d.cts +3 -3
  52. package/dist/draft10-session.d.ts +3 -3
  53. package/dist/draft10.d.cts +5 -5
  54. package/dist/draft10.d.ts +5 -5
  55. package/dist/draft11-session.d.cts +3 -3
  56. package/dist/draft11-session.d.ts +3 -3
  57. package/dist/draft11.d.cts +5 -5
  58. package/dist/draft11.d.ts +5 -5
  59. package/dist/draft12-session.d.cts +3 -3
  60. package/dist/draft12-session.d.ts +3 -3
  61. package/dist/draft12.d.cts +5 -5
  62. package/dist/draft12.d.ts +5 -5
  63. package/dist/draft13-session.d.cts +3 -3
  64. package/dist/draft13-session.d.ts +3 -3
  65. package/dist/draft13.d.cts +5 -5
  66. package/dist/draft13.d.ts +5 -5
  67. package/dist/draft14-session.d.cts +3 -3
  68. package/dist/draft14-session.d.ts +3 -3
  69. package/dist/draft14.d.cts +5 -5
  70. package/dist/draft14.d.ts +5 -5
  71. package/dist/draft15-session.d.cts +3 -3
  72. package/dist/draft15-session.d.ts +3 -3
  73. package/dist/draft15.d.cts +5 -5
  74. package/dist/draft15.d.ts +5 -5
  75. package/dist/draft16-session.d.cts +3 -3
  76. package/dist/draft16-session.d.ts +3 -3
  77. package/dist/draft16.d.cts +5 -5
  78. package/dist/draft16.d.ts +5 -5
  79. package/dist/draft17-session.d.cts +3 -3
  80. package/dist/draft17-session.d.ts +3 -3
  81. package/dist/draft17.d.cts +4 -4
  82. package/dist/draft17.d.ts +4 -4
  83. package/dist/draft18-session.d.cts +3 -3
  84. package/dist/draft18-session.d.ts +3 -3
  85. package/dist/draft18.d.cts +4 -4
  86. package/dist/draft18.d.ts +4 -4
  87. package/dist/draft19-session.d.cts +3 -3
  88. package/dist/draft19-session.d.ts +3 -3
  89. package/dist/draft19.d.cts +4 -4
  90. package/dist/draft19.d.ts +4 -4
  91. package/dist/draft20-session.d.cts +3 -3
  92. package/dist/draft20-session.d.ts +3 -3
  93. package/dist/draft20.d.cts +4 -4
  94. package/dist/draft20.d.ts +4 -4
  95. package/dist/draft21-session.cjs +8 -0
  96. package/dist/draft21-session.d.cts +195 -0
  97. package/dist/draft21-session.d.ts +195 -0
  98. package/dist/draft21-session.js +8 -0
  99. package/dist/draft21.cjs +222 -0
  100. package/dist/draft21.d.cts +176 -0
  101. package/dist/draft21.d.ts +176 -0
  102. package/dist/draft21.js +222 -0
  103. package/dist/index.cjs +7 -1
  104. package/dist/index.d.cts +23 -18
  105. package/dist/index.d.ts +23 -18
  106. package/dist/index.js +7 -1
  107. package/dist/{session-types-Dn7b3RZM.d.ts → session-types-Cxx7W8zZ.d.ts} +1 -1
  108. package/dist/{session-types-B9idsih-.d.cts → session-types-DZkI_qFG.d.cts} +1 -1
  109. package/dist/session.cjs +5 -1
  110. package/dist/session.d.cts +5 -3
  111. package/dist/session.d.ts +5 -3
  112. package/dist/session.js +5 -1
  113. package/dist/{types-DG5_iKuv.d.cts → types-2NisMA8_.d.cts} +1 -1
  114. package/dist/{types-DG5_iKuv.d.ts → types-2NisMA8_.d.ts} +1 -1
  115. package/dist/types-DDwidj2d.d.cts +371 -0
  116. package/dist/types-DDwidj2d.d.ts +371 -0
  117. package/package.json +14 -2
  118. package/src/core/auth-redaction.ts +0 -2
  119. package/src/core/types.ts +1 -0
  120. package/src/drafts/draft19/codec.ts +1 -1
  121. package/src/drafts/draft20/codec.ts +1 -1
  122. package/src/drafts/draft21/codec.ts +1816 -0
  123. package/src/drafts/draft21/data-streams.ts +1338 -0
  124. package/src/drafts/draft21/error-codes.ts +135 -0
  125. package/src/drafts/draft21/index.ts +168 -0
  126. package/src/drafts/draft21/messages.ts +68 -0
  127. package/src/drafts/draft21/rules.ts +107 -0
  128. package/src/drafts/draft21/session-fsm.ts +1063 -0
  129. package/src/drafts/draft21/session.ts +21 -0
  130. package/src/drafts/draft21/types.ts +473 -0
  131. package/src/index.ts +9 -1
  132. package/src/session.ts +4 -0
@@ -0,0 +1,21 @@
1
+ import { Draft21SessionFSM } from './session-fsm.js'
2
+
3
+ export type {
4
+ ProtocolViolation,
5
+ SessionPhase,
6
+ SideEffect,
7
+ TransitionResult,
8
+ ValidationResult,
9
+ } from '../../core/session-types.js'
10
+ export type {
11
+ FillFetchStreamPhase,
12
+ FillFetchStreamState,
13
+ PublisherSide,
14
+ RequestKind,
15
+ } from './session-fsm.js'
16
+
17
+ export function createDraft21SessionState(role: 'client' | 'server'): Draft21SessionFSM {
18
+ return new Draft21SessionFSM(role)
19
+ }
20
+
21
+ export { Draft21SessionFSM }
@@ -0,0 +1,473 @@
1
+ // Draft-21 specific message types
2
+
3
+ // Unknown parameter for passthrough
4
+ export interface UnknownParam {
5
+ readonly id: string // e.g. "0x21"
6
+ readonly length: number
7
+ readonly raw_hex: string
8
+ }
9
+
10
+ // Authorization token parameter (nested structure within length-prefixed param)
11
+ export interface AuthorizationToken {
12
+ readonly alias_type: bigint // 0=DELETE, 1=REGISTER, 2=USE_ALIAS, 3=USE_VALUE
13
+ readonly token_alias?: bigint // present for DELETE(0), REGISTER(1), USE_ALIAS(2)
14
+ readonly token_type?: bigint // present for REGISTER(1), USE_VALUE(3)
15
+ readonly token_value?: Uint8Array // present for REGISTER(1), USE_VALUE(3)
16
+ }
17
+
18
+ // Setup options (KVP encoding, no count prefix) — unchanged from draft-19
19
+ export interface Draft21SetupOptions {
20
+ path?: string // 0x01 odd
21
+ authorization_token?: readonly AuthorizationToken[] // 0x03 odd
22
+ max_auth_token_cache_size?: bigint // 0x04 even
23
+ authority?: string // 0x05 odd
24
+ max_filter_ranges?: bigint // 0x06 even
25
+ moqt_implementation?: string // 0x07 odd
26
+ max_request_updates?: bigint // 0x08 even
27
+ unknown?: UnknownParam[]
28
+ }
29
+
30
+ /**
31
+ * LOCATION_FILTER (0x21) — draft-21 Section 3.3.1.
32
+ *
33
+ * The draft-19 `Filter Type` discriminator (0x1 Next Group Start / 0x2 Largest
34
+ * Object / 0x3 AbsoluteStart / 0x4 AbsoluteRange) is gone; the shape is the
35
+ * number of vi64 fields the value holds. The fields below carry the wire
36
+ * values verbatim, unresolved:
37
+ *
38
+ * - 1 field → `start_group` alone is RELATIVE: start is
39
+ * {Largest Object.Group + 1 - start_group, 0}. Open-ended.
40
+ * - 2 fields → absolute start {start_group, start_object}, except that
41
+ * {0, 0} means the Next Object. Open-ended.
42
+ * - 3 fields → end group is `start_group + end_group_delta`; `end_object`
43
+ * omitted means every object in that group.
44
+ * - 4 fields → the fully specified INCLUSIVE range
45
+ * {start_group, start_object} … {start_group + end_group_delta,
46
+ * end_object}.
47
+ *
48
+ * `removed: true` is the `Length == 0` form, which in REQUEST_UPDATE removes an
49
+ * existing filter.
50
+ *
51
+ * The range is inclusive at both ends. draft-19's "last Object, plus 1" and
52
+ * "Object == 0 means the whole group" conventions are gone, so nothing here is
53
+ * ever incremented or decremented on the way in or out.
54
+ */
55
+ export interface LocationFilter {
56
+ readonly start_group?: bigint
57
+ readonly start_object?: bigint
58
+ readonly end_group_delta?: bigint
59
+ readonly end_object?: bigint
60
+ readonly removed?: boolean // Length == 0: no filter / remove the filter
61
+ }
62
+
63
+ // Range Filter parameter (0x25-0x29). Selects Objects/Tracks by integer
64
+ // ranges over Object header fields or Property values.
65
+ export interface RangeFilterRange {
66
+ readonly start: bigint
67
+ readonly end?: bigint // omitted on the final Range = open-ended (no upper bound)
68
+ }
69
+
70
+ export interface RangeFilter {
71
+ readonly set_id?: bigint
72
+ readonly property_type?: bigint // only for OBJECT_PROPERTY_FILTER / TRACK_PROPERTY_FILTER
73
+ readonly ranges?: RangeFilterRange[]
74
+ readonly removed?: boolean // REQUEST_UPDATE length-0 form: remove this filter
75
+ }
76
+
77
+ // Largest object location parameter
78
+ export interface LargestObject {
79
+ readonly group: bigint
80
+ readonly object: bigint
81
+ }
82
+
83
+ /**
84
+ * FILL_PARAMETERS (0x23) value — NEW in draft-20 (Section 9.20.16).
85
+ *
86
+ * A separate parameter scope carrying only the settings that differ from the
87
+ * subscription's. Table 6 closes the list to exactly these eight types;
88
+ * TRACK_PROPERTY_FILTER (0x29) is deliberately excluded.
89
+ *
90
+ * The mere presence of the parameter is what requests a fill fetch stream, so
91
+ * an empty value is meaningful — it asks for a fill with everything inherited.
92
+ */
93
+ export interface Draft21FillParameters {
94
+ fill_timeout?: bigint // 0x0a varint
95
+ subscriber_priority?: bigint // 0x20 uint8
96
+ location_filter?: LocationFilter // 0x21 length-prefixed — selects the FILL range
97
+ group_order?: bigint // 0x22 uint8
98
+ // Section 3.3.2 permits each of the five more than once in a message: a
99
+ // filter parameter carries one SetID, so two alternatives over the same
100
+ // field need two parameters. A single filter is a one-element list.
101
+ subgroup_filter?: readonly RangeFilter[] // 0x25 length-prefixed
102
+ objectid_filter?: readonly RangeFilter[] // 0x26 length-prefixed
103
+ priority_filter?: readonly RangeFilter[] // 0x27 length-prefixed
104
+ object_property_filter?: readonly RangeFilter[] // 0x28 length-prefixed
105
+ }
106
+
107
+ // Message Parameters (delta-encoded types, count-prefixed)
108
+ export interface Draft21Params {
109
+ object_delivery_timeout?: bigint // 0x02 varint
110
+ authorization_token?: readonly AuthorizationToken[] // 0x03 length-prefixed nested
111
+ rendezvous_timeout?: bigint // 0x04 varint
112
+ subgroup_delivery_timeout?: bigint // 0x06 varint
113
+ expires?: bigint // 0x08 varint
114
+ largest_object?: LargestObject // 0x09 Location (2 bare varints, NOT length-prefixed)
115
+ fill_timeout?: bigint // 0x0a varint
116
+ forward?: bigint // 0x10 uint8
117
+ subscriber_priority?: bigint // 0x20 uint8
118
+ location_filter?: LocationFilter // 0x21 length-prefixed; see LocationFilter for the draft-21 shape
119
+ group_order?: bigint // 0x22 uint8
120
+ fill_parameters?: Draft21FillParameters // 0x23 length-prefixed nested (NEW in draft-20)
121
+ // Section 3.3.2 permits each of the five more than once in a message: a
122
+ // filter parameter carries one SetID, so two alternatives over the same
123
+ // field need two parameters. A single filter is a one-element list.
124
+ subgroup_filter?: readonly RangeFilter[] // 0x25 length-prefixed
125
+ objectid_filter?: readonly RangeFilter[] // 0x26 length-prefixed
126
+ priority_filter?: readonly RangeFilter[] // 0x27 length-prefixed
127
+ object_property_filter?: readonly RangeFilter[] // 0x28 length-prefixed
128
+ track_property_filter?: readonly RangeFilter[] // 0x29 length-prefixed
129
+ new_group_request?: bigint // 0x32 varint
130
+ track_namespace_prefix?: string[] // 0x34 Track Namespace encoding
131
+ include_properties?: bigint // 0x35 uint8, 0 or 1, default 1 (NEW in draft-20)
132
+ unknown?: UnknownParam[]
133
+ }
134
+
135
+ // Track properties (KVP encoding, no count prefix, read until end of payload)
136
+ export interface Draft21TrackProperties {
137
+ object_delivery_timeout?: bigint // 0x02 even varint
138
+ max_cache_duration?: bigint // 0x04 even varint
139
+ subgroup_delivery_timeout?: bigint // 0x06 even varint
140
+ immutable_properties?: Uint8Array // 0x0b odd length-prefixed
141
+ default_publisher_priority?: bigint // 0x0e even varint
142
+ default_publisher_group_order?: bigint // 0x22 even varint
143
+ dynamic_groups?: bigint // 0x30 even varint
144
+ unknown?: UnknownParam[]
145
+ }
146
+
147
+ // Draft-21 message type tag union
148
+ export type Draft21MessageType =
149
+ | 'setup'
150
+ | 'subscribe'
151
+ | 'subscribe_ok'
152
+ | 'request_update'
153
+ | 'publish_state_notify'
154
+ | 'publish'
155
+ | 'publish_done'
156
+ | 'publish_namespace'
157
+ | 'namespace'
158
+ | 'namespace_done'
159
+ | 'subscribe_namespace'
160
+ | 'subscribe_tracks'
161
+ | 'publish_skipped'
162
+ | 'fetch'
163
+ | 'fetch_ok'
164
+ | 'track_status'
165
+ | 'request_ok'
166
+ | 'request_error'
167
+ | 'goaway'
168
+
169
+ // Base
170
+ export interface Draft21BaseMessage {
171
+ readonly type: Draft21MessageType
172
+ }
173
+
174
+ // Setup — single unified message (0x2F00)
175
+ export interface Draft21Setup extends Draft21BaseMessage {
176
+ readonly type: 'setup'
177
+ readonly options: Draft21SetupOptions
178
+ }
179
+
180
+ export interface Draft21Subscribe extends Draft21BaseMessage {
181
+ readonly type: 'subscribe'
182
+ readonly request_id: bigint
183
+ readonly track_namespace: string[]
184
+ readonly track_name: string
185
+ readonly parameters: Draft21Params
186
+ }
187
+
188
+ export interface Draft21SubscribeOk extends Draft21BaseMessage {
189
+ readonly type: 'subscribe_ok'
190
+ readonly track_alias: bigint
191
+ readonly parameters: Draft21Params
192
+ readonly track_properties: Draft21TrackProperties
193
+ }
194
+
195
+ export interface Draft21RequestUpdate extends Draft21BaseMessage {
196
+ readonly type: 'request_update'
197
+ readonly request_id: bigint
198
+ readonly parameters: Draft21Params
199
+ }
200
+
201
+ /**
202
+ * PUBLISH_STATE_NOTIFY (0x22) — NEW in draft-20, Section 9.10.
203
+ *
204
+ * No Request ID: the message is identified by the subscription's bidirectional
205
+ * stream it arrives on, like SUBSCRIBE_OK, PUBLISH_DONE and FETCH_OK.
206
+ */
207
+ export interface Draft21PublishStateNotify extends Draft21BaseMessage {
208
+ readonly type: 'publish_state_notify'
209
+ readonly parameters: Draft21Params
210
+ }
211
+
212
+ export interface Draft21Publish extends Draft21BaseMessage {
213
+ readonly type: 'publish'
214
+ readonly request_id: bigint
215
+ readonly track_namespace: string[]
216
+ readonly track_name: string
217
+ readonly track_alias: bigint
218
+ readonly parameters: Draft21Params
219
+ readonly track_properties: Draft21TrackProperties
220
+ }
221
+
222
+ export interface Draft21PublishDone extends Draft21BaseMessage {
223
+ readonly type: 'publish_done'
224
+ readonly status_code: bigint
225
+ /**
226
+ * Number of streams opened for the subscription, including empty subgroups
227
+ * and — new in draft-20 — fill fetch streams (Section 9.9), or the
228
+ * `UNKNOWN_STREAM_COUNT` sentinel exported from `codec.ts` (2^64 - 1, raised
229
+ * from draft-19's 2^62 - 1) when the publisher cannot state it exactly.
230
+ *
231
+ * `bigint`, not `number`: the sentinel does not fit a double.
232
+ */
233
+ readonly stream_count: bigint
234
+ readonly reason_phrase: string
235
+ }
236
+
237
+ export interface Draft21PublishNamespace extends Draft21BaseMessage {
238
+ readonly type: 'publish_namespace'
239
+ readonly request_id: bigint
240
+ readonly track_namespace: string[]
241
+ readonly parameters: Draft21Params
242
+ }
243
+
244
+ export interface Draft21Namespace extends Draft21BaseMessage {
245
+ readonly type: 'namespace'
246
+ readonly namespace_suffix: string[]
247
+ }
248
+
249
+ export interface Draft21NamespaceDone extends Draft21BaseMessage {
250
+ readonly type: 'namespace_done'
251
+ readonly namespace_suffix: string[]
252
+ }
253
+
254
+ export interface Draft21SubscribeNamespace extends Draft21BaseMessage {
255
+ readonly type: 'subscribe_namespace'
256
+ readonly request_id: bigint
257
+ readonly namespace_prefix: string[]
258
+ readonly parameters: Draft21Params
259
+ }
260
+
261
+ export interface Draft21SubscribeTracks extends Draft21BaseMessage {
262
+ readonly type: 'subscribe_tracks'
263
+ readonly request_id: bigint
264
+ readonly namespace_prefix: string[]
265
+ readonly parameters: Draft21Params
266
+ }
267
+
268
+ export interface Draft21PublishSkipped extends Draft21BaseMessage {
269
+ readonly type: 'publish_skipped'
270
+ readonly namespace_suffix: string[]
271
+ readonly track_name: string
272
+ }
273
+
274
+ /**
275
+ * FETCH (0x16) — the byte layout was rewritten in draft-20 (Section 9.11).
276
+ *
277
+ * Gone: the `Fetch Type` field and its enum, the `Standalone Fetch` and
278
+ * `Joining Fetch` structures, and the inline `Start Location` / `End Location`.
279
+ * Track Namespace and Track Name are inline fields of FETCH itself, and the
280
+ * range travels in the LOCATION_FILTER parameter. A FETCH with no
281
+ * LOCATION_FILTER covers {0,0} through Largest Object, inclusive.
282
+ *
283
+ * The codepoint did not change, so a draft-19 decoder fed one of these reads
284
+ * the Number of Track Namespace Fields count as a Fetch Type and mis-parses in
285
+ * silence. There is no in-band version signal that catches it.
286
+ */
287
+ export interface Draft21Fetch extends Draft21BaseMessage {
288
+ readonly type: 'fetch'
289
+ readonly request_id: bigint
290
+ readonly track_namespace: string[]
291
+ readonly track_name: string
292
+ readonly parameters: Draft21Params
293
+ }
294
+
295
+ /**
296
+ * FETCH_OK (0x18) — bytes identical to draft-19, meaning changed.
297
+ *
298
+ * `end_group` / `end_object` are the INCLUSIVE end of the range the response
299
+ * covers: the last Object actually covered. draft-19's "the last Object, plus
300
+ * 1; or 0 to indicate the entire Group" is gone (draft-21 Section 9.12 with
301
+ * Section 3.3.1). The same bytes mean a different object under the two drafts,
302
+ * and nothing on the wire distinguishes them.
303
+ */
304
+ export interface Draft21FetchOk extends Draft21BaseMessage {
305
+ readonly type: 'fetch_ok'
306
+ readonly end_of_track: number // uint8
307
+ readonly end_group: bigint
308
+ readonly end_object: bigint
309
+ readonly parameters: Draft21Params
310
+ readonly track_properties: Draft21TrackProperties
311
+ }
312
+
313
+ // Track Status — same format as SUBSCRIBE with the type set to 0xD
314
+ export interface Draft21TrackStatus extends Draft21BaseMessage {
315
+ readonly type: 'track_status'
316
+ readonly request_id: bigint
317
+ readonly track_namespace: string[]
318
+ readonly track_name: string
319
+ readonly parameters: Draft21Params
320
+ }
321
+
322
+ // REQUEST_OK — also the PUBLISH_OK / REQUEST_UPDATE_OK / TRACK_STATUS_OK alias
323
+ export interface Draft21RequestOk extends Draft21BaseMessage {
324
+ readonly type: 'request_ok'
325
+ readonly parameters: Draft21Params
326
+ readonly track_properties: Draft21TrackProperties
327
+ }
328
+
329
+ /**
330
+ * Redirect structure, used inside REQUEST_ERROR when error_code = REDIRECT (0x34).
331
+ *
332
+ * draft-21 Section 9.4.1 names the namespace/name pair "the Redirect target"
333
+ * and dropped draft-19's rule that a zero-length pair meant "reuse the values
334
+ * from the original request". An empty namespace and name are now a literal
335
+ * empty namespace and name.
336
+ */
337
+ export interface Redirect {
338
+ readonly connect_uri: string
339
+ readonly track_namespace: string[]
340
+ readonly track_name: string
341
+ }
342
+
343
+ export interface Draft21RequestError extends Draft21BaseMessage {
344
+ readonly type: 'request_error'
345
+ readonly error_code: bigint
346
+ readonly retry_interval: bigint
347
+ readonly reason_phrase: string
348
+ readonly redirect?: Redirect
349
+ }
350
+
351
+ export interface Draft21GoAway extends Draft21BaseMessage {
352
+ readonly type: 'goaway'
353
+ readonly new_session_uri: string
354
+ readonly timeout: bigint
355
+ }
356
+
357
+ // Union of all draft-21 control messages
358
+ export type Draft21Message =
359
+ | Draft21Setup
360
+ | Draft21Subscribe
361
+ | Draft21SubscribeOk
362
+ | Draft21RequestUpdate
363
+ | Draft21PublishStateNotify
364
+ | Draft21Publish
365
+ | Draft21PublishDone
366
+ | Draft21PublishNamespace
367
+ | Draft21Namespace
368
+ | Draft21NamespaceDone
369
+ | Draft21SubscribeNamespace
370
+ | Draft21SubscribeTracks
371
+ | Draft21PublishSkipped
372
+ | Draft21Fetch
373
+ | Draft21FetchOk
374
+ | Draft21TrackStatus
375
+ | Draft21RequestOk
376
+ | Draft21RequestError
377
+ | Draft21GoAway
378
+
379
+ // ─── Data stream types ──────────────────────────────────────────────────────
380
+
381
+ export interface ObjectPayload {
382
+ readonly type: 'object'
383
+ readonly byteOffset: number
384
+ readonly payloadByteOffset: number
385
+ readonly objectId: bigint
386
+ /** The Object ID Delta as it appeared on the wire, before delta resolution. */
387
+ readonly objectIdDelta?: bigint
388
+ readonly payloadLength: number
389
+ readonly status?: bigint
390
+ readonly extensionData: Uint8Array
391
+ readonly objectProperties?: Record<string, bigint>
392
+ readonly payload: Uint8Array
393
+ }
394
+
395
+ export interface SubgroupStream {
396
+ readonly type: 'subgroup'
397
+ /** SUBGROUP_HEADER `Type Flags` (draft-21 Section 11.3.1). */
398
+ readonly headerType: number
399
+ readonly trackAlias: bigint
400
+ readonly groupId: bigint
401
+ readonly subgroupId: bigint
402
+ readonly publisherPriority: number
403
+ readonly endOfGroup?: boolean
404
+ readonly firstObject?: boolean
405
+ readonly objects: ObjectPayload[]
406
+ }
407
+
408
+ export interface DatagramObject {
409
+ readonly type: 'datagram'
410
+ /** OBJECT_DATAGRAM `Type Flags` (draft-21 Section 11.2.1). */
411
+ readonly datagramType: number
412
+ readonly trackAlias: bigint
413
+ readonly groupId: bigint
414
+ readonly objectId: bigint
415
+ readonly publisherPriority: number
416
+ readonly endOfGroup?: boolean
417
+ readonly objectStatus?: bigint
418
+ readonly objectProperties?: Record<string, bigint>
419
+ readonly payloadLength: number
420
+ readonly payload: Uint8Array
421
+ }
422
+
423
+ export interface FetchObjectPayload extends ObjectPayload {
424
+ readonly serializationFlags: number
425
+ readonly groupId: bigint
426
+ /** The Group ID Delta as it appeared on the wire, before delta resolution. */
427
+ readonly groupIdDelta?: bigint
428
+ readonly subgroupId: bigint
429
+ readonly publisherPriority: number
430
+ readonly objectProperties?: Record<string, bigint>
431
+ }
432
+
433
+ export interface FetchStream {
434
+ readonly type: 'fetch'
435
+ /**
436
+ * The Request ID of the message that opened the stream. In draft-21 that is
437
+ * not necessarily a FETCH: a fill fetch stream (Section 3.4) carries the
438
+ * Request ID of the SUBSCRIBE or REQUEST_UPDATE that requested the fill.
439
+ */
440
+ readonly requestId: bigint
441
+ readonly objects: FetchObjectPayload[]
442
+ }
443
+
444
+ export type Draft21DataStream = SubgroupStream | DatagramObject | FetchStream
445
+
446
+ // Streaming data stream decoder types
447
+ export interface SubgroupStreamHeader {
448
+ readonly type: 'subgroup_header'
449
+ /**
450
+ * SUBGROUP_HEADER `Type Flags`, the same value `SubgroupStream.headerType`
451
+ * carries. It is reported so the incremental decoder does not drop the flags
452
+ * the header encodes, which is what lets a consumer tell the modes apart.
453
+ */
454
+ readonly headerType: number
455
+ readonly trackAlias: bigint
456
+ readonly groupId: bigint
457
+ /**
458
+ * Under Subgroup Mode 0b01 this is the first Object's ID, which is why the
459
+ * header is not emitted until that Object has been read.
460
+ */
461
+ readonly subgroupId: bigint
462
+ readonly publisherPriority: number
463
+ readonly endOfGroup?: boolean
464
+ readonly firstObject?: boolean
465
+ }
466
+
467
+ export interface FetchStreamHeader {
468
+ readonly type: 'fetch_header'
469
+ readonly requestId: bigint
470
+ }
471
+
472
+ export type DataStreamHeader = SubgroupStreamHeader | FetchStreamHeader
473
+ export type DataStreamEvent = DataStreamHeader | ObjectPayload
package/src/index.ts CHANGED
@@ -40,6 +40,8 @@ import type { Draft19Codec } from './drafts/draft19/codec.js'
40
40
  import { createDraft19Codec } from './drafts/draft19/codec.js'
41
41
  import type { Draft20Codec } from './drafts/draft20/codec.js'
42
42
  import { createDraft20Codec } from './drafts/draft20/codec.js'
43
+ import type { Draft21Codec } from './drafts/draft21/codec.js'
44
+ import { createDraft21Codec } from './drafts/draft21/codec.js'
43
45
 
44
46
  /**
45
47
  * Version identifiers for each MoQT draft, keyed by short aliases.
@@ -69,6 +71,7 @@ export const DRAFT_VERSIONS: Record<string, bigint> = {
69
71
  '18': 0xff000012n,
70
72
  '19': 0xff000013n,
71
73
  '20': 0xff000014n,
74
+ '21': 0xff000015n,
72
75
  }
73
76
 
74
77
  export function createCodec(options: CodecOptions & { draft: '07' }): Draft07Codec
@@ -85,6 +88,7 @@ export function createCodec(options: CodecOptions & { draft: '17' }): Draft17Cod
85
88
  export function createCodec(options: CodecOptions & { draft: '18' }): Draft18Codec
86
89
  export function createCodec(options: CodecOptions & { draft: '19' }): Draft19Codec
87
90
  export function createCodec(options: CodecOptions & { draft: '20' }): Draft20Codec
91
+ export function createCodec(options: CodecOptions & { draft: '21' }): Draft21Codec
88
92
 
89
93
  /**
90
94
  * Create a codec for the specified draft version.
@@ -109,6 +113,7 @@ export function createCodec(
109
113
  | Draft18Codec
110
114
  | Draft19Codec
111
115
  | Draft20Codec
116
+ | Draft21Codec
112
117
  export function createCodec(
113
118
  options: CodecOptions,
114
119
  ):
@@ -125,7 +130,8 @@ export function createCodec(
125
130
  | Draft17Codec
126
131
  | Draft18Codec
127
132
  | Draft19Codec
128
- | Draft20Codec {
133
+ | Draft20Codec
134
+ | Draft21Codec {
129
135
  const draft = DRAFT_VERSIONS[options.draft]
130
136
  if (!draft) {
131
137
  throw new Error(
@@ -164,6 +170,8 @@ export function createCodec(
164
170
  return createDraft19Codec()
165
171
  case '20':
166
172
  return createDraft20Codec()
173
+ case '21':
174
+ return createDraft21Codec()
167
175
  default:
168
176
  throw new Error(`Unsupported draft: ${draft}`)
169
177
  }
package/src/session.ts CHANGED
@@ -36,6 +36,8 @@ import { createDraft19SessionState } from './drafts/draft19/session.js'
36
36
  import type { Draft19Message, Draft19MessageType } from './drafts/draft19/types.js'
37
37
  import { createDraft20SessionState } from './drafts/draft20/session.js'
38
38
  import type { Draft20Message, Draft20MessageType } from './drafts/draft20/types.js'
39
+ import { createDraft21SessionState } from './drafts/draft21/session.js'
40
+ import type { Draft21Message, Draft21MessageType } from './drafts/draft21/types.js'
39
41
 
40
42
  type DraftSessionStateMap = {
41
43
  '07': SessionState<Draft07Message, Draft07MessageType>
@@ -52,6 +54,7 @@ type DraftSessionStateMap = {
52
54
  '18': SessionState<Draft18Message, Draft18MessageType>
53
55
  '19': SessionState<Draft19Message, Draft19MessageType>
54
56
  '20': SessionState<Draft20Message, Draft20MessageType>
57
+ '21': SessionState<Draft21Message, Draft21MessageType>
55
58
  }
56
59
 
57
60
  /**
@@ -77,6 +80,7 @@ export function createSessionState<T extends Draft>(
77
80
  '18': createDraft18SessionState,
78
81
  '19': createDraft19SessionState,
79
82
  '20': createDraft20SessionState,
83
+ '21': createDraft21SessionState,
80
84
  }
81
85
 
82
86
  const factory = factories[draft]