{"version":3,"sources":["../../../src/schema/types/memberdef-stringify.ts"],"sourcesContent":["import MemberDef from './memberdef';\r\nimport { STANDARD_MEMBERDEF_PROPS, IO_MARKERS } from '../../facade/serialization-constants';\r\nimport TokenNode from '../../parser/nodes/tokens';\r\n\r\n/**\r\n * Stringifies a MemberDef into its schema definition format.\r\n *\r\n * @param memberDef The MemberDef to stringify\r\n * @param includeTypes Whether to include type annotations\r\n * @returns The stringified schema definition for this member\r\n *\r\n * @example\r\n * ```typescript\r\n * // Simple type\r\n * stringifyMemberDef({ type: 'string', path: 'name' }, true)\r\n * // → \"string\"\r\n *\r\n * // With constraints\r\n * stringifyMemberDef({ type: 'number', min: 0, max: 100 }, true)\r\n * // → \"{number, min:0, max:100}\"\r\n *\r\n * // Nested object (includes type annotations for reconstruction)\r\n * stringifyMemberDef({\r\n *   type: 'object',\r\n *   schema: { names: ['street', 'city'], defs: {...} }\r\n * }, true)\r\n * // → \"{street: string, city: string}\"\r\n *\r\n * // Schema variable reference\r\n * stringifyMemberDef({\r\n *   type: 'object',\r\n *   schema: new TokenNode('$address', {...})\r\n * }, true)\r\n * // → \"$address\"\r\n *\r\n * // Schema reference via schemaRef\r\n * stringifyMemberDef({\r\n *   type: 'object',\r\n *   schemaRef: '$address'\r\n * }, true)\r\n * // → \"$address\"\r\n * ```\r\n */\r\nexport function stringifyMemberDef(memberDef: MemberDef, includeTypes: boolean): string {\r\n  // Handle array with schema reference - output as [$schemaRef]\r\n  if (memberDef.type === 'array' && memberDef.schemaRef) {\r\n    return `[${memberDef.schemaRef}]`;\r\n  }\r\n\r\n  // Handle object schema reference (schemaRef property)\r\n  if (memberDef.schemaRef) {\r\n    return memberDef.schemaRef;\r\n  }\r\n\r\n  // Handle nested objects with embedded schema\r\n  if (memberDef.type === 'object' && memberDef.schema) {\r\n    return formatNestedSchema(memberDef.schema);\r\n  }\r\n\r\n  // Skip type annotation if not requested or if type is 'any'\r\n  if (!includeTypes || !memberDef.type || memberDef.type === 'any') {\r\n    return '';\r\n  }\r\n\r\n  // Special handling for array type with 'of' property\r\n  if (memberDef.type === 'array' && memberDef.of) {\r\n    return stringifyArrayMemberDef(memberDef);\r\n  }\r\n\r\n  // Detect constraint properties\r\n  const constraintProps = detectConstraintProperties(memberDef);\r\n\r\n  // Format with or without constraints\r\n  if (constraintProps.length > 0) {\r\n    return formatTypeWithConstraints(memberDef.type, memberDef, constraintProps);\r\n  } else {\r\n    return memberDef.type;\r\n  }\r\n}\r\n\r\n/**\r\n * Formats a nested object schema into {field1, field2, ...} notation.\r\n * Applies SRP by isolating nested schema formatting logic.\r\n *\r\n * Handles both:\r\n * - Schema instances: formats as {field1, field2, ...}\r\n * - Schema variable references (TokenNode with $name): outputs as $name\r\n *\r\n * @param schema The nested schema to format (Schema instance or TokenNode reference)\r\n * @returns Formatted nested object string or schema variable reference\r\n */\r\nfunction formatNestedSchema(schema: any): string {\r\n  // Handle schema variable reference (e.g., $employee, $address)\r\n  if (schema instanceof TokenNode) {\r\n    if (typeof schema.value === 'string' && schema.value.startsWith('$')) {\r\n      return schema.value; // Return the reference as-is: $employee\r\n    }\r\n  }\r\n\r\n  // Handle string reference directly\r\n  if (typeof schema === 'string' && schema.startsWith('$')) {\r\n    return schema;\r\n  }\r\n\r\n  const nestedFields: string[] = [];\r\n\r\n  if (schema.names) {\r\n    for (const nestedName of schema.names) {\r\n      const nestedMember = schema.defs[nestedName];\r\n      let nestedField = nestedName;\r\n\r\n      if (nestedMember?.optional) {\r\n        nestedField += IO_MARKERS.OPTIONAL;\r\n      }\r\n      if (nestedMember?.null) {\r\n        nestedField += IO_MARKERS.NULLABLE;\r\n      }\r\n\r\n      // Add type annotation for nested member if it has constraints or is object/array\r\n      const typeAnnotation = stringifyMemberDef(nestedMember, true);\r\n      if (typeAnnotation) {\r\n        nestedField += `: ${typeAnnotation}`;\r\n      }\r\n\r\n      nestedFields.push(nestedField);\r\n    }\r\n  }\r\n\r\n  return `{${nestedFields.join(', ')}}`;\r\n}\r\n\r\n/**\r\n * Detects which MemberDef properties are constraints (non-standard properties).\r\n * Applies SRP by isolating constraint detection logic.\r\n *\r\n * @param memberDef The MemberDef to analyze\r\n * @returns Array of constraint property names\r\n */\r\nfunction detectConstraintProperties(memberDef: MemberDef): string[] {\r\n  const constraintProps: string[] = [];\r\n\r\n  for (const key in memberDef) {\r\n    if (!STANDARD_MEMBERDEF_PROPS.has(key) && memberDef[key] !== undefined) {\r\n      constraintProps.push(key);\r\n    }\r\n  }\r\n\r\n  return constraintProps;\r\n}\r\n\r\n/**\r\n * Formats a type with its constraints in bracket notation.\r\n *\r\n * @param type The base type name\r\n * @param memberDef The full MemberDef containing constraint values\r\n * @param constraintProps Array of constraint property names\r\n * @returns Formatted string: {type, key1:value1, key2:value2, ...}\r\n */\r\nfunction formatTypeWithConstraints(\r\n  type: string,\r\n  memberDef: MemberDef,\r\n  constraintProps: string[]\r\n): string {\r\n  const parts = [type];\r\n\r\n  for (const prop of constraintProps) {\r\n    const value = memberDef[prop];\r\n    const formattedValue = formatConstraintValue(value);\r\n    parts.push(`${prop}:${formattedValue}`);\r\n  }\r\n\r\n  return `{${parts.join(', ')}}`;\r\n}\r\n\r\n/**\r\n * Special handling for array type MemberDefs.\r\n *\r\n * @param memberDef The array MemberDef with 'of' property\r\n * @returns Formatted array type string\r\n *\r\n * @example\r\n * ```typescript\r\n * // Simple element type\r\n * stringifyArrayMemberDef({ type: 'array', of: 'string' })\r\n * // → \"[string]\"\r\n *\r\n * // Complex element type with constraints\r\n * stringifyArrayMemberDef({\r\n *   type: 'array',\r\n *   of: { type: 'number', min: 0, max: 100 }\r\n * })\r\n * // → \"[{number, min:0, max:100}]\"\r\n *\r\n * // Nested object element type\r\n * stringifyArrayMemberDef({\r\n *   type: 'array',\r\n *   of: { type: 'object', schema: { names: ['name', 'age'], defs: {...} } }\r\n * })\r\n * // → \"[{name: string, age: number}]\"\r\n * ```\r\n */\r\nfunction stringifyArrayMemberDef(memberDef: MemberDef): string {\r\n  const ofType = memberDef.of;\r\n\r\n  // No element type specified\r\n  if (!ofType) {\r\n    return memberDef.type; // Just 'array'\r\n  }\r\n\r\n  // Simple string element type\r\n  if (typeof ofType === 'string') {\r\n    return `[${ofType}]`;\r\n  }\r\n\r\n  // Complex element type (MemberDef object)\r\n  if (typeof ofType === 'object' && ofType.type) {\r\n    const elementMemberDef = ofType as MemberDef;\r\n\r\n    // Nested object with schema\r\n    if (elementMemberDef.type === 'object' && elementMemberDef.schema) {\r\n      const nestedFormat = formatNestedSchema(elementMemberDef.schema);\r\n      return `[${nestedFormat}]`;\r\n    }\r\n\r\n    // Nested array (array of arrays)\r\n    if (elementMemberDef.type === 'array' && elementMemberDef.of) {\r\n      const nestedArrayFormat = stringifyArrayMemberDef(elementMemberDef);\r\n      return `[${nestedArrayFormat}]`;\r\n    }\r\n\r\n    // Element type with constraints\r\n    const constraintProps = detectConstraintProperties(elementMemberDef);\r\n    if (constraintProps.length > 0) {\r\n      const formatted = formatTypeWithConstraints(\r\n        elementMemberDef.type,\r\n        elementMemberDef,\r\n        constraintProps\r\n      );\r\n      return `[${formatted}]`;\r\n    }\r\n\r\n    // Simple element type without constraints\r\n    return `[${elementMemberDef.type}]`;\r\n  }\r\n\r\n  // Fallback: generic array\r\n  return memberDef.type;\r\n}\r\n\r\n/**\r\n * Formats a constraint value for output in schema definition.\r\n * Handles primitives, arrays, and nested objects recursively.\r\n *\r\n * @param value The constraint value to format\r\n * @returns Formatted string representation\r\n */\r\nexport function formatConstraintValue(value: any): string {\r\n  if (value === null) return 'null';\r\n  if (value === undefined) return 'undefined';\r\n\r\n  if (typeof value === 'string') {\r\n    // Escape quotes in string values\r\n    return `\"${value.replace(/\"/g, '\\\\\"')}\"`;\r\n  }\r\n\r\n  if (typeof value === 'boolean') {\r\n    return value ? IO_MARKERS.TRUE : IO_MARKERS.FALSE;\r\n  }\r\n\r\n  if (typeof value === 'number') {\r\n    return String(value);\r\n  }\r\n\r\n  if (Array.isArray(value)) {\r\n    const formatted = value.map(v => formatConstraintValue(v));\r\n    return `[${formatted.join(', ')}]`;\r\n  }\r\n\r\n  if (typeof value === 'object') {\r\n    // For complex objects, use JSON representation\r\n    // Future enhancement: recursive MemberDef formatting\r\n    return JSON.stringify(value);\r\n  }\r\n\r\n  return String(value);\r\n}\r\n"],"mappings":"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","names":["TokenNode"]}