@moqtap/codec 0.8.1 → 0.9.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 (127) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README.md +16 -4
  3. package/dist/chunk-BMJMY6FX.cjs +868 -0
  4. package/dist/chunk-MAXEHYVB.cjs +2362 -0
  5. package/dist/{chunk-3YAR3I3S.js → chunk-Q7NSUXXB.js} +3 -1
  6. package/dist/{chunk-VWXUT5R2.cjs → chunk-TVSFDQYE.cjs} +3 -1
  7. package/dist/chunk-WX5PU7HF.js +868 -0
  8. package/dist/chunk-YJGOD3Y4.js +2362 -0
  9. package/dist/{codec-BLYAy2OP.d.ts → codec--CVeqGQv.d.ts} +1 -1
  10. package/dist/{codec-DujHf55Z.d.ts → codec-BJ7BHuiZ.d.ts} +1 -1
  11. package/dist/{codec-D47r_-Rl.d.ts → codec-BKsVu3Fr.d.ts} +1 -1
  12. package/dist/{codec-BNS3gS77.d.ts → codec-BMwgZIgG.d.ts} +1 -1
  13. package/dist/{codec-CI0BjmHc.d.ts → codec-BNy5syCU.d.ts} +1 -1
  14. package/dist/{codec-v6Vloc7H.d.ts → codec-BQa6Qsav.d.ts} +1 -1
  15. package/dist/codec-Bym-K2q2.d.cts +49 -0
  16. package/dist/{codec-D2JbI2tp.d.ts → codec-C006F75E.d.ts} +1 -1
  17. package/dist/codec-C5evFHL-.d.ts +49 -0
  18. package/dist/{codec-DQWQSam3.d.cts → codec-C6Mx4bwz.d.cts} +1 -1
  19. package/dist/{codec-DL0njGkL.d.ts → codec-CA6nbbEk.d.ts} +1 -1
  20. package/dist/{codec-D89DWXbv.d.cts → codec-CSBFdPgP.d.cts} +1 -1
  21. package/dist/{codec-DvcJgYKq.d.cts → codec-CXCjya_G.d.cts} +1 -1
  22. package/dist/{codec-hvkJfCF5.d.cts → codec-C_xxsbKy.d.cts} +1 -1
  23. package/dist/{codec-BOyrk_C9.d.cts → codec-Cfo_z5ET.d.cts} +1 -1
  24. package/dist/{codec-xeuGZY77.d.cts → codec-CgZdadPt.d.cts} +2 -2
  25. package/dist/{codec-WwwUipaU.d.ts → codec-Cl73EfRW.d.ts} +1 -1
  26. package/dist/{codec-BOtv3R5j.d.cts → codec-CtvFK4aV.d.cts} +1 -1
  27. package/dist/{codec-DAePx2NL.d.ts → codec-CviAa4lp.d.ts} +2 -2
  28. package/dist/{codec-DJmV04i0.d.ts → codec-D4RvFQmu.d.ts} +1 -1
  29. package/dist/{codec-cou9XBMF.d.cts → codec-DAyiF5sq.d.cts} +1 -1
  30. package/dist/{codec-CyApDKwf.d.cts → codec-DJmqoIsp.d.cts} +1 -1
  31. package/dist/{codec-NMsTK0GX.d.cts → codec-DchsPfr3.d.cts} +1 -1
  32. package/dist/{codec-DplRgIKq.d.ts → codec-Dl_QIXMz.d.ts} +1 -1
  33. package/dist/{codec-N3g1lxQQ.d.cts → codec-DzLvG8Wb.d.cts} +1 -1
  34. package/dist/{codec-D95gT98n.d.cts → codec-DzkdW4kO.d.cts} +1 -1
  35. package/dist/{codec-CWj5iTxA.d.ts → codec-O-1Js7h4.d.ts} +1 -1
  36. package/dist/{codec-BqqoYdh_.d.cts → codec-vddqy0KY.d.cts} +1 -1
  37. package/dist/draft07-session.d.cts +3 -3
  38. package/dist/draft07-session.d.ts +3 -3
  39. package/dist/draft07.d.cts +3 -3
  40. package/dist/draft07.d.ts +3 -3
  41. package/dist/draft08-session.d.cts +3 -3
  42. package/dist/draft08-session.d.ts +3 -3
  43. package/dist/draft08.d.cts +4 -4
  44. package/dist/draft08.d.ts +4 -4
  45. package/dist/draft09-session.d.cts +3 -3
  46. package/dist/draft09-session.d.ts +3 -3
  47. package/dist/draft09.d.cts +4 -4
  48. package/dist/draft09.d.ts +4 -4
  49. package/dist/draft10-session.d.cts +3 -3
  50. package/dist/draft10-session.d.ts +3 -3
  51. package/dist/draft10.d.cts +4 -4
  52. package/dist/draft10.d.ts +4 -4
  53. package/dist/draft11-session.d.cts +3 -3
  54. package/dist/draft11-session.d.ts +3 -3
  55. package/dist/draft11.d.cts +4 -4
  56. package/dist/draft11.d.ts +4 -4
  57. package/dist/draft12-session.d.cts +3 -3
  58. package/dist/draft12-session.d.ts +3 -3
  59. package/dist/draft12.d.cts +4 -4
  60. package/dist/draft12.d.ts +4 -4
  61. package/dist/draft13-session.d.cts +3 -3
  62. package/dist/draft13-session.d.ts +3 -3
  63. package/dist/draft13.d.cts +4 -4
  64. package/dist/draft13.d.ts +4 -4
  65. package/dist/draft14-session.d.cts +3 -3
  66. package/dist/draft14-session.d.ts +3 -3
  67. package/dist/draft14.d.cts +4 -4
  68. package/dist/draft14.d.ts +4 -4
  69. package/dist/draft15-session.d.cts +3 -3
  70. package/dist/draft15-session.d.ts +3 -3
  71. package/dist/draft15.d.cts +4 -4
  72. package/dist/draft15.d.ts +4 -4
  73. package/dist/draft16-session.d.cts +3 -3
  74. package/dist/draft16-session.d.ts +3 -3
  75. package/dist/draft16.d.cts +4 -4
  76. package/dist/draft16.d.ts +4 -4
  77. package/dist/draft17-session.d.cts +3 -3
  78. package/dist/draft17-session.d.ts +3 -3
  79. package/dist/draft17.d.cts +3 -3
  80. package/dist/draft17.d.ts +3 -3
  81. package/dist/draft18-session.d.cts +3 -3
  82. package/dist/draft18-session.d.ts +3 -3
  83. package/dist/draft18.d.cts +3 -3
  84. package/dist/draft18.d.ts +3 -3
  85. package/dist/draft19-session.d.cts +3 -3
  86. package/dist/draft19-session.d.ts +3 -3
  87. package/dist/draft19.cjs +2 -2
  88. package/dist/draft19.d.cts +3 -3
  89. package/dist/draft19.d.ts +3 -3
  90. package/dist/draft19.js +1 -1
  91. package/dist/draft20-session.cjs +8 -0
  92. package/dist/draft20-session.d.cts +195 -0
  93. package/dist/draft20-session.d.ts +195 -0
  94. package/dist/draft20-session.js +8 -0
  95. package/dist/draft20.cjs +217 -0
  96. package/dist/draft20.d.cts +175 -0
  97. package/dist/draft20.d.ts +175 -0
  98. package/dist/draft20.js +217 -0
  99. package/dist/index.cjs +9 -3
  100. package/dist/index.d.cts +32 -17
  101. package/dist/index.d.ts +32 -17
  102. package/dist/index.js +8 -2
  103. package/dist/{session-types-KsqyVp6y.d.cts → session-types-B9idsih-.d.cts} +13 -1
  104. package/dist/{session-types-C0l_-Ups.d.ts → session-types-Dn7b3RZM.d.ts} +13 -1
  105. package/dist/session.cjs +5 -1
  106. package/dist/session.d.cts +5 -3
  107. package/dist/session.d.ts +5 -3
  108. package/dist/session.js +5 -1
  109. package/dist/types-CWCQwuvy.d.cts +359 -0
  110. package/dist/types-CWCQwuvy.d.ts +359 -0
  111. package/dist/{types-CdCSIfvI.d.cts → types-DG5_iKuv.d.cts} +1 -1
  112. package/dist/{types-CdCSIfvI.d.ts → types-DG5_iKuv.d.ts} +1 -1
  113. package/package.json +16 -3
  114. package/src/core/session-types.ts +7 -0
  115. package/src/core/types.ts +1 -0
  116. package/src/drafts/draft19/codec.ts +4 -2
  117. package/src/drafts/draft20/codec.ts +1737 -0
  118. package/src/drafts/draft20/data-streams.ts +1291 -0
  119. package/src/drafts/draft20/error-codes.ts +135 -0
  120. package/src/drafts/draft20/index.ts +165 -0
  121. package/src/drafts/draft20/messages.ts +68 -0
  122. package/src/drafts/draft20/rules.ts +107 -0
  123. package/src/drafts/draft20/session-fsm.ts +1063 -0
  124. package/src/drafts/draft20/session.ts +21 -0
  125. package/src/drafts/draft20/types.ts +455 -0
  126. package/src/index.ts +20 -2
  127. package/src/session.ts +4 -0
@@ -0,0 +1,21 @@
1
+ import { Draft20SessionFSM } 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 createDraft20SessionState(role: 'client' | 'server'): Draft20SessionFSM {
18
+ return new Draft20SessionFSM(role)
19
+ }
20
+
21
+ export { Draft20SessionFSM }
@@ -0,0 +1,455 @@
1
+ // Draft-20 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 Draft20SetupOptions {
20
+ path?: string // 0x01 odd
21
+ authorization_token?: 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) — restructured in draft-20 (Section 5.1.2).
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 10.2.15).
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 Draft20FillParameters {
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
+ subgroup_filter?: RangeFilter // 0x25 length-prefixed
99
+ objectid_filter?: RangeFilter // 0x26 length-prefixed
100
+ priority_filter?: RangeFilter // 0x27 length-prefixed
101
+ object_property_filter?: RangeFilter // 0x28 length-prefixed
102
+ }
103
+
104
+ // Message Parameters (delta-encoded types, count-prefixed)
105
+ export interface Draft20Params {
106
+ object_delivery_timeout?: bigint // 0x02 varint
107
+ authorization_token?: AuthorizationToken // 0x03 length-prefixed nested
108
+ rendezvous_timeout?: bigint // 0x04 varint
109
+ subgroup_delivery_timeout?: bigint // 0x06 varint
110
+ expires?: bigint // 0x08 varint
111
+ largest_object?: LargestObject // 0x09 Location (2 bare varints, NOT length-prefixed)
112
+ fill_timeout?: bigint // 0x0a varint
113
+ forward?: bigint // 0x10 uint8
114
+ subscriber_priority?: bigint // 0x20 uint8
115
+ location_filter?: LocationFilter // 0x21 length-prefixed (restructured in draft-20)
116
+ group_order?: bigint // 0x22 uint8
117
+ fill_parameters?: Draft20FillParameters // 0x23 length-prefixed nested (NEW in draft-20)
118
+ subgroup_filter?: RangeFilter // 0x25 length-prefixed
119
+ objectid_filter?: RangeFilter // 0x26 length-prefixed
120
+ priority_filter?: RangeFilter // 0x27 length-prefixed
121
+ object_property_filter?: RangeFilter // 0x28 length-prefixed
122
+ track_property_filter?: RangeFilter // 0x29 length-prefixed
123
+ new_group_request?: bigint // 0x32 varint
124
+ track_namespace_prefix?: string[] // 0x34 Track Namespace encoding
125
+ include_properties?: bigint // 0x35 uint8, 0 or 1, default 1 (NEW in draft-20)
126
+ unknown?: UnknownParam[]
127
+ }
128
+
129
+ // Track properties (KVP encoding, no count prefix, read until end of payload)
130
+ export interface Draft20TrackProperties {
131
+ object_delivery_timeout?: bigint // 0x02 even varint
132
+ max_cache_duration?: bigint // 0x04 even varint
133
+ subgroup_delivery_timeout?: bigint // 0x06 even varint
134
+ immutable_properties?: Uint8Array // 0x0b odd length-prefixed
135
+ default_publisher_priority?: bigint // 0x0e even varint
136
+ default_publisher_group_order?: bigint // 0x22 even varint
137
+ dynamic_groups?: bigint // 0x30 even varint
138
+ unknown?: UnknownParam[]
139
+ }
140
+
141
+ // Draft-20 message type tag union
142
+ export type Draft20MessageType =
143
+ | 'setup'
144
+ | 'subscribe'
145
+ | 'subscribe_ok'
146
+ | 'request_update'
147
+ | 'publish_state_notify'
148
+ | 'publish'
149
+ | 'publish_done'
150
+ | 'publish_namespace'
151
+ | 'namespace'
152
+ | 'namespace_done'
153
+ | 'subscribe_namespace'
154
+ | 'subscribe_tracks'
155
+ | 'publish_skipped'
156
+ | 'fetch'
157
+ | 'fetch_ok'
158
+ | 'track_status'
159
+ | 'request_ok'
160
+ | 'request_error'
161
+ | 'goaway'
162
+
163
+ // Base
164
+ export interface Draft20BaseMessage {
165
+ readonly type: Draft20MessageType
166
+ }
167
+
168
+ // Setup — single unified message (0x2F00)
169
+ export interface Draft20Setup extends Draft20BaseMessage {
170
+ readonly type: 'setup'
171
+ readonly options: Draft20SetupOptions
172
+ }
173
+
174
+ export interface Draft20Subscribe extends Draft20BaseMessage {
175
+ readonly type: 'subscribe'
176
+ readonly request_id: bigint
177
+ readonly track_namespace: string[]
178
+ readonly track_name: string
179
+ readonly parameters: Draft20Params
180
+ }
181
+
182
+ export interface Draft20SubscribeOk extends Draft20BaseMessage {
183
+ readonly type: 'subscribe_ok'
184
+ readonly track_alias: bigint
185
+ readonly parameters: Draft20Params
186
+ readonly track_properties: Draft20TrackProperties
187
+ }
188
+
189
+ export interface Draft20RequestUpdate extends Draft20BaseMessage {
190
+ readonly type: 'request_update'
191
+ readonly request_id: bigint
192
+ readonly parameters: Draft20Params
193
+ }
194
+
195
+ /**
196
+ * PUBLISH_STATE_NOTIFY (0x22) — NEW in draft-20, Section 10.10.
197
+ *
198
+ * No Request ID: the message is identified by the subscription's bidirectional
199
+ * stream it arrives on, like SUBSCRIBE_OK, PUBLISH_DONE and FETCH_OK.
200
+ */
201
+ export interface Draft20PublishStateNotify extends Draft20BaseMessage {
202
+ readonly type: 'publish_state_notify'
203
+ readonly parameters: Draft20Params
204
+ }
205
+
206
+ export interface Draft20Publish extends Draft20BaseMessage {
207
+ readonly type: 'publish'
208
+ readonly request_id: bigint
209
+ readonly track_namespace: string[]
210
+ readonly track_name: string
211
+ readonly track_alias: bigint
212
+ readonly parameters: Draft20Params
213
+ readonly track_properties: Draft20TrackProperties
214
+ }
215
+
216
+ export interface Draft20PublishDone extends Draft20BaseMessage {
217
+ readonly type: 'publish_done'
218
+ readonly status_code: bigint
219
+ /**
220
+ * Number of streams opened for the subscription, including empty subgroups
221
+ * and — new in draft-20 — fill fetch streams (Section 10.12), or the
222
+ * `UNKNOWN_STREAM_COUNT` sentinel exported from `codec.ts` (2^64 - 1, raised
223
+ * from draft-19's 2^62 - 1) when the publisher cannot state it exactly.
224
+ *
225
+ * `bigint`, not `number`: the sentinel does not fit a double.
226
+ */
227
+ readonly stream_count: bigint
228
+ readonly reason_phrase: string
229
+ }
230
+
231
+ export interface Draft20PublishNamespace extends Draft20BaseMessage {
232
+ readonly type: 'publish_namespace'
233
+ readonly request_id: bigint
234
+ readonly track_namespace: string[]
235
+ readonly parameters: Draft20Params
236
+ }
237
+
238
+ export interface Draft20Namespace extends Draft20BaseMessage {
239
+ readonly type: 'namespace'
240
+ readonly namespace_suffix: string[]
241
+ }
242
+
243
+ export interface Draft20NamespaceDone extends Draft20BaseMessage {
244
+ readonly type: 'namespace_done'
245
+ readonly namespace_suffix: string[]
246
+ }
247
+
248
+ export interface Draft20SubscribeNamespace extends Draft20BaseMessage {
249
+ readonly type: 'subscribe_namespace'
250
+ readonly request_id: bigint
251
+ readonly namespace_prefix: string[]
252
+ readonly parameters: Draft20Params
253
+ }
254
+
255
+ export interface Draft20SubscribeTracks extends Draft20BaseMessage {
256
+ readonly type: 'subscribe_tracks'
257
+ readonly request_id: bigint
258
+ readonly namespace_prefix: string[]
259
+ readonly parameters: Draft20Params
260
+ }
261
+
262
+ export interface Draft20PublishSkipped extends Draft20BaseMessage {
263
+ readonly type: 'publish_skipped'
264
+ readonly namespace_suffix: string[]
265
+ readonly track_name: string
266
+ }
267
+
268
+ /**
269
+ * FETCH (0x16) — the byte layout was rewritten in draft-20 (Section 10.13).
270
+ *
271
+ * Gone: the `Fetch Type` field and its enum, the `Standalone Fetch` and
272
+ * `Joining Fetch` structures, and the inline `Start Location` / `End Location`.
273
+ * Track Namespace and Track Name are inline fields of FETCH itself, and the
274
+ * range travels in the LOCATION_FILTER parameter. A FETCH with no
275
+ * LOCATION_FILTER covers {0,0} through Largest Object, inclusive.
276
+ *
277
+ * The codepoint did not change, so a draft-19 decoder fed one of these reads
278
+ * the Number of Track Namespace Fields count as a Fetch Type and mis-parses in
279
+ * silence. There is no in-band version signal that catches it.
280
+ */
281
+ export interface Draft20Fetch extends Draft20BaseMessage {
282
+ readonly type: 'fetch'
283
+ readonly request_id: bigint
284
+ readonly track_namespace: string[]
285
+ readonly track_name: string
286
+ readonly parameters: Draft20Params
287
+ }
288
+
289
+ /**
290
+ * FETCH_OK (0x18) — bytes identical to draft-19, meaning changed.
291
+ *
292
+ * `end_group` / `end_object` are the INCLUSIVE end of the range the response
293
+ * covers: the last Object actually covered. draft-19's "the last Object, plus
294
+ * 1; or 0 to indicate the entire Group" is gone (draft-20 Section 10.14 with
295
+ * Section 5.1.2). The same bytes mean a different object under the two drafts,
296
+ * and nothing on the wire distinguishes them.
297
+ */
298
+ export interface Draft20FetchOk extends Draft20BaseMessage {
299
+ readonly type: 'fetch_ok'
300
+ readonly end_of_track: number // uint8
301
+ readonly end_group: bigint
302
+ readonly end_object: bigint
303
+ readonly parameters: Draft20Params
304
+ readonly track_properties: Draft20TrackProperties
305
+ }
306
+
307
+ // Track Status — same format as SUBSCRIBE with the type set to 0xD
308
+ export interface Draft20TrackStatus extends Draft20BaseMessage {
309
+ readonly type: 'track_status'
310
+ readonly request_id: bigint
311
+ readonly track_namespace: string[]
312
+ readonly track_name: string
313
+ readonly parameters: Draft20Params
314
+ }
315
+
316
+ // REQUEST_OK — also the PUBLISH_OK / REQUEST_UPDATE_OK / TRACK_STATUS_OK alias
317
+ export interface Draft20RequestOk extends Draft20BaseMessage {
318
+ readonly type: 'request_ok'
319
+ readonly parameters: Draft20Params
320
+ readonly track_properties: Draft20TrackProperties
321
+ }
322
+
323
+ /**
324
+ * Redirect structure, used inside REQUEST_ERROR when error_code = REDIRECT (0x34).
325
+ *
326
+ * draft-20 Section 10.6.1 names the namespace/name pair "the Redirect target"
327
+ * and dropped draft-19's rule that a zero-length pair meant "reuse the values
328
+ * from the original request". An empty namespace and name are now a literal
329
+ * empty namespace and name.
330
+ */
331
+ export interface Redirect {
332
+ readonly connect_uri: string
333
+ readonly track_namespace: string[]
334
+ readonly track_name: string
335
+ }
336
+
337
+ export interface Draft20RequestError extends Draft20BaseMessage {
338
+ readonly type: 'request_error'
339
+ readonly error_code: bigint
340
+ readonly retry_interval: bigint
341
+ readonly reason_phrase: string
342
+ readonly redirect?: Redirect
343
+ }
344
+
345
+ export interface Draft20GoAway extends Draft20BaseMessage {
346
+ readonly type: 'goaway'
347
+ readonly new_session_uri: string
348
+ readonly timeout: bigint
349
+ }
350
+
351
+ // Union of all draft-20 control messages
352
+ export type Draft20Message =
353
+ | Draft20Setup
354
+ | Draft20Subscribe
355
+ | Draft20SubscribeOk
356
+ | Draft20RequestUpdate
357
+ | Draft20PublishStateNotify
358
+ | Draft20Publish
359
+ | Draft20PublishDone
360
+ | Draft20PublishNamespace
361
+ | Draft20Namespace
362
+ | Draft20NamespaceDone
363
+ | Draft20SubscribeNamespace
364
+ | Draft20SubscribeTracks
365
+ | Draft20PublishSkipped
366
+ | Draft20Fetch
367
+ | Draft20FetchOk
368
+ | Draft20TrackStatus
369
+ | Draft20RequestOk
370
+ | Draft20RequestError
371
+ | Draft20GoAway
372
+
373
+ // ─── Data stream types ──────────────────────────────────────────────────────
374
+
375
+ export interface ObjectPayload {
376
+ readonly type: 'object'
377
+ readonly byteOffset: number
378
+ readonly payloadByteOffset: number
379
+ readonly objectId: bigint
380
+ /** The Object ID Delta as it appeared on the wire, before delta resolution. */
381
+ readonly objectIdDelta?: bigint
382
+ readonly payloadLength: number
383
+ readonly status?: bigint
384
+ readonly extensionData: Uint8Array
385
+ readonly objectProperties?: Record<string, bigint>
386
+ readonly payload: Uint8Array
387
+ }
388
+
389
+ export interface SubgroupStream {
390
+ readonly type: 'subgroup'
391
+ /** SUBGROUP_HEADER `Type Flags` (draft-20 Section 11.4.2). */
392
+ readonly headerType: number
393
+ readonly trackAlias: bigint
394
+ readonly groupId: bigint
395
+ readonly subgroupId: bigint
396
+ readonly publisherPriority: number
397
+ readonly endOfGroup?: boolean
398
+ readonly firstObject?: boolean
399
+ readonly objects: ObjectPayload[]
400
+ }
401
+
402
+ export interface DatagramObject {
403
+ readonly type: 'datagram'
404
+ /** OBJECT_DATAGRAM `Type Flags` (draft-20 Section 11.3.1). */
405
+ readonly datagramType: number
406
+ readonly trackAlias: bigint
407
+ readonly groupId: bigint
408
+ readonly objectId: bigint
409
+ readonly publisherPriority: number
410
+ readonly endOfGroup?: boolean
411
+ readonly objectStatus?: bigint
412
+ readonly objectProperties?: Record<string, bigint>
413
+ readonly payloadLength: number
414
+ readonly payload: Uint8Array
415
+ }
416
+
417
+ export interface FetchObjectPayload extends ObjectPayload {
418
+ readonly serializationFlags: number
419
+ readonly groupId: bigint
420
+ /** The Group ID Delta as it appeared on the wire, before delta resolution. */
421
+ readonly groupIdDelta?: bigint
422
+ readonly subgroupId: bigint
423
+ readonly publisherPriority: number
424
+ readonly objectProperties?: Record<string, bigint>
425
+ }
426
+
427
+ export interface FetchStream {
428
+ readonly type: 'fetch'
429
+ /**
430
+ * The Request ID of the message that opened the stream. In draft-20 that is
431
+ * not necessarily a FETCH: a fill fetch stream (Section 5.1.3) carries the
432
+ * Request ID of the SUBSCRIBE or REQUEST_UPDATE that requested the fill.
433
+ */
434
+ readonly requestId: bigint
435
+ readonly objects: FetchObjectPayload[]
436
+ }
437
+
438
+ export type Draft20DataStream = SubgroupStream | DatagramObject | FetchStream
439
+
440
+ // Streaming data stream decoder types
441
+ export interface SubgroupStreamHeader {
442
+ readonly type: 'subgroup_header'
443
+ readonly trackAlias: bigint
444
+ readonly groupId: bigint
445
+ readonly subgroupId: bigint
446
+ readonly publisherPriority: number
447
+ }
448
+
449
+ export interface FetchStreamHeader {
450
+ readonly type: 'fetch_header'
451
+ readonly requestId: bigint
452
+ }
453
+
454
+ export type DataStreamHeader = SubgroupStreamHeader | FetchStreamHeader
455
+ export type DataStreamEvent = DataStreamHeader | ObjectPayload
package/src/index.ts CHANGED
@@ -38,9 +38,21 @@ import type { Draft18Codec } from './drafts/draft18/codec.js'
38
38
  import { createDraft18Codec } from './drafts/draft18/codec.js'
39
39
  import type { Draft19Codec } from './drafts/draft19/codec.js'
40
40
  import { createDraft19Codec } from './drafts/draft19/codec.js'
41
+ import type { Draft20Codec } from './drafts/draft20/codec.js'
42
+ import { createDraft20Codec } from './drafts/draft20/codec.js'
41
43
 
42
44
  /**
43
- * Wire version numbers for each MoQT draft, keyed by short aliases.
45
+ * Version identifiers for each MoQT draft, keyed by short aliases.
46
+ *
47
+ * Only the entries up to '14' are wire values: those drafts negotiated the
48
+ * version inside CLIENT_SETUP/SERVER_SETUP and really do put `0xff0000NN` on
49
+ * the wire. From draft-15 on, the version is negotiated by ALPN (raw QUIC) or
50
+ * `WT-Available-Protocols` (WebTransport) as the string `moqt-NN`, and no
51
+ * version number is sent at all — so '15' through '20' are *derived*
52
+ * identifiers kept as stable numeric keys, not observed values. Do not report
53
+ * one to a user as a version seen on the wire; report the protocol string.
54
+ * Each draft's own module exports it (e.g. `PROTOCOL_STRING` in
55
+ * `@moqtap/codec/draft20`).
44
56
  */
45
57
  export const DRAFT_VERSIONS: Record<string, bigint> = {
46
58
  '07': 0xff000007n,
@@ -56,6 +68,7 @@ export const DRAFT_VERSIONS: Record<string, bigint> = {
56
68
  '17': 0xff000011n,
57
69
  '18': 0xff000012n,
58
70
  '19': 0xff000013n,
71
+ '20': 0xff000014n,
59
72
  }
60
73
 
61
74
  export function createCodec(options: CodecOptions & { draft: '07' }): Draft07Codec
@@ -71,6 +84,7 @@ export function createCodec(options: CodecOptions & { draft: '16' }): Draft16Cod
71
84
  export function createCodec(options: CodecOptions & { draft: '17' }): Draft17Codec
72
85
  export function createCodec(options: CodecOptions & { draft: '18' }): Draft18Codec
73
86
  export function createCodec(options: CodecOptions & { draft: '19' }): Draft19Codec
87
+ export function createCodec(options: CodecOptions & { draft: '20' }): Draft20Codec
74
88
 
75
89
  /**
76
90
  * Create a codec for the specified draft version.
@@ -94,6 +108,7 @@ export function createCodec(
94
108
  | Draft17Codec
95
109
  | Draft18Codec
96
110
  | Draft19Codec
111
+ | Draft20Codec
97
112
  export function createCodec(
98
113
  options: CodecOptions,
99
114
  ):
@@ -109,7 +124,8 @@ export function createCodec(
109
124
  | Draft16Codec
110
125
  | Draft17Codec
111
126
  | Draft18Codec
112
- | Draft19Codec {
127
+ | Draft19Codec
128
+ | Draft20Codec {
113
129
  const draft = DRAFT_VERSIONS[options.draft]
114
130
  if (!draft) {
115
131
  throw new Error(
@@ -146,6 +162,8 @@ export function createCodec(
146
162
  return createDraft18Codec()
147
163
  case '19':
148
164
  return createDraft19Codec()
165
+ case '20':
166
+ return createDraft20Codec()
149
167
  default:
150
168
  throw new Error(`Unsupported draft: ${draft}`)
151
169
  }
package/src/session.ts CHANGED
@@ -34,6 +34,8 @@ import { createDraft18SessionState } from './drafts/draft18/session.js'
34
34
  import type { Draft18Message, Draft18MessageType } from './drafts/draft18/types.js'
35
35
  import { createDraft19SessionState } from './drafts/draft19/session.js'
36
36
  import type { Draft19Message, Draft19MessageType } from './drafts/draft19/types.js'
37
+ import { createDraft20SessionState } from './drafts/draft20/session.js'
38
+ import type { Draft20Message, Draft20MessageType } from './drafts/draft20/types.js'
37
39
 
38
40
  type DraftSessionStateMap = {
39
41
  '07': SessionState<Draft07Message, Draft07MessageType>
@@ -49,6 +51,7 @@ type DraftSessionStateMap = {
49
51
  '17': SessionState<Draft17Message, Draft17MessageType>
50
52
  '18': SessionState<Draft18Message, Draft18MessageType>
51
53
  '19': SessionState<Draft19Message, Draft19MessageType>
54
+ '20': SessionState<Draft20Message, Draft20MessageType>
52
55
  }
53
56
 
54
57
  /**
@@ -73,6 +76,7 @@ export function createSessionState<T extends Draft>(
73
76
  '17': createDraft17SessionState,
74
77
  '18': createDraft18SessionState,
75
78
  '19': createDraft19SessionState,
79
+ '20': createDraft20SessionState,
76
80
  }
77
81
 
78
82
  const factory = factories[draft]