UNPKG

nuvira-parser

Version:

Nuvira Database. New Database format (Readable & Easy to use), (Inbuilt Schema & constraints & rules & relations).

207 lines 8.08 kB
export class SQONSchema { lines; position; parsedSchema; errors; allowedTypes; schemaName; constructor({ lines, position = 0, allowedTypes = [] }) { this.lines = lines; this.position = position; this.parsedSchema = {}; this.errors = []; this.allowedTypes = allowedTypes; this.schemaName = 'unnamed-schema'; } parseSchema() { let schemaNameFound = false; while (this.position < this.lines.length) { const line = this.lines[this.position].trim(); if (line.startsWith('!#')) { this.position++; continue; } if (line === "@end") { break; } this.processLine(line); this.position++; } return { schemaName: this.schemaName, parsedSchema: this.parsedSchema, errors: this.errors, lines: this.lines, position: this.position }; } processSchemaName(lines) { for (const line of lines) { const match = line.match(/^@schema:\s*([a-zA-Z0-9_-]+)$/); if (match) { const schemaName = match[1]; if (/[^a-zA-Z0-9_-]/.test(schemaName)) { this.errors.push({ line: this.position + 1, message: `Invalid schema name format. The name must only contain alphanumeric characters, underscores, or hyphens. No spaces or special symbols are allowed.`, }); return null; } this.schemaName = schemaName; return schemaName; } } this.errors.push({ line: this.position + 1, message: `Invalid schema name format. The name should not contain spaces and may include hyphens and underscores only.`, }); return null; } /** * Processes each line of the schema and updates the parsedSchema and errors accordingly. * * @param {string} line - The line of schema to process. */ processLine(line) { if (!line || line.startsWith('!#')) { return; } if (line.includes("->")) { let [key, value] = line.split("->").map((s) => s.trim()); const types = this.parseSubTypes(value); if ((types.includes("Object") || types.includes("ObjectArray") || types.includes("Object[]")) && types.some((type) => type !== "Object" && type !== "ObjectArray" && type !== "Object[]")) { this.errors.push({ line: this.position + 1, message: `Invalid combination: ${types.join(", ")} for key: ${key}. Only 'Object' or 'ObjectArray' can be used with each other, but no other types.`, }); return; } if (value.startsWith("Object {")) { this.parsedSchema[key] = { type: ["Object"], properties: this.parseInlineNestedObject(), }; } else if (value.startsWith("ObjectArray {") || value.startsWith("Object[] {")) { this.parsedSchema[key] = { type: ["ObjectArray"], items: this.parseInlineNestedArray(), }; } else { const invalidTypes = types.filter((type) => !this.allowedTypes.includes(type)); if (invalidTypes.length > 0) { this.errors.push({ line: this.position + 1, message: `Invalid types: ${invalidTypes.join(", ")} for key: ${key}`, }); return; } this.parsedSchema[key] = { type: types }; } } } /** * Parses a nested array schema defined inline within the schema. * * @returns {Record<string, any>} The parsed nested array schema. */ parseInlineNestedArray() { const arraySchema = {}; this.position++; while (this.position < this.lines.length) { const line = this.lines[this.position].trim(); if (line.startsWith('!#')) { this.position++; continue; } if (line === "}") break; if (line.includes("->")) { let [nestedKey, nestedValue] = line.split("->").map((s) => s.trim()); const types = this.parseSubTypes(nestedValue); const invalidTypes = types.filter((type) => !this.allowedTypes.includes(type)); if (invalidTypes.length > 0) { this.errors.push({ line: this.position + 1, message: `Invalid types: ${invalidTypes.join(", ")} for key: ${nestedKey}`, }); return arraySchema; } if (nestedValue.startsWith("Object {")) { arraySchema[nestedKey] = { type: ["Object"], properties: this.parseInlineNestedObject(), }; } else if (nestedValue.startsWith("ObjectArray {") || nestedValue.startsWith("Object[] {")) { arraySchema[nestedKey] = { type: ["ObjectArray"], items: this.parseInlineNestedArray(), }; } else { arraySchema[nestedKey] = { type: types }; } } this.position++; } return arraySchema; } /** * Parses a nested object schema defined inline within the schema. * * @returns {Record<string, any>} The parsed nested object schema. */ parseInlineNestedObject() { const nestedObject = {}; this.position++; while (this.position < this.lines.length) { const line = this.lines[this.position].trim(); if (line.startsWith('!#')) { this.position++; continue; } if (line === "}") break; if (line.includes("->")) { let [nestedKey, nestedValue] = line.split("->").map((s) => s.trim()); const types = this.parseSubTypes(nestedValue); const invalidTypes = types.filter((type) => !this.allowedTypes.includes(type)); if (invalidTypes.length > 0) { this.errors.push({ line: this.position + 1, message: `Invalid types: ${invalidTypes.join(", ")} for key: ${nestedKey}`, }); return nestedObject; } if (nestedValue.startsWith("Object {")) { nestedObject[nestedKey] = { type: ["Object"], properties: this.parseInlineNestedObject(), }; } else if (nestedValue.startsWith("ObjectArray {") || nestedValue.startsWith("Object[] {")) { nestedObject[nestedKey] = { type: ["ObjectArray"], items: this.parseInlineNestedArray(), }; } else { nestedObject[nestedKey] = { type: types }; } } this.position++; } return nestedObject; } /** * Parses the types defined in the schema for a given value. * * @param {string} value - The value to extract types from. * @returns {string[]} An array of types. */ parseSubTypes(value) { return value .split("|") .map((v) => v.trim()) .map((v) => v.replace(/[\s\{\}]+$/, "")) .filter((v) => v); } } //# sourceMappingURL=schema.js.map