@tomgiee/tsdp 1.0.1 → 1.1.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 (68) hide show
  1. package/README.md +0 -39
  2. package/dist/src/builder/media-builder.d.ts.map +1 -1
  3. package/dist/src/builder/media-builder.js +5 -12
  4. package/dist/src/builder/session-builder.d.ts.map +1 -1
  5. package/dist/src/builder/session-builder.js +4 -14
  6. package/dist/src/index.d.ts +6 -10
  7. package/dist/src/index.d.ts.map +1 -1
  8. package/dist/src/index.js +37 -49
  9. package/dist/src/parser/core.d.ts +366 -0
  10. package/dist/src/parser/core.d.ts.map +1 -0
  11. package/dist/src/parser/core.js +802 -0
  12. package/dist/src/parser/field-parser.d.ts +51 -8
  13. package/dist/src/parser/field-parser.d.ts.map +1 -1
  14. package/dist/src/parser/field-parser.js +91 -23
  15. package/dist/src/parser/media-parser.d.ts +1 -1
  16. package/dist/src/parser/media-parser.d.ts.map +1 -1
  17. package/dist/src/parser/media-parser.js +9 -15
  18. package/dist/src/parser/session-parser.d.ts.map +1 -1
  19. package/dist/src/parser/session-parser.js +16 -17
  20. package/dist/src/parser/time-parser.d.ts +1 -1
  21. package/dist/src/parser/time-parser.d.ts.map +1 -1
  22. package/dist/src/parser/time-parser.js +8 -8
  23. package/dist/src/serializer/fields.d.ts +167 -0
  24. package/dist/src/serializer/fields.d.ts.map +1 -0
  25. package/dist/src/serializer/fields.js +320 -0
  26. package/dist/src/serializer/media-serializer.js +6 -7
  27. package/dist/src/serializer/session-serializer.js +13 -15
  28. package/dist/src/types/attributes.d.ts.map +1 -1
  29. package/dist/src/types/fields.d.ts +5 -5
  30. package/dist/src/types/fields.d.ts.map +1 -1
  31. package/dist/src/types/fields.js +4 -4
  32. package/dist/src/types/media.d.ts +9 -10
  33. package/dist/src/types/media.d.ts.map +1 -1
  34. package/dist/src/types/media.js +2 -4
  35. package/dist/src/types/network.d.ts +15 -56
  36. package/dist/src/types/network.d.ts.map +1 -1
  37. package/dist/src/types/network.js +3 -34
  38. package/dist/src/types/primitives.d.ts +3 -147
  39. package/dist/src/types/primitives.d.ts.map +1 -1
  40. package/dist/src/types/primitives.js +2 -171
  41. package/dist/src/types/session.d.ts +14 -14
  42. package/dist/src/types/session.d.ts.map +1 -1
  43. package/dist/src/types/time.d.ts +4 -4
  44. package/dist/src/types/time.d.ts.map +1 -1
  45. package/dist/src/types/time.js +8 -6
  46. package/dist/src/utils/address-parser.d.ts +4 -4
  47. package/dist/src/utils/address-parser.d.ts.map +1 -1
  48. package/dist/src/utils/address-parser.js +9 -16
  49. package/dist/src/validator/validator.d.ts +94 -0
  50. package/dist/src/validator/validator.d.ts.map +1 -0
  51. package/dist/src/validator/validator.js +573 -0
  52. package/dist/tests/unit/parser/attribute-parser.test.js +106 -107
  53. package/dist/tests/unit/parser/field-parser.test.js +66 -66
  54. package/dist/tests/unit/parser/media-parser.test.js +38 -38
  55. package/dist/tests/unit/parser/primitive-parser.test.js +89 -90
  56. package/dist/tests/unit/parser/scanner.test.js +32 -32
  57. package/dist/tests/unit/parser/time-parser.test.js +22 -22
  58. package/dist/tests/unit/serializer/attribute-serializer.test.js +22 -22
  59. package/dist/tests/unit/serializer/field-serializer.test.js +57 -57
  60. package/dist/tests/unit/serializer/media-serializer.test.js +5 -6
  61. package/dist/tests/unit/serializer/session-serializer.test.js +24 -24
  62. package/dist/tests/unit/serializer/time-serializer.test.js +16 -16
  63. package/dist/tests/unit/types/network.test.js +21 -56
  64. package/dist/tests/unit/types/primitives.test.js +0 -39
  65. package/dist/tests/unit/validator/media-validator.test.js +34 -35
  66. package/dist/tests/unit/validator/semantic-validator.test.js +36 -37
  67. package/dist/tests/unit/validator/session-validator.test.js +54 -54
  68. package/package.json +1 -1
@@ -3,13 +3,13 @@
3
3
  * Tests for media-parser.ts
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const scanner_1 = require("../../../src/parser/scanner");
6
+ const core_1 = require("../../../src/parser/core");
7
7
  const media_parser_1 = require("../../../src/parser/media-parser");
8
8
  const errors_1 = require("../../../src/types/errors");
9
9
  describe('media-parser', () => {
10
10
  describe('parseMediaField', () => {
11
11
  it('should parse audio media with simple port', () => {
12
- const scanner = new scanner_1.Scanner('audio 49170 RTP/AVP 0 8 101');
12
+ const scanner = new core_1.Scanner('audio 49170 RTP/AVP 0 8 101');
13
13
  const media = (0, media_parser_1.parseMediaField)(scanner);
14
14
  expect(media.type).toBe('audio');
15
15
  expect(media.port.kind).toBe('simple');
@@ -20,7 +20,7 @@ describe('media-parser', () => {
20
20
  expect(media.formats).toEqual(['0', '8', '101']);
21
21
  });
22
22
  it('should parse video media', () => {
23
- const scanner = new scanner_1.Scanner('video 51372 RTP/AVP 99');
23
+ const scanner = new core_1.Scanner('video 51372 RTP/AVP 99');
24
24
  const media = (0, media_parser_1.parseMediaField)(scanner);
25
25
  expect(media.type).toBe('video');
26
26
  expect(media.port.kind).toBe('simple');
@@ -31,7 +31,7 @@ describe('media-parser', () => {
31
31
  expect(media.formats).toEqual(['99']);
32
32
  });
33
33
  it('should parse media with port range', () => {
34
- const scanner = new scanner_1.Scanner('audio 49170/2 RTP/AVP 0');
34
+ const scanner = new core_1.Scanner('audio 49170/2 RTP/AVP 0');
35
35
  const media = (0, media_parser_1.parseMediaField)(scanner);
36
36
  expect(media.type).toBe('audio');
37
37
  expect(media.port.kind).toBe('range');
@@ -43,30 +43,30 @@ describe('media-parser', () => {
43
43
  expect(media.formats).toEqual(['0']);
44
44
  });
45
45
  it('should parse text media', () => {
46
- const scanner = new scanner_1.Scanner('text 49174 RTP/AVP 96');
46
+ const scanner = new core_1.Scanner('text 49174 RTP/AVP 96');
47
47
  const media = (0, media_parser_1.parseMediaField)(scanner);
48
48
  expect(media.type).toBe('text');
49
49
  });
50
50
  it('should parse application media', () => {
51
- const scanner = new scanner_1.Scanner('application 49175 udp wb');
51
+ const scanner = new core_1.Scanner('application 49175 udp wb');
52
52
  const media = (0, media_parser_1.parseMediaField)(scanner);
53
53
  expect(media.type).toBe('application');
54
54
  expect(media.proto).toBe('udp');
55
55
  expect(media.formats).toEqual(['wb']);
56
56
  });
57
57
  it('should parse message media', () => {
58
- const scanner = new scanner_1.Scanner('message 49176 RTP/AVP 97');
58
+ const scanner = new core_1.Scanner('message 49176 RTP/AVP 97');
59
59
  const media = (0, media_parser_1.parseMediaField)(scanner);
60
60
  expect(media.type).toBe('message');
61
61
  });
62
62
  it('should parse image media', () => {
63
- const scanner = new scanner_1.Scanner('image 49177 udp t38');
63
+ const scanner = new core_1.Scanner('image 49177 udp t38');
64
64
  const media = (0, media_parser_1.parseMediaField)(scanner);
65
65
  expect(media.type).toBe('image');
66
66
  expect(media.formats).toEqual(['t38']);
67
67
  });
68
68
  it('should parse media with port 0 (disabled)', () => {
69
- const scanner = new scanner_1.Scanner('audio 0 RTP/AVP 0');
69
+ const scanner = new core_1.Scanner('audio 0 RTP/AVP 0');
70
70
  const media = (0, media_parser_1.parseMediaField)(scanner);
71
71
  expect(media.port.kind).toBe('simple');
72
72
  if (media.port.kind === 'simple') {
@@ -74,47 +74,47 @@ describe('media-parser', () => {
74
74
  }
75
75
  });
76
76
  it('should parse media with multiple formats', () => {
77
- const scanner = new scanner_1.Scanner('audio 49170 RTP/AVP 0 8 3 18 101');
77
+ const scanner = new core_1.Scanner('audio 49170 RTP/AVP 0 8 3 18 101');
78
78
  const media = (0, media_parser_1.parseMediaField)(scanner);
79
79
  expect(media.formats).toHaveLength(5);
80
80
  expect(media.formats).toEqual(['0', '8', '3', '18', '101']);
81
81
  });
82
82
  it('should parse media with RTP/SAVP protocol', () => {
83
- const scanner = new scanner_1.Scanner('audio 49170 RTP/SAVP 0');
83
+ const scanner = new core_1.Scanner('audio 49170 RTP/SAVP 0');
84
84
  const media = (0, media_parser_1.parseMediaField)(scanner);
85
85
  expect(media.proto).toBe('RTP/SAVP');
86
86
  });
87
87
  it('should parse media with RTP/SAVPF protocol', () => {
88
- const scanner = new scanner_1.Scanner('audio 49170 RTP/SAVPF 111');
88
+ const scanner = new core_1.Scanner('audio 49170 RTP/SAVPF 111');
89
89
  const media = (0, media_parser_1.parseMediaField)(scanner);
90
90
  expect(media.proto).toBe('RTP/SAVPF');
91
91
  });
92
92
  it('should throw for invalid port number', () => {
93
- expect(() => (0, media_parser_1.parseMediaField)(new scanner_1.Scanner('audio abc RTP/AVP 0'))).toThrow(errors_1.ParseError);
94
- expect(() => (0, media_parser_1.parseMediaField)(new scanner_1.Scanner('audio abc RTP/AVP 0'))).toThrow('Invalid port number');
93
+ expect(() => (0, media_parser_1.parseMediaField)(new core_1.Scanner('audio abc RTP/AVP 0'))).toThrow(errors_1.ParseError);
94
+ expect(() => (0, media_parser_1.parseMediaField)(new core_1.Scanner('audio abc RTP/AVP 0'))).toThrow('Invalid port number');
95
95
  });
96
96
  it('should throw for invalid port range', () => {
97
- expect(() => (0, media_parser_1.parseMediaField)(new scanner_1.Scanner('audio 49170/abc RTP/AVP 0'))).toThrow(errors_1.ParseError);
98
- expect(() => (0, media_parser_1.parseMediaField)(new scanner_1.Scanner('audio 49170/abc RTP/AVP 0'))).toThrow('Invalid port range');
97
+ expect(() => (0, media_parser_1.parseMediaField)(new core_1.Scanner('audio 49170/abc RTP/AVP 0'))).toThrow(errors_1.ParseError);
98
+ expect(() => (0, media_parser_1.parseMediaField)(new core_1.Scanner('audio 49170/abc RTP/AVP 0'))).toThrow('Invalid port range');
99
99
  });
100
100
  it('should throw for missing formats', () => {
101
- expect(() => (0, media_parser_1.parseMediaField)(new scanner_1.Scanner('audio 49170 RTP/AVP'))).toThrow(errors_1.ParseError);
102
- expect(() => (0, media_parser_1.parseMediaField)(new scanner_1.Scanner('audio 49170 RTP/AVP'))).toThrow('at least one media format');
101
+ expect(() => (0, media_parser_1.parseMediaField)(new core_1.Scanner('audio 49170 RTP/AVP'))).toThrow(errors_1.ParseError);
102
+ expect(() => (0, media_parser_1.parseMediaField)(new core_1.Scanner('audio 49170 RTP/AVP'))).toThrow('at least one media format');
103
103
  });
104
104
  it('should throw for port out of range', () => {
105
- expect(() => (0, media_parser_1.parseMediaField)(new scanner_1.Scanner('audio 70000 RTP/AVP 0'))).toThrow();
105
+ expect(() => (0, media_parser_1.parseMediaField)(new core_1.Scanner('audio 70000 RTP/AVP 0'))).toThrow();
106
106
  });
107
107
  it('should throw for negative port', () => {
108
- expect(() => (0, media_parser_1.parseMediaField)(new scanner_1.Scanner('audio -1 RTP/AVP 0'))).toThrow();
108
+ expect(() => (0, media_parser_1.parseMediaField)(new core_1.Scanner('audio -1 RTP/AVP 0'))).toThrow();
109
109
  });
110
110
  it('should throw for invalid port range format', () => {
111
- expect(() => (0, media_parser_1.parseMediaField)(new scanner_1.Scanner('audio 49170/2/3 RTP/AVP 0'))).toThrow(errors_1.ParseError);
112
- expect(() => (0, media_parser_1.parseMediaField)(new scanner_1.Scanner('audio 49170/2/3 RTP/AVP 0'))).toThrow('Invalid port range format');
111
+ expect(() => (0, media_parser_1.parseMediaField)(new core_1.Scanner('audio 49170/2/3 RTP/AVP 0'))).toThrow(errors_1.ParseError);
112
+ expect(() => (0, media_parser_1.parseMediaField)(new core_1.Scanner('audio 49170/2/3 RTP/AVP 0'))).toThrow('Invalid port range format');
113
113
  });
114
114
  });
115
115
  describe('parseMediaDescription', () => {
116
116
  it('should parse minimal media description (m= only)', () => {
117
- const mediaScanner = new scanner_1.Scanner('audio 49170 RTP/AVP 0');
117
+ const mediaScanner = new core_1.Scanner('audio 49170 RTP/AVP 0');
118
118
  const md = (0, media_parser_1.parseMediaDescription)(mediaScanner, []);
119
119
  expect(md.media.type).toBe('audio');
120
120
  expect(md.information).toBeUndefined();
@@ -124,14 +124,14 @@ describe('media-parser', () => {
124
124
  expect(md.attributes).toHaveLength(0);
125
125
  });
126
126
  it('should parse media description with information', () => {
127
- const mediaScanner = new scanner_1.Scanner('audio 49170 RTP/AVP 0');
127
+ const mediaScanner = new core_1.Scanner('audio 49170 RTP/AVP 0');
128
128
  const md = (0, media_parser_1.parseMediaDescription)(mediaScanner, [
129
129
  { type: 'i', value: 'Audio Stream' },
130
130
  ]);
131
131
  expect(md.information).toBe('Audio Stream');
132
132
  });
133
133
  it('should parse media description with connection', () => {
134
- const mediaScanner = new scanner_1.Scanner('audio 49170 RTP/AVP 0');
134
+ const mediaScanner = new core_1.Scanner('audio 49170 RTP/AVP 0');
135
135
  const md = (0, media_parser_1.parseMediaDescription)(mediaScanner, [
136
136
  { type: 'c', value: 'IN IP4 192.168.1.100' },
137
137
  ]);
@@ -140,7 +140,7 @@ describe('media-parser', () => {
140
140
  expect(md.connections[0].addrType).toBe('IP4');
141
141
  });
142
142
  it('should parse media description with multiple connections', () => {
143
- const mediaScanner = new scanner_1.Scanner('audio 49170 RTP/AVP 0');
143
+ const mediaScanner = new core_1.Scanner('audio 49170 RTP/AVP 0');
144
144
  const md = (0, media_parser_1.parseMediaDescription)(mediaScanner, [
145
145
  { type: 'c', value: 'IN IP4 192.168.1.100' },
146
146
  { type: 'c', value: 'IN IP4 192.168.1.101' },
@@ -148,7 +148,7 @@ describe('media-parser', () => {
148
148
  expect(md.connections).toHaveLength(2);
149
149
  });
150
150
  it('should parse media description with bandwidth', () => {
151
- const mediaScanner = new scanner_1.Scanner('audio 49170 RTP/AVP 0');
151
+ const mediaScanner = new core_1.Scanner('audio 49170 RTP/AVP 0');
152
152
  const md = (0, media_parser_1.parseMediaDescription)(mediaScanner, [
153
153
  { type: 'b', value: 'AS:64' },
154
154
  ]);
@@ -157,7 +157,7 @@ describe('media-parser', () => {
157
157
  expect(md.bandwidths[0].value).toBe(64);
158
158
  });
159
159
  it('should parse media description with multiple bandwidths', () => {
160
- const mediaScanner = new scanner_1.Scanner('audio 49170 RTP/AVP 0');
160
+ const mediaScanner = new core_1.Scanner('audio 49170 RTP/AVP 0');
161
161
  const md = (0, media_parser_1.parseMediaDescription)(mediaScanner, [
162
162
  { type: 'b', value: 'AS:64' },
163
163
  { type: 'b', value: 'CT:128' },
@@ -165,14 +165,14 @@ describe('media-parser', () => {
165
165
  expect(md.bandwidths).toHaveLength(2);
166
166
  });
167
167
  it('should parse media description with key', () => {
168
- const mediaScanner = new scanner_1.Scanner('audio 49170 RTP/AVP 0');
168
+ const mediaScanner = new core_1.Scanner('audio 49170 RTP/AVP 0');
169
169
  const md = (0, media_parser_1.parseMediaDescription)(mediaScanner, [
170
170
  { type: 'k', value: 'clear:mykey123' },
171
171
  ]);
172
172
  expect(md.key).toBe('clear:mykey123');
173
173
  });
174
174
  it('should parse media description with attributes', () => {
175
- const mediaScanner = new scanner_1.Scanner('audio 49170 RTP/AVP 0 8');
175
+ const mediaScanner = new core_1.Scanner('audio 49170 RTP/AVP 0 8');
176
176
  const md = (0, media_parser_1.parseMediaDescription)(mediaScanner, [
177
177
  { type: 'a', value: 'rtpmap:0 PCMU/8000' },
178
178
  { type: 'a', value: 'rtpmap:8 PCMA/8000' },
@@ -182,7 +182,7 @@ describe('media-parser', () => {
182
182
  expect(md.attributes).toHaveLength(4);
183
183
  });
184
184
  it('should parse complete media description with all fields', () => {
185
- const mediaScanner = new scanner_1.Scanner('audio 49170 RTP/AVP 0');
185
+ const mediaScanner = new core_1.Scanner('audio 49170 RTP/AVP 0');
186
186
  const md = (0, media_parser_1.parseMediaDescription)(mediaScanner, [
187
187
  { type: 'i', value: 'Voice' },
188
188
  { type: 'c', value: 'IN IP4 192.168.1.100' },
@@ -198,7 +198,7 @@ describe('media-parser', () => {
198
198
  expect(md.attributes).toHaveLength(2);
199
199
  });
200
200
  it('should parse media description with correct field ordering', () => {
201
- const mediaScanner = new scanner_1.Scanner('video 51372 RTP/AVP 99');
201
+ const mediaScanner = new core_1.Scanner('video 51372 RTP/AVP 99');
202
202
  const md = (0, media_parser_1.parseMediaDescription)(mediaScanner, [
203
203
  { type: 'i', value: 'Video Stream' },
204
204
  { type: 'c', value: 'IN IP4 192.168.1.100' },
@@ -211,31 +211,31 @@ describe('media-parser', () => {
211
211
  expect(md.information).toBe('Video Stream');
212
212
  });
213
213
  it('should throw for duplicate information field', () => {
214
- const mediaScanner = new scanner_1.Scanner('audio 49170 RTP/AVP 0');
214
+ const mediaScanner = new core_1.Scanner('audio 49170 RTP/AVP 0');
215
215
  expect(() => (0, media_parser_1.parseMediaDescription)(mediaScanner, [
216
216
  { type: 'i', value: 'First' },
217
217
  { type: 'i', value: 'Second' },
218
218
  ])).toThrow(errors_1.ParseError);
219
- expect(() => (0, media_parser_1.parseMediaDescription)(new scanner_1.Scanner('audio 49170 RTP/AVP 0'), [
219
+ expect(() => (0, media_parser_1.parseMediaDescription)(new core_1.Scanner('audio 49170 RTP/AVP 0'), [
220
220
  { type: 'i', value: 'First' },
221
221
  { type: 'i', value: 'Second' },
222
222
  ])).toThrow('Duplicate information field');
223
223
  });
224
224
  it('should throw for duplicate key field', () => {
225
- const mediaScanner = new scanner_1.Scanner('audio 49170 RTP/AVP 0');
225
+ const mediaScanner = new core_1.Scanner('audio 49170 RTP/AVP 0');
226
226
  expect(() => (0, media_parser_1.parseMediaDescription)(mediaScanner, [
227
227
  { type: 'k', value: 'clear:key1' },
228
228
  { type: 'k', value: 'clear:key2' },
229
229
  ])).toThrow(errors_1.ParseError);
230
- expect(() => (0, media_parser_1.parseMediaDescription)(new scanner_1.Scanner('audio 49170 RTP/AVP 0'), [
230
+ expect(() => (0, media_parser_1.parseMediaDescription)(new core_1.Scanner('audio 49170 RTP/AVP 0'), [
231
231
  { type: 'k', value: 'clear:key1' },
232
232
  { type: 'k', value: 'clear:key2' },
233
233
  ])).toThrow('Duplicate key field');
234
234
  });
235
235
  it('should throw for unexpected field type', () => {
236
- const mediaScanner = new scanner_1.Scanner('audio 49170 RTP/AVP 0');
236
+ const mediaScanner = new core_1.Scanner('audio 49170 RTP/AVP 0');
237
237
  expect(() => (0, media_parser_1.parseMediaDescription)(mediaScanner, [{ type: 'v', value: '0' }])).toThrow(errors_1.ParseError);
238
- expect(() => (0, media_parser_1.parseMediaDescription)(new scanner_1.Scanner('audio 49170 RTP/AVP 0'), [{ type: 'v', value: '0' }])).toThrow('Unexpected field type');
238
+ expect(() => (0, media_parser_1.parseMediaDescription)(new core_1.Scanner('audio 49170 RTP/AVP 0'), [{ type: 'v', value: '0' }])).toThrow('Unexpected field type');
239
239
  });
240
240
  });
241
241
  });
@@ -3,258 +3,257 @@
3
3
  * Tests for primitive-parser.ts
4
4
  */
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const scanner_1 = require("../../../src/parser/scanner");
7
- const primitive_parser_1 = require("../../../src/parser/primitive-parser");
6
+ const core_1 = require("../../../src/parser/core");
8
7
  const errors_1 = require("../../../src/types/errors");
9
8
  describe('primitive-parser', () => {
10
9
  describe('parseToken', () => {
11
10
  it('should parse valid tokens', () => {
12
- const scanner = new scanner_1.Scanner('RTP');
13
- const token = (0, primitive_parser_1.parseToken)(scanner);
11
+ const scanner = new core_1.Scanner('RTP');
12
+ const token = (0, core_1.parseToken)(scanner);
14
13
  expect(token).toBe('RTP');
15
14
  });
16
15
  it('should parse tokens with various characters', () => {
17
- const scanner = new scanner_1.Scanner('a1B2-test.name_v123');
18
- const token = (0, primitive_parser_1.parseToken)(scanner);
16
+ const scanner = new core_1.Scanner('a1B2-test.name_v123');
17
+ const token = (0, core_1.parseToken)(scanner);
19
18
  expect(token).toBe('a1B2-test.name_v123');
20
19
  });
21
20
  it('should stop at whitespace', () => {
22
- const scanner = new scanner_1.Scanner('token next');
23
- const token = (0, primitive_parser_1.parseToken)(scanner);
21
+ const scanner = new core_1.Scanner('token next');
22
+ const token = (0, core_1.parseToken)(scanner);
24
23
  expect(token).toBe('token');
25
24
  expect(scanner.peek()).toBe(' ');
26
25
  });
27
26
  it('should throw if no token found', () => {
28
- const scanner = new scanner_1.Scanner(' ');
29
- expect(() => (0, primitive_parser_1.parseToken)(scanner)).toThrow(errors_1.ParseError);
27
+ const scanner = new core_1.Scanner(' ');
28
+ expect(() => (0, core_1.parseToken)(scanner)).toThrow(errors_1.ParseError);
30
29
  });
31
30
  });
32
31
  describe('parseInteger', () => {
33
32
  it('should parse positive integers', () => {
34
- const scanner = new scanner_1.Scanner('12345');
35
- const num = (0, primitive_parser_1.parseInteger)(scanner);
33
+ const scanner = new core_1.Scanner('12345');
34
+ const num = (0, core_1.parseInteger)(scanner);
36
35
  expect(num).toBe(12345);
37
36
  });
38
37
  it('should parse zero', () => {
39
- const scanner = new scanner_1.Scanner('0');
40
- const num = (0, primitive_parser_1.parseInteger)(scanner);
38
+ const scanner = new core_1.Scanner('0');
39
+ const num = (0, core_1.parseInteger)(scanner);
41
40
  expect(num).toBe(0);
42
41
  });
43
42
  it('should stop at non-digit', () => {
44
- const scanner = new scanner_1.Scanner('123abc');
45
- const num = (0, primitive_parser_1.parseInteger)(scanner);
43
+ const scanner = new core_1.Scanner('123abc');
44
+ const num = (0, core_1.parseInteger)(scanner);
46
45
  expect(num).toBe(123);
47
46
  expect(scanner.peek()).toBe('a');
48
47
  });
49
48
  it('should throw if no digits found', () => {
50
- const scanner = new scanner_1.Scanner('abc');
51
- expect(() => (0, primitive_parser_1.parseInteger)(scanner)).toThrow(errors_1.ParseError);
49
+ const scanner = new core_1.Scanner('abc');
50
+ expect(() => (0, core_1.parseInteger)(scanner)).toThrow(errors_1.ParseError);
52
51
  });
53
52
  });
54
53
  describe('parseByte', () => {
55
54
  it('should parse valid byte values', () => {
56
- expect((0, primitive_parser_1.parseByte)(new scanner_1.Scanner('0'))).toBe(0);
57
- expect((0, primitive_parser_1.parseByte)(new scanner_1.Scanner('128'))).toBe(128);
58
- expect((0, primitive_parser_1.parseByte)(new scanner_1.Scanner('255'))).toBe(255);
55
+ expect((0, core_1.parseByte)(new core_1.Scanner('0'))).toBe(0);
56
+ expect((0, core_1.parseByte)(new core_1.Scanner('128'))).toBe(128);
57
+ expect((0, core_1.parseByte)(new core_1.Scanner('255'))).toBe(255);
59
58
  });
60
59
  it('should throw for values > 255', () => {
61
- expect(() => (0, primitive_parser_1.parseByte)(new scanner_1.Scanner('256'))).toThrow(errors_1.ParseError);
62
- expect(() => (0, primitive_parser_1.parseByte)(new scanner_1.Scanner('256'))).toThrow('out of range');
60
+ expect(() => (0, core_1.parseByte)(new core_1.Scanner('256'))).toThrow(errors_1.ParseError);
61
+ expect(() => (0, core_1.parseByte)(new core_1.Scanner('256'))).toThrow('out of range');
63
62
  });
64
63
  it('should throw for negative values', () => {
65
- const scanner = new scanner_1.Scanner('-1');
66
- expect(() => (0, primitive_parser_1.parseByte)(scanner)).toThrow(errors_1.ParseError);
64
+ const scanner = new core_1.Scanner('-1');
65
+ expect(() => (0, core_1.parseByte)(scanner)).toThrow(errors_1.ParseError);
67
66
  });
68
67
  });
69
68
  describe('parseNonWSString', () => {
70
69
  it('should parse non-whitespace string', () => {
71
- const scanner = new scanner_1.Scanner('hello world');
72
- const str = (0, primitive_parser_1.parseNonWSString)(scanner);
70
+ const scanner = new core_1.Scanner('hello world');
71
+ const str = (0, core_1.parseNonWSString)(scanner);
73
72
  expect(str).toBe('hello');
74
73
  expect(scanner.peek()).toBe(' ');
75
74
  });
76
75
  it('should stop at newline', () => {
77
- const scanner = new scanner_1.Scanner('test\nnext');
78
- const str = (0, primitive_parser_1.parseNonWSString)(scanner);
76
+ const scanner = new core_1.Scanner('test\nnext');
77
+ const str = (0, core_1.parseNonWSString)(scanner);
79
78
  expect(str).toBe('test');
80
79
  expect(scanner.peek()).toBe('\n');
81
80
  });
82
81
  it('should throw if starts with whitespace', () => {
83
- const scanner = new scanner_1.Scanner(' test');
84
- expect(() => (0, primitive_parser_1.parseNonWSString)(scanner)).toThrow(errors_1.ParseError);
82
+ const scanner = new core_1.Scanner(' test');
83
+ expect(() => (0, core_1.parseNonWSString)(scanner)).toThrow(errors_1.ParseError);
85
84
  });
86
85
  });
87
86
  describe('parseByteString', () => {
88
87
  it('should parse byte-string', () => {
89
- const scanner = new scanner_1.Scanner('test123!@#');
90
- const str = (0, primitive_parser_1.parseByteString)(scanner);
88
+ const scanner = new core_1.Scanner('test123!@#');
89
+ const str = (0, core_1.parseByteString)(scanner);
91
90
  expect(str).toBe('test123!@#');
92
91
  });
93
92
  it('should stop at newline', () => {
94
- const scanner = new scanner_1.Scanner('test\nnext');
95
- const str = (0, primitive_parser_1.parseByteString)(scanner);
93
+ const scanner = new core_1.Scanner('test\nnext');
94
+ const str = (0, core_1.parseByteString)(scanner);
96
95
  expect(str).toBe('test');
97
96
  });
98
97
  });
99
98
  describe('parseIP4Address', () => {
100
99
  it('should parse valid IPv4 addresses', () => {
101
- expect((0, primitive_parser_1.parseIP4Address)(new scanner_1.Scanner('192.168.1.1'))).toBe('192.168.1.1');
102
- expect((0, primitive_parser_1.parseIP4Address)(new scanner_1.Scanner('0.0.0.0'))).toBe('0.0.0.0');
103
- expect((0, primitive_parser_1.parseIP4Address)(new scanner_1.Scanner('255.255.255.255'))).toBe('255.255.255.255');
100
+ expect((0, core_1.parseIP4Address)(new core_1.Scanner('192.168.1.1'))).toBe('192.168.1.1');
101
+ expect((0, core_1.parseIP4Address)(new core_1.Scanner('0.0.0.0'))).toBe('0.0.0.0');
102
+ expect((0, core_1.parseIP4Address)(new core_1.Scanner('255.255.255.255'))).toBe('255.255.255.255');
104
103
  });
105
104
  it('should stop at whitespace', () => {
106
- const scanner = new scanner_1.Scanner('192.168.1.1 next');
107
- const addr = (0, primitive_parser_1.parseIP4Address)(scanner);
105
+ const scanner = new core_1.Scanner('192.168.1.1 next');
106
+ const addr = (0, core_1.parseIP4Address)(scanner);
108
107
  expect(addr).toBe('192.168.1.1');
109
108
  expect(scanner.peek()).toBe(' ');
110
109
  });
111
110
  it('should throw for invalid IPv4', () => {
112
- expect(() => (0, primitive_parser_1.parseIP4Address)(new scanner_1.Scanner('256.1.1.1'))).toThrow(errors_1.ParseError);
113
- expect(() => (0, primitive_parser_1.parseIP4Address)(new scanner_1.Scanner('192.168.1'))).toThrow(errors_1.ParseError);
111
+ expect(() => (0, core_1.parseIP4Address)(new core_1.Scanner('256.1.1.1'))).toThrow(errors_1.ParseError);
112
+ expect(() => (0, core_1.parseIP4Address)(new core_1.Scanner('192.168.1'))).toThrow(errors_1.ParseError);
114
113
  });
115
114
  });
116
115
  describe('parseIP6Address', () => {
117
116
  it('should parse valid IPv6 addresses', () => {
118
- expect((0, primitive_parser_1.parseIP6Address)(new scanner_1.Scanner('2001:db8::1'))).toBe('2001:db8::1');
119
- expect((0, primitive_parser_1.parseIP6Address)(new scanner_1.Scanner('::1'))).toBe('::1');
120
- expect((0, primitive_parser_1.parseIP6Address)(new scanner_1.Scanner('fe80::1'))).toBe('fe80::1');
117
+ expect((0, core_1.parseIP6Address)(new core_1.Scanner('2001:db8::1'))).toBe('2001:db8::1');
118
+ expect((0, core_1.parseIP6Address)(new core_1.Scanner('::1'))).toBe('::1');
119
+ expect((0, core_1.parseIP6Address)(new core_1.Scanner('fe80::1'))).toBe('fe80::1');
121
120
  });
122
121
  it('should parse IPv6 with mixed IPv4', () => {
123
- const addr = (0, primitive_parser_1.parseIP6Address)(new scanner_1.Scanner('::ffff:192.0.2.1'));
122
+ const addr = (0, core_1.parseIP6Address)(new core_1.Scanner('::ffff:192.0.2.1'));
124
123
  expect(addr).toBe('::ffff:192.0.2.1');
125
124
  });
126
125
  it('should stop at whitespace', () => {
127
- const scanner = new scanner_1.Scanner('2001:db8::1 next');
128
- const addr = (0, primitive_parser_1.parseIP6Address)(scanner);
126
+ const scanner = new core_1.Scanner('2001:db8::1 next');
127
+ const addr = (0, core_1.parseIP6Address)(scanner);
129
128
  expect(addr).toBe('2001:db8::1');
130
129
  expect(scanner.peek()).toBe(' ');
131
130
  });
132
131
  it('should throw for invalid IPv6', () => {
133
- expect(() => (0, primitive_parser_1.parseIP6Address)(new scanner_1.Scanner('gggg::1'))).toThrow(errors_1.ParseError);
134
- expect(() => (0, primitive_parser_1.parseIP6Address)(new scanner_1.Scanner('::1::2'))).toThrow(errors_1.ParseError);
132
+ expect(() => (0, core_1.parseIP6Address)(new core_1.Scanner('gggg::1'))).toThrow(errors_1.ParseError);
133
+ expect(() => (0, core_1.parseIP6Address)(new core_1.Scanner('::1::2'))).toThrow(errors_1.ParseError);
135
134
  });
136
135
  });
137
136
  describe('parseFQDN', () => {
138
137
  it('should parse valid FQDNs', () => {
139
- expect((0, primitive_parser_1.parseFQDN)(new scanner_1.Scanner('example.com'))).toBe('example.com');
140
- expect((0, primitive_parser_1.parseFQDN)(new scanner_1.Scanner('sub.domain.example.org'))).toBe('sub.domain.example.org');
141
- expect((0, primitive_parser_1.parseFQDN)(new scanner_1.Scanner('localhost'))).toBe('localhost');
138
+ expect((0, core_1.parseFQDN)(new core_1.Scanner('example.com'))).toBe('example.com');
139
+ expect((0, core_1.parseFQDN)(new core_1.Scanner('sub.domain.example.org'))).toBe('sub.domain.example.org');
140
+ expect((0, core_1.parseFQDN)(new core_1.Scanner('localhost'))).toBe('localhost');
142
141
  });
143
142
  it('should parse FQDN with hyphens', () => {
144
- expect((0, primitive_parser_1.parseFQDN)(new scanner_1.Scanner('my-server.example.com'))).toBe('my-server.example.com');
143
+ expect((0, core_1.parseFQDN)(new core_1.Scanner('my-server.example.com'))).toBe('my-server.example.com');
145
144
  });
146
145
  it('should stop at whitespace', () => {
147
- const scanner = new scanner_1.Scanner('example.com next');
148
- const fqdn = (0, primitive_parser_1.parseFQDN)(scanner);
146
+ const scanner = new core_1.Scanner('example.com next');
147
+ const fqdn = (0, core_1.parseFQDN)(scanner);
149
148
  expect(fqdn).toBe('example.com');
150
149
  expect(scanner.peek()).toBe(' ');
151
150
  });
152
151
  it('should throw for invalid FQDN', () => {
153
- expect(() => (0, primitive_parser_1.parseFQDN)(new scanner_1.Scanner('-invalid.com'))).toThrow(errors_1.ParseError);
154
- expect(() => (0, primitive_parser_1.parseFQDN)(new scanner_1.Scanner('invalid-.com'))).toThrow(errors_1.ParseError);
152
+ expect(() => (0, core_1.parseFQDN)(new core_1.Scanner('-invalid.com'))).toThrow(errors_1.ParseError);
153
+ expect(() => (0, core_1.parseFQDN)(new core_1.Scanner('invalid-.com'))).toThrow(errors_1.ParseError);
155
154
  });
156
155
  });
157
156
  describe('parseNtpTime', () => {
158
157
  it('should parse NTP timestamps', () => {
159
- expect((0, primitive_parser_1.parseNtpTime)(new scanner_1.Scanner('0'))).toBe(0);
160
- expect((0, primitive_parser_1.parseNtpTime)(new scanner_1.Scanner('3724394400'))).toBe(3724394400);
158
+ expect((0, core_1.parseNtpTime)(new core_1.Scanner('0'))).toBe(0);
159
+ expect((0, core_1.parseNtpTime)(new core_1.Scanner('3724394400'))).toBe(3724394400);
161
160
  });
162
161
  it('should stop at non-digit', () => {
163
- const scanner = new scanner_1.Scanner('123 456');
164
- const time = (0, primitive_parser_1.parseNtpTime)(scanner);
162
+ const scanner = new core_1.Scanner('123 456');
163
+ const time = (0, core_1.parseNtpTime)(scanner);
165
164
  expect(time).toBe(123);
166
165
  expect(scanner.peek()).toBe(' ');
167
166
  });
168
167
  it('should throw for negative values', () => {
169
- const scanner = new scanner_1.Scanner('-1');
170
- expect(() => (0, primitive_parser_1.parseNtpTime)(scanner)).toThrow(errors_1.ParseError);
168
+ const scanner = new core_1.Scanner('-1');
169
+ expect(() => (0, core_1.parseNtpTime)(scanner)).toThrow(errors_1.ParseError);
171
170
  });
172
171
  });
173
172
  describe('parseTypedTime', () => {
174
173
  it('should parse time with days', () => {
175
- const time = (0, primitive_parser_1.parseTypedTime)(new scanner_1.Scanner('7d'));
174
+ const time = (0, core_1.parseTypedTime)(new core_1.Scanner('7d'));
176
175
  expect(time.value).toBe(7);
177
176
  expect(time.unit).toBe('days');
178
177
  });
179
178
  it('should parse time with hours', () => {
180
- const time = (0, primitive_parser_1.parseTypedTime)(new scanner_1.Scanner('3h'));
179
+ const time = (0, core_1.parseTypedTime)(new core_1.Scanner('3h'));
181
180
  expect(time.value).toBe(3);
182
181
  expect(time.unit).toBe('hours');
183
182
  });
184
183
  it('should parse time with minutes', () => {
185
- const time = (0, primitive_parser_1.parseTypedTime)(new scanner_1.Scanner('120m'));
184
+ const time = (0, core_1.parseTypedTime)(new core_1.Scanner('120m'));
186
185
  expect(time.value).toBe(120);
187
186
  expect(time.unit).toBe('minutes');
188
187
  });
189
188
  it('should parse time with seconds (no suffix)', () => {
190
- const time = (0, primitive_parser_1.parseTypedTime)(new scanner_1.Scanner('3600'));
189
+ const time = (0, core_1.parseTypedTime)(new core_1.Scanner('3600'));
191
190
  expect(time.value).toBe(3600);
192
191
  expect(time.unit).toBe('seconds');
193
192
  });
194
193
  it('should parse time with explicit seconds', () => {
195
- const time = (0, primitive_parser_1.parseTypedTime)(new scanner_1.Scanner('30s'));
194
+ const time = (0, core_1.parseTypedTime)(new core_1.Scanner('30s'));
196
195
  expect(time.value).toBe(30);
197
196
  expect(time.unit).toBe('seconds');
198
197
  });
199
198
  it('should stop at whitespace', () => {
200
- const scanner = new scanner_1.Scanner('7d 3h');
201
- const time = (0, primitive_parser_1.parseTypedTime)(scanner);
199
+ const scanner = new core_1.Scanner('7d 3h');
200
+ const time = (0, core_1.parseTypedTime)(scanner);
202
201
  expect(time.value).toBe(7);
203
202
  expect(time.unit).toBe('days');
204
203
  expect(scanner.peek()).toBe(' ');
205
204
  });
206
205
  it('should throw for invalid format', () => {
207
- expect(() => (0, primitive_parser_1.parseTypedTime)(new scanner_1.Scanner('abc'))).toThrow(errors_1.ParseError);
206
+ expect(() => (0, core_1.parseTypedTime)(new core_1.Scanner('abc'))).toThrow(errors_1.ParseError);
208
207
  });
209
208
  });
210
209
  describe('parseEmail', () => {
211
210
  it('should parse email address', () => {
212
- const scanner = new scanner_1.Scanner('user@example.com\n');
213
- const email = (0, primitive_parser_1.parseEmail)(scanner);
211
+ const scanner = new core_1.Scanner('user@example.com\n');
212
+ const email = (0, core_1.parseEmail)(scanner);
214
213
  expect(email).toBe('user@example.com');
215
214
  });
216
215
  it('should parse email with display name', () => {
217
- const scanner = new scanner_1.Scanner('John Doe <john@example.com>\n');
218
- const email = (0, primitive_parser_1.parseEmail)(scanner);
216
+ const scanner = new core_1.Scanner('John Doe <john@example.com>\n');
217
+ const email = (0, core_1.parseEmail)(scanner);
219
218
  expect(email).toBe('John Doe <john@example.com>');
220
219
  });
221
220
  it('should stop at newline', () => {
222
- const scanner = new scanner_1.Scanner('user@example.com\r\nnext line');
223
- const email = (0, primitive_parser_1.parseEmail)(scanner);
221
+ const scanner = new core_1.Scanner('user@example.com\r\nnext line');
222
+ const email = (0, core_1.parseEmail)(scanner);
224
223
  expect(email).toBe('user@example.com');
225
224
  });
226
225
  });
227
226
  describe('parsePhone', () => {
228
227
  it('should parse phone number', () => {
229
- const scanner = new scanner_1.Scanner('+1-555-1234\n');
230
- const phone = (0, primitive_parser_1.parsePhone)(scanner);
228
+ const scanner = new core_1.Scanner('+1-555-1234\n');
229
+ const phone = (0, core_1.parsePhone)(scanner);
231
230
  expect(phone).toBe('+1-555-1234');
232
231
  });
233
232
  it('should parse phone with display name', () => {
234
- const scanner = new scanner_1.Scanner('John Doe +1-555-1234\n');
235
- const phone = (0, primitive_parser_1.parsePhone)(scanner);
233
+ const scanner = new core_1.Scanner('John Doe +1-555-1234\n');
234
+ const phone = (0, core_1.parsePhone)(scanner);
236
235
  expect(phone).toBe('John Doe +1-555-1234');
237
236
  });
238
237
  it('should stop at newline', () => {
239
- const scanner = new scanner_1.Scanner('+1-555-1234\r\nnext');
240
- const phone = (0, primitive_parser_1.parsePhone)(scanner);
238
+ const scanner = new core_1.Scanner('+1-555-1234\r\nnext');
239
+ const phone = (0, core_1.parsePhone)(scanner);
241
240
  expect(phone).toBe('+1-555-1234');
242
241
  });
243
242
  });
244
243
  describe('parseURI', () => {
245
244
  it('should parse HTTP URI', () => {
246
- const scanner = new scanner_1.Scanner('http://example.com/path\n');
247
- const uri = (0, primitive_parser_1.parseURI)(scanner);
245
+ const scanner = new core_1.Scanner('http://example.com/path\n');
246
+ const uri = (0, core_1.parseURI)(scanner);
248
247
  expect(uri).toBe('http://example.com/path');
249
248
  });
250
249
  it('should parse HTTPS URI', () => {
251
- const scanner = new scanner_1.Scanner('https://example.com:8080/path?query=value\n');
252
- const uri = (0, primitive_parser_1.parseURI)(scanner);
250
+ const scanner = new core_1.Scanner('https://example.com:8080/path?query=value\n');
251
+ const uri = (0, core_1.parseURI)(scanner);
253
252
  expect(uri).toBe('https://example.com:8080/path?query=value');
254
253
  });
255
254
  it('should stop at newline', () => {
256
- const scanner = new scanner_1.Scanner('http://example.com\r\nnext');
257
- const uri = (0, primitive_parser_1.parseURI)(scanner);
255
+ const scanner = new core_1.Scanner('http://example.com\r\nnext');
256
+ const uri = (0, core_1.parseURI)(scanner);
258
257
  expect(uri).toBe('http://example.com');
259
258
  });
260
259
  });