@moqtap/codec 0.8.1 → 0.10.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 (194) hide show
  1. package/CHANGELOG.md +75 -0
  2. package/README.md +16 -4
  3. package/dist/{chunk-KCH4BQXK.cjs → chunk-AQ445VV7.cjs} +15 -9
  4. package/dist/{chunk-UZO5Z2XT.cjs → chunk-BIBMDTU5.cjs} +12 -6
  5. package/dist/chunk-BMJMY6FX.cjs +868 -0
  6. package/dist/{chunk-23KRITJ6.js → chunk-BX2N7TZM.js} +14 -8
  7. package/dist/{chunk-XQGEOFGE.js → chunk-CF5DDD3Q.js} +14 -8
  8. package/dist/chunk-FT3HDNIB.js +2374 -0
  9. package/dist/{chunk-TMXRYOBS.js → chunk-G53WYUXL.js} +13 -7
  10. package/dist/{chunk-JKMYAUGY.js → chunk-K2B3OVFK.js} +11 -8
  11. package/dist/{chunk-3YAR3I3S.js → chunk-KGDVC4O6.js} +36 -22
  12. package/dist/{chunk-VWXUT5R2.cjs → chunk-KTNERCTZ.cjs} +36 -22
  13. package/dist/{chunk-H6DTAIWM.js → chunk-L5DRACXS.js} +22 -16
  14. package/dist/{chunk-UA5XFP4O.cjs → chunk-OUNN4IQB.cjs} +14 -8
  15. package/dist/{chunk-NH4L6NIY.js → chunk-OZRK73NQ.js} +12 -6
  16. package/dist/{chunk-PU2KV7VP.cjs → chunk-RYKQXBG6.cjs} +12 -6
  17. package/dist/{chunk-EVCPBFSR.cjs → chunk-SDJTSMOW.cjs} +23 -17
  18. package/dist/chunk-T4VWPKDG.cjs +2374 -0
  19. package/dist/{chunk-2XH6PHXR.js → chunk-TSUZ6GJV.js} +12 -6
  20. package/dist/{chunk-QGIHC6BA.cjs → chunk-UKKDOOUO.cjs} +12 -9
  21. package/dist/{chunk-BV6MITLO.js → chunk-WCPENYNE.js} +14 -8
  22. package/dist/{chunk-IADVBKEJ.cjs → chunk-WCTMPDUX.cjs} +15 -9
  23. package/dist/chunk-WX5PU7HF.js +868 -0
  24. package/dist/{chunk-7ENEWAMZ.cjs → chunk-XCRCAUGI.cjs} +15 -9
  25. package/dist/{codec-BLYAy2OP.d.ts → codec--CVeqGQv.d.ts} +1 -1
  26. package/dist/{codec-BNS3gS77.d.ts → codec-08ZOr5wI.d.ts} +2 -2
  27. package/dist/{codec-DujHf55Z.d.ts → codec-BJ7BHuiZ.d.ts} +1 -1
  28. package/dist/{codec-CI0BjmHc.d.ts → codec-BNy5syCU.d.ts} +1 -1
  29. package/dist/{codec-N3g1lxQQ.d.cts → codec-Bd60SGKH.d.cts} +2 -2
  30. package/dist/{codec-xeuGZY77.d.cts → codec-BrTi4K7r.d.cts} +3 -3
  31. package/dist/{codec-DJmV04i0.d.ts → codec-Bux_Q40X.d.ts} +2 -2
  32. package/dist/{codec-BqqoYdh_.d.cts → codec-BxQTybUX.d.cts} +2 -2
  33. package/dist/{codec-D2JbI2tp.d.ts → codec-C3mdsGx3.d.ts} +2 -2
  34. package/dist/{codec-DQWQSam3.d.cts → codec-C6Mx4bwz.d.cts} +1 -1
  35. package/dist/{codec-DAePx2NL.d.ts → codec-CBdOIfMY.d.ts} +3 -3
  36. package/dist/codec-CFWu5KVT.d.cts +49 -0
  37. package/dist/{codec-CyApDKwf.d.cts → codec-CWnf8mn_.d.cts} +2 -2
  38. package/dist/{codec-DvcJgYKq.d.cts → codec-CXCjya_G.d.cts} +1 -1
  39. package/dist/{codec-BOyrk_C9.d.cts → codec-Cfo_z5ET.d.cts} +1 -1
  40. package/dist/{codec-v6Vloc7H.d.ts → codec-Cm3D261p.d.ts} +2 -2
  41. package/dist/codec-CwZ6OCPP.d.ts +49 -0
  42. package/dist/{codec-NMsTK0GX.d.cts → codec-Czejcmxr.d.cts} +2 -2
  43. package/dist/{codec-hvkJfCF5.d.cts → codec-DNmiG2e0.d.cts} +2 -2
  44. package/dist/{codec-CWj5iTxA.d.ts → codec-DOmAmFkI.d.ts} +2 -2
  45. package/dist/{codec-WwwUipaU.d.ts → codec-DaXjRrOV.d.ts} +2 -2
  46. package/dist/{codec-DplRgIKq.d.ts → codec-Dl_QIXMz.d.ts} +1 -1
  47. package/dist/{codec-D95gT98n.d.cts → codec-DzkdW4kO.d.cts} +1 -1
  48. package/dist/{codec-cou9XBMF.d.cts → codec-EvybrBuY.d.cts} +2 -2
  49. package/dist/{codec-DL0njGkL.d.ts → codec-alVA27Uc.d.ts} +2 -2
  50. package/dist/{codec-D89DWXbv.d.cts → codec-f7vxeVIS.d.cts} +2 -2
  51. package/dist/{codec-D47r_-Rl.d.ts → codec-gl4_QEva.d.ts} +2 -2
  52. package/dist/{codec-BOtv3R5j.d.cts → codec-guzqtfMk.d.cts} +2 -2
  53. package/dist/draft07-session.d.cts +3 -3
  54. package/dist/draft07-session.d.ts +3 -3
  55. package/dist/draft07.d.cts +3 -3
  56. package/dist/draft07.d.ts +3 -3
  57. package/dist/draft08-session.d.cts +3 -3
  58. package/dist/draft08-session.d.ts +3 -3
  59. package/dist/draft08.d.cts +4 -4
  60. package/dist/draft08.d.ts +4 -4
  61. package/dist/draft09-session.d.cts +3 -3
  62. package/dist/draft09-session.d.ts +3 -3
  63. package/dist/draft09.d.cts +4 -4
  64. package/dist/draft09.d.ts +4 -4
  65. package/dist/draft10-session.d.cts +3 -3
  66. package/dist/draft10-session.d.ts +3 -3
  67. package/dist/draft10.d.cts +4 -4
  68. package/dist/draft10.d.ts +4 -4
  69. package/dist/draft11-session.d.cts +4 -4
  70. package/dist/draft11-session.d.ts +4 -4
  71. package/dist/draft11.cjs +2 -2
  72. package/dist/draft11.d.cts +6 -6
  73. package/dist/draft11.d.ts +6 -6
  74. package/dist/draft11.js +1 -1
  75. package/dist/draft12-session.d.cts +4 -4
  76. package/dist/draft12-session.d.ts +4 -4
  77. package/dist/draft12.cjs +2 -2
  78. package/dist/draft12.d.cts +6 -6
  79. package/dist/draft12.d.ts +6 -6
  80. package/dist/draft12.js +1 -1
  81. package/dist/draft13-session.d.cts +4 -4
  82. package/dist/draft13-session.d.ts +4 -4
  83. package/dist/draft13.cjs +2 -2
  84. package/dist/draft13.d.cts +6 -6
  85. package/dist/draft13.d.ts +6 -6
  86. package/dist/draft13.js +1 -1
  87. package/dist/draft14-session.d.cts +4 -4
  88. package/dist/draft14-session.d.ts +4 -4
  89. package/dist/draft14.cjs +2 -2
  90. package/dist/draft14.d.cts +6 -6
  91. package/dist/draft14.d.ts +6 -6
  92. package/dist/draft14.js +1 -1
  93. package/dist/draft15-session.d.cts +4 -4
  94. package/dist/draft15-session.d.ts +4 -4
  95. package/dist/draft15.cjs +2 -2
  96. package/dist/draft15.d.cts +6 -6
  97. package/dist/draft15.d.ts +6 -6
  98. package/dist/draft15.js +1 -1
  99. package/dist/draft16-session.d.cts +4 -4
  100. package/dist/draft16-session.d.ts +4 -4
  101. package/dist/draft16.cjs +2 -2
  102. package/dist/draft16.d.cts +6 -6
  103. package/dist/draft16.d.ts +6 -6
  104. package/dist/draft16.js +1 -1
  105. package/dist/draft17-session.d.cts +4 -4
  106. package/dist/draft17-session.d.ts +4 -4
  107. package/dist/draft17.cjs +2 -2
  108. package/dist/draft17.d.cts +5 -5
  109. package/dist/draft17.d.ts +5 -5
  110. package/dist/draft17.js +1 -1
  111. package/dist/draft18-session.d.cts +4 -4
  112. package/dist/draft18-session.d.ts +4 -4
  113. package/dist/draft18.cjs +2 -2
  114. package/dist/draft18.d.cts +5 -5
  115. package/dist/draft18.d.ts +5 -5
  116. package/dist/draft18.js +1 -1
  117. package/dist/draft19-session.d.cts +4 -4
  118. package/dist/draft19-session.d.ts +4 -4
  119. package/dist/draft19.cjs +2 -2
  120. package/dist/draft19.d.cts +5 -5
  121. package/dist/draft19.d.ts +5 -5
  122. package/dist/draft19.js +1 -1
  123. package/dist/draft20-session.cjs +8 -0
  124. package/dist/draft20-session.d.cts +195 -0
  125. package/dist/draft20-session.d.ts +195 -0
  126. package/dist/draft20-session.js +8 -0
  127. package/dist/draft20.cjs +217 -0
  128. package/dist/draft20.d.cts +175 -0
  129. package/dist/draft20.d.ts +175 -0
  130. package/dist/draft20.js +217 -0
  131. package/dist/index.cjs +25 -19
  132. package/dist/index.d.cts +41 -26
  133. package/dist/index.d.ts +41 -26
  134. package/dist/index.js +16 -10
  135. package/dist/{session-types-KsqyVp6y.d.cts → session-types-B9idsih-.d.cts} +13 -1
  136. package/dist/{session-types-C0l_-Ups.d.ts → session-types-Dn7b3RZM.d.ts} +13 -1
  137. package/dist/session.cjs +5 -1
  138. package/dist/session.d.cts +14 -12
  139. package/dist/session.d.ts +14 -12
  140. package/dist/session.js +5 -1
  141. package/dist/{types-Cqp10JtB.d.cts → types-Bg86GGVZ.d.cts} +2 -2
  142. package/dist/{types-Cqp10JtB.d.ts → types-Bg86GGVZ.d.ts} +2 -2
  143. package/dist/{types-zHgCS6o5.d.cts → types-C1rxh-id.d.cts} +7 -7
  144. package/dist/{types-zHgCS6o5.d.ts → types-C1rxh-id.d.ts} +7 -7
  145. package/dist/{types-Bio-91Rt.d.cts → types-CI_SX4Xe.d.cts} +2 -2
  146. package/dist/{types-Bio-91Rt.d.ts → types-CI_SX4Xe.d.ts} +2 -2
  147. package/dist/types-CY-QWxd-.d.cts +359 -0
  148. package/dist/types-CY-QWxd-.d.ts +359 -0
  149. package/dist/{types-Cm9fjeYC.d.cts → types-CZTzbIzQ.d.cts} +2 -2
  150. package/dist/{types-Cm9fjeYC.d.ts → types-CZTzbIzQ.d.ts} +2 -2
  151. package/dist/{types-HI_bbXka.d.cts → types-CmqT0jUf.d.cts} +1 -1
  152. package/dist/{types-HI_bbXka.d.ts → types-CmqT0jUf.d.ts} +1 -1
  153. package/dist/{types-Ck45Ex5S.d.cts → types-D0kTgUuL.d.cts} +1 -1
  154. package/dist/{types-Ck45Ex5S.d.ts → types-D0kTgUuL.d.ts} +1 -1
  155. package/dist/{types-D9eiB_9A.d.cts → types-D4bmW8rY.d.cts} +2 -2
  156. package/dist/{types-D9eiB_9A.d.ts → types-D4bmW8rY.d.ts} +2 -2
  157. package/dist/{types-CdCSIfvI.d.cts → types-DG5_iKuv.d.cts} +1 -1
  158. package/dist/{types-CdCSIfvI.d.ts → types-DG5_iKuv.d.ts} +1 -1
  159. package/dist/{types-CXlSn0I9.d.cts → types-DjxexghA.d.cts} +2 -2
  160. package/dist/{types-CXlSn0I9.d.ts → types-DjxexghA.d.ts} +2 -2
  161. package/dist/{types-CPaYBsMG.d.cts → types-pShrs3fN.d.cts} +2 -2
  162. package/dist/{types-CPaYBsMG.d.ts → types-pShrs3fN.d.ts} +2 -2
  163. package/package.json +16 -3
  164. package/src/core/session-types.ts +7 -0
  165. package/src/core/types.ts +1 -0
  166. package/src/drafts/draft11/codec.ts +11 -8
  167. package/src/drafts/draft11/types.ts +1 -1
  168. package/src/drafts/draft12/codec.ts +22 -16
  169. package/src/drafts/draft12/types.ts +2 -2
  170. package/src/drafts/draft13/codec.ts +14 -8
  171. package/src/drafts/draft13/types.ts +2 -2
  172. package/src/drafts/draft14/codec.ts +14 -8
  173. package/src/drafts/draft14/types.ts +1 -1
  174. package/src/drafts/draft15/codec.ts +14 -8
  175. package/src/drafts/draft15/types.ts +2 -2
  176. package/src/drafts/draft16/codec.ts +13 -7
  177. package/src/drafts/draft16/types.ts +2 -2
  178. package/src/drafts/draft17/codec.ts +12 -6
  179. package/src/drafts/draft17/types.ts +2 -2
  180. package/src/drafts/draft18/codec.ts +12 -6
  181. package/src/drafts/draft18/types.ts +2 -2
  182. package/src/drafts/draft19/codec.ts +37 -23
  183. package/src/drafts/draft19/types.ts +10 -7
  184. package/src/drafts/draft20/codec.ts +1749 -0
  185. package/src/drafts/draft20/data-streams.ts +1291 -0
  186. package/src/drafts/draft20/error-codes.ts +135 -0
  187. package/src/drafts/draft20/index.ts +165 -0
  188. package/src/drafts/draft20/messages.ts +68 -0
  189. package/src/drafts/draft20/rules.ts +107 -0
  190. package/src/drafts/draft20/session-fsm.ts +1063 -0
  191. package/src/drafts/draft20/session.ts +21 -0
  192. package/src/drafts/draft20/types.ts +461 -0
  193. package/src/index.ts +20 -2
  194. 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,461 @@
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?: 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) — 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
+ // Section 5.1.4 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 Draft20Params {
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 (restructured in draft-20)
119
+ group_order?: bigint // 0x22 uint8
120
+ fill_parameters?: Draft20FillParameters // 0x23 length-prefixed nested (NEW in draft-20)
121
+ // Section 5.1.4 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 Draft20TrackProperties {
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-20 message type tag union
148
+ export type Draft20MessageType =
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 Draft20BaseMessage {
171
+ readonly type: Draft20MessageType
172
+ }
173
+
174
+ // Setup — single unified message (0x2F00)
175
+ export interface Draft20Setup extends Draft20BaseMessage {
176
+ readonly type: 'setup'
177
+ readonly options: Draft20SetupOptions
178
+ }
179
+
180
+ export interface Draft20Subscribe extends Draft20BaseMessage {
181
+ readonly type: 'subscribe'
182
+ readonly request_id: bigint
183
+ readonly track_namespace: string[]
184
+ readonly track_name: string
185
+ readonly parameters: Draft20Params
186
+ }
187
+
188
+ export interface Draft20SubscribeOk extends Draft20BaseMessage {
189
+ readonly type: 'subscribe_ok'
190
+ readonly track_alias: bigint
191
+ readonly parameters: Draft20Params
192
+ readonly track_properties: Draft20TrackProperties
193
+ }
194
+
195
+ export interface Draft20RequestUpdate extends Draft20BaseMessage {
196
+ readonly type: 'request_update'
197
+ readonly request_id: bigint
198
+ readonly parameters: Draft20Params
199
+ }
200
+
201
+ /**
202
+ * PUBLISH_STATE_NOTIFY (0x22) — NEW in draft-20, Section 10.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 Draft20PublishStateNotify extends Draft20BaseMessage {
208
+ readonly type: 'publish_state_notify'
209
+ readonly parameters: Draft20Params
210
+ }
211
+
212
+ export interface Draft20Publish extends Draft20BaseMessage {
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: Draft20Params
219
+ readonly track_properties: Draft20TrackProperties
220
+ }
221
+
222
+ export interface Draft20PublishDone extends Draft20BaseMessage {
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 10.12), 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 Draft20PublishNamespace extends Draft20BaseMessage {
238
+ readonly type: 'publish_namespace'
239
+ readonly request_id: bigint
240
+ readonly track_namespace: string[]
241
+ readonly parameters: Draft20Params
242
+ }
243
+
244
+ export interface Draft20Namespace extends Draft20BaseMessage {
245
+ readonly type: 'namespace'
246
+ readonly namespace_suffix: string[]
247
+ }
248
+
249
+ export interface Draft20NamespaceDone extends Draft20BaseMessage {
250
+ readonly type: 'namespace_done'
251
+ readonly namespace_suffix: string[]
252
+ }
253
+
254
+ export interface Draft20SubscribeNamespace extends Draft20BaseMessage {
255
+ readonly type: 'subscribe_namespace'
256
+ readonly request_id: bigint
257
+ readonly namespace_prefix: string[]
258
+ readonly parameters: Draft20Params
259
+ }
260
+
261
+ export interface Draft20SubscribeTracks extends Draft20BaseMessage {
262
+ readonly type: 'subscribe_tracks'
263
+ readonly request_id: bigint
264
+ readonly namespace_prefix: string[]
265
+ readonly parameters: Draft20Params
266
+ }
267
+
268
+ export interface Draft20PublishSkipped extends Draft20BaseMessage {
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 10.13).
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 Draft20Fetch extends Draft20BaseMessage {
288
+ readonly type: 'fetch'
289
+ readonly request_id: bigint
290
+ readonly track_namespace: string[]
291
+ readonly track_name: string
292
+ readonly parameters: Draft20Params
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-20 Section 10.14 with
301
+ * Section 5.1.2). The same bytes mean a different object under the two drafts,
302
+ * and nothing on the wire distinguishes them.
303
+ */
304
+ export interface Draft20FetchOk extends Draft20BaseMessage {
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: Draft20Params
310
+ readonly track_properties: Draft20TrackProperties
311
+ }
312
+
313
+ // Track Status — same format as SUBSCRIBE with the type set to 0xD
314
+ export interface Draft20TrackStatus extends Draft20BaseMessage {
315
+ readonly type: 'track_status'
316
+ readonly request_id: bigint
317
+ readonly track_namespace: string[]
318
+ readonly track_name: string
319
+ readonly parameters: Draft20Params
320
+ }
321
+
322
+ // REQUEST_OK — also the PUBLISH_OK / REQUEST_UPDATE_OK / TRACK_STATUS_OK alias
323
+ export interface Draft20RequestOk extends Draft20BaseMessage {
324
+ readonly type: 'request_ok'
325
+ readonly parameters: Draft20Params
326
+ readonly track_properties: Draft20TrackProperties
327
+ }
328
+
329
+ /**
330
+ * Redirect structure, used inside REQUEST_ERROR when error_code = REDIRECT (0x34).
331
+ *
332
+ * draft-20 Section 10.6.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 Draft20RequestError extends Draft20BaseMessage {
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 Draft20GoAway extends Draft20BaseMessage {
352
+ readonly type: 'goaway'
353
+ readonly new_session_uri: string
354
+ readonly timeout: bigint
355
+ }
356
+
357
+ // Union of all draft-20 control messages
358
+ export type Draft20Message =
359
+ | Draft20Setup
360
+ | Draft20Subscribe
361
+ | Draft20SubscribeOk
362
+ | Draft20RequestUpdate
363
+ | Draft20PublishStateNotify
364
+ | Draft20Publish
365
+ | Draft20PublishDone
366
+ | Draft20PublishNamespace
367
+ | Draft20Namespace
368
+ | Draft20NamespaceDone
369
+ | Draft20SubscribeNamespace
370
+ | Draft20SubscribeTracks
371
+ | Draft20PublishSkipped
372
+ | Draft20Fetch
373
+ | Draft20FetchOk
374
+ | Draft20TrackStatus
375
+ | Draft20RequestOk
376
+ | Draft20RequestError
377
+ | Draft20GoAway
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-20 Section 11.4.2). */
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-20 Section 11.3.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-20 that is
437
+ * not necessarily a FETCH: a fill fetch stream (Section 5.1.3) 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 Draft20DataStream = SubgroupStream | DatagramObject | FetchStream
445
+
446
+ // Streaming data stream decoder types
447
+ export interface SubgroupStreamHeader {
448
+ readonly type: 'subgroup_header'
449
+ readonly trackAlias: bigint
450
+ readonly groupId: bigint
451
+ readonly subgroupId: bigint
452
+ readonly publisherPriority: number
453
+ }
454
+
455
+ export interface FetchStreamHeader {
456
+ readonly type: 'fetch_header'
457
+ readonly requestId: bigint
458
+ }
459
+
460
+ export type DataStreamHeader = SubgroupStreamHeader | FetchStreamHeader
461
+ 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]