mlld
Version:
mlld: llm scripting language
1 lines • 20.4 kB
Source Map (JSON)
{"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}"]}