"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var index_exports = {}; __export(index_exports, { ParseError: () => ParseError, createValidator: () => createValidator, defineSchema: () => defineSchema, parseSchema: () => parseSchema, parseValue: () => parseValue }); module.exports = __toCommonJS(index_exports); // src/parser.ts var ParseError = class extends Error { constructor(message, position) { super(position !== void 0 ? `${message} at position ${position}` : message); this.position = position; this.name = "ParseError"; } }; var Parser = class { constructor(input) { this.pos = 0; this.input = input; } peek() { return this.input[this.pos] || ""; } consume() { return this.input[this.pos++] || ""; } skipWhitespace() { while (this.pos < this.input.length && /\s/.test(this.input[this.pos])) { this.pos++; } } match(str) { return this.input.slice(this.pos, this.pos + str.length) === str; } consumeStr(str) { if (this.match(str)) { this.pos += str.length; return true; } return false; } getPosition() { return this.pos; } getInputLength() { return this.input.length; } parseSchema() { this.skipWhitespace(); if (this.consumeStr("string")) { if (this.consumeStr("[")) { this.skipWhitespace(); if (!this.consumeStr("]")) { throw new ParseError("Expected ]", this.pos); } return { type: "array", element: { type: "string" } }; } return { type: "string" }; } if (this.consumeStr("number")) { if (this.consumeStr("[")) { this.skipWhitespace(); if (!this.consumeStr("]")) { throw new ParseError("Expected ]", this.pos); } return { type: "array", element: { type: "number" } }; } return { type: "number" }; } if (this.consumeStr("boolean")) { if (this.consumeStr("[")) { this.skipWhitespace(); if (!this.consumeStr("]")) { throw new ParseError("Expected ]", this.pos); } return { type: "array", element: { type: "boolean" } }; } return { type: "boolean" }; } if (this.consumeStr("[")) { const elements = []; this.skipWhitespace(); if (this.peek() === "]") { this.consume(); throw new ParseError("Empty array/tuple not allowed", this.pos); } elements.push(this.parseSchema()); this.skipWhitespace(); if (this.consumeStr(";")) { const remainingElements = []; while (true) { this.skipWhitespace(); remainingElements.push(this.parseSchema()); this.skipWhitespace(); if (!this.consumeStr(";")) { break; } } elements.push(...remainingElements); } this.skipWhitespace(); if (!this.consumeStr("]")) { throw new ParseError("Expected ]", this.pos); } if (this.consumeStr("[")) { this.skipWhitespace(); if (!this.consumeStr("]")) { throw new ParseError("Expected ]", this.pos); } if (elements.length === 1) { return { type: "array", element: elements[0] }; } return { type: "array", element: { type: "tuple", elements } }; } if (elements.length === 1) { return { type: "array", element: elements[0] }; } return { type: "tuple", elements }; } let identifier = ""; while (this.pos < this.input.length && /[a-zA-Z0-9\-_]/.test(this.peek())) { identifier += this.consume(); } if (identifier.length > 0) { if (this.consumeStr("[")) { this.skipWhitespace(); if (!this.consumeStr("]")) { throw new ParseError("Expected ]", this.pos); } return { type: "array", element: { type: "string" } }; } return { type: "string" }; } throw new ParseError(`Unexpected character: ${this.peek()}`, this.pos); } }; function parseSchema(schemaString) { const parser = new Parser(schemaString.trim()); const schema = parser.parseSchema(); if (parser.getPosition() < parser.getInputLength()) { throw new ParseError("Unexpected input after schema", parser.getPosition()); } return schema; } // src/validator.ts var ValueParser = class { constructor(input) { this.pos = 0; this.input = input; } peek() { return this.input[this.pos] || ""; } consume() { return this.input[this.pos++] || ""; } skipWhitespace() { while (this.pos < this.input.length && /\s/.test(this.input[this.pos])) { this.pos++; } } consumeStr(str) { if (this.input.slice(this.pos, this.pos + str.length) === str) { this.pos += str.length; return true; } return false; } parseValue(schema, allowOmitBrackets = false) { this.skipWhitespace(); switch (schema.type) { case "string": return this.parseStringValue(); case "number": return this.parseNumberValue(); case "boolean": return this.parseBooleanValue(); case "tuple": return this.parseTupleValue(schema, allowOmitBrackets); case "array": return this.parseArrayValue(schema, allowOmitBrackets); default: throw new ParseError(`Unknown schema type: ${schema.type}`, this.pos); } } parseStringValue() { let result = ""; while (this.pos < this.input.length) { const char = this.peek(); if (char === "\\") { this.consume(); const nextChar = this.consume(); if (nextChar === ";" || nextChar === "[" || nextChar === "]" || nextChar === "\\") { result += nextChar; } else { result += "\\" + nextChar; } } else if (char === ";" || char === "]") { break; } else { result += this.consume(); } } return result.trim(); } parseNumberValue() { let numStr = ""; while (this.pos < this.input.length && /[\d.\-+eE]/.test(this.peek())) { numStr += this.consume(); } const num = parseFloat(numStr); if (isNaN(num)) { throw new ParseError("Invalid number", this.pos - numStr.length); } return num; } parseBooleanValue() { if (this.consumeStr("true")) { return true; } if (this.consumeStr("false")) { return false; } throw new ParseError("Expected true or false", this.pos); } parseTupleValue(schema, allowOmitBrackets) { let hasOpenBracket = false; if (this.peek() === "[") { this.consume(); hasOpenBracket = true; } else if (!allowOmitBrackets) { throw new ParseError("Expected [", this.pos); } this.skipWhitespace(); if (this.peek() === "]" && hasOpenBracket) { this.consume(); return []; } const result = []; for (let i = 0; i < schema.elements.length; i++) { this.skipWhitespace(); result.push(this.parseValue(schema.elements[i], false)); this.skipWhitespace(); if (i < schema.elements.length - 1) { if (!this.consumeStr(";")) { throw new ParseError("Expected ;", this.pos); } } } this.skipWhitespace(); if (hasOpenBracket) { if (!this.consumeStr("]")) { throw new ParseError("Expected ]", this.pos); } } return result; } parseArrayValue(schema, allowOmitBrackets) { let hasOpenBracket = false; const elementIsTupleOrArray = schema.element.type === "tuple" || schema.element.type === "array"; if (this.peek() === "[") { if (!elementIsTupleOrArray) { this.consume(); hasOpenBracket = true; } else if (this.input[this.pos + 1] === "[") { this.consume(); hasOpenBracket = true; } } if (!hasOpenBracket && !allowOmitBrackets && !elementIsTupleOrArray) { throw new ParseError("Expected [", this.pos); } this.skipWhitespace(); if (this.peek() === "]" && hasOpenBracket) { this.consume(); return []; } const result = []; while (true) { this.skipWhitespace(); result.push(this.parseValue(schema.element, false)); this.skipWhitespace(); if (!this.consumeStr(";")) { break; } } this.skipWhitespace(); if (hasOpenBracket) { if (!this.consumeStr("]")) { throw new ParseError("Expected ]", this.pos); } } return result; } getPosition() { return this.pos; } getInputLength() { return this.input.length; } }; function parseValue(schema, valueString) { const parser = new ValueParser(valueString.trim()); const allowOmitBrackets = schema.type === "tuple" || schema.type === "array"; const value = parser.parseValue(schema, allowOmitBrackets); if (parser.getPosition() < parser.getInputLength()) { throw new ParseError("Unexpected input after value", parser.getPosition()); } return value; } function createValidator(schema) { return function validate(value) { switch (schema.type) { case "string": return typeof value === "string"; case "number": return typeof value === "number" && !isNaN(value); case "boolean": return typeof value === "boolean"; case "tuple": if (!Array.isArray(value)) return false; if (value.length !== schema.elements.length) return false; return schema.elements.every( (elementSchema, index) => createValidator(elementSchema)(value[index]) ); case "array": if (!Array.isArray(value)) return false; return value.every((item) => createValidator(schema.element)(item)); default: return false; } }; } // src/index.ts function defineSchema(schemaString) { const schema = parseSchema(schemaString); const validator = createValidator(schema); return { schema, validator, parse: (valueString) => parseValue(schema, valueString) }; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { ParseError, createValidator, defineSchema, parseSchema, parseValue });