{"version":3,"file":"serialization.cjs","sources":["../../../../../src/lib/serialization.ts"],"sourcesContent":["/**\r\n * UI Schema Serialization/Deserialization\r\n * \r\n * Functions for converting UISchema to/from JSON strings.\r\n * Ensures round-trip consistency for schema persistence.\r\n */\r\n\r\nimport type { UISchema, ValidationResult, ValidationError } from '../types';\r\n\r\n/**\r\n * Serialization options\r\n */\r\nexport interface SerializeOptions {\r\n  /** Pretty print with indentation */\r\n  pretty?: boolean;\r\n  /** Indentation spaces (default: 2) */\r\n  indent?: number;\r\n}\r\n\r\n/**\r\n * Deserialization result\r\n */\r\nexport interface DeserializeResult {\r\n  /** Whether deserialization was successful */\r\n  success: boolean;\r\n  /** The deserialized schema (if successful) */\r\n  schema?: UISchema;\r\n  /** Error message (if failed) */\r\n  error?: string;\r\n  /** Error position in the JSON string */\r\n  position?: number;\r\n}\r\n\r\n/**\r\n * Serialize a UISchema to a JSON string\r\n * \r\n * @param schema - The UISchema to serialize\r\n * @param options - Serialization options\r\n * @returns JSON string representation of the schema\r\n */\r\nexport function serialize(schema: UISchema, options: SerializeOptions = {}): string {\r\n  const { pretty = true, indent = 2 } = options;\r\n  \r\n  if (pretty) {\r\n    return JSON.stringify(schema, null, indent);\r\n  }\r\n  \r\n  return JSON.stringify(schema);\r\n}\r\n\r\n\r\n/**\r\n * Deserialize a JSON string to a UISchema\r\n * \r\n * @param json - The JSON string to deserialize\r\n * @returns DeserializeResult with the schema or error information\r\n */\r\nexport function deserialize(json: string): DeserializeResult {\r\n  // Handle empty or whitespace-only input\r\n  if (!json || json.trim() === '') {\r\n    return {\r\n      success: false,\r\n      error: 'Empty input: JSON string is empty or contains only whitespace',\r\n    };\r\n  }\r\n\r\n  try {\r\n    const parsed = JSON.parse(json);\r\n    \r\n    // Basic structure validation\r\n    const validation = validateBasicStructure(parsed);\r\n    if (!validation.valid) {\r\n      return {\r\n        success: false,\r\n        error: validation.errors.map(e => e.message).join('; '),\r\n      };\r\n    }\r\n    \r\n    return {\r\n      success: true,\r\n      schema: parsed as UISchema,\r\n    };\r\n  } catch (e) {\r\n    const error = e as SyntaxError;\r\n    // Extract position from error message if available\r\n    const positionMatch = error.message.match(/position (\\d+)/i);\r\n    const position = positionMatch ? parseInt(positionMatch[1], 10) : undefined;\r\n    \r\n    return {\r\n      success: false,\r\n      error: `JSON parse error: ${error.message}`,\r\n      position,\r\n    };\r\n  }\r\n}\r\n\r\n/**\r\n * Validate basic structure of a parsed object\r\n * Checks for required fields: version and root\r\n */\r\nfunction validateBasicStructure(obj: unknown): ValidationResult {\r\n  const errors: ValidationError[] = [];\r\n  \r\n  if (typeof obj !== 'object' || obj === null) {\r\n    errors.push({\r\n      path: '',\r\n      message: 'Schema must be an object',\r\n      code: 'INVALID_TYPE',\r\n    });\r\n    return { valid: false, errors };\r\n  }\r\n  \r\n  const schema = obj as Record<string, unknown>;\r\n  \r\n  // Check version field\r\n  if (!('version' in schema)) {\r\n    errors.push({\r\n      path: 'version',\r\n      message: 'Missing required field: version',\r\n      code: 'MISSING_FIELD',\r\n    });\r\n  } else if (typeof schema.version !== 'string') {\r\n    errors.push({\r\n      path: 'version',\r\n      message: 'Field \"version\" must be a string',\r\n      code: 'INVALID_TYPE',\r\n    });\r\n  }\r\n  \r\n  // Check root field\r\n  if (!('root' in schema)) {\r\n    errors.push({\r\n      path: 'root',\r\n      message: 'Missing required field: root',\r\n      code: 'MISSING_FIELD',\r\n    });\r\n  } else {\r\n    const rootErrors = validateComponent(schema.root, 'root');\r\n    errors.push(...rootErrors);\r\n  }\r\n  \r\n  return {\r\n    valid: errors.length === 0,\r\n    errors,\r\n  };\r\n}\r\n\r\n\r\n/**\r\n * Validate a UIComponent structure recursively\r\n */\r\nfunction validateComponent(obj: unknown, path: string): ValidationError[] {\r\n  const errors: ValidationError[] = [];\r\n  \r\n  if (typeof obj !== 'object' || obj === null) {\r\n    errors.push({\r\n      path,\r\n      message: `Component at \"${path}\" must be an object`,\r\n      code: 'INVALID_TYPE',\r\n    });\r\n    return errors;\r\n  }\r\n  \r\n  const component = obj as Record<string, unknown>;\r\n  \r\n  // Check id field\r\n  if (!('id' in component)) {\r\n    errors.push({\r\n      path: `${path}.id`,\r\n      message: `Missing required field: id at \"${path}\"`,\r\n      code: 'MISSING_FIELD',\r\n    });\r\n  } else if (typeof component.id !== 'string') {\r\n    errors.push({\r\n      path: `${path}.id`,\r\n      message: `Field \"id\" must be a string at \"${path}\"`,\r\n      code: 'INVALID_TYPE',\r\n    });\r\n  }\r\n  \r\n  // Check type field\r\n  if (!('type' in component)) {\r\n    errors.push({\r\n      path: `${path}.type`,\r\n      message: `Missing required field: type at \"${path}\"`,\r\n      code: 'MISSING_FIELD',\r\n    });\r\n  } else if (typeof component.type !== 'string') {\r\n    errors.push({\r\n      path: `${path}.type`,\r\n      message: `Field \"type\" must be a string at \"${path}\"`,\r\n      code: 'INVALID_TYPE',\r\n    });\r\n  }\r\n  \r\n  // Recursively validate children\r\n  if ('children' in component && component.children !== undefined) {\r\n    if (!Array.isArray(component.children)) {\r\n      errors.push({\r\n        path: `${path}.children`,\r\n        message: `Field \"children\" must be an array at \"${path}\"`,\r\n        code: 'INVALID_TYPE',\r\n      });\r\n    } else {\r\n      component.children.forEach((child, index) => {\r\n        const childErrors = validateComponent(child, `${path}.children[${index}]`);\r\n        errors.push(...childErrors);\r\n      });\r\n    }\r\n  }\r\n  \r\n  return errors;\r\n}\r\n\r\n/**\r\n * Check if two UISchemas are structurally equal\r\n * Used for round-trip consistency testing\r\n */\r\nexport function schemasEqual(a: UISchema, b: UISchema): boolean {\r\n  return JSON.stringify(a) === JSON.stringify(b);\r\n}\r\n"],"names":["serialize","schema","options","pretty","indent","deserialize","json","parsed","validation","validateBasicStructure","e","error","positionMatch","position","obj","errors","rootErrors","validateComponent","path","component","child","index","childErrors","schemasEqual","a","b"],"mappings":"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"}