@tomgiee/tsdp 1.0.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 (171) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +124 -0
  3. package/dist/src/builder/media-builder.d.ts +221 -0
  4. package/dist/src/builder/media-builder.d.ts.map +1 -0
  5. package/dist/src/builder/media-builder.js +385 -0
  6. package/dist/src/builder/session-builder.d.ts +195 -0
  7. package/dist/src/builder/session-builder.d.ts.map +1 -0
  8. package/dist/src/builder/session-builder.js +366 -0
  9. package/dist/src/index.d.ts +67 -0
  10. package/dist/src/index.d.ts.map +1 -0
  11. package/dist/src/index.js +250 -0
  12. package/dist/src/parser/attribute-parser.d.ts +100 -0
  13. package/dist/src/parser/attribute-parser.d.ts.map +1 -0
  14. package/dist/src/parser/attribute-parser.js +217 -0
  15. package/dist/src/parser/field-parser.d.ts +124 -0
  16. package/dist/src/parser/field-parser.d.ts.map +1 -0
  17. package/dist/src/parser/field-parser.js +335 -0
  18. package/dist/src/parser/media-parser.d.ts +45 -0
  19. package/dist/src/parser/media-parser.d.ts.map +1 -0
  20. package/dist/src/parser/media-parser.js +157 -0
  21. package/dist/src/parser/primitive-parser.d.ts +138 -0
  22. package/dist/src/parser/primitive-parser.d.ts.map +1 -0
  23. package/dist/src/parser/primitive-parser.js +316 -0
  24. package/dist/src/parser/scanner.d.ts +142 -0
  25. package/dist/src/parser/scanner.d.ts.map +1 -0
  26. package/dist/src/parser/scanner.js +284 -0
  27. package/dist/src/parser/session-parser.d.ts +35 -0
  28. package/dist/src/parser/session-parser.d.ts.map +1 -0
  29. package/dist/src/parser/session-parser.js +207 -0
  30. package/dist/src/parser/time-parser.d.ts +74 -0
  31. package/dist/src/parser/time-parser.d.ts.map +1 -0
  32. package/dist/src/parser/time-parser.js +168 -0
  33. package/dist/src/serializer/attribute-serializer.d.ts +18 -0
  34. package/dist/src/serializer/attribute-serializer.d.ts.map +1 -0
  35. package/dist/src/serializer/attribute-serializer.js +34 -0
  36. package/dist/src/serializer/field-serializer.d.ts +112 -0
  37. package/dist/src/serializer/field-serializer.d.ts.map +1 -0
  38. package/dist/src/serializer/field-serializer.js +212 -0
  39. package/dist/src/serializer/media-serializer.d.ts +31 -0
  40. package/dist/src/serializer/media-serializer.d.ts.map +1 -0
  41. package/dist/src/serializer/media-serializer.js +83 -0
  42. package/dist/src/serializer/session-serializer.d.ts +29 -0
  43. package/dist/src/serializer/session-serializer.d.ts.map +1 -0
  44. package/dist/src/serializer/session-serializer.js +99 -0
  45. package/dist/src/serializer/time-serializer.d.ts +46 -0
  46. package/dist/src/serializer/time-serializer.d.ts.map +1 -0
  47. package/dist/src/serializer/time-serializer.js +86 -0
  48. package/dist/src/types/attributes.d.ts +318 -0
  49. package/dist/src/types/attributes.d.ts.map +1 -0
  50. package/dist/src/types/attributes.js +225 -0
  51. package/dist/src/types/errors.d.ts +129 -0
  52. package/dist/src/types/errors.d.ts.map +1 -0
  53. package/dist/src/types/errors.js +186 -0
  54. package/dist/src/types/fields.d.ts +100 -0
  55. package/dist/src/types/fields.d.ts.map +1 -0
  56. package/dist/src/types/fields.js +48 -0
  57. package/dist/src/types/media.d.ts +148 -0
  58. package/dist/src/types/media.d.ts.map +1 -0
  59. package/dist/src/types/media.js +137 -0
  60. package/dist/src/types/network.d.ts +136 -0
  61. package/dist/src/types/network.d.ts.map +1 -0
  62. package/dist/src/types/network.js +130 -0
  63. package/dist/src/types/primitives.d.ts +193 -0
  64. package/dist/src/types/primitives.d.ts.map +1 -0
  65. package/dist/src/types/primitives.js +195 -0
  66. package/dist/src/types/session.d.ts +122 -0
  67. package/dist/src/types/session.d.ts.map +1 -0
  68. package/dist/src/types/session.js +81 -0
  69. package/dist/src/types/time.d.ts +129 -0
  70. package/dist/src/types/time.d.ts.map +1 -0
  71. package/dist/src/types/time.js +84 -0
  72. package/dist/src/utils/address-parser.d.ts +100 -0
  73. package/dist/src/utils/address-parser.d.ts.map +1 -0
  74. package/dist/src/utils/address-parser.js +338 -0
  75. package/dist/src/utils/format-validators.d.ts +77 -0
  76. package/dist/src/utils/format-validators.d.ts.map +1 -0
  77. package/dist/src/utils/format-validators.js +504 -0
  78. package/dist/src/utils/line-reader.d.ts +84 -0
  79. package/dist/src/utils/line-reader.d.ts.map +1 -0
  80. package/dist/src/utils/line-reader.js +169 -0
  81. package/dist/src/utils/time-converter.d.ts +99 -0
  82. package/dist/src/utils/time-converter.d.ts.map +1 -0
  83. package/dist/src/utils/time-converter.js +195 -0
  84. package/dist/src/validator/media-validator.d.ts +27 -0
  85. package/dist/src/validator/media-validator.d.ts.map +1 -0
  86. package/dist/src/validator/media-validator.js +241 -0
  87. package/dist/src/validator/semantic-validator.d.ts +47 -0
  88. package/dist/src/validator/semantic-validator.d.ts.map +1 -0
  89. package/dist/src/validator/semantic-validator.js +207 -0
  90. package/dist/src/validator/session-validator.d.ts +36 -0
  91. package/dist/src/validator/session-validator.d.ts.map +1 -0
  92. package/dist/src/validator/session-validator.js +280 -0
  93. package/dist/tests/integration/round-trip.test.d.ts +5 -0
  94. package/dist/tests/integration/round-trip.test.d.ts.map +1 -0
  95. package/dist/tests/integration/round-trip.test.js +320 -0
  96. package/dist/tests/integration/voip-examples.test.d.ts +5 -0
  97. package/dist/tests/integration/voip-examples.test.d.ts.map +1 -0
  98. package/dist/tests/integration/voip-examples.test.js +361 -0
  99. package/dist/tests/unit/builder/media-builder.test.d.ts +5 -0
  100. package/dist/tests/unit/builder/media-builder.test.d.ts.map +1 -0
  101. package/dist/tests/unit/builder/media-builder.test.js +524 -0
  102. package/dist/tests/unit/builder/session-builder.test.d.ts +5 -0
  103. package/dist/tests/unit/builder/session-builder.test.d.ts.map +1 -0
  104. package/dist/tests/unit/builder/session-builder.test.js +367 -0
  105. package/dist/tests/unit/parser/attribute-parser.test.d.ts +5 -0
  106. package/dist/tests/unit/parser/attribute-parser.test.d.ts.map +1 -0
  107. package/dist/tests/unit/parser/attribute-parser.test.js +319 -0
  108. package/dist/tests/unit/parser/field-parser.test.d.ts +5 -0
  109. package/dist/tests/unit/parser/field-parser.test.d.ts.map +1 -0
  110. package/dist/tests/unit/parser/field-parser.test.js +355 -0
  111. package/dist/tests/unit/parser/media-parser.test.d.ts +5 -0
  112. package/dist/tests/unit/parser/media-parser.test.d.ts.map +1 -0
  113. package/dist/tests/unit/parser/media-parser.test.js +241 -0
  114. package/dist/tests/unit/parser/primitive-parser.test.d.ts +5 -0
  115. package/dist/tests/unit/parser/primitive-parser.test.d.ts.map +1 -0
  116. package/dist/tests/unit/parser/primitive-parser.test.js +261 -0
  117. package/dist/tests/unit/parser/scanner.test.d.ts +5 -0
  118. package/dist/tests/unit/parser/scanner.test.d.ts.map +1 -0
  119. package/dist/tests/unit/parser/scanner.test.js +241 -0
  120. package/dist/tests/unit/parser/session-parser.test.d.ts +5 -0
  121. package/dist/tests/unit/parser/session-parser.test.d.ts.map +1 -0
  122. package/dist/tests/unit/parser/session-parser.test.js +346 -0
  123. package/dist/tests/unit/parser/time-parser.test.d.ts +5 -0
  124. package/dist/tests/unit/parser/time-parser.test.d.ts.map +1 -0
  125. package/dist/tests/unit/parser/time-parser.test.js +173 -0
  126. package/dist/tests/unit/serializer/attribute-serializer.test.d.ts +5 -0
  127. package/dist/tests/unit/serializer/attribute-serializer.test.d.ts.map +1 -0
  128. package/dist/tests/unit/serializer/attribute-serializer.test.js +78 -0
  129. package/dist/tests/unit/serializer/field-serializer.test.d.ts +5 -0
  130. package/dist/tests/unit/serializer/field-serializer.test.d.ts.map +1 -0
  131. package/dist/tests/unit/serializer/field-serializer.test.js +159 -0
  132. package/dist/tests/unit/serializer/media-serializer.test.d.ts +5 -0
  133. package/dist/tests/unit/serializer/media-serializer.test.d.ts.map +1 -0
  134. package/dist/tests/unit/serializer/media-serializer.test.js +155 -0
  135. package/dist/tests/unit/serializer/session-serializer.test.d.ts +5 -0
  136. package/dist/tests/unit/serializer/session-serializer.test.d.ts.map +1 -0
  137. package/dist/tests/unit/serializer/session-serializer.test.js +317 -0
  138. package/dist/tests/unit/serializer/time-serializer.test.d.ts +5 -0
  139. package/dist/tests/unit/serializer/time-serializer.test.d.ts.map +1 -0
  140. package/dist/tests/unit/serializer/time-serializer.test.js +115 -0
  141. package/dist/tests/unit/types/errors.test.d.ts +5 -0
  142. package/dist/tests/unit/types/errors.test.d.ts.map +1 -0
  143. package/dist/tests/unit/types/errors.test.js +127 -0
  144. package/dist/tests/unit/types/network.test.d.ts +5 -0
  145. package/dist/tests/unit/types/network.test.d.ts.map +1 -0
  146. package/dist/tests/unit/types/network.test.js +132 -0
  147. package/dist/tests/unit/types/primitives.test.d.ts +5 -0
  148. package/dist/tests/unit/types/primitives.test.d.ts.map +1 -0
  149. package/dist/tests/unit/types/primitives.test.js +108 -0
  150. package/dist/tests/unit/utils/address-parser.test.d.ts +5 -0
  151. package/dist/tests/unit/utils/address-parser.test.d.ts.map +1 -0
  152. package/dist/tests/unit/utils/address-parser.test.js +203 -0
  153. package/dist/tests/unit/utils/format-validators.test.d.ts +5 -0
  154. package/dist/tests/unit/utils/format-validators.test.d.ts.map +1 -0
  155. package/dist/tests/unit/utils/format-validators.test.js +224 -0
  156. package/dist/tests/unit/utils/line-reader.test.d.ts +5 -0
  157. package/dist/tests/unit/utils/line-reader.test.d.ts.map +1 -0
  158. package/dist/tests/unit/utils/line-reader.test.js +157 -0
  159. package/dist/tests/unit/utils/time-converter.test.d.ts +5 -0
  160. package/dist/tests/unit/utils/time-converter.test.d.ts.map +1 -0
  161. package/dist/tests/unit/utils/time-converter.test.js +190 -0
  162. package/dist/tests/unit/validator/media-validator.test.d.ts +5 -0
  163. package/dist/tests/unit/validator/media-validator.test.d.ts.map +1 -0
  164. package/dist/tests/unit/validator/media-validator.test.js +313 -0
  165. package/dist/tests/unit/validator/semantic-validator.test.d.ts +5 -0
  166. package/dist/tests/unit/validator/semantic-validator.test.d.ts.map +1 -0
  167. package/dist/tests/unit/validator/semantic-validator.test.js +262 -0
  168. package/dist/tests/unit/validator/session-validator.test.d.ts +5 -0
  169. package/dist/tests/unit/validator/session-validator.test.d.ts.map +1 -0
  170. package/dist/tests/unit/validator/session-validator.test.js +447 -0
  171. package/package.json +50 -0
@@ -0,0 +1,225 @@
1
+ "use strict";
2
+ /**
3
+ * SDP attribute types (RFC 8866 Section 6)
4
+ *
5
+ * Defines types for SDP attributes, both property and value attributes.
6
+ * Includes 20+ predefined attributes with strong typing.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.MEDIA_ONLY_ATTRIBUTES = exports.SESSION_ONLY_ATTRIBUTES = exports.ATTRIBUTE_USAGE_LEVELS = void 0;
10
+ exports.createPropertyAttribute = createPropertyAttribute;
11
+ exports.createValueAttribute = createValueAttribute;
12
+ exports.createRecvonly = createRecvonly;
13
+ exports.createSendrecv = createSendrecv;
14
+ exports.createSendonly = createSendonly;
15
+ exports.createInactive = createInactive;
16
+ exports.createRtpmap = createRtpmap;
17
+ exports.createFmtp = createFmtp;
18
+ exports.createPtime = createPtime;
19
+ exports.createMaxptime = createMaxptime;
20
+ exports.getAttributeUsageLevel = getAttributeUsageLevel;
21
+ exports.isValidAtSessionLevel = isValidAtSessionLevel;
22
+ exports.isValidAtMediaLevel = isValidAtMediaLevel;
23
+ exports.isPropertyAttribute = isPropertyAttribute;
24
+ exports.isValueAttribute = isValueAttribute;
25
+ exports.isDirectionAttribute = isDirectionAttribute;
26
+ // ============================================================================
27
+ // Helper Functions for Creating Attributes
28
+ // ============================================================================
29
+ /**
30
+ * Create a property attribute
31
+ */
32
+ function createPropertyAttribute(name) {
33
+ return {
34
+ kind: 'property',
35
+ name,
36
+ };
37
+ }
38
+ /**
39
+ * Create a value attribute
40
+ */
41
+ function createValueAttribute(name, value) {
42
+ return {
43
+ kind: 'value',
44
+ name,
45
+ value,
46
+ };
47
+ }
48
+ /**
49
+ * Create recvonly attribute
50
+ */
51
+ function createRecvonly() {
52
+ return { kind: 'property', name: 'recvonly' };
53
+ }
54
+ /**
55
+ * Create sendrecv attribute
56
+ */
57
+ function createSendrecv() {
58
+ return { kind: 'property', name: 'sendrecv' };
59
+ }
60
+ /**
61
+ * Create sendonly attribute
62
+ */
63
+ function createSendonly() {
64
+ return { kind: 'property', name: 'sendonly' };
65
+ }
66
+ /**
67
+ * Create inactive attribute
68
+ */
69
+ function createInactive() {
70
+ return { kind: 'property', name: 'inactive' };
71
+ }
72
+ /**
73
+ * Create rtpmap attribute
74
+ */
75
+ function createRtpmap(payloadType, encodingName, clockRate, encodingParams) {
76
+ let value = `${payloadType} ${encodingName}/${clockRate}`;
77
+ if (encodingParams !== undefined) {
78
+ value += `/${encodingParams}`;
79
+ }
80
+ return {
81
+ kind: 'value',
82
+ name: 'rtpmap',
83
+ value,
84
+ };
85
+ }
86
+ /**
87
+ * Create fmtp attribute
88
+ */
89
+ function createFmtp(format, parameters) {
90
+ return {
91
+ kind: 'value',
92
+ name: 'fmtp',
93
+ value: `${format} ${parameters}`,
94
+ };
95
+ }
96
+ /**
97
+ * Create ptime attribute
98
+ */
99
+ function createPtime(milliseconds) {
100
+ if (milliseconds <= 0) {
101
+ throw new Error('Packet time must be positive');
102
+ }
103
+ return {
104
+ kind: 'value',
105
+ name: 'ptime',
106
+ value: milliseconds.toString(),
107
+ };
108
+ }
109
+ /**
110
+ * Create maxptime attribute
111
+ */
112
+ function createMaxptime(milliseconds) {
113
+ if (milliseconds <= 0) {
114
+ throw new Error('Maximum packet time must be positive');
115
+ }
116
+ return {
117
+ kind: 'value',
118
+ name: 'maxptime',
119
+ value: milliseconds.toString(),
120
+ };
121
+ }
122
+ /**
123
+ * Map of predefined attribute names to their allowed usage levels
124
+ *
125
+ * Per RFC 8866 Section 6:
126
+ * - Session only: cat (6.1), keywds (6.2), tool (6.3), type (6.9), charset (6.10)
127
+ * - Media only: ptime (6.4), maxptime (6.5), rtpmap (6.6), orient (6.8),
128
+ * framerate (6.13), quality (6.14), fmtp (6.15)
129
+ * - Both levels: recvonly, sendrecv, sendonly, inactive (6.7), sdplang (6.11), lang (6.12)
130
+ */
131
+ exports.ATTRIBUTE_USAGE_LEVELS = {
132
+ // Session-level only attributes
133
+ cat: 'session',
134
+ keywds: 'session',
135
+ tool: 'session',
136
+ type: 'session',
137
+ charset: 'session',
138
+ // Media-level only attributes
139
+ ptime: 'media',
140
+ maxptime: 'media',
141
+ rtpmap: 'media',
142
+ fmtp: 'media',
143
+ orient: 'media',
144
+ framerate: 'media',
145
+ quality: 'media',
146
+ // Both session and media level attributes
147
+ recvonly: 'both',
148
+ sendrecv: 'both',
149
+ sendonly: 'both',
150
+ inactive: 'both',
151
+ sdplang: 'both',
152
+ lang: 'both',
153
+ };
154
+ /**
155
+ * Get the usage level for an attribute
156
+ *
157
+ * @param attributeName - Name of the attribute
158
+ * @returns Usage level, or undefined for unknown/extension attributes
159
+ */
160
+ function getAttributeUsageLevel(attributeName) {
161
+ return exports.ATTRIBUTE_USAGE_LEVELS[attributeName];
162
+ }
163
+ /**
164
+ * Check if an attribute is valid at session level
165
+ *
166
+ * @param attributeName - Name of the attribute
167
+ * @returns true if valid at session level, false if media-only, undefined if unknown
168
+ */
169
+ function isValidAtSessionLevel(attributeName) {
170
+ const level = exports.ATTRIBUTE_USAGE_LEVELS[attributeName];
171
+ if (level === undefined) {
172
+ return undefined; // Unknown attribute, allow by default
173
+ }
174
+ return level === 'session' || level === 'both';
175
+ }
176
+ /**
177
+ * Check if an attribute is valid at media level
178
+ *
179
+ * @param attributeName - Name of the attribute
180
+ * @returns true if valid at media level, false if session-only, undefined if unknown
181
+ */
182
+ function isValidAtMediaLevel(attributeName) {
183
+ const level = exports.ATTRIBUTE_USAGE_LEVELS[attributeName];
184
+ if (level === undefined) {
185
+ return undefined; // Unknown attribute, allow by default
186
+ }
187
+ return level === 'media' || level === 'both';
188
+ }
189
+ /**
190
+ * Names of attributes that are only valid at session level
191
+ */
192
+ exports.SESSION_ONLY_ATTRIBUTES = Object.entries(exports.ATTRIBUTE_USAGE_LEVELS)
193
+ .filter(([_, level]) => level === 'session')
194
+ .map(([name]) => name);
195
+ /**
196
+ * Names of attributes that are only valid at media level
197
+ */
198
+ exports.MEDIA_ONLY_ATTRIBUTES = Object.entries(exports.ATTRIBUTE_USAGE_LEVELS)
199
+ .filter(([_, level]) => level === 'media')
200
+ .map(([name]) => name);
201
+ // ============================================================================
202
+ // Type Guards
203
+ // ============================================================================
204
+ /**
205
+ * Check if attribute is a property attribute
206
+ */
207
+ function isPropertyAttribute(attr) {
208
+ return attr.kind === 'property';
209
+ }
210
+ /**
211
+ * Check if attribute is a value attribute
212
+ */
213
+ function isValueAttribute(attr) {
214
+ return attr.kind === 'value';
215
+ }
216
+ /**
217
+ * Check if attribute is a direction attribute
218
+ */
219
+ function isDirectionAttribute(attr) {
220
+ return (attr.kind === 'property' &&
221
+ (attr.name === 'recvonly' ||
222
+ attr.name === 'sendrecv' ||
223
+ attr.name === 'sendonly' ||
224
+ attr.name === 'inactive'));
225
+ }
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Error types for SDP parsing, validation, and serialization (RFC 8866)
3
+ *
4
+ * All errors extend SdpError and are thrown (not returned) per user preference
5
+ * for exception-based error handling.
6
+ */
7
+ import { Position } from './primitives';
8
+ /**
9
+ * Base error class for all SDP-related errors
10
+ */
11
+ export declare class SdpError extends Error {
12
+ /**
13
+ * Error code for programmatic error handling
14
+ */
15
+ readonly code: string;
16
+ constructor(message: string, code: string);
17
+ }
18
+ /**
19
+ * Error thrown during SDP parsing when input is syntactically invalid
20
+ *
21
+ * Includes position information (line, column, offset) for debugging
22
+ */
23
+ export declare class ParseError extends SdpError {
24
+ /**
25
+ * Line number where error occurred (1-indexed)
26
+ */
27
+ readonly line: number;
28
+ /**
29
+ * Column number where error occurred (1-indexed)
30
+ */
31
+ readonly column: number;
32
+ /**
33
+ * Optional snippet of input around the error location
34
+ */
35
+ readonly input?: string;
36
+ constructor(message: string, line: number, column: number, input?: string);
37
+ /**
38
+ * Create a ParseError from a Position object
39
+ */
40
+ static fromPosition(message: string, position: Position, input?: string): ParseError;
41
+ /**
42
+ * Get a formatted error message with context
43
+ */
44
+ getDetailedMessage(): string;
45
+ }
46
+ /**
47
+ * Error thrown when input doesn't match expected grammar
48
+ *
49
+ * Extends ParseError with additional information about what was expected
50
+ * vs what was actually found.
51
+ */
52
+ export declare class GrammarError extends ParseError {
53
+ /**
54
+ * What was expected at this position
55
+ */
56
+ readonly expected: string;
57
+ /**
58
+ * What was actually found at this position
59
+ */
60
+ readonly actual: string;
61
+ constructor(message: string, line: number, column: number, expected: string, actual: string, input?: string);
62
+ }
63
+ /**
64
+ * Error thrown when SDP content violates RFC 8866 semantic constraints
65
+ *
66
+ * Semantic validation happens after successful parsing and checks things like:
67
+ * - Required fields are present
68
+ * - Field ordering is correct
69
+ * - Cross-field dependencies are satisfied
70
+ * - Values are within valid ranges
71
+ */
72
+ export declare class ValidationError extends SdpError {
73
+ /**
74
+ * Name of the field that failed validation (optional)
75
+ */
76
+ readonly field?: string;
77
+ /**
78
+ * RFC 8866 constraint that was violated (optional)
79
+ * Format: "RFC8866:Section.Subsection"
80
+ */
81
+ readonly constraint?: string;
82
+ constructor(message: string, field?: string, constraint?: string);
83
+ /**
84
+ * Create a ValidationError for a missing required field
85
+ */
86
+ static missingField(field: string, constraint?: string): ValidationError;
87
+ /**
88
+ * Create a ValidationError for an invalid field value
89
+ */
90
+ static invalidValue(field: string, value: unknown, reason: string, constraint?: string): ValidationError;
91
+ /**
92
+ * Create a ValidationError for incorrect field ordering
93
+ */
94
+ static incorrectOrdering(field: string, expectedBefore: string, constraint?: string): ValidationError;
95
+ /**
96
+ * Create a ValidationError for violated constraints
97
+ */
98
+ static constraintViolation(message: string, constraint: string): ValidationError;
99
+ }
100
+ /**
101
+ * Error thrown when attempting to serialize invalid SDP objects
102
+ *
103
+ * This typically indicates a programming error where an invalid
104
+ * SessionDescription object was constructed.
105
+ */
106
+ export declare class SerializationError extends SdpError {
107
+ /**
108
+ * Name of the field that failed serialization (optional)
109
+ */
110
+ readonly field?: string;
111
+ constructor(message: string, field?: string);
112
+ }
113
+ /**
114
+ * Error thrown by builder classes when attempting to build invalid SDP
115
+ *
116
+ * Helps catch errors early during SDP construction before serialization.
117
+ */
118
+ export declare class BuilderError extends SdpError {
119
+ constructor(message: string);
120
+ /**
121
+ * Create a BuilderError for missing required field
122
+ */
123
+ static missingRequired(field: string): BuilderError;
124
+ /**
125
+ * Create a BuilderError for invalid configuration
126
+ */
127
+ static invalidConfiguration(message: string): BuilderError;
128
+ }
129
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../../src/types/errors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAMxC;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC;;OAEG;IACH,SAAgB,IAAI,EAAE,MAAM,CAAC;gBAEjB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;CAU1C;AAMD;;;;GAIG;AACH,qBAAa,UAAW,SAAQ,QAAQ;IACtC;;OAEG;IACH,SAAgB,IAAI,EAAE,MAAM,CAAC;IAE7B;;OAEG;IACH,SAAgB,MAAM,EAAE,MAAM,CAAC;IAE/B;;OAEG;IACH,SAAgB,KAAK,CAAC,EAAE,MAAM,CAAC;gBAEnB,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;IASzE;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU;IAIpF;;OAEG;IACH,kBAAkB,IAAI,MAAM;CAe7B;AAMD;;;;;GAKG;AACH,qBAAa,YAAa,SAAQ,UAAU;IAC1C;;OAEG;IACH,SAAgB,QAAQ,EAAE,MAAM,CAAC;IAEjC;;OAEG;IACH,SAAgB,MAAM,EAAE,MAAM,CAAC;gBAG7B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,MAAM;CAQjB;AAMD;;;;;;;;GAQG;AACH,qBAAa,eAAgB,SAAQ,QAAQ;IAC3C;;OAEG;IACH,SAAgB,KAAK,CAAC,EAAE,MAAM,CAAC;IAE/B;;;OAGG;IACH,SAAgB,UAAU,CAAC,EAAE,MAAM,CAAC;gBAExB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;IAiBhE;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe;IAIxE;;OAEG;IACH,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe;IAQxG;;OAEG;IACH,MAAM,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,eAAe;IAQrG;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,eAAe;CAGjF;AAMD;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,QAAQ;IAC9C;;OAEG;IACH,SAAgB,KAAK,CAAC,EAAE,MAAM,CAAC;gBAEnB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM;CAW5C;AAMD;;;;GAIG;AACH,qBAAa,YAAa,SAAQ,QAAQ;gBAC5B,OAAO,EAAE,MAAM;IAK3B;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY;IAInD;;OAEG;IACH,MAAM,CAAC,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,YAAY;CAG3D"}
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ /**
3
+ * Error types for SDP parsing, validation, and serialization (RFC 8866)
4
+ *
5
+ * All errors extend SdpError and are thrown (not returned) per user preference
6
+ * for exception-based error handling.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.BuilderError = exports.SerializationError = exports.ValidationError = exports.GrammarError = exports.ParseError = exports.SdpError = void 0;
10
+ // ============================================================================
11
+ // Base SDP Error
12
+ // ============================================================================
13
+ /**
14
+ * Base error class for all SDP-related errors
15
+ */
16
+ class SdpError extends Error {
17
+ constructor(message, code) {
18
+ super(message);
19
+ this.name = 'SdpError';
20
+ this.code = code;
21
+ // Maintains proper stack trace for where our error was thrown (only available on V8)
22
+ if (Error.captureStackTrace) {
23
+ Error.captureStackTrace(this, this.constructor);
24
+ }
25
+ }
26
+ }
27
+ exports.SdpError = SdpError;
28
+ // ============================================================================
29
+ // Parse Error
30
+ // ============================================================================
31
+ /**
32
+ * Error thrown during SDP parsing when input is syntactically invalid
33
+ *
34
+ * Includes position information (line, column, offset) for debugging
35
+ */
36
+ class ParseError extends SdpError {
37
+ constructor(message, line, column, input) {
38
+ const fullMessage = `Parse error at line ${line}, column ${column}: ${message}`;
39
+ super(fullMessage, 'PARSE_ERROR');
40
+ this.name = 'ParseError';
41
+ this.line = line;
42
+ this.column = column;
43
+ this.input = input;
44
+ }
45
+ /**
46
+ * Create a ParseError from a Position object
47
+ */
48
+ static fromPosition(message, position, input) {
49
+ return new ParseError(message, position.line, position.column, input);
50
+ }
51
+ /**
52
+ * Get a formatted error message with context
53
+ */
54
+ getDetailedMessage() {
55
+ let msg = `${this.message}`;
56
+ if (this.input) {
57
+ const lines = this.input.split('\n');
58
+ const errorLine = lines[this.line - 1];
59
+ if (errorLine) {
60
+ msg += `\n\n${errorLine}\n`;
61
+ msg += ' '.repeat(this.column - 1) + '^';
62
+ }
63
+ }
64
+ return msg;
65
+ }
66
+ }
67
+ exports.ParseError = ParseError;
68
+ // ============================================================================
69
+ // Grammar Error (specialized Parse Error)
70
+ // ============================================================================
71
+ /**
72
+ * Error thrown when input doesn't match expected grammar
73
+ *
74
+ * Extends ParseError with additional information about what was expected
75
+ * vs what was actually found.
76
+ */
77
+ class GrammarError extends ParseError {
78
+ constructor(message, line, column, expected, actual, input) {
79
+ const fullMessage = `${message} (expected: ${expected}, found: ${actual})`;
80
+ super(fullMessage, line, column, input);
81
+ this.name = 'GrammarError';
82
+ this.expected = expected;
83
+ this.actual = actual;
84
+ }
85
+ }
86
+ exports.GrammarError = GrammarError;
87
+ // ============================================================================
88
+ // Validation Error
89
+ // ============================================================================
90
+ /**
91
+ * Error thrown when SDP content violates RFC 8866 semantic constraints
92
+ *
93
+ * Semantic validation happens after successful parsing and checks things like:
94
+ * - Required fields are present
95
+ * - Field ordering is correct
96
+ * - Cross-field dependencies are satisfied
97
+ * - Values are within valid ranges
98
+ */
99
+ class ValidationError extends SdpError {
100
+ constructor(message, field, constraint) {
101
+ let fullMessage = message;
102
+ if (field) {
103
+ fullMessage = `Validation error in field '${field}': ${message}`;
104
+ }
105
+ if (constraint) {
106
+ fullMessage += ` (violates ${constraint})`;
107
+ }
108
+ super(fullMessage, 'VALIDATION_ERROR');
109
+ this.name = 'ValidationError';
110
+ this.field = field;
111
+ this.constraint = constraint;
112
+ }
113
+ /**
114
+ * Create a ValidationError for a missing required field
115
+ */
116
+ static missingField(field, constraint) {
117
+ return new ValidationError(`Required field is missing`, field, constraint);
118
+ }
119
+ /**
120
+ * Create a ValidationError for an invalid field value
121
+ */
122
+ static invalidValue(field, value, reason, constraint) {
123
+ return new ValidationError(`Invalid value '${String(value)}': ${reason}`, field, constraint);
124
+ }
125
+ /**
126
+ * Create a ValidationError for incorrect field ordering
127
+ */
128
+ static incorrectOrdering(field, expectedBefore, constraint) {
129
+ return new ValidationError(`Field '${field}' must appear before '${expectedBefore}'`, field, constraint);
130
+ }
131
+ /**
132
+ * Create a ValidationError for violated constraints
133
+ */
134
+ static constraintViolation(message, constraint) {
135
+ return new ValidationError(message, undefined, constraint);
136
+ }
137
+ }
138
+ exports.ValidationError = ValidationError;
139
+ // ============================================================================
140
+ // Serialization Error
141
+ // ============================================================================
142
+ /**
143
+ * Error thrown when attempting to serialize invalid SDP objects
144
+ *
145
+ * This typically indicates a programming error where an invalid
146
+ * SessionDescription object was constructed.
147
+ */
148
+ class SerializationError extends SdpError {
149
+ constructor(message, field) {
150
+ let fullMessage = message;
151
+ if (field) {
152
+ fullMessage = `Serialization error in field '${field}': ${message}`;
153
+ }
154
+ super(fullMessage, 'SERIALIZATION_ERROR');
155
+ this.name = 'SerializationError';
156
+ this.field = field;
157
+ }
158
+ }
159
+ exports.SerializationError = SerializationError;
160
+ // ============================================================================
161
+ // Builder Error
162
+ // ============================================================================
163
+ /**
164
+ * Error thrown by builder classes when attempting to build invalid SDP
165
+ *
166
+ * Helps catch errors early during SDP construction before serialization.
167
+ */
168
+ class BuilderError extends SdpError {
169
+ constructor(message) {
170
+ super(message, 'BUILDER_ERROR');
171
+ this.name = 'BuilderError';
172
+ }
173
+ /**
174
+ * Create a BuilderError for missing required field
175
+ */
176
+ static missingRequired(field) {
177
+ return new BuilderError(`Required field '${field}' has not been set`);
178
+ }
179
+ /**
180
+ * Create a BuilderError for invalid configuration
181
+ */
182
+ static invalidConfiguration(message) {
183
+ return new BuilderError(`Invalid configuration: ${message}`);
184
+ }
185
+ }
186
+ exports.BuilderError = BuilderError;
@@ -0,0 +1,100 @@
1
+ /**
2
+ * SDP field types (RFC 8866)
3
+ *
4
+ * Defines types for individual SDP fields such as Origin, Connection, Bandwidth, etc.
5
+ */
6
+ import { Username, SessionId, SessionVersion, NetType, AddrType, BandwidthType } from './primitives';
7
+ import { UnicastAddress, ConnectionAddress } from './network';
8
+ /**
9
+ * Origin field (RFC 8866 Section 5.2)
10
+ *
11
+ * Format: o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
12
+ *
13
+ * The origin field gives the originator of the session and a session identifier.
14
+ */
15
+ export interface Origin {
16
+ /**
17
+ * Username of the session originator
18
+ * Use "-" if the originating host does not support the concept of user IDs
19
+ */
20
+ readonly username: Username;
21
+ /**
22
+ * Numeric string such that the tuple of username, sess-id, nettype, addrtype,
23
+ * and unicast-address forms a globally unique identifier for the session.
24
+ * Recommended to be an NTP timestamp.
25
+ */
26
+ readonly sessId: SessionId;
27
+ /**
28
+ * Version number for this session description.
29
+ * Incremented when the session data is modified.
30
+ * Recommended to be an NTP timestamp.
31
+ */
32
+ readonly sessVersion: SessionVersion;
33
+ /**
34
+ * Type of network (typically "IN" for Internet)
35
+ */
36
+ readonly netType: NetType;
37
+ /**
38
+ * Type of address (IP4, IP6, or other)
39
+ */
40
+ readonly addrType: AddrType;
41
+ /**
42
+ * Address of the machine from which the session was created
43
+ */
44
+ readonly unicastAddress: UnicastAddress;
45
+ }
46
+ /**
47
+ * Connection field (RFC 8866 Section 5.7)
48
+ *
49
+ * Format: c=<nettype> <addrtype> <connection-address>
50
+ *
51
+ * Contains connection data. May appear at session level and/or media level.
52
+ * At least one MUST be present at session level or in each media description.
53
+ */
54
+ export interface Connection {
55
+ /**
56
+ * Type of network (typically "IN" for Internet)
57
+ */
58
+ readonly netType: NetType;
59
+ /**
60
+ * Type of address (IP4, IP6, or other)
61
+ */
62
+ readonly addrType: AddrType;
63
+ /**
64
+ * Connection address (unicast or multicast)
65
+ */
66
+ readonly connectionAddress: ConnectionAddress;
67
+ }
68
+ /**
69
+ * Bandwidth field (RFC 8866 Section 5.8)
70
+ *
71
+ * Format: b=<bwtype>:<bandwidth>
72
+ *
73
+ * Denotes the proposed bandwidth to be used by the session or media.
74
+ */
75
+ export interface Bandwidth {
76
+ /**
77
+ * Type of bandwidth
78
+ * - "CT": Conference Total - total bandwidth of all media
79
+ * - "AS": Application Specific - bandwidth for a single media stream
80
+ * - Or a registered extension type
81
+ */
82
+ readonly type: BandwidthType;
83
+ /**
84
+ * Bandwidth value in kilobits per second
85
+ */
86
+ readonly value: number;
87
+ }
88
+ /**
89
+ * Create an Origin field
90
+ */
91
+ export declare function createOrigin(username: string, sessId: string, sessVersion: string, netType: NetType, addrType: AddrType, unicastAddress: UnicastAddress): Origin;
92
+ /**
93
+ * Create a Connection field
94
+ */
95
+ export declare function createConnection(netType: NetType, addrType: AddrType, connectionAddress: ConnectionAddress): Connection;
96
+ /**
97
+ * Create a Bandwidth field
98
+ */
99
+ export declare function createBandwidth(type: string, value: number): Bandwidth;
100
+ //# sourceMappingURL=fields.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fields.d.ts","sourceRoot":"","sources":["../../../src/types/fields.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,QAAQ,EACR,SAAS,EACT,cAAc,EACd,OAAO,EACP,QAAQ,EAMR,aAAa,EACd,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAM9D;;;;;;GAMG;AACH,MAAM,WAAW,MAAM;IACrB;;;OAGG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAE5B;;;;OAIG;IACH,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC;IAE3B;;;;OAIG;IACH,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IAErC;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAE5B;;OAEG;IACH,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;CACzC;AAMD;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAE5B;;OAEG;IACH,QAAQ,CAAC,iBAAiB,EAAE,iBAAiB,CAAC;CAC/C;AAMD;;;;;;GAMG;AACH,MAAM,WAAW,SAAS;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAE7B;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAMD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EACnB,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,cAAc,GAC7B,MAAM,CASR;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,EAClB,iBAAiB,EAAE,iBAAiB,GACnC,UAAU,CAMZ;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAQtE"}
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ /**
3
+ * SDP field types (RFC 8866)
4
+ *
5
+ * Defines types for individual SDP fields such as Origin, Connection, Bandwidth, etc.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.createOrigin = createOrigin;
9
+ exports.createConnection = createConnection;
10
+ exports.createBandwidth = createBandwidth;
11
+ // ============================================================================
12
+ // Helper Functions for Creating Field Types
13
+ // ============================================================================
14
+ /**
15
+ * Create an Origin field
16
+ */
17
+ function createOrigin(username, sessId, sessVersion, netType, addrType, unicastAddress) {
18
+ return {
19
+ username: username,
20
+ sessId: sessId,
21
+ sessVersion: sessVersion,
22
+ netType,
23
+ addrType,
24
+ unicastAddress,
25
+ };
26
+ }
27
+ /**
28
+ * Create a Connection field
29
+ */
30
+ function createConnection(netType, addrType, connectionAddress) {
31
+ return {
32
+ netType,
33
+ addrType,
34
+ connectionAddress,
35
+ };
36
+ }
37
+ /**
38
+ * Create a Bandwidth field
39
+ */
40
+ function createBandwidth(type, value) {
41
+ if (value < 0) {
42
+ throw new Error('Bandwidth value must be non-negative');
43
+ }
44
+ return {
45
+ type: type,
46
+ value,
47
+ };
48
+ }