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