{"version":3,"sources":["../interpreter/utils/ast-evaluation.ts","../interpreter/core/json-formatter.ts"],"names":["createASTAwareJSONReplacer","replacer","key","val","obj","tokest","_extension","undefined","content","valWithContent","Array","isArray","length","firstItem","textNode","type","varRef","identifier","dataObj","entries","plainObj","entry","value","properties","dataArr","items","execVal","params","paramNames","join","typeVal","def","definition","Object","hasWrappedContent","values","some","v","processed","k","JSONFormatter","stringify","options","pretty","indent","handleExecutables","handleNamespaces","shouldPrettyPrint","compactJson","JSON","hasNestedStructures","result","keys","lines","split","map","l","trim","depth","item","stringifyNamespace","namespaceObject","cleaned","frontmatter","exports","variables","executables","fm","__meta__","internalFields","hasExports","includes","__executable"],"mappings":"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","file":"chunk-VWPKQQNW.mjs","sourcesContent":["/**\n * Shared utilities for AST node evaluation and JSON serialization\n */\n\nimport type { MlldNode } from '@core/types';\nimport type { Environment } from '../env/Environment';\nimport type { SecurityDescriptor } from '@core/types/security';\n\n/**\n * Creates a JSON replacer function that properly handles AST nodes\n * This is used to ensure consistent serialization across the codebase\n */\nexport function createASTAwareJSONReplacer() {\n  const replacer = (key: string, val: unknown): unknown => {\n    // Handle LoadContentResult - return content for string representation\n    if (val && typeof val === 'object' && 'content' in val && 'filename' in val && 'tokest' in val) {\n      // This looks like a LoadContentResult - check if it has the getters\n      const obj = val as any;\n      if (typeof obj.tokest === 'number' || obj._extension !== undefined) {\n        // This is a LoadContentResult - return its content for JSON serialization\n        return obj.content;\n      }\n    }\n    // Handle wrapped strings (quotes, backticks, brackets)\n    if (val && typeof val === 'object' && 'wrapperType' in val && 'content' in val) {\n      const valWithContent = val as { wrapperType: string; content: unknown[] };\n      if (Array.isArray(valWithContent.content)) {\n        // Extract the string content from wrapped strings\n        if (valWithContent.content.length > 0) {\n          const firstItem = valWithContent.content[0];\n          if (firstItem && typeof firstItem === 'object' && 'type' in firstItem && 'content' in firstItem) {\n            const textNode = firstItem as { type: string; content: string };\n            if (textNode.type === 'Text') {\n              return textNode.content;\n            }\n          }\n        }\n        // Handle empty content - return empty string instead of the wrapper object\n        if (valWithContent.content.length === 0) {\n          return '';\n        }\n      }\n      // TODO: Handle interpolated content in wrapped strings\n      return ''; // Fallback for unhandled content\n    }\n    \n    // Handle raw Text nodes\n    if (val && typeof val === 'object' && 'type' in val && 'content' in val) {\n      const textNode = val as { type: string; content: string };\n      if (textNode.type === 'Text') {\n        return textNode.content;\n      }\n    }\n    \n    // Convert VariableReference nodes to their string representation\n    if (val && typeof val === 'object' && 'type' in val && 'identifier' in val) {\n      const varRef = val as { type: string; identifier: string };\n      if (varRef.type === 'VariableReference') {\n        return `@${varRef.identifier}`;\n      }\n    }\n    \n    // Convert nested DataObject types to plain objects\n    if (\n      val &&\n      typeof val === 'object' &&\n      'type' in val &&\n      (val as any).type === 'object'\n    ) {\n      const dataObj = val as any;\n\n      // New format: entries\n      if (Array.isArray(dataObj.entries)) {\n        const plainObj: Record<string, unknown> = {};\n        for (const entry of dataObj.entries) {\n          if (entry.type === 'pair') {\n            plainObj[entry.key] = entry.value;\n          }\n          // Skip spreads - they need evaluation\n        }\n        return plainObj;\n      }\n\n      // Old format: properties\n      if (dataObj.properties) {\n        return dataObj.properties;\n      }\n\n      // Not an AST object node – let JSON.stringify handle it normally\n      return val;\n    }\n    \n    // Convert nested DataArray types to plain arrays\n    if (val && typeof val === 'object' && 'type' in val && 'items' in val) {\n      const dataArr = val as { type: string; items: unknown[] };\n      if (dataArr.type === 'array') {\n        return dataArr.items;\n      }\n    }\n    \n    // Hide raw executable details in JSON output\n    if (val && typeof val === 'object' && '__executable' in val) {\n      const execVal = val as { __executable: boolean; paramNames?: string[] };\n      const params = execVal.paramNames || [];\n      return `<function(${params.join(', ')})>`;\n    }\n    \n    // Handle executable variables\n    if (val && typeof val === 'object' && 'type' in val) {\n      const typeVal = val as { type: string; value?: unknown; definition?: unknown };\n      if (typeVal.type === 'executable') {\n        const def = typeVal.value || typeVal.definition || {};\n        const params = (def as { paramNames?: string[] }).paramNames || [];\n        return `<function(${params.join(', ')})>`;\n      }\n    }\n    \n    // Handle plain objects that might contain wrapped values\n    // This is important for objects in arrays that don't have a 'type' property\n    if (val && typeof val === 'object' && val.constructor === Object && !('type' in val)) {\n      // Check if any property has wrapped content\n      const hasWrappedContent = Object.values(val).some(v => \n        v && typeof v === 'object' && 'wrapperType' in v && 'content' in v\n      );\n      \n      if (hasWrappedContent) {\n        // Process the object's properties\n        const processed: Record<string, unknown> = {};\n        for (const [k, v] of Object.entries(val)) {\n          processed[k] = replacer(k, v); // Recursively call the replacer\n        }\n        return processed;\n      }\n    }\n    \n    return val;\n  };\n  \n  return replacer;\n}\n\n/**\n * Evaluates a node to extract its runtime value\n * Handles wrapped strings and Text nodes that may not be fully evaluated\n */\nexport async function evaluateNodeToValue(node: unknown, env?: Environment): Promise<unknown> {\n  if (!node || typeof node !== 'object') {\n    return node;\n  }\n  \n  // Handle wrapped strings\n  if ('wrapperType' in node && 'content' in node) {\n    const wrappedNode = node as { wrapperType: string; content: unknown[] };\n    if (Array.isArray(wrappedNode.content)) {\n      if (wrappedNode.content.length > 0) {\n        const firstItem = wrappedNode.content[0];\n        if (firstItem && typeof firstItem === 'object' && 'type' in firstItem && 'content' in firstItem) {\n          const textNode = firstItem as { type: string; content: string };\n          if (textNode.type === 'Text') {\n            return textNode.content;\n          }\n        }\n      }\n      // If we have an env and interpolate function, use it for complex content\n      if (env && wrappedNode.content.length > 0) {\n        const { interpolate } = await import('../core/interpreter');\n        const descriptors: SecurityDescriptor[] = [];\n        const text = await interpolate(wrappedNode.content as MlldNode[], env, undefined, {\n          collectSecurityDescriptor: descriptor => {\n            if (descriptor) {\n              descriptors.push(descriptor);\n            }\n          }\n        });\n        const merged =\n          descriptors.length === 1\n            ? descriptors[0]\n            : descriptors.length > 1\n              ? env.mergeSecurityDescriptors(...descriptors)\n              : undefined;\n        if (merged) {\n          env.recordSecurityDescriptor(merged);\n        }\n        return text;\n      }\n    }\n  }\n  \n  // Handle raw Text nodes\n  if ('type' in node && 'content' in node) {\n    const textNode = node as { type: string; content: string };\n    if (textNode.type === 'Text') {\n      return textNode.content;\n    }\n  }\n  \n  return node;\n}\n","import { createASTAwareJSONReplacer } from '../utils/ast-evaluation';\n\nexport interface JSONFormatOptions {\n  pretty?: boolean;\n  indent?: number;\n  handleExecutables?: boolean;\n  handleNamespaces?: boolean;\n}\n\nexport class JSONFormatter {\n  /**\n   * Single source of truth for JSON serialization in mlld\n   */\n  static stringify(value: any, options: JSONFormatOptions = {}): string {\n    const {\n      pretty = false,\n      indent = 2,\n      handleExecutables = true,\n      handleNamespaces = true\n    } = options;\n    \n    // Use our existing shared replacer\n    const replacer = createASTAwareJSONReplacer();\n    \n    // Smart pretty-printing: only pretty-print if the object is complex enough\n    let shouldPrettyPrint = pretty;\n    if (pretty) {\n      const compactJson = JSON.stringify(value, replacer);\n      // Only pretty-print if it's longer than 60 chars or has nested objects/arrays\n      shouldPrettyPrint = compactJson.length > 60 || this.hasNestedStructures(value);\n    }\n    \n    const result = JSON.stringify(value, replacer, shouldPrettyPrint ? indent : undefined);\n    \n    // Post-process: for single-key objects that were pretty-printed, keep them on one line but with spaces\n    if (pretty && typeof value === 'object' && value !== null && !Array.isArray(value)) {\n      const keys = Object.keys(value);\n      if (keys.length === 1 && shouldPrettyPrint) {\n        // Check if this is a simple single-key object (not nested)\n        const val = value[keys[0]];\n        if (typeof val !== 'object' || val === null) {\n          // Convert multiline format to single-line with spaces (no extra spaces around braces)\n          const lines = result.split('\\n').map(l => l.trim());\n          if (lines.length === 3 && lines[0] === '{' && lines[2] === '}') {\n            return `{${lines[1]}}`;\n          }\n        }\n      }\n    }\n    \n    return result;\n  }\n  \n  /**\n   * Check if a value has nested objects or arrays that warrant pretty-printing\n   */\n  private static hasNestedStructures(value: any, depth = 0): boolean {\n    if (depth > 2) return true; // Deep nesting\n    \n    if (Array.isArray(value)) {\n      // For arrays: pretty print if more than 1 item OR if any item is an object/complex\n      return value.length > 1 || value.some(item => \n        typeof item === 'object' && item !== null\n      );\n    }\n    \n    if (typeof value === 'object' && value !== null) {\n      const keys = Object.keys(value);\n      // Always pretty-print objects (even single-key ones for consistent spacing)\n      // But skip if it's an empty object\n      return keys.length > 0;\n    }\n    \n    return false;\n  }\n  \n  /**\n   * Special formatting for namespace objects\n   * Shows only frontmatter and exported variables, not internal structure\n   */\n  static stringifyNamespace(namespaceObject: any): string {\n    const cleaned: any = {\n      frontmatter: {},\n      exports: {\n        variables: {},\n        executables: {}\n      }\n    };\n    \n    // Add frontmatter if present\n    const fm = namespaceObject.fm || namespaceObject.frontmatter || namespaceObject.__meta__;\n    if (fm && Object.keys(fm).length > 0) {\n      cleaned.frontmatter = fm;\n    }\n    \n    // Separate variables and executables\n    const internalFields = ['fm', 'frontmatter', '__meta__'];\n    let hasExports = false;\n    \n    for (const [key, value] of Object.entries(namespaceObject)) {\n      if (!internalFields.includes(key)) {\n        hasExports = true;\n        // Check if it's an executable\n        if (value && typeof value === 'object' && (value as any).__executable) {\n          const params = (value as any).paramNames || [];\n          cleaned.exports.executables[key] = `<function(${params.join(', ')})>`;\n        } else if (value && typeof value === 'object' && value.type === 'executable') {\n          // Handle variable-stored executables\n          const def = value.value || value.definition || {};\n          const params = def.paramNames || [];\n          cleaned.exports.executables[key] = `<function(${params.join(', ')})>`;\n        } else {\n          cleaned.exports.variables[key] = value;\n        }\n      }\n    }\n    \n    // If no exports, remove the exports section\n    if (!hasExports) {\n      delete cleaned.exports;\n    }\n    \n    // If no frontmatter, remove that section\n    if (Object.keys(cleaned.frontmatter).length === 0) {\n      delete cleaned.frontmatter;\n    }\n    \n    // If nothing left, just return an empty object representation\n    if (Object.keys(cleaned).length === 0) {\n      return '{}';\n    }\n    \n    return this.stringify(cleaned, { pretty: true, handleExecutables: false });\n  }\n}"]}