typed-csv 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.
package/dist/index.mjs ADDED
@@ -0,0 +1,845 @@
1
+ // src/parser.ts
2
+ var ParseError = class extends Error {
3
+ constructor(message, position, schema, value) {
4
+ let fullMessage = message;
5
+ if (position !== void 0) {
6
+ fullMessage += ` at position ${position}`;
7
+ }
8
+ if (schema !== void 0) {
9
+ fullMessage += `. Schema: ${schema}`;
10
+ }
11
+ if (value !== void 0) {
12
+ fullMessage += `. Value: ${value}`;
13
+ }
14
+ super(fullMessage);
15
+ this.position = position;
16
+ this.schema = schema;
17
+ this.value = value;
18
+ this.name = "ParseError";
19
+ }
20
+ };
21
+ var Parser = class {
22
+ constructor(input) {
23
+ this.pos = 0;
24
+ this.input = input;
25
+ }
26
+ peek() {
27
+ return this.input[this.pos] || "";
28
+ }
29
+ consume() {
30
+ return this.input[this.pos++] || "";
31
+ }
32
+ skipWhitespace() {
33
+ while (this.pos < this.input.length && /\s/.test(this.input[this.pos])) {
34
+ this.pos++;
35
+ }
36
+ }
37
+ match(str) {
38
+ return this.input.slice(this.pos, this.pos + str.length) === str;
39
+ }
40
+ consumeStr(str) {
41
+ if (this.match(str)) {
42
+ this.pos += str.length;
43
+ return true;
44
+ }
45
+ return false;
46
+ }
47
+ getPosition() {
48
+ return this.pos;
49
+ }
50
+ getInputLength() {
51
+ return this.input.length;
52
+ }
53
+ parseSchema() {
54
+ this.skipWhitespace();
55
+ let schema = this.parseSchemaInternal();
56
+ this.skipWhitespace();
57
+ if (this.consumeStr("[")) {
58
+ this.skipWhitespace();
59
+ if (!this.consumeStr("]")) {
60
+ throw new ParseError("Expected ]", this.pos);
61
+ }
62
+ schema = { type: "array", element: schema };
63
+ this.skipWhitespace();
64
+ }
65
+ if (this.consumeStr("|")) {
66
+ const members = [schema];
67
+ while (true) {
68
+ this.skipWhitespace();
69
+ const member = this.parseSchemaInternal();
70
+ members.push(member);
71
+ this.skipWhitespace();
72
+ if (!this.consumeStr("|")) {
73
+ break;
74
+ }
75
+ }
76
+ return {
77
+ type: "union",
78
+ members
79
+ };
80
+ }
81
+ return schema;
82
+ }
83
+ parseSchemaInternal() {
84
+ this.skipWhitespace();
85
+ if (this.consumeStr("(")) {
86
+ this.skipWhitespace();
87
+ const schema = this.parseSchema();
88
+ this.skipWhitespace();
89
+ if (!this.consumeStr(")")) {
90
+ throw new ParseError("Expected )", this.pos);
91
+ }
92
+ this.skipWhitespace();
93
+ if (this.consumeStr("[")) {
94
+ this.skipWhitespace();
95
+ if (!this.consumeStr("]")) {
96
+ throw new ParseError("Expected ]", this.pos);
97
+ }
98
+ return { type: "array", element: schema };
99
+ }
100
+ return schema;
101
+ }
102
+ if (this.peek() === '"' || this.peek() === "'") {
103
+ return this.parseStringLiteralSchema();
104
+ }
105
+ if (this.consumeStr("~")) {
106
+ return this.parseReverseReferenceSchema();
107
+ }
108
+ if (this.consumeStr("@")) {
109
+ return this.parseReferenceSchema();
110
+ }
111
+ if (this.consumeStr("string")) {
112
+ if (this.consumeStr("[")) {
113
+ this.skipWhitespace();
114
+ if (!this.consumeStr("]")) {
115
+ throw new ParseError("Expected ]", this.pos);
116
+ }
117
+ return { type: "array", element: { type: "string" } };
118
+ }
119
+ return { type: "string" };
120
+ }
121
+ if (this.consumeStr("number")) {
122
+ if (this.consumeStr("[")) {
123
+ this.skipWhitespace();
124
+ if (!this.consumeStr("]")) {
125
+ throw new ParseError("Expected ]", this.pos);
126
+ }
127
+ return { type: "array", element: { type: "number" } };
128
+ }
129
+ return { type: "number" };
130
+ }
131
+ if (this.consumeStr("int")) {
132
+ if (this.consumeStr("[")) {
133
+ this.skipWhitespace();
134
+ if (!this.consumeStr("]")) {
135
+ throw new ParseError("Expected ]", this.pos);
136
+ }
137
+ return { type: "array", element: { type: "int" } };
138
+ }
139
+ return { type: "int" };
140
+ }
141
+ if (this.consumeStr("float")) {
142
+ if (this.consumeStr("[")) {
143
+ this.skipWhitespace();
144
+ if (!this.consumeStr("]")) {
145
+ throw new ParseError("Expected ]", this.pos);
146
+ }
147
+ return { type: "array", element: { type: "float" } };
148
+ }
149
+ return { type: "float" };
150
+ }
151
+ if (this.consumeStr("boolean")) {
152
+ if (this.consumeStr("[")) {
153
+ this.skipWhitespace();
154
+ if (!this.consumeStr("]")) {
155
+ throw new ParseError("Expected ]", this.pos);
156
+ }
157
+ return { type: "array", element: { type: "boolean" } };
158
+ }
159
+ return { type: "boolean" };
160
+ }
161
+ if (this.consumeStr("[")) {
162
+ const elements = [];
163
+ this.skipWhitespace();
164
+ if (this.peek() === "]") {
165
+ this.consume();
166
+ throw new ParseError("Empty array/tuple not allowed", this.pos);
167
+ }
168
+ elements.push(this.parseNamedSchema());
169
+ this.skipWhitespace();
170
+ if (this.consumeStr(";")) {
171
+ const remainingElements = [];
172
+ while (true) {
173
+ this.skipWhitespace();
174
+ remainingElements.push(this.parseNamedSchema());
175
+ this.skipWhitespace();
176
+ if (!this.consumeStr(";")) {
177
+ break;
178
+ }
179
+ }
180
+ elements.push(...remainingElements);
181
+ }
182
+ this.skipWhitespace();
183
+ if (!this.consumeStr("]")) {
184
+ throw new ParseError("Expected ]", this.pos);
185
+ }
186
+ if (this.consumeStr("[")) {
187
+ this.skipWhitespace();
188
+ if (!this.consumeStr("]")) {
189
+ throw new ParseError("Expected ]", this.pos);
190
+ }
191
+ if (elements.length === 1 && !elements[0].name) {
192
+ return { type: "array", element: elements[0].schema };
193
+ }
194
+ return { type: "array", element: { type: "tuple", elements } };
195
+ }
196
+ if (elements.length === 1 && !elements[0].name) {
197
+ return { type: "array", element: elements[0].schema };
198
+ }
199
+ return { type: "tuple", elements };
200
+ }
201
+ throw new ParseError(
202
+ `Unknown type: ${this.peek() || "end of input"}`,
203
+ this.pos
204
+ );
205
+ }
206
+ parseStringLiteralSchema() {
207
+ const value = this.parseStringLiteral();
208
+ return {
209
+ type: "stringLiteral",
210
+ value
211
+ };
212
+ }
213
+ parseStringLiteral() {
214
+ const quote = this.peek();
215
+ if (quote !== '"' && quote !== "'") {
216
+ throw new ParseError("Expected string literal with quotes", this.pos);
217
+ }
218
+ this.consume();
219
+ let value = "";
220
+ while (this.pos < this.input.length) {
221
+ const char = this.peek();
222
+ if (char === "\\") {
223
+ this.consume();
224
+ const nextChar = this.consume();
225
+ if (nextChar === '"' || nextChar === "'" || nextChar === "\\" || nextChar === "|" || nextChar === ";" || nextChar === "(" || nextChar === ")") {
226
+ value += nextChar;
227
+ } else {
228
+ value += "\\" + nextChar;
229
+ }
230
+ } else if (char === quote) {
231
+ this.consume();
232
+ return value;
233
+ } else {
234
+ value += this.consume();
235
+ }
236
+ }
237
+ throw new ParseError("Unterminated string literal", this.pos);
238
+ }
239
+ parseNamedSchema() {
240
+ this.skipWhitespace();
241
+ const startpos = this.pos;
242
+ let identifier = "";
243
+ while (this.pos < this.input.length && /[a-zA-Z0-9\-_]/.test(this.peek())) {
244
+ identifier += this.consume();
245
+ }
246
+ if (identifier.length === 0) {
247
+ const schema = this.parseSchema();
248
+ return { schema };
249
+ }
250
+ this.skipWhitespace();
251
+ if (this.consumeStr(":")) {
252
+ this.skipWhitespace();
253
+ const name = identifier;
254
+ const schema = this.parseSchema();
255
+ return { name, schema };
256
+ } else {
257
+ this.pos = startpos;
258
+ const schema = this.parseSchema();
259
+ return { schema };
260
+ }
261
+ }
262
+ parseReferenceSchema() {
263
+ let tableName = "";
264
+ while (this.pos < this.input.length && /[a-zA-Z0-9\-_]/.test(this.peek())) {
265
+ tableName += this.consume();
266
+ }
267
+ if (tableName.length === 0) {
268
+ throw new ParseError("Expected table name after @", this.pos);
269
+ }
270
+ this.skipWhitespace();
271
+ if (this.consumeStr("[]")) {
272
+ this.skipWhitespace();
273
+ const isOptional2 = this.consumeStr("?");
274
+ return {
275
+ type: "reference",
276
+ tableName,
277
+ isArray: true,
278
+ isOptional: isOptional2
279
+ };
280
+ }
281
+ const isOptional = this.consumeStr("?");
282
+ return {
283
+ type: "reference",
284
+ tableName,
285
+ isArray: false,
286
+ isOptional
287
+ };
288
+ }
289
+ parseReverseReferenceSchema() {
290
+ let tableName = "";
291
+ while (this.pos < this.input.length && /[a-zA-Z0-9\-_]/.test(this.peek())) {
292
+ tableName += this.consume();
293
+ }
294
+ if (tableName.length === 0) {
295
+ throw new ParseError("Expected table name after ~", this.pos);
296
+ }
297
+ this.skipWhitespace();
298
+ if (!this.consumeStr("(")) {
299
+ throw new ParseError(
300
+ "Expected ( after reverse reference table name",
301
+ this.pos
302
+ );
303
+ }
304
+ this.skipWhitespace();
305
+ let foreignKey = "";
306
+ while (this.pos < this.input.length && /[a-zA-Z0-9\-_]/.test(this.peek())) {
307
+ foreignKey += this.consume();
308
+ }
309
+ if (foreignKey.length === 0) {
310
+ throw new ParseError("Expected foreign key name inside ()", this.pos);
311
+ }
312
+ this.skipWhitespace();
313
+ if (!this.consumeStr(")")) {
314
+ throw new ParseError("Expected ) after foreign key name", this.pos);
315
+ }
316
+ this.skipWhitespace();
317
+ const isOptional = this.consumeStr("?");
318
+ return {
319
+ type: "reverseReference",
320
+ tableName,
321
+ foreignKey,
322
+ isOptional
323
+ };
324
+ }
325
+ };
326
+ function parseSchema(schemaString) {
327
+ const parser = new Parser(schemaString.trim());
328
+ const schema = parser.parseSchema();
329
+ if (parser.getPosition() < parser.getInputLength()) {
330
+ throw new ParseError("Unexpected input after schema", parser.getPosition());
331
+ }
332
+ return schema;
333
+ }
334
+
335
+ // src/type-utils.ts
336
+ function schemaToTypeString(schema, resourceNames) {
337
+ switch (schema.type) {
338
+ case "string":
339
+ return "string";
340
+ case "number":
341
+ case "int":
342
+ case "float":
343
+ return "number";
344
+ case "boolean":
345
+ return "boolean";
346
+ case "stringLiteral":
347
+ return `"${schema.value}"`;
348
+ case "union":
349
+ return schema.members.map((m) => schemaToTypeString(m, resourceNames)).join(" | ");
350
+ case "reference": {
351
+ const typeName = resourceNames?.get(schema.tableName) || schema.tableName.charAt(0).toUpperCase() + schema.tableName.slice(1);
352
+ const baseType = schema.isArray ? `${typeName}[]` : typeName;
353
+ return schema.isOptional ? `${baseType} | null` : baseType;
354
+ }
355
+ case "reverseReference": {
356
+ const typeName = resourceNames?.get(schema.tableName) || schema.tableName.charAt(0).toUpperCase() + schema.tableName.slice(1);
357
+ const baseType = `${typeName}[]`;
358
+ return schema.isOptional ? `${baseType} | null` : baseType;
359
+ }
360
+ case "array":
361
+ if (schema.element.type === "tuple") {
362
+ const tupleElements2 = schema.element.elements.map((el) => {
363
+ const typeStr = schemaToTypeString(el.schema, resourceNames);
364
+ return el.name ? `${el.name}: ${typeStr}` : typeStr;
365
+ });
366
+ return `[${tupleElements2.join(", ")}][]`;
367
+ }
368
+ const elementType = schemaToTypeString(schema.element, resourceNames);
369
+ if (schema.element.type === "union") {
370
+ return `(${elementType})[]`;
371
+ }
372
+ return `${elementType}[]`;
373
+ case "tuple":
374
+ const tupleElements = schema.elements.map((el) => {
375
+ const typeStr = schemaToTypeString(el.schema, resourceNames);
376
+ return el.name ? `${el.name}: ${typeStr}` : typeStr;
377
+ });
378
+ return `[${tupleElements.join(", ")}]`;
379
+ default:
380
+ return "unknown";
381
+ }
382
+ }
383
+ function createValidator(schema) {
384
+ return function validate(value) {
385
+ switch (schema.type) {
386
+ case "string":
387
+ return typeof value === "string";
388
+ case "number":
389
+ return typeof value === "number" && !isNaN(value);
390
+ case "int":
391
+ return typeof value === "number" && !isNaN(value) && Number.isInteger(value);
392
+ case "float":
393
+ return typeof value === "number" && !isNaN(value);
394
+ case "boolean":
395
+ return typeof value === "boolean";
396
+ case "stringLiteral":
397
+ return typeof value === "string" && value === schema.value;
398
+ case "union":
399
+ return schema.members.some((member) => createValidator(member)(value));
400
+ case "tuple":
401
+ if (!Array.isArray(value)) return false;
402
+ if (value.length !== schema.elements.length) return false;
403
+ return schema.elements.every(
404
+ (elementSchema, index) => createValidator(elementSchema.schema)(value[index])
405
+ );
406
+ case "array":
407
+ if (!Array.isArray(value)) return false;
408
+ return value.every((item) => createValidator(schema.element)(item));
409
+ case "reference":
410
+ if (schema.isOptional && value === null) return true;
411
+ if (schema.isArray) {
412
+ return Array.isArray(value) && value.every((id) => typeof id === "string");
413
+ }
414
+ return typeof value === "string" || Array.isArray(value) && value.every((id) => typeof id === "string");
415
+ case "reverseReference":
416
+ if (schema.isOptional && value === null) return true;
417
+ return Array.isArray(value);
418
+ default:
419
+ return false;
420
+ }
421
+ };
422
+ }
423
+
424
+ // src/value-parser.ts
425
+ var ValueParser = class {
426
+ constructor(input, schemaString) {
427
+ this.pos = 0;
428
+ this.input = input;
429
+ this.schemaString = schemaString;
430
+ }
431
+ peek() {
432
+ return this.input[this.pos] || "";
433
+ }
434
+ consume() {
435
+ return this.input[this.pos++] || "";
436
+ }
437
+ skipWhitespace() {
438
+ while (this.pos < this.input.length && /\s/.test(this.input[this.pos])) {
439
+ this.pos++;
440
+ }
441
+ }
442
+ consumeStr(str) {
443
+ if (this.input.slice(this.pos, this.pos + str.length) === str) {
444
+ this.pos += str.length;
445
+ return true;
446
+ }
447
+ return false;
448
+ }
449
+ parseValue(schema, allowOmitBrackets = false) {
450
+ this.skipWhitespace();
451
+ switch (schema.type) {
452
+ case "string":
453
+ return this.parseStringValue();
454
+ case "number":
455
+ return this.parseNumberValue();
456
+ case "int":
457
+ return this.parseIntValue();
458
+ case "float":
459
+ return this.parseFloatValue();
460
+ case "boolean":
461
+ return this.parseBooleanValue();
462
+ case "stringLiteral":
463
+ return this.parseStringLiteralValue(schema);
464
+ case "union":
465
+ return this.parseUnionValue(schema);
466
+ case "tuple":
467
+ return this.parseTupleValue(schema, allowOmitBrackets);
468
+ case "array":
469
+ return this.parseArrayValue(schema, allowOmitBrackets);
470
+ case "reference":
471
+ return this.parseReferenceValue(schema);
472
+ case "reverseReference":
473
+ return null;
474
+ default:
475
+ throw new ParseError(
476
+ `Unknown schema type: ${schema.type}`,
477
+ this.pos,
478
+ this.schemaString,
479
+ this.input
480
+ );
481
+ }
482
+ }
483
+ parseStringValue() {
484
+ let result = "";
485
+ while (this.pos < this.input.length) {
486
+ const char = this.peek();
487
+ if (char === "\\") {
488
+ this.consume();
489
+ const nextChar = this.consume();
490
+ if (nextChar === ";" || nextChar === "[" || nextChar === "]" || nextChar === "\\") {
491
+ result += nextChar;
492
+ } else {
493
+ result += "\\" + nextChar;
494
+ }
495
+ } else if (char === ";" || char === "]") {
496
+ break;
497
+ } else {
498
+ result += this.consume();
499
+ }
500
+ }
501
+ return result.trim();
502
+ }
503
+ parseNumberValue() {
504
+ let numStr = "";
505
+ while (this.pos < this.input.length && /[\d.\-+eE]/.test(this.peek())) {
506
+ numStr += this.consume();
507
+ }
508
+ const num = parseFloat(numStr);
509
+ if (isNaN(num)) {
510
+ throw new ParseError(
511
+ "Invalid number",
512
+ this.pos - numStr.length,
513
+ this.schemaString,
514
+ this.input
515
+ );
516
+ }
517
+ return num;
518
+ }
519
+ parseIntValue() {
520
+ let numStr = "";
521
+ while (this.pos < this.input.length && /[\d.\-+eE]/.test(this.peek())) {
522
+ numStr += this.consume();
523
+ }
524
+ const num = parseFloat(numStr);
525
+ if (isNaN(num)) {
526
+ throw new ParseError(
527
+ "Invalid number",
528
+ this.pos - numStr.length,
529
+ this.schemaString,
530
+ this.input
531
+ );
532
+ }
533
+ if (!Number.isInteger(num)) {
534
+ throw new ParseError(
535
+ "Expected integer value",
536
+ this.pos - numStr.length,
537
+ this.schemaString,
538
+ this.input
539
+ );
540
+ }
541
+ return num;
542
+ }
543
+ parseFloatValue() {
544
+ return this.parseNumberValue();
545
+ }
546
+ parseBooleanValue() {
547
+ if (this.consumeStr("true")) {
548
+ return true;
549
+ }
550
+ if (this.consumeStr("false")) {
551
+ return false;
552
+ }
553
+ throw new ParseError(
554
+ "Expected true or false",
555
+ this.pos,
556
+ this.schemaString,
557
+ this.input
558
+ );
559
+ }
560
+ parseStringLiteralValue(schema) {
561
+ const quote = this.peek();
562
+ if (quote === '"' || quote === "'") {
563
+ this.consume();
564
+ let value = "";
565
+ while (this.pos < this.input.length) {
566
+ const char = this.peek();
567
+ if (char === "\\") {
568
+ this.consume();
569
+ const nextChar = this.consume();
570
+ if (nextChar === '"' || nextChar === "'" || nextChar === "\\" || nextChar === ";") {
571
+ value += nextChar;
572
+ } else {
573
+ value += "\\" + nextChar;
574
+ }
575
+ } else if (char === quote) {
576
+ this.consume();
577
+ if (value !== schema.value) {
578
+ throw new ParseError(
579
+ `Invalid value '"${value}"'. Expected '"${schema.value}"'`,
580
+ this.pos,
581
+ this.schemaString,
582
+ this.input
583
+ );
584
+ }
585
+ return value;
586
+ } else {
587
+ value += this.consume();
588
+ }
589
+ }
590
+ throw new ParseError(
591
+ "Unterminated string literal",
592
+ this.pos,
593
+ this.schemaString,
594
+ this.input
595
+ );
596
+ } else {
597
+ let value = "";
598
+ while (this.pos < this.input.length) {
599
+ const char = this.peek();
600
+ if (char === ";" || char === "]" || char === ")") {
601
+ break;
602
+ }
603
+ value += this.consume();
604
+ }
605
+ value = value.trim();
606
+ if (value !== schema.value) {
607
+ throw new ParseError(
608
+ `Invalid value '${value}'. Expected '${schema.value}'`,
609
+ this.pos - value.length,
610
+ this.schemaString,
611
+ this.input
612
+ );
613
+ }
614
+ return value;
615
+ }
616
+ }
617
+ parseUnionValue(schema) {
618
+ const savedPos = this.pos;
619
+ const errors = [];
620
+ for (let i = 0; i < schema.members.length; i++) {
621
+ this.pos = savedPos;
622
+ try {
623
+ return this.parseValue(schema.members[i], false);
624
+ } catch (e) {
625
+ errors.push(e);
626
+ }
627
+ }
628
+ throw new ParseError(
629
+ `Value does not match any union member. Tried ${schema.members.length} alternatives.`,
630
+ this.pos,
631
+ this.schemaString,
632
+ this.input
633
+ );
634
+ }
635
+ parseTupleValue(schema, allowOmitBrackets) {
636
+ let hasOpenBracket = false;
637
+ if (this.peek() === "[") {
638
+ this.consume();
639
+ hasOpenBracket = true;
640
+ } else if (!allowOmitBrackets) {
641
+ throw new ParseError(
642
+ "Expected [",
643
+ this.pos,
644
+ this.schemaString,
645
+ this.input
646
+ );
647
+ }
648
+ this.skipWhitespace();
649
+ if (this.peek() === "]" && hasOpenBracket) {
650
+ this.consume();
651
+ return [];
652
+ }
653
+ const result = [];
654
+ for (let i = 0; i < schema.elements.length; i++) {
655
+ this.skipWhitespace();
656
+ const elementSchema = schema.elements[i];
657
+ if (elementSchema.name) {
658
+ this.skipWhitespace();
659
+ const savedPos = this.pos;
660
+ if (this.consumeStr(`${elementSchema.name}:`)) {
661
+ this.skipWhitespace();
662
+ } else {
663
+ this.pos = savedPos;
664
+ }
665
+ }
666
+ result.push(this.parseValue(elementSchema.schema, false));
667
+ this.skipWhitespace();
668
+ if (i < schema.elements.length - 1) {
669
+ if (!this.consumeStr(";")) {
670
+ throw new ParseError(
671
+ "Expected ;",
672
+ this.pos,
673
+ this.schemaString,
674
+ this.input
675
+ );
676
+ }
677
+ }
678
+ }
679
+ this.skipWhitespace();
680
+ if (hasOpenBracket) {
681
+ if (!this.consumeStr("]")) {
682
+ throw new ParseError(
683
+ "Expected ]",
684
+ this.pos,
685
+ this.schemaString,
686
+ this.input
687
+ );
688
+ }
689
+ }
690
+ return result;
691
+ }
692
+ parseArrayValue(schema, allowOmitBrackets) {
693
+ let hasOpenBracket = false;
694
+ const elementIsTupleOrArray = schema.element.type === "tuple" || schema.element.type === "array";
695
+ if (this.pos >= this.input.length || !this.input.trim()) {
696
+ return [];
697
+ }
698
+ if (this.peek() === "[") {
699
+ if (!elementIsTupleOrArray) {
700
+ this.consume();
701
+ hasOpenBracket = true;
702
+ } else {
703
+ const savedPos = this.pos;
704
+ this.consume();
705
+ this.skipWhitespace();
706
+ if (this.peek() === "]") {
707
+ this.consume();
708
+ return [];
709
+ } else if (this.peek() === "[") {
710
+ hasOpenBracket = true;
711
+ } else {
712
+ this.pos = savedPos;
713
+ }
714
+ }
715
+ }
716
+ if (!hasOpenBracket && !allowOmitBrackets && !elementIsTupleOrArray) {
717
+ throw new ParseError(
718
+ "Expected [",
719
+ this.pos,
720
+ this.schemaString,
721
+ this.input
722
+ );
723
+ }
724
+ this.skipWhitespace();
725
+ if (this.peek() === "]" && hasOpenBracket) {
726
+ this.consume();
727
+ return [];
728
+ }
729
+ const result = [];
730
+ while (true) {
731
+ this.skipWhitespace();
732
+ result.push(this.parseValue(schema.element, elementIsTupleOrArray));
733
+ this.skipWhitespace();
734
+ if (!this.consumeStr(";")) {
735
+ break;
736
+ }
737
+ }
738
+ this.skipWhitespace();
739
+ if (hasOpenBracket) {
740
+ if (!this.consumeStr("]")) {
741
+ throw new ParseError(
742
+ "Expected ]",
743
+ this.pos,
744
+ this.schemaString,
745
+ this.input
746
+ );
747
+ }
748
+ }
749
+ return result;
750
+ }
751
+ parseReferenceValue(schema) {
752
+ if (schema.isOptional) {
753
+ this.skipWhitespace();
754
+ if (this.pos >= this.input.length) {
755
+ return null;
756
+ }
757
+ }
758
+ if (schema.isArray) {
759
+ let hasOpenBracket = false;
760
+ if (this.peek() === "[") {
761
+ this.consume();
762
+ hasOpenBracket = true;
763
+ }
764
+ this.skipWhitespace();
765
+ if (this.peek() === "]" && hasOpenBracket) {
766
+ this.consume();
767
+ return [];
768
+ }
769
+ const ids = [];
770
+ while (true) {
771
+ this.skipWhitespace();
772
+ let id = "";
773
+ while (this.pos < this.input.length && this.peek() !== ";" && this.peek() !== "]") {
774
+ id += this.consume();
775
+ }
776
+ ids.push(id.trim());
777
+ this.skipWhitespace();
778
+ if (!this.consumeStr(";")) {
779
+ break;
780
+ }
781
+ }
782
+ if (hasOpenBracket) {
783
+ if (!this.consumeStr("]")) {
784
+ throw new ParseError(
785
+ "Expected ]",
786
+ this.pos,
787
+ this.schemaString,
788
+ this.input
789
+ );
790
+ }
791
+ }
792
+ return ids;
793
+ } else {
794
+ let id = "";
795
+ while (this.pos < this.input.length) {
796
+ const char = this.peek();
797
+ if (char === ";" || char === "]" || char === ",") {
798
+ break;
799
+ }
800
+ id += this.consume();
801
+ }
802
+ return id.trim();
803
+ }
804
+ }
805
+ getPosition() {
806
+ return this.pos;
807
+ }
808
+ getInputLength() {
809
+ return this.input.length;
810
+ }
811
+ };
812
+ function parseValue(schema, valueString, schemaString) {
813
+ const sStr = schemaString || schemaToTypeString(schema);
814
+ const parser = new ValueParser(valueString.trim(), sStr);
815
+ const allowOmitBrackets = schema.type === "tuple" || schema.type === "array";
816
+ const value = parser.parseValue(schema, allowOmitBrackets);
817
+ if (parser.getPosition() < parser.getInputLength()) {
818
+ throw new ParseError(
819
+ "Unexpected input after value",
820
+ parser.getPosition(),
821
+ sStr,
822
+ valueString.trim()
823
+ );
824
+ }
825
+ return value;
826
+ }
827
+
828
+ // src/index.ts
829
+ function defineSchema(schemaString) {
830
+ const schema = parseSchema(schemaString);
831
+ const validator = createValidator(schema);
832
+ return {
833
+ schema,
834
+ validator,
835
+ parse: (valueString) => parseValue(schema, valueString)
836
+ };
837
+ }
838
+ export {
839
+ ParseError,
840
+ createValidator,
841
+ defineSchema,
842
+ parseSchema,
843
+ parseValue,
844
+ schemaToTypeString
845
+ };