@bravostudioai/react 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/_virtual/main.js +3 -2
- package/dist/cli/commands/generate.js +161 -1438
- package/dist/cli/commands/generate.js.map +1 -1
- package/dist/codegen/generator.js +473 -0
- package/dist/codegen/generator.js.map +1 -0
- package/dist/codegen/parser.js +720 -0
- package/dist/codegen/parser.js.map +1 -0
- package/dist/components/EncoreApp.js +197 -162
- package/dist/components/EncoreApp.js.map +1 -1
- package/dist/contexts/EncoreRouterContext.js +13 -0
- package/dist/contexts/EncoreRouterContext.js.map +1 -0
- package/dist/hooks/usePusherUpdates.js +4 -2
- package/dist/hooks/usePusherUpdates.js.map +1 -1
- package/dist/lib/dynamicModules.js +75 -85
- package/dist/lib/dynamicModules.js.map +1 -1
- package/dist/lib/moduleRegistry.js +20 -0
- package/dist/lib/moduleRegistry.js.map +1 -0
- package/dist/lib/packages.js +1 -3
- package/dist/lib/packages.js.map +1 -1
- package/dist/src/cli/commands/generate.d.ts.map +1 -1
- package/dist/src/codegen/generator.d.ts +10 -0
- package/dist/src/codegen/generator.d.ts.map +1 -0
- package/dist/src/codegen/index.d.ts +4 -0
- package/dist/src/codegen/index.d.ts.map +1 -0
- package/dist/src/codegen/parser.d.ts +37 -0
- package/dist/src/codegen/parser.d.ts.map +1 -0
- package/dist/src/codegen/types.d.ts +53 -0
- package/dist/src/codegen/types.d.ts.map +1 -0
- package/dist/src/components/EncoreApp.d.ts +5 -1
- package/dist/src/components/EncoreApp.d.ts.map +1 -1
- package/dist/src/contexts/EncoreRouterContext.d.ts +10 -0
- package/dist/src/contexts/EncoreRouterContext.d.ts.map +1 -0
- package/dist/src/hooks/useAuthRedirect.d.ts.map +1 -1
- package/dist/src/lib/dynamicModules.d.ts +1 -5
- package/dist/src/lib/dynamicModules.d.ts.map +1 -1
- package/dist/src/lib/moduleRegistry.d.ts +9 -0
- package/dist/src/lib/moduleRegistry.d.ts.map +1 -0
- package/dist/src/lib/packages.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/generate.ts +88 -2723
- package/src/codegen/generator.ts +877 -0
- package/src/codegen/index.ts +3 -0
- package/src/codegen/parser.ts +1614 -0
- package/src/codegen/types.ts +58 -0
- package/src/components/EncoreApp.tsx +75 -22
- package/src/contexts/EncoreRouterContext.ts +28 -0
- package/src/hooks/useAuthRedirect.ts +56 -55
- package/src/lib/packages.ts +8 -15
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate.js","sources":["../../../src/cli/commands/generate.ts"],"sourcesContent":["\n\nimport { writeFile, mkdir, readFile } from \"fs/promises\";\nimport { join, dirname } from \"path\";\nimport { existsSync } from \"fs\";\nimport dotenv from \"dotenv\";\nimport {\n CONST_APPS_SERVICE_URL,\n CONST_COMPONENTS_CDN_URL,\n} from \"../../../constants\";\n\ndotenv.config();\n\n// Default apps service URL (can be overridden with APPS_SERVICE_URL env var)\nconst APPS_SERVICE_URL =\n process.env.APPS_SERVICE_URL ||\n process.env.VITE_APPS_SERVICE_URL ||\n CONST_APPS_SERVICE_URL ||\n \"https://apps-service-dev.bravostudio.app\";\nconsole.log(`Using APPS_SERVICE_URL: ${APPS_SERVICE_URL}`);\nconst COMPONENTS_CDN_URL =\n CONST_COMPONENTS_CDN_URL || \"https://apps-public-dev.bravostudio.app\";\n\ninterface ComponentInfo {\n id: string;\n name: string;\n type: string;\n tags: string[];\n propName: string; // Sanitized name for prop\n propType: string; // TypeScript type for the prop\n}\n\ninterface ArrayContainerInfo {\n id: string;\n name: string;\n propName: string;\n components: ComponentInfo[];\n}\n\ninterface SliderInfo {\n id: string;\n name: string;\n arrayContainer: ArrayContainerInfo | null;\n}\n\ninterface InputGroupInfo {\n groupName: string;\n groupType: string; // \"single\" for radio button behavior\n elements: Array<{\n id: string;\n name: string;\n }>;\n}\n\ninterface FormInfo {\n formId: string;\n formName: string;\n submitButtonId?: string;\n inputs: Array<{\n id: string;\n name: string;\n type: string;\n propName: string; // Sanitized and qualified prop name\n _parentPath?: string[]; // Temporary: parent path for qualification\n }>;\n}\n\ninterface SelectInputInfo {\n id: string;\n name: string;\n propName: string; // e.g., \"contractType\" for value prop, generates onContractTypeChange handler\n _parentPath?: string[]; // For qualification if duplicates\n}\n\ninterface ActionButtonInfo {\n id: string;\n name: string;\n propName: string; // e.g., \"bookButton\" generates onBookButtonClick handler\n actionType: string; // \"remote\", \"link\", etc.\n _parentPath?: string[];\n}\n\nasync function downloadFile(\n url: string,\n headers?: Record<string, string>\n): Promise<string> {\n const response = await fetch(url, {\n headers: headers || {},\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to download ${url}: ${response.status} ${response.statusText}`\n );\n }\n\n return await response.text();\n}\n\nfunction sanitizePropName(name: string): string {\n // Convert to camelCase and remove invalid characters\n const cleaned = name\n .replace(/[^a-zA-Z0-9\\s]/g, \"\") // Remove special chars\n .trim();\n\n if (!cleaned) return \"item\";\n\n return cleaned\n .split(/\\s+/)\n .map((word, index) => {\n if (!word) return \"\";\n // Handle all-uppercase words (like \"SHOP\", \"NOW\") by lowercasing them first\n const normalizedWord =\n word === word.toUpperCase() && word.length > 1\n ? word.toLowerCase()\n : word;\n const firstChar = normalizedWord.charAt(0);\n const rest = normalizedWord.slice(1);\n if (index === 0) {\n return firstChar.toLowerCase() + rest;\n }\n return firstChar.toUpperCase() + rest;\n })\n .join(\"\")\n .replace(/^[0-9]/, \"_$&\"); // Prefix numbers with underscore\n}\n\nfunction generateQualifiedPropName(\n componentName: string,\n parentPath: string[]\n): string {\n // Start with the component's own name\n const baseName = sanitizePropName(componentName);\n\n // If no parent path, just return the base name\n if (parentPath.length === 0) {\n return baseName;\n }\n\n // Filter out empty parts and reverse so we build from root to leaf\n const validParentParts = parentPath\n .filter((part) => part && part.trim())\n .reverse();\n\n if (validParentParts.length === 0) {\n return baseName;\n }\n\n // Build qualified name: parent1Parent2ComponentName\n // Each parent part is sanitized individually, then combined\n const sanitizedParentParts = validParentParts.map((part) =>\n sanitizePropName(part)\n );\n\n // Join parent parts (all start uppercase) with base name (starts lowercase)\n const parentPrefix = sanitizedParentParts\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join(\"\");\n\n return parentPrefix + baseName;\n}\n\n/**\n * Finds the minimal distinguishing path suffix for a component when compared to others.\n * Returns the shortest suffix (from root side, working towards leaf) that makes this path unique.\n *\n * The algorithm finds where paths first diverge from the root, then takes the minimal\n * distinguishing part from that divergence point towards the leaf.\n *\n * Example:\n * - thisPath: [Frame11, Frame31, Frame18]\n * - otherPaths: [[Frame11, Frame31, Frame28, Frame29, Frame15]]\n * - Common prefix: [Frame11, Frame31]\n * - Divergence at index 2\n * - Returns: [Frame18] (just the immediate distinguishing parent)\n */\nfunction findMinimalDistinguishingPath(\n thisPath: string[],\n otherPaths: string[][]\n): string[] {\n if (otherPaths.length === 0) {\n // No other paths to compare, return empty (no qualification needed)\n return [];\n }\n\n // Find the longest common prefix (from root side)\n let commonPrefixLength = 0;\n const maxCommonLength = Math.min(\n thisPath.length,\n ...otherPaths.map((p) => p.length)\n );\n\n for (let i = 0; i < maxCommonLength; i++) {\n const thisPart = thisPath[i];\n // Check if all other paths have the same part at this position\n const allMatch = otherPaths.every((otherPath) => {\n return otherPath[i] === thisPart;\n });\n\n if (allMatch) {\n commonPrefixLength++;\n } else {\n break;\n }\n }\n\n // The distinguishing part starts after the common prefix\n const distinguishingSuffix = thisPath.slice(commonPrefixLength);\n\n // Now find the minimal suffix that's unique\n // Try progressively shorter suffixes (from root side) until we find one that's unique\n for (\n let suffixLength = 1;\n suffixLength <= distinguishingSuffix.length;\n suffixLength++\n ) {\n const thisSuffix = distinguishingSuffix.slice(0, suffixLength);\n\n // Check if this suffix is unique when combined with the common prefix\n const isUnique = otherPaths.every((otherPath) => {\n // If other path is shorter than common prefix + suffix, it can't match\n if (otherPath.length < commonPrefixLength + suffixLength) {\n return true; // Different length means unique\n }\n // Check if the suffix matches at the divergence point\n const otherSuffix = otherPath.slice(\n commonPrefixLength,\n commonPrefixLength + suffixLength\n );\n return !arraysEqual(thisSuffix, otherSuffix);\n });\n\n if (isUnique) {\n // Found minimal distinguishing suffix\n return thisSuffix;\n }\n }\n\n // If we get here, paths are identical (shouldn't happen, but handle it)\n return distinguishingSuffix;\n}\n\n/**\n * Helper to compare two arrays for equality\n */\nfunction arraysEqual(a: string[], b: string[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((val, idx) => val === b[idx]);\n}\n\nfunction getComponentPropType(\n componentType: string,\n _componentName: string\n): string {\n if (componentType === \"component:image\") {\n return \"string\"; // imageUrl\n }\n if (componentType === \"component:text\") {\n return \"string\"; // text\n }\n if (componentType?.startsWith(\"component:input-\")) {\n // Input types generally return strings\n if (componentType === \"component:input-image\") {\n return \"string\"; // image URL\n }\n return \"string\"; // text inputs, email, password, etc.\n }\n // Default to any for unknown types\n return \"any\";\n}\n\nfunction getComponentPropName(componentType: string): string {\n if (componentType === \"component:image\") {\n return \"imageUrl\";\n }\n if (componentType === \"component:text\") {\n return \"text\";\n }\n return \"value\";\n}\n\nfunction findSlidersAndDataBindings(pageData: any): SliderInfo[] {\n const sliders: SliderInfo[] = [];\n\n function traverse(node: any, path: string[] = []): void {\n if (!node || typeof node !== \"object\") return;\n\n // Check if this is a slider container\n if (node.type === \"container:slider\") {\n const slider: SliderInfo = {\n id: node.id,\n name: node.name || \"Slider\",\n arrayContainer: null,\n };\n\n // Recursively look for containers with encore:data:array tag inside the slider\n let arrayContainer: any = null;\n\n function findArrayContainer(containerNode: any): void {\n if (arrayContainer) return; // Already found one\n\n if (!containerNode || typeof containerNode !== \"object\") return;\n\n // Check if this node is the array container\n if (\n Array.isArray(containerNode.tags) &&\n (containerNode.tags.includes(\"encore:data:array\") ||\n containerNode.tags.includes(\"bravo:data:array\"))\n ) {\n arrayContainer = containerNode;\n return;\n }\n\n // Recursively search children\n if (containerNode.body && Array.isArray(containerNode.body)) {\n containerNode.body.forEach(findArrayContainer);\n }\n if (\n containerNode.containers &&\n Array.isArray(containerNode.containers)\n ) {\n containerNode.containers.forEach(findArrayContainer);\n }\n if (\n containerNode.components &&\n Array.isArray(containerNode.components)\n ) {\n containerNode.components.forEach(findArrayContainer);\n }\n }\n\n // Start search from the slider node itself (checking its children)\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach(findArrayContainer);\n }\n // Also check components if they exist directly\n if (\n !arrayContainer &&\n node.components &&\n Array.isArray(node.components)\n ) {\n node.components.forEach(findArrayContainer);\n }\n\n if (arrayContainer) {\n const container = arrayContainer;\n let components: ComponentInfo[] = [];\n\n // Find all components with encore:data tag, and also image components\n const imageComponents: any[] = [];\n\n function findDataComponents(\n comp: any,\n parentPath: string[] = []\n ): void {\n if (!comp || typeof comp !== \"object\") return;\n\n // Track image components separately (they might not have encore:data tag)\n if (comp.type === \"component:image\") {\n imageComponents.push(comp);\n }\n\n if (\n Array.isArray(comp.tags) &&\n (comp.tags.includes(\"encore:data\") ||\n comp.tags.includes(\"bravo:data\"))\n ) {\n const basePropName = sanitizePropName(comp.name || \"item\");\n const propType = getComponentPropType(comp.type, comp.name);\n // const propKey = getComponentPropName(comp.type);\n\n components.push({\n id: comp.id,\n name: comp.name || \"Unnamed\",\n type: comp.type,\n tags: comp.tags || [],\n propName: basePropName, // Will be qualified later if needed\n propType,\n // Store parent path for later qualification\n _parentPath: [...parentPath],\n } as ComponentInfo & { _parentPath: string[] });\n }\n\n // Build parent path: include this node's name if it's a container/component with a name\n // Skip generic \"Frame\" names - they're usually not meaningful for distinction\n const currentParentPath = [...parentPath];\n if (\n comp.name &&\n (comp.type?.startsWith(\"container:\") ||\n comp.type?.startsWith(\"component:\"))\n ) {\n const name = comp.name.trim();\n // Filter out generic \"Frame\" names (case-insensitive, with or without numbers/spaces)\n // But keep meaningful names like \"TripSlideFrame\" that contain other words\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(comp.name);\n }\n }\n\n // Recursively search children\n if (comp.components && Array.isArray(comp.components)) {\n comp.components.forEach((child: any) =>\n findDataComponents(child, currentParentPath)\n );\n }\n }\n\n if (container.components && Array.isArray(container.components)) {\n container.components.forEach((comp: any) =>\n findDataComponents(comp, [])\n );\n }\n\n // After finding all components, if we have image components but no image with encore:data,\n // add the first image component\n const hasImageWithData = components.some(\n (c) => c.type === \"component:image\"\n );\n if (!hasImageWithData && imageComponents.length > 0) {\n const imageComp = imageComponents[0];\n // For image components, use \"imageUrl\" as the prop name\n // Clean the name first, then if it contains \"image\", just use \"imageUrl\"\n const rawName = (imageComp.name || \"image\").toLowerCase();\n const basePropName = rawName.includes(\"image\")\n ? \"imageUrl\"\n : sanitizePropName(imageComp.name || \"image\");\n components.push({\n id: imageComp.id,\n name: imageComp.name || \"Image\",\n type: imageComp.type,\n tags: imageComp.tags || [],\n propName: basePropName, // Will be qualified later if needed\n propType: \"string\", // imageUrl is always string\n _parentPath: [],\n } as ComponentInfo & { _parentPath: string[] });\n }\n\n // Detect duplicates and qualify them with minimal distinguishing paths\n // First pass: collect all base prop names and group duplicates\n const propNameGroups = new Map<\n string,\n Array<ComponentInfo & { _parentPath: string[] }>\n >();\n components.forEach((comp) => {\n const compWithPath = comp as ComponentInfo & {\n _parentPath: string[];\n };\n const baseName = comp.propName;\n if (!propNameGroups.has(baseName)) {\n propNameGroups.set(baseName, []);\n }\n propNameGroups.get(baseName)!.push(compWithPath);\n });\n\n // Second pass: for each group with duplicates, find minimal distinguishing paths\n // and ensure all qualified names are unique\n propNameGroups.forEach((group, _baseName) => {\n if (group.length === 1) {\n // No duplicates, keep the simple name\n return;\n }\n\n // First, find minimal distinguishing paths for all components\n group.forEach((comp) => {\n const otherPaths = group\n .filter((c) => c.id !== comp.id)\n .map((c) => c._parentPath || []);\n\n const minimalPath = findMinimalDistinguishingPath(\n comp._parentPath || [],\n otherPaths\n );\n\n // Use the minimal distinguishing path to qualify the name\n comp.propName = generateQualifiedPropName(\n comp.name || \"item\",\n minimalPath\n );\n });\n\n // Check if qualified names are still duplicates and expand paths if needed\n let hasDuplicates = true;\n let iteration = 0;\n const maxIterations = 10; // Safety limit\n\n while (hasDuplicates && iteration < maxIterations) {\n iteration++;\n const qualifiedNameGroups = new Map<\n string,\n Array<ComponentInfo & { _parentPath: string[] }>\n >();\n group.forEach((comp) => {\n if (!qualifiedNameGroups.has(comp.propName)) {\n qualifiedNameGroups.set(comp.propName, []);\n }\n qualifiedNameGroups.get(comp.propName)!.push(comp);\n });\n\n hasDuplicates = false;\n // For each group of still-duplicated qualified names, expand their paths\n qualifiedNameGroups.forEach((dupGroup, _qualifiedName) => {\n if (dupGroup.length > 1) {\n hasDuplicates = true;\n // Expand the distinguishing path for each duplicate\n dupGroup.forEach((comp) => {\n \n\n // Find a longer distinguishing path by comparing with others in the duplicate group\n const fullPath = comp._parentPath || [];\n const otherFullPaths = dupGroup\n .filter((c) => c.id !== comp.id)\n .map((c) => c._parentPath || []);\n\n // Find where this path diverges from others in the duplicate group\n let commonPrefixLength = 0;\n const maxCommonLength = Math.min(\n fullPath.length,\n ...otherFullPaths.map((p) => p.length)\n );\n\n for (let i = 0; i < maxCommonLength; i++) {\n const thisPart = fullPath[i];\n const allMatch = otherFullPaths.every((otherPath) => {\n return otherPath[i] === thisPart;\n });\n if (allMatch) {\n commonPrefixLength++;\n } else {\n break;\n }\n }\n\n // Use progressively more of the distinguishing suffix until unique\n const distinguishingSuffix =\n fullPath.slice(commonPrefixLength);\n\n // Try expanding the distinguishing suffix until we find a unique name\n let foundUnique = false;\n for (\n let suffixLength = 1;\n suffixLength <= distinguishingSuffix.length;\n suffixLength++\n ) {\n const expandedPath = distinguishingSuffix.slice(\n 0,\n suffixLength\n );\n const testQualifiedName = generateQualifiedPropName(\n comp.name || \"item\",\n expandedPath\n );\n\n // Check if this qualified name is unique among ALL components (not just duplicates)\n const isUnique = components.every((otherComp) => {\n if (otherComp.id === comp.id) return true;\n // If other component is in the same duplicate group, compare expanded paths\n if (dupGroup.some((c) => c.id === otherComp.id)) {\n const otherFullPath =\n (\n otherComp as ComponentInfo & {\n _parentPath: string[];\n }\n )._parentPath || [];\n const otherCommonPrefixLength = Math.min(\n commonPrefixLength,\n otherFullPath.length\n );\n const otherDistinguishingSuffix = otherFullPath.slice(\n otherCommonPrefixLength\n );\n const otherExpandedPath =\n otherDistinguishingSuffix.slice(0, suffixLength);\n const otherQualifiedName = generateQualifiedPropName(\n otherComp.name || \"item\",\n otherExpandedPath\n );\n return testQualifiedName !== otherQualifiedName;\n }\n // For components outside the duplicate group, just check the final prop name\n return testQualifiedName !== otherComp.propName;\n });\n\n if (isUnique) {\n comp.propName = testQualifiedName;\n foundUnique = true;\n break;\n }\n }\n\n // If we couldn't find a unique name with the distinguishing suffix,\n // use the distinguishing suffix we found (it's the minimal we can do)\n // We'll handle truly identical paths with numeric suffixes in the final pass\n if (!foundUnique) {\n // Use the distinguishing suffix - it's the minimal distinguishing part\n // Even if it's not globally unique yet, it's better than the full path\n comp.propName = generateQualifiedPropName(\n comp.name || \"item\",\n distinguishingSuffix.length > 0\n ? distinguishingSuffix\n : []\n );\n }\n });\n }\n });\n }\n\n // Final check: if there are still duplicates after using full paths,\n // and they have identical paths, use numeric suffixes as last resort\n const finalQualifiedNameGroups = new Map<\n string,\n Array<ComponentInfo & { _parentPath: string[] }>\n >();\n group.forEach((comp) => {\n if (!finalQualifiedNameGroups.has(comp.propName)) {\n finalQualifiedNameGroups.set(comp.propName, []);\n }\n finalQualifiedNameGroups.get(comp.propName)!.push(comp);\n });\n\n finalQualifiedNameGroups.forEach(\n (finalDupGroup, finalQualifiedName) => {\n if (finalDupGroup.length > 1) {\n // Check if all duplicates have identical paths\n const allPathsIdentical = finalDupGroup.every((comp) => {\n const thisPath = comp._parentPath || [];\n return finalDupGroup.every((otherComp) => {\n if (otherComp.id === comp.id) return true;\n const otherPath = otherComp._parentPath || [];\n return arraysEqual(thisPath, otherPath);\n });\n });\n\n // Only use numeric suffixes if paths are truly identical\n if (allPathsIdentical) {\n let index = 0;\n finalDupGroup.forEach((comp) => {\n if (index > 0) {\n comp.propName = `${finalQualifiedName}${index + 1}`;\n }\n index++;\n });\n }\n }\n }\n );\n\n // Remove the temporary _parentPath property\n group.forEach((comp) => {\n delete (comp as any)._parentPath;\n });\n });\n\n // If we have an image component, remove color components with similar names\n // (they're usually placeholders/backgrounds)\n if (imageComponents.length > 0) {\n const imageComp = imageComponents[0];\n const imageName = (imageComp.name || \"\").toLowerCase();\n components = components.filter((comp) => {\n // Keep image components\n if (comp.type === \"component:image\") return true;\n // Remove color components that seem to be placeholders for images\n if (comp.type === \"component:color\") {\n const compName = (comp.name || \"\").toLowerCase();\n // If color component name is similar to image name, it's likely a placeholder\n if (imageName.includes(compName) || compName.includes(\"image\")) {\n return false;\n }\n }\n return true;\n });\n }\n\n slider.arrayContainer = {\n id: container.id,\n name: container.name || \"Item\",\n propName: sanitizePropName(container.name || \"items\"),\n components,\n };\n }\n\n sliders.push(slider);\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) => traverse(child, [...path, \"body\"]));\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, [...path, \"containers\"])\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, [...path, \"components\"])\n );\n }\n }\n\n // Start traversal from page data\n // Try multiple possible locations for the body\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n return sliders;\n}\n\nfunction findStandaloneComponents(pageData: any): ComponentInfo[] {\n const components: ComponentInfo[] = [];\n const sliderIds = new Set<string>();\n\n // First, collect all slider IDs to exclude their children\n function collectSliderIds(node: any): void {\n if (!node || typeof node !== \"object\") return;\n\n if (node.type === \"container:slider\") {\n sliderIds.add(node.id);\n }\n\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach(collectSliderIds);\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach(collectSliderIds);\n }\n }\n\n // Traverse to find standalone components with bravo:data tags\n // Track parent component names for qualification\n function traverse(\n node: any,\n parentId?: string,\n parentPath: string[] = []\n ): void {\n if (!node || typeof node !== \"object\") return;\n\n // Skip if we're inside a slider\n if (parentId && sliderIds.has(parentId)) return;\n\n // Check if this component has bravo:data tag\n if (\n Array.isArray(node.tags) &&\n (node.tags.includes(\"encore:data\") || node.tags.includes(\"bravo:data\")) &&\n (node.type === \"component:text\" || node.type === \"component:image\")\n ) {\n const basePropName = sanitizePropName(node.name || \"item\");\n const propType = getComponentPropType(node.type, node.name);\n\n components.push({\n id: node.id,\n name: node.name || \"Unnamed\",\n type: node.type,\n tags: node.tags || [],\n propName: basePropName, // Will be qualified later if needed\n propType,\n // Store parent path for later qualification\n _parentPath: [...parentPath],\n } as ComponentInfo & { _parentPath: string[] });\n }\n\n // Build parent path: include this node's name if it's a container/component with a name\n // Skip generic \"Frame\" names - they're usually not meaningful for distinction\n const currentParentPath = [...parentPath];\n if (\n node.name &&\n (node.type?.startsWith(\"container:\") ||\n node.type?.startsWith(\"component:\"))\n ) {\n const name = node.name.trim();\n // Filter out generic \"Frame\" names (case-insensitive, with or without numbers/spaces)\n // But keep meaningful names like \"TripSlideFrame\" that contain other words\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(node.name);\n }\n }\n\n // Recursively traverse children\n const currentId = node.id;\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) =>\n traverse(child, currentId, currentParentPath)\n );\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, currentId, currentParentPath)\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, currentId, currentParentPath)\n );\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach(collectSliderIds);\n body.forEach((node: any) => traverse(node));\n }\n\n // Detect duplicates and qualify them with minimal distinguishing paths\n // First pass: collect all base prop names and group duplicates\n const propNameGroups = new Map<\n string,\n Array<ComponentInfo & { _parentPath: string[] }>\n >();\n components.forEach((comp) => {\n const compWithPath = comp as ComponentInfo & { _parentPath: string[] };\n const baseName = comp.propName;\n if (!propNameGroups.has(baseName)) {\n propNameGroups.set(baseName, []);\n }\n propNameGroups.get(baseName)!.push(compWithPath);\n });\n\n // Second pass: for each group with duplicates, find minimal distinguishing paths\n // and ensure all qualified names are unique\n propNameGroups.forEach((group, _baseName) => {\n if (group.length === 1) {\n // No duplicates, keep the simple name\n return;\n }\n\n // First, find minimal distinguishing paths for all components\n group.forEach((comp) => {\n const otherPaths = group\n .filter((c) => c.id !== comp.id)\n .map((c) => c._parentPath || []);\n\n const minimalPath = findMinimalDistinguishingPath(\n comp._parentPath || [],\n otherPaths\n );\n\n // Use the minimal distinguishing path to qualify the name\n comp.propName = generateQualifiedPropName(\n comp.name || \"item\",\n minimalPath\n );\n });\n\n // Check if qualified names are still duplicates and expand paths if needed\n let hasDuplicates = true;\n let iteration = 0;\n const maxIterations = 10; // Safety limit\n\n while (hasDuplicates && iteration < maxIterations) {\n iteration++;\n const qualifiedNameGroups = new Map<\n string,\n Array<ComponentInfo & { _parentPath: string[] }>\n >();\n group.forEach((comp) => {\n if (!qualifiedNameGroups.has(comp.propName)) {\n qualifiedNameGroups.set(comp.propName, []);\n }\n qualifiedNameGroups.get(comp.propName)!.push(comp);\n });\n\n hasDuplicates = false;\n // For each group of still-duplicated qualified names, expand their paths\n qualifiedNameGroups.forEach((dupGroup, _qualifiedName) => {\n if (dupGroup.length > 1) {\n hasDuplicates = true;\n // Expand the distinguishing path for each duplicate\n dupGroup.forEach((comp) => {\n \n\n // Find a longer distinguishing path by comparing with others in the duplicate group\n const fullPath = comp._parentPath || [];\n const otherFullPaths = dupGroup\n .filter((c) => c.id !== comp.id)\n .map((c) => c._parentPath || []);\n\n // Find where this path diverges from others in the duplicate group\n let commonPrefixLength = 0;\n const maxCommonLength = Math.min(\n fullPath.length,\n ...otherFullPaths.map((p) => p.length)\n );\n\n for (let i = 0; i < maxCommonLength; i++) {\n const thisPart = fullPath[i];\n const allMatch = otherFullPaths.every((otherPath) => {\n return otherPath[i] === thisPart;\n });\n if (allMatch) {\n commonPrefixLength++;\n } else {\n break;\n }\n }\n\n // Use progressively more of the distinguishing suffix until unique\n const distinguishingSuffix = fullPath.slice(commonPrefixLength);\n\n // Try expanding the distinguishing suffix until we find a unique name\n let foundUnique = false;\n for (\n let suffixLength = 1;\n suffixLength <= distinguishingSuffix.length;\n suffixLength++\n ) {\n const expandedPath = distinguishingSuffix.slice(0, suffixLength);\n const testQualifiedName = generateQualifiedPropName(\n comp.name || \"item\",\n expandedPath\n );\n\n // Check if this qualified name is unique among ALL components (not just duplicates)\n const isUnique = components.every((otherComp) => {\n if (otherComp.id === comp.id) return true;\n // If other component is in the same duplicate group, compare expanded paths\n if (dupGroup.some((c) => c.id === otherComp.id)) {\n const otherFullPath =\n (otherComp as ComponentInfo & { _parentPath: string[] })\n ._parentPath || [];\n const otherCommonPrefixLength = Math.min(\n commonPrefixLength,\n otherFullPath.length\n );\n const otherDistinguishingSuffix = otherFullPath.slice(\n otherCommonPrefixLength\n );\n const otherExpandedPath = otherDistinguishingSuffix.slice(\n 0,\n suffixLength\n );\n const otherQualifiedName = generateQualifiedPropName(\n otherComp.name || \"item\",\n otherExpandedPath\n );\n return testQualifiedName !== otherQualifiedName;\n }\n // For components outside the duplicate group, just check the final prop name\n return testQualifiedName !== otherComp.propName;\n });\n\n if (isUnique) {\n comp.propName = testQualifiedName;\n foundUnique = true;\n break;\n }\n }\n\n // If we couldn't find a unique name with the distinguishing suffix,\n // use the full path to ensure uniqueness (even if it makes names longer)\n if (!foundUnique) {\n comp.propName = generateQualifiedPropName(\n comp.name || \"item\",\n fullPath\n );\n }\n });\n }\n });\n }\n\n // Final check: if there are still duplicates after using full paths,\n // and they have identical paths, use numeric suffixes as last resort\n const finalQualifiedNameGroups = new Map<\n string,\n Array<ComponentInfo & { _parentPath: string[] }>\n >();\n group.forEach((comp) => {\n if (!finalQualifiedNameGroups.has(comp.propName)) {\n finalQualifiedNameGroups.set(comp.propName, []);\n }\n finalQualifiedNameGroups.get(comp.propName)!.push(comp);\n });\n\n finalQualifiedNameGroups.forEach((finalDupGroup, finalQualifiedName) => {\n if (finalDupGroup.length > 1) {\n // Check if all duplicates have identical paths\n const allPathsIdentical = finalDupGroup.every((comp) => {\n const thisPath = comp._parentPath || [];\n return finalDupGroup.every((otherComp) => {\n if (otherComp.id === comp.id) return true;\n const otherPath = otherComp._parentPath || [];\n return arraysEqual(thisPath, otherPath);\n });\n });\n\n // Only use numeric suffixes if paths are truly identical\n if (allPathsIdentical) {\n let index = 0;\n finalDupGroup.forEach((comp) => {\n if (index > 0) {\n comp.propName = `${finalQualifiedName}${index + 1}`;\n }\n index++;\n });\n }\n }\n });\n\n // Remove the temporary _parentPath property\n group.forEach((comp) => {\n delete (comp as any)._parentPath;\n });\n });\n\n return components;\n}\n\nfunction findInputGroups(pageData: any): InputGroupInfo[] {\n const groupsMap = new Map<string, InputGroupInfo>();\n\n function traverse(node: any): void {\n if (!node || typeof node !== \"object\") return;\n\n // Check if this is an input-stateful-set with input-group tag\n if (\n node.type === \"component:input-stateful-set\" &&\n Array.isArray(node.tags)\n ) {\n const inputGroupTag = node.tags.find((tag: string) =>\n tag.startsWith(\"input-group:\")\n );\n if (inputGroupTag) {\n const parts = inputGroupTag.split(\":\");\n if (parts.length >= 3) {\n const groupType = parts[1];\n const groupName = parts[2];\n\n if (!groupsMap.has(groupName)) {\n groupsMap.set(groupName, {\n groupName,\n groupType,\n elements: [],\n });\n }\n\n const group = groupsMap.get(groupName)!;\n group.elements.push({\n id: node.id,\n name: node.name || \"Unnamed\",\n });\n }\n }\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach(traverse);\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach(traverse);\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach(traverse);\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n return Array.from(groupsMap.values());\n}\n\nfunction findForms(pageData: any): FormInfo[] {\n const forms: FormInfo[] = [];\n\n function traverse(node: any, parentContainer?: any): void {\n if (!node || typeof node !== \"object\") return;\n\n // Check if this is a container that might be a form\n const isContainer =\n node.type?.startsWith(\"container:\") || node.type === \"container:default\";\n const isNamedForm =\n node.name?.toLowerCase().includes(\"form\") ||\n (Array.isArray(node.tags) && node.tags.includes(\"form\"));\n\n // Check if this container or any child has a submit action\n let hasSubmitAction = false;\n let submitButtonId: string | undefined;\n\n function checkForSubmitAction(n: any): void {\n if (!n || typeof n !== \"object\") return;\n\n // Check if this node has a submit action\n if (\n Array.isArray(n.tags) &&\n (n.tags.includes(\"action:submit\") || n.tags.includes(\"submit\"))\n ) {\n hasSubmitAction = true;\n submitButtonId = n.id;\n return;\n }\n\n // Check actions\n if (n.actions?.tap?.action === \"submit\") {\n hasSubmitAction = true;\n submitButtonId = n.id;\n return;\n }\n\n // Recursively check children\n if (n.components && Array.isArray(n.components)) {\n n.components.forEach(checkForSubmitAction);\n }\n if (n.body && Array.isArray(n.body)) {\n n.body.forEach(checkForSubmitAction);\n }\n }\n\n // If this looks like a form container, check for submit actions\n if (isContainer && (isNamedForm || parentContainer === undefined)) {\n checkForSubmitAction(node);\n }\n\n // If we found a form container (has submit action or is named \"form\")\n if (isContainer && (hasSubmitAction || isNamedForm)) {\n const inputs: FormInfo[\"inputs\"] = [];\n\n // Find all input components within this container\n function findInputs(n: any, parentPath: string[] = []): void {\n if (!n || typeof n !== \"object\") return;\n\n // Check if this is an input component\n if (\n n.type?.startsWith(\"component:input-\") ||\n n.type === \"component:input-text\" ||\n n.type === \"component:input-image\" ||\n n.type === \"component:input-email\" ||\n n.type === \"component:input-password\" ||\n n.type === \"component:input-select\"\n ) {\n const basePropName = sanitizePropName(n.name || \"Unnamed input\");\n inputs.push({\n id: n.id,\n name: n.name || \"Unnamed input\",\n type: n.type,\n propName: basePropName, // Will be qualified later if needed\n _parentPath: [...parentPath], // Store parent path for qualification\n });\n }\n\n // Build parent path: include this node's name if it's a container/component with a name\n // Skip generic \"Frame\" names - they're usually not meaningful for distinction\n const currentParentPath = [...parentPath];\n if (\n n.name &&\n (n.type?.startsWith(\"container:\") || n.type?.startsWith(\"component:\"))\n ) {\n const name = n.name.trim();\n // Filter out generic \"Frame\" names (case-insensitive, with or without numbers/spaces)\n // But keep meaningful names like \"TripSlideFrame\" that contain other words\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(n.name);\n }\n }\n\n // Recursively search children\n if (n.components && Array.isArray(n.components)) {\n n.components.forEach((child: any) =>\n findInputs(child, currentParentPath)\n );\n }\n if (n.body && Array.isArray(n.body)) {\n n.body.forEach((child: any) => findInputs(child, currentParentPath));\n }\n }\n\n findInputs(node, []);\n\n // Only add form if it has inputs\n if (inputs.length > 0) {\n forms.push({\n formId: node.id,\n formName: node.name || \"Form\",\n submitButtonId,\n inputs,\n });\n }\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) =>\n traverse(child, isContainer ? node : parentContainer)\n );\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, isContainer ? node : parentContainer)\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, isContainer ? node : parentContainer)\n );\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n return forms;\n}\n\n/**\n * Finds standalone select input components (input-select) that are NOT inside forms.\n * These should be exposed as controlled inputs with value and onChange props.\n */\nfunction findStandaloneSelectInputs(\n pageData: any,\n forms: FormInfo[]\n): SelectInputInfo[] {\n const selectInputs: SelectInputInfo[] = [];\n\n // Collect all input IDs that are already in forms\n const formInputIds = new Set<string>();\n forms.forEach((form) => {\n form.inputs.forEach((input) => {\n formInputIds.add(input.id);\n });\n });\n\n // Traverse to find input-select components not in forms\n function traverse(node: any, parentPath: string[] = []): void {\n if (!node || typeof node !== \"object\") return;\n\n // Check if this is an input-select component\n if (node.type === \"component:input-select\" && !formInputIds.has(node.id)) {\n const basePropName = sanitizePropName(node.name || \"selectInput\");\n selectInputs.push({\n id: node.id,\n name: node.name || \"Select Input\",\n propName: basePropName,\n _parentPath: [...parentPath],\n });\n }\n\n // Build parent path for qualification\n const currentParentPath = [...parentPath];\n if (\n node.name &&\n (node.type?.startsWith(\"container:\") ||\n node.type?.startsWith(\"component:\"))\n ) {\n const name = node.name.trim();\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(node.name);\n }\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) => traverse(child, currentParentPath));\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, currentParentPath)\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, currentParentPath)\n );\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n // Qualify duplicate prop names\n qualifySelectInputs(selectInputs);\n\n return selectInputs;\n}\n\n/**\n * Qualifies select input prop names to ensure uniqueness.\n */\nfunction qualifySelectInputs(selectInputs: SelectInputInfo[]): void {\n const propNameGroups = new Map<\n string,\n Array<SelectInputInfo & { _parentPath: string[] }>\n >();\n\n selectInputs.forEach((input) => {\n const inputWithPath = input as SelectInputInfo & { _parentPath: string[] };\n const baseName = input.propName;\n if (!propNameGroups.has(baseName)) {\n propNameGroups.set(baseName, []);\n }\n propNameGroups.get(baseName)!.push(inputWithPath);\n });\n\n propNameGroups.forEach((group, _baseName) => {\n if (group.length === 1) {\n delete (group[0] as any)._parentPath;\n return;\n }\n\n // Find minimal distinguishing paths for duplicates\n group.forEach((input) => {\n const otherPaths = group\n .filter((i) => i.id !== input.id)\n .map((i) => i._parentPath || []);\n\n const minimalPath = findMinimalDistinguishingPath(\n input._parentPath || [],\n otherPaths\n );\n\n input.propName = generateQualifiedPropName(\n input.name || \"input\",\n minimalPath\n );\n });\n\n // Clean up\n group.forEach((input) => {\n delete (input as any)._parentPath;\n });\n });\n}\n\n/**\n * Finds action buttons - components that have action tags (action:remote, action:link, etc.)\n * or have actions defined. These should be exposed with onClick handlers.\n */\nfunction findActionButtons(pageData: any): ActionButtonInfo[] {\n const buttons: ActionButtonInfo[] = [];\n\n function traverse(node: any, parentPath: string[] = []): void {\n if (!node || typeof node !== \"object\") return;\n\n // Check if this component has an action tag or actions defined\n const hasActionTag =\n Array.isArray(node.tags) &&\n node.tags.some((tag: string) => tag.startsWith(\"action:\"));\n const hasActions = node.actions && typeof node.actions === \"object\";\n\n if (hasActionTag || hasActions) {\n // Determine the action type\n let actionType = \"tap\";\n if (Array.isArray(node.tags)) {\n const actionTag = node.tags.find((tag: string) =>\n tag.startsWith(\"action:\")\n );\n if (actionTag) {\n actionType = actionTag.replace(\"action:\", \"\");\n }\n }\n if (node.actions?.tap?.action) {\n actionType = node.actions.tap.action;\n }\n\n const basePropName = sanitizePropName(node.name || \"button\");\n buttons.push({\n id: node.id,\n name: node.name || \"Button\",\n propName: basePropName,\n actionType,\n _parentPath: [...parentPath],\n });\n }\n\n // Build parent path for qualification\n const currentParentPath = [...parentPath];\n if (\n node.name &&\n (node.type?.startsWith(\"container:\") ||\n node.type?.startsWith(\"component:\"))\n ) {\n const name = node.name.trim();\n const isGenericFrame =\n /^frame\\s*\\d*$/i.test(name) || name.toUpperCase() === \"FRAME\";\n if (name && !isGenericFrame) {\n currentParentPath.push(node.name);\n }\n }\n\n // Recursively traverse children\n if (node.body && Array.isArray(node.body)) {\n node.body.forEach((child: any) => traverse(child, currentParentPath));\n }\n if (node.containers && Array.isArray(node.containers)) {\n node.containers.forEach((child: any) =>\n traverse(child, currentParentPath)\n );\n }\n if (node.components && Array.isArray(node.components)) {\n node.components.forEach((child: any) =>\n traverse(child, currentParentPath)\n );\n }\n }\n\n // Start traversal from page data\n const body =\n pageData.data?.body || pageData.body || (pageData as any).data?.body || [];\n\n if (Array.isArray(body) && body.length > 0) {\n body.forEach((node: any) => traverse(node));\n }\n\n // Qualify duplicate prop names\n qualifyActionButtons(buttons);\n\n return buttons;\n}\n\n/**\n * Qualifies action button prop names to ensure uniqueness.\n */\nfunction qualifyActionButtons(buttons: ActionButtonInfo[]): void {\n const propNameGroups = new Map<\n string,\n Array<ActionButtonInfo & { _parentPath: string[] }>\n >();\n\n buttons.forEach((button) => {\n const buttonWithPath = button as ActionButtonInfo & {\n _parentPath: string[];\n };\n const baseName = button.propName;\n if (!propNameGroups.has(baseName)) {\n propNameGroups.set(baseName, []);\n }\n propNameGroups.get(baseName)!.push(buttonWithPath);\n });\n\n propNameGroups.forEach((group, _baseName) => {\n if (group.length === 1) {\n delete (group[0] as any)._parentPath;\n return;\n }\n\n // Find minimal distinguishing paths for duplicates\n group.forEach((button) => {\n const otherPaths = group\n .filter((b) => b.id !== button.id)\n .map((b) => b._parentPath || []);\n\n const minimalPath = findMinimalDistinguishingPath(\n button._parentPath || [],\n otherPaths\n );\n\n button.propName = generateQualifiedPropName(\n button.name || \"button\",\n minimalPath\n );\n });\n\n // Clean up\n group.forEach((button) => {\n delete (button as any)._parentPath;\n });\n });\n}\n\n/**\n * Qualifies form input prop names to ensure uniqueness within each form.\n * Only qualifies where necessary, using minimal distinguishing paths.\n */\nfunction qualifyFormInputs(forms: FormInfo[]): void {\n forms.forEach((form) => {\n const inputs = form.inputs;\n\n // Group inputs by base prop name\n const propNameGroups = new Map<\n string,\n Array<FormInfo[\"inputs\"][0] & { _parentPath: string[] }>\n >();\n\n inputs.forEach((input) => {\n const inputWithPath = input as FormInfo[\"inputs\"][0] & {\n _parentPath: string[];\n };\n const baseName = input.propName;\n if (!propNameGroups.has(baseName)) {\n propNameGroups.set(baseName, []);\n }\n propNameGroups.get(baseName)!.push(inputWithPath);\n });\n\n // For each group with duplicates, find minimal distinguishing paths\n propNameGroups.forEach((group, _baseName) => {\n if (group.length === 1) {\n // No duplicates, keep the simple name\n // Remove the temporary _parentPath property\n delete (group[0] as any)._parentPath;\n return;\n }\n\n // Find minimal distinguishing paths for all inputs\n group.forEach((input) => {\n const otherPaths = group\n .filter((i) => i.id !== input.id)\n .map((i) => i._parentPath || []);\n\n const minimalPath = findMinimalDistinguishingPath(\n input._parentPath || [],\n otherPaths\n );\n\n // Use the minimal distinguishing path to qualify the name\n input.propName = generateQualifiedPropName(\n input.name || \"input\",\n minimalPath\n );\n });\n\n // Check if qualified names are still duplicates and expand paths if needed\n let hasDuplicates = true;\n let iteration = 0;\n const maxIterations = 10; // Safety limit\n\n while (hasDuplicates && iteration < maxIterations) {\n iteration++;\n const qualifiedNameGroups = new Map<\n string,\n Array<FormInfo[\"inputs\"][0] & { _parentPath: string[] }>\n >();\n group.forEach((input) => {\n if (!qualifiedNameGroups.has(input.propName)) {\n qualifiedNameGroups.set(input.propName, []);\n }\n qualifiedNameGroups.get(input.propName)!.push(input);\n });\n\n hasDuplicates = false;\n // For each group of still-duplicated qualified names, expand their paths\n qualifiedNameGroups.forEach((dupGroup, _qualifiedName) => {\n if (dupGroup.length > 1) {\n hasDuplicates = true;\n // Expand the distinguishing path for each duplicate\n dupGroup.forEach((input) => {\n const fullPath = input._parentPath || [];\n const otherFullPaths = dupGroup\n .filter((i) => i.id !== input.id)\n .map((i) => i._parentPath || []);\n\n // Find where this path diverges from others in the duplicate group\n let commonPrefixLength = 0;\n const maxCommonLength = Math.min(\n fullPath.length,\n ...otherFullPaths.map((p) => p.length)\n );\n\n for (let i = 0; i < maxCommonLength; i++) {\n const thisPart = fullPath[i];\n const allMatch = otherFullPaths.every((otherPath) => {\n return otherPath[i] === thisPart;\n });\n if (allMatch) {\n commonPrefixLength++;\n } else {\n break;\n }\n }\n\n // Use progressively more of the distinguishing suffix until unique\n const distinguishingSuffix = fullPath.slice(commonPrefixLength);\n\n // Try expanding the distinguishing suffix until we find a unique name\n let foundUnique = false;\n for (\n let suffixLength = 1;\n suffixLength <= distinguishingSuffix.length;\n suffixLength++\n ) {\n const expandedPath = distinguishingSuffix.slice(\n 0,\n suffixLength\n );\n const testQualifiedName = generateQualifiedPropName(\n input.name || \"input\",\n expandedPath\n );\n\n // Check if this qualified name is unique among ALL inputs in this form\n const isUnique = inputs.every((otherInput) => {\n if (otherInput.id === input.id) return true;\n // If other input is in the same duplicate group, compare expanded paths\n if (dupGroup.some((i) => i.id === otherInput.id)) {\n const otherFullPath =\n (\n otherInput as FormInfo[\"inputs\"][0] & {\n _parentPath: string[];\n }\n )._parentPath || [];\n const otherCommonPrefixLength = Math.min(\n commonPrefixLength,\n otherFullPath.length\n );\n const otherDistinguishingSuffix = otherFullPath.slice(\n otherCommonPrefixLength\n );\n const otherExpandedPath = otherDistinguishingSuffix.slice(\n 0,\n suffixLength\n );\n const otherQualifiedName = generateQualifiedPropName(\n otherInput.name || \"input\",\n otherExpandedPath\n );\n return testQualifiedName !== otherQualifiedName;\n }\n // For inputs outside the duplicate group, just check the final prop name\n return testQualifiedName !== otherInput.propName;\n });\n\n if (isUnique) {\n input.propName = testQualifiedName;\n foundUnique = true;\n break;\n }\n }\n\n // If we couldn't find a unique name with the distinguishing suffix,\n // use the distinguishing suffix we found (it's the minimal we can do)\n if (!foundUnique) {\n input.propName = generateQualifiedPropName(\n input.name || \"input\",\n distinguishingSuffix.length > 0 ? distinguishingSuffix : []\n );\n }\n });\n }\n });\n }\n\n // Final check: if there are still duplicates after using full paths,\n // and they have identical paths, use numeric suffixes as last resort\n const finalQualifiedNameGroups = new Map<\n string,\n Array<FormInfo[\"inputs\"][0] & { _parentPath: string[] }>\n >();\n group.forEach((input) => {\n if (!finalQualifiedNameGroups.has(input.propName)) {\n finalQualifiedNameGroups.set(input.propName, []);\n }\n finalQualifiedNameGroups.get(input.propName)!.push(input);\n });\n\n finalQualifiedNameGroups.forEach((finalDupGroup, finalQualifiedName) => {\n if (finalDupGroup.length > 1) {\n // Check if all duplicates have identical paths\n const allPathsIdentical = finalDupGroup.every((input) => {\n const thisPath = input._parentPath || [];\n return finalDupGroup.every((otherInput) => {\n if (otherInput.id === input.id) return true;\n const otherPath = otherInput._parentPath || [];\n return arraysEqual(thisPath, otherPath);\n });\n });\n\n // Only use numeric suffixes if paths are truly identical\n if (allPathsIdentical) {\n let index = 0;\n finalDupGroup.forEach((input) => {\n if (index > 0) {\n input.propName = `${finalQualifiedName}${index + 1}`;\n }\n index++;\n });\n }\n }\n });\n\n // Remove the temporary _parentPath property\n group.forEach((input) => {\n delete (input as any)._parentPath;\n });\n });\n });\n}\n\nfunction generateComponentCode(\n appId: string,\n pageId: string,\n componentName: string,\n sliders: SliderInfo[],\n standaloneComponents: ComponentInfo[],\n inputGroups: InputGroupInfo[],\n forms: FormInfo[],\n selectInputs: SelectInputInfo[],\n actionButtons: ActionButtonInfo[],\n isProduction: boolean = false\n): string {\n // Generate prop types\n const propTypes: string[] = [];\n const controlPropTypes: string[] = [];\n const inputGroupPropTypes: string[] = [];\n const formPropTypes: string[] = [];\n const selectInputPropTypes: string[] = [];\n const actionButtonPropTypes: string[] = [];\n\n // Add standalone component props\n standaloneComponents.forEach((comp) => {\n propTypes.push(` ${comp.propName}?: ${comp.propType};`);\n });\n\n // Add input group props\n inputGroups.forEach((group) => {\n const propName = sanitizePropName(group.groupName);\n inputGroupPropTypes.push(` ${propName}?: string;`);\n inputGroupPropTypes.push(\n ` on${propName[0].toUpperCase()}${propName.slice(\n 1\n )}Change?: (value: string) => void;`\n );\n });\n\n // Generate form data interfaces and props\n const formDataInterfaces: string[] = [];\n forms.forEach((form) => {\n const formPropName = sanitizePropName(form.formName);\n const formDataTypeName = `${formPropName[0].toUpperCase()}${formPropName.slice(\n 1\n )}FormData`;\n\n // Generate interface for form data with human-readable property names\n const formDataProps: string[] = [];\n form.inputs.forEach((input) => {\n const inputPropName = input.propName; // Use qualified prop name\n const inputType = getComponentPropType(input.type, input.name);\n formDataProps.push(` ${inputPropName}: ${inputType};`);\n });\n\n formDataInterfaces.push(`export interface ${formDataTypeName} {\n${formDataProps.join(\"\\n\")}\n}`);\n\n // Add the callback prop with proper typing\n formPropTypes.push(\n ` on${formPropName[0].toUpperCase()}${formPropName.slice(\n 1\n )}Submit?: (formData: ${formDataTypeName}) => void;`\n );\n });\n\n // Add standalone select input props (controlled value + onChange + options)\n selectInputs.forEach((input) => {\n const propName = input.propName;\n const capitalizedPropName = propName[0].toUpperCase() + propName.slice(1);\n selectInputPropTypes.push(` ${propName}?: string;`);\n selectInputPropTypes.push(\n ` ${propName}Options?: Array<string | { value: string; label: string }>;`\n );\n selectInputPropTypes.push(\n ` on${capitalizedPropName}Change?: (value: string) => void;`\n );\n });\n\n // Add action button props (onClick)\n actionButtons.forEach((button) => {\n const propName = button.propName;\n const capitalizedPropName = propName[0].toUpperCase() + propName.slice(1);\n actionButtonPropTypes.push(` on${capitalizedPropName}Click?: () => void;`);\n });\n\n sliders.forEach((slider) => {\n if (slider.arrayContainer && slider.arrayContainer.components.length > 0) {\n const container = slider.arrayContainer;\n const itemTypeName = `${container.propName[0].toUpperCase()}${container.propName.slice(\n 1\n )}Item`;\n propTypes.push(` ${container.propName}: ${itemTypeName}[];`);\n }\n\n // Add control props for each slider/repeating container\n const sliderPropName = sanitizePropName(slider.name || \"container\");\n controlPropTypes.push(` ${sliderPropName}CurrentIndex?: number;`);\n controlPropTypes.push(\n ` on${sliderPropName[0].toUpperCase()}${sliderPropName.slice(\n 1\n )}IndexChange?: (index: number) => void;`\n );\n });\n\n const allPropTypes = [\n ...propTypes,\n ...controlPropTypes,\n ...inputGroupPropTypes,\n ...formPropTypes,\n ...selectInputPropTypes,\n ...actionButtonPropTypes,\n ];\n const hasProps = allPropTypes.length > 0;\n const propsInterface = hasProps\n ? `export interface ${componentName}Props {\n${allPropTypes.join(\"\\n\")}\n}`\n : \"\";\n\n const itemTypes = sliders\n .filter((s) => s.arrayContainer && s.arrayContainer.components.length > 0)\n .map((slider) => {\n const container = slider.arrayContainer!;\n const itemTypeName = `${container.propName[0].toUpperCase()}${container.propName.slice(\n 1\n )}Item`;\n const itemProps = container.components\n .map((comp) => {\n return ` ${comp.propName}: ${comp.propType};`;\n })\n .join(\"\\n\");\n return `export interface ${itemTypeName} {\n${itemProps}\n}`;\n })\n .join(\"\\n\\n\");\n\n const formDataTypes = formDataInterfaces.join(\"\\n\\n\");\n\n // Generate data mapping\n const dataMapping: string[] = [];\n const controlMapping: string[] = [];\n\n // Add standalone component mappings\n standaloneComponents.forEach((comp) => {\n const propKey = getComponentPropName(comp.type);\n dataMapping.push(` // ${comp.name}\n ...(props.${comp.propName} !== undefined && { \"${comp.id}\": { ${propKey}: props.${comp.propName} } as any }),`);\n });\n\n // Add select input mappings (for controlled values and options)\n selectInputs.forEach((input) => {\n dataMapping.push(` // ${input.name}\n ...((props.${input.propName} !== undefined || props.${input.propName}Options !== undefined) && { \n \"${input.id}\": { \n ...(props.${input.propName} !== undefined && { value: props.${input.propName} }),\n ...(props.${input.propName}Options !== undefined && { options: props.${input.propName}Options }),\n } as any \n }),`);\n });\n\n sliders.forEach((slider) => {\n if (slider.arrayContainer && slider.arrayContainer.components.length > 0) {\n const container = slider.arrayContainer;\n const itemMapping = container.components\n .map((comp) => {\n const propKey = getComponentPropName(comp.type);\n return ` // ${comp.name}\n \"${comp.id}\": {\n ${propKey}: item.${comp.propName},\n }`;\n })\n .join(\",\\n\");\n\n dataMapping.push(` // ${container.name}\n \"${container.id}\": props.${container.propName}.map((item) => ({\n${itemMapping}\n })),`);\n }\n\n // Generate control mapping for each slider\n const sliderPropName = sanitizePropName(slider.name || \"container\");\n const controlPropName = `${sliderPropName[0].toUpperCase()}${sliderPropName.slice(\n 1\n )}IndexChange`;\n const controlEntry: string[] = [];\n if (slider.id) {\n controlEntry.push(` // ${slider.name}`);\n controlEntry.push(` \"${slider.id}\": {`);\n controlEntry.push(\n ` currentIndex: props.${sliderPropName}CurrentIndex,`\n );\n controlEntry.push(` onIndexChange: props.on${controlPropName},`);\n controlEntry.push(` }`);\n }\n if (controlEntry.length > 0) {\n controlMapping.push(controlEntry.join(\"\\n\"));\n }\n });\n\n const repeatingContainerControlsCode =\n controlMapping.length > 0\n ? `\\n repeatingContainerControls={{\n${controlMapping.join(\",\\n\")}\n }}`\n : \"\";\n\n // Generate input group mappings\n const inputGroupMapping: string[] = [];\n const inputGroupHandlers: string[] = [];\n\n // Generate form submission handlers\n // const formHandlers: string[] = [];\n\n // Start action handler if we have input groups, forms, select inputs, or action buttons\n if (\n inputGroups.length > 0 ||\n forms.length > 0 ||\n selectInputs.length > 0 ||\n actionButtons.length > 0\n ) {\n inputGroupHandlers.push(` const handleAction = (payload: any) => {`);\n inputGroupHandlers.push(` const { action } = payload?.bravo || {};`);\n inputGroupHandlers.push(``);\n\n // Add select input handling\n if (selectInputs.length > 0) {\n inputGroupHandlers.push(` // Handle select input changes`);\n inputGroupHandlers.push(\n ` if (action?.action === \"input-change\" || action?.action === \"select-change\") {`\n );\n inputGroupHandlers.push(` const nodeId = action?.nodeId;`);\n inputGroupHandlers.push(` const value = action?.params?.value;`);\n inputGroupHandlers.push(``);\n\n selectInputs.forEach((input) => {\n const propName = input.propName;\n const capitalizedPropName =\n propName[0].toUpperCase() + propName.slice(1);\n const handlerPropName = `on${capitalizedPropName}Change`;\n inputGroupHandlers.push(` // ${input.name}`);\n inputGroupHandlers.push(\n ` if (nodeId === \"${input.id}\" && props.${handlerPropName}) {`\n );\n inputGroupHandlers.push(` props.${handlerPropName}(value);`);\n inputGroupHandlers.push(` return;`);\n inputGroupHandlers.push(` }`);\n });\n\n inputGroupHandlers.push(` }`);\n inputGroupHandlers.push(``);\n }\n\n // Add action button handling\n if (actionButtons.length > 0) {\n inputGroupHandlers.push(` // Handle button clicks`);\n inputGroupHandlers.push(\n ` if (action?.action === \"remote\" || action?.action === \"tap\" || action?.action === \"link\") {`\n );\n inputGroupHandlers.push(` const nodeId = action?.nodeId;`);\n inputGroupHandlers.push(``);\n\n actionButtons.forEach((button) => {\n const propName = button.propName;\n const capitalizedPropName =\n propName[0].toUpperCase() + propName.slice(1);\n const handlerPropName = `on${capitalizedPropName}Click`;\n inputGroupHandlers.push(` // ${button.name}`);\n inputGroupHandlers.push(\n ` if (nodeId === \"${button.id}\" && props.${handlerPropName}) {`\n );\n inputGroupHandlers.push(` props.${handlerPropName}();`);\n inputGroupHandlers.push(` return;`);\n inputGroupHandlers.push(` }`);\n });\n\n inputGroupHandlers.push(` }`);\n inputGroupHandlers.push(``);\n }\n\n // Add input group handling\n if (inputGroups.length > 0) {\n inputGroupHandlers.push(\n ` if (action?.action === \"input-group-change\") {`\n );\n inputGroupHandlers.push(\n ` const { groupName, value } = action.params;`\n );\n\n inputGroups.forEach((group) => {\n const propName = sanitizePropName(group.groupName);\n const handlerPropName = `on${propName[0].toUpperCase()}${propName.slice(\n 1\n )}Change`;\n inputGroupHandlers.push(\n ` if (groupName === \"${group.groupName}\" && props.${handlerPropName}) {`\n );\n inputGroupHandlers.push(` props.${handlerPropName}(value);`);\n inputGroupHandlers.push(` return;`);\n inputGroupHandlers.push(` }`);\n });\n\n inputGroupHandlers.push(` }`);\n inputGroupHandlers.push(``);\n }\n\n // Add form submission handling\n if (forms.length > 0) {\n inputGroupHandlers.push(` if (action?.action === \"submit\") {`);\n inputGroupHandlers.push(` // Get form inputs from Encore state`);\n inputGroupHandlers.push(\n ` const formInputs = useEncoreState.getState().formInputs[\"${pageId}\"] || {};`\n );\n inputGroupHandlers.push(` const submitNodeId = action?.nodeId;`);\n inputGroupHandlers.push(``);\n\n forms.forEach((form, index) => {\n const formPropName = sanitizePropName(form.formName);\n const handlerPropName = `on${formPropName[0].toUpperCase()}${formPropName.slice(\n 1\n )}Submit`;\n\n if (index > 0) {\n inputGroupHandlers.push(``);\n }\n inputGroupHandlers.push(\n ` // Form: ${form.formName} (${form.formId})`\n );\n // Check if this form's submit button was clicked (if submitButtonId is available)\n if (form.submitButtonId) {\n inputGroupHandlers.push(\n ` if (submitNodeId === \"${form.submitButtonId}\" && props.${handlerPropName}) {`\n );\n } else if (forms.length === 1) {\n // If only one form, don't check submit button ID\n inputGroupHandlers.push(` if (props.${handlerPropName}) {`);\n } else {\n // Multiple forms but no submit button ID - check all\n inputGroupHandlers.push(` if (props.${handlerPropName}) {`);\n }\n inputGroupHandlers.push(` // Extract form inputs for this form`);\n const formDataTypeName = `${formPropName[0].toUpperCase()}${formPropName.slice(\n 1\n )}FormData`;\n inputGroupHandlers.push(\n ` const formData: ${formDataTypeName} = {`\n );\n const formDataEntries: string[] = [];\n form.inputs.forEach((input) => {\n const inputPropName = input.propName; // Use qualified prop name\n formDataEntries.push(\n ` ${inputPropName}: formInputs[\"${input.id}\"]`\n );\n });\n inputGroupHandlers.push(formDataEntries.join(\",\\n\"));\n inputGroupHandlers.push(` };`);\n inputGroupHandlers.push(` props.${handlerPropName}(formData);`);\n inputGroupHandlers.push(\n ` // Note: Default form submission will still proceed after callback`\n );\n inputGroupHandlers.push(` }`);\n });\n\n inputGroupHandlers.push(` }`);\n }\n\n inputGroupHandlers.push(` };`);\n }\n\n // Generate input groups code\n inputGroups.forEach((group) => {\n const propName = sanitizePropName(group.groupName);\n inputGroupMapping.push(\n ` ...(props.${propName} !== undefined && { ${propName}: props.${propName} }),`\n );\n });\n\n const inputGroupsCode =\n inputGroupMapping.length > 0\n ? `\\n inputGroups={{\n${inputGroupMapping.join(\"\\n\")}\n }}`\n : \"\";\n\n const onActionCode =\n inputGroupHandlers.length > 0 ? `\\n onAction={handleAction}` : \"\";\n\n const propsParameter = hasProps ? `props: ${componentName}Props` : \"\";\n const propsInterfaceSection = propsInterface ? `${propsInterface}\\n\\n` : \"\";\n\n return `/**\n * ${componentName}\n * \n * Wrapper component for Encore Studio app.\n * See README.md for detailed documentation.\n */\n\nimport { EncoreApp${\n forms.length > 0 ? \", useEncoreState\" : \"\"\n } } from \"@bravostudioai/react\";\n${isProduction ? `import productionData from \"./data.json\";` : \"\"}\n\n${itemTypes ? `${itemTypes}\\n\\n` : \"\"}${\n formDataTypes ? `${formDataTypes}\\n\\n` : \"\"\n }${propsInterfaceSection}export function ${componentName}(${propsParameter}) {\n${inputGroupHandlers.length > 0 ? inputGroupHandlers.join(\"\\n\") : \"\"}\n return (\n <EncoreApp\n appId=\"${appId}\"\n pageId=\"${pageId}\"\n ${isProduction ? `appDefinition={productionData.app}\n pageDefinition={productionData.page}\n componentCode={productionData.componentCode}` : \"\"}\n data={{\n${dataMapping.join(\"\\n\")}\n }}${repeatingContainerControlsCode}${inputGroupsCode}${onActionCode}\n />\n );\n}\n\nexport default ${componentName};\n`;\n}\n\nfunction generateReadme(\n appId: string,\n pageId: string,\n appName: string,\n pageName: string,\n componentName: string,\n sliders: SliderInfo[],\n standaloneComponents: ComponentInfo[],\n inputGroups: InputGroupInfo[],\n forms: FormInfo[],\n selectInputs: SelectInputInfo[],\n actionButtons: ActionButtonInfo[]\n): string {\n const componentDocs: string[] = [];\n const controlDocs: string[] = [];\n const selectInputDocs: string[] = [];\n const actionButtonDocs: string[] = [];\n\n // Add standalone component documentation\n standaloneComponents.forEach((comp) => {\n componentDocs.push(`### \\`${comp.propName}\\` (${comp.propType}, optional)\n\n${comp.name} (${comp.type}) - Component ID: ${comp.id}`);\n });\n\n sliders.forEach((slider) => {\n if (slider.arrayContainer && slider.arrayContainer.components.length > 0) {\n const container = slider.arrayContainer;\n\n // Generate component documentation\n const compDocs = container.components\n .map((comp) => {\n return `- \\`${comp.propName}\\` (${comp.propType}): ${comp.name} (${comp.type}) - Component ID: ${comp.id}`;\n })\n .join(\"\\n\");\n\n componentDocs.push(`### \\`${\n container.propName\n }\\` (${container.propName[0].toUpperCase()}${container.propName.slice(\n 1\n )}Item[])\n\nArray of items for \"${container.name}\" container (ID: ${container.id})\n\n**Properties:**\n\n${compDocs}`);\n }\n\n // Generate control documentation for each slider/repeating container\n const sliderPropName = sanitizePropName(slider.name || \"container\");\n const controlPropName = `${sliderPropName[0].toUpperCase()}${sliderPropName.slice(\n 1\n )}IndexChange`;\n controlDocs.push(`### \\`${sliderPropName}CurrentIndex\\` (number, optional)\n\nControls the currently visible slide/index for the \"${slider.name}\" container (ID: ${slider.id}).\n\nWhen provided, the slider operates in controlled mode - the parent component controls which slide is displayed. When not provided, the slider manages its own state.\n\n### \\`on${controlPropName}\\` ((index: number) => void, optional)\n\nCallback fired when the user navigates to a different slide. Called with the new slide index (0-based).\n\nThis event fires whenever the slide changes, whether by user interaction, automatic advancement, or programmatic control.`);\n });\n\n const dataPropsSection =\n componentDocs.length > 0\n ? componentDocs.join(\"\\n\\n\")\n : \"This component currently has no data-bound props.\";\n\n const controlPropsSection =\n controlDocs.length > 0\n ? `## Control Props\n\nThese props allow you to imperatively control repeating containers (sliders, lists, etc.) and receive notifications when the current index changes.\n\n${controlDocs.join(\"\\n\\n\")}`\n : \"\";\n\n // Generate input group documentation\n const inputGroupDocs: string[] = [];\n inputGroups.forEach((group) => {\n const propName = sanitizePropName(group.groupName);\n const handlerPropName = `on${propName[0].toUpperCase()}${propName.slice(\n 1\n )}Change`;\n const elementsList = group.elements\n .map((el) => `- \"${el.name}\"`)\n .join(\"\\n\");\n\n inputGroupDocs.push(`### \\`${propName}\\` (string, optional)\n\nSets which element is active in the \"${group.groupName}\" input group (type: ${group.groupType}).\n\n**Available elements:**\n${elementsList}\n\n### \\`${handlerPropName}\\` ((value: string) => void, optional)\n\nCallback fired when the user selects a different element in the \"${group.groupName}\" input group. Called with the name of the selected element.`);\n });\n\n const inputGroupPropsSection =\n inputGroupDocs.length > 0\n ? `## Input Group Props\n\nThese props allow you to control input groups (radio button-like behavior) and receive notifications when the selection changes.\n\n${inputGroupDocs.join(\"\\n\\n\")}`\n : \"\";\n\n // Generate form documentation\n const formDocs: string[] = [];\n forms.forEach((form) => {\n const formPropName = sanitizePropName(form.formName);\n const handlerPropName = `on${formPropName[0].toUpperCase()}${formPropName.slice(\n 1\n )}Submit`;\n const formDataTypeName = `${formPropName[0].toUpperCase()}${formPropName.slice(\n 1\n )}FormData`;\n const inputsList = form.inputs\n .map((input) => {\n const inputPropName = input.propName; // Use qualified prop name\n const inputType = getComponentPropType(input.type, input.name);\n return `- \\`${inputPropName}\\` (${inputType}) - ${input.name}`;\n })\n .join(\"\\n\");\n\n formDocs.push(`### \\`${handlerPropName}\\` ((formData: ${formDataTypeName}) => void, optional)\n\nCallback fired when the \"${\n form.formName\n }\" form is submitted. Called with a typed object containing all form input values with human-readable property names.\n\n**Form data shape:**\n\\`\\`\\`typescript\ninterface ${formDataTypeName} {\n${form.inputs\n .map((input) => {\n const inputPropName = input.propName; // Use qualified prop name\n const inputType = getComponentPropType(input.type, input.name);\n return ` ${inputPropName}: ${inputType};`;\n })\n .join(\"\\n\")}\n}\n\\`\\`\\`\n\n**Form inputs:**\n${inputsList}`);\n });\n\n const formPropsSection =\n formDocs.length > 0\n ? `## Form Submission Props\n\nThese props allow you to handle form submissions and access form input values.\n\n${formDocs.join(\"\\n\\n\")}`\n : \"\";\n\n // Generate select input documentation\n selectInputs.forEach((input) => {\n const propName = input.propName;\n const capitalizedPropName = propName[0].toUpperCase() + propName.slice(1);\n const handlerPropName = `on${capitalizedPropName}Change`;\n const optionsPropName = `${propName}Options`;\n\n selectInputDocs.push(`### \\`${propName}\\` (string, optional)\n\nControls the selected value of the \"${input.name}\" dropdown (Component ID: ${input.id}).\n\nWhen provided, the select input operates in controlled mode - the parent component controls the current value.\n\n### \\`${optionsPropName}\\` (Array<string | { value: string; label: string }>, optional)\n\nSets the available options for the \"${input.name}\" dropdown. Can be an array of strings (used as both value and label) or an array of objects with \\`value\\` and \\`label\\` properties.\n\n**Example:**\n\\`\\`\\`tsx\n// Simple string array\n${optionsPropName}={[\"Option 1\", \"Option 2\", \"Option 3\"]}\n\n// Object array with separate values and labels\n${optionsPropName}={[\n { value: \"opt1\", label: \"Option 1\" },\n { value: \"opt2\", label: \"Option 2\" },\n]}\n\\`\\`\\`\n\n### \\`${handlerPropName}\\` ((value: string) => void, optional)\n\nCallback fired when the user selects a different option in the \"${input.name}\" dropdown. Called with the selected value.`);\n });\n\n const selectInputPropsSection =\n selectInputDocs.length > 0\n ? `## Select Input Props\n\nThese props allow you to control select/dropdown inputs and respond to value changes.\n\n${selectInputDocs.join(\"\\n\\n\")}`\n : \"\";\n\n // Generate action button documentation\n actionButtons.forEach((button) => {\n const propName = button.propName;\n const capitalizedPropName = propName[0].toUpperCase() + propName.slice(1);\n const handlerPropName = `on${capitalizedPropName}Click`;\n\n actionButtonDocs.push(`### \\`${handlerPropName}\\` (() => void, optional)\n\nCallback fired when the \"${button.name}\" button is clicked (Component ID: ${button.id}).\n\nAction type: \\`${button.actionType}\\``);\n });\n\n const actionButtonPropsSection =\n actionButtonDocs.length > 0\n ? `## Action Button Props\n\nThese props allow you to respond to button clicks and other user interactions.\n\n${actionButtonDocs.join(\"\\n\\n\")}`\n : \"\";\n\n const propsSection = `## Props\n\n### Data Props\n\n${dataPropsSection}\n\n${controlPropsSection}\n\n${inputGroupPropsSection}\n\n${formPropsSection}\n\n${selectInputPropsSection}\n\n${actionButtonPropsSection}`;\n\n const usageExample =\n sliders.length > 0 && sliders[0].arrayContainer\n ? `<${componentName}\n ${sliders\n .map((s) =>\n s.arrayContainer\n ? `${s.arrayContainer.propName}={[\n {\n ${s.arrayContainer?.components\n .map(\n (c) =>\n `${c.propName}: \"${\n c.type === \"component:image\"\n ? \"https://example.com/image.jpg\"\n : \"Example value\"\n }\"`\n )\n .join(\",\\n \")}\n }\n ]}`\n : \"\"\n )\n .filter(Boolean)\n .join(\"\\n \")}\n/>`\n : `<${componentName} />`;\n\n // Generate control example\n let controlExample = \"\";\n if (sliders.length > 0 && sliders[0]) {\n const firstSlider = sliders[0];\n const sliderPropName = sanitizePropName(firstSlider.name || \"container\");\n const controlPropName = `${sliderPropName[0].toUpperCase()}${sliderPropName.slice(\n 1\n )}IndexChange`;\n\n controlExample = `## Controlling Slides\n\nYou can imperatively control which slide is displayed and listen for slide changes:\n\n\\`\\`\\`tsx\nimport { useState } from \"react\";\nimport { ${componentName} } from \"./${componentName}\";\n\nfunction MyComponent() {\n const [currentSlide, setCurrentSlide] = useState(0);\n\n return (\n <>\n <button onClick={() => setCurrentSlide((prev) => Math.max(0, prev - 1))}>\n Previous\n </button>\n <button onClick={() => setCurrentSlide((prev) => prev + 1)}>\n Next\n </button>\n <${componentName}\n ${sliders\n .map((s) =>\n s.arrayContainer\n ? `${s.arrayContainer.propName}={[/* array of items */]}`\n : \"\"\n )\n .filter(Boolean)\n .join(\"\\n \")}\n ${sliderPropName}CurrentIndex={currentSlide}\n on${controlPropName}={(index) => setCurrentSlide(index)}\n />\n </>\n );\n}\n\\`\\`\\``;\n }\n\n return `# ${componentName}\n\nEncore App Wrapper Component\n\nThis component wraps the Encore Studio app **\"${appName}\"** (App ID: \\`${appId}\\`) for the page **\"${pageName}\"** (Page ID: \\`${pageId}\\`).\n\nThe component automatically maps props to data-bound components within the app. Components marked with \\`encore:data\\` tags are exposed as props, allowing you to dynamically populate content.\n\n${propsSection}\n\n## Usage\n\n\\`\\`\\`tsx\nimport { ${componentName} } from \"./${componentName}\";\n\nfunction MyComponent() {\n return (\n <${componentName}\n ${sliders\n .map((s) =>\n s.arrayContainer\n ? `${s.arrayContainer.propName}={[/* array of items */]}`\n : \"\"\n )\n .filter(Boolean)\n .join(\"\\n \")}\n />\n );\n}\n\\`\\`\\`\n\n## Example\n\n\\`\\`\\`tsx\n${usageExample}\n\\`\\`\\`\n\n${controlExample}\n`;\n}\n\nfunction generateNames(\n appName: string,\n pageName: string\n): { directoryPath: string; componentName: string } {\n const appCamel = sanitizePropName(appName);\n const pageCamel = sanitizePropName(pageName);\n // Capitalize first letter for PascalCase\n const appPascal = appCamel.charAt(0).toUpperCase() + appCamel.slice(1);\n const pagePascal = pageCamel.charAt(0).toUpperCase() + pageCamel.slice(1);\n return {\n directoryPath: join(appPascal, pagePascal),\n componentName: pagePascal,\n };\n}\n\nasync function getAppPages(\n appId: string\n): Promise<{ pages: any[]; appData: any }> {\n const url = `${APPS_SERVICE_URL}/devices/apps/${appId}`;\n console.log(`Fetching app data from ${url}...`);\n try {\n const content = await downloadFile(url);\n const appData = JSON.parse(content);\n const pages = appData?.app?.data?.pages || [];\n return { pages, appData };\n } catch (error) {\n console.error(\"Failed to fetch app data:\", error);\n throw error;\n }\n}\n\nasync function generateWrapper({\n appId,\n pageId,\n outputPath,\n cachedAppData,\n isProduction,\n}: {\n appId: string;\n pageId: string;\n outputPath: string;\n cachedAppData?: any;\n isProduction?: boolean;\n}) {\n console.log(`Generating wrapper for app: ${appId}, page: ${pageId}`);\n\n // Determine final output path - we'll update it after we get app/page names\n let finalOutputPath = outputPath;\n let needsFilenameGeneration = false;\n const pathExt = outputPath.split(\".\").pop()?.toLowerCase();\n if (\n pathExt !== \"tsx\" &&\n pathExt !== \"ts\" &&\n pathExt !== \"jsx\" &&\n pathExt !== \"js\"\n ) {\n // Path doesn't have a file extension, treat as directory\n const { stat } = await import(\"fs/promises\");\n try {\n const pathStats = await stat(outputPath);\n if (pathStats.isDirectory()) {\n needsFilenameGeneration = true;\n }\n } catch {\n // Path doesn't exist, check if it looks like a directory (no extension)\n if (!pathExt || outputPath.endsWith(\"/\")) {\n needsFilenameGeneration = true;\n }\n }\n }\n\n if (needsFilenameGeneration) {\n console.log(\n `Output path is a directory, will generate filename from app/page names`\n );\n }\n\n console.log(`Output path: ${outputPath}`);\n\n // Create temp directory for downloaded files\n const tempDir = join(process.cwd(), \".temp-bravo\", appId, pageId);\n if (!existsSync(tempDir)) {\n await mkdir(tempDir, { recursive: true });\n }\n\n // Download files (skip app.json if we have cached data)\n const files: Array<{\n url: string;\n filename: string;\n headers?: Record<string, string>;\n skipIfCached?: boolean;\n }> = [\n {\n url: `${APPS_SERVICE_URL}/devices/apps/${appId}`,\n filename: \"app.json\",\n skipIfCached: true,\n },\n {\n url: `${APPS_SERVICE_URL}/devices/apps/${appId}/node/${pageId}`,\n filename: \"page.json\",\n },\n {\n url: `${COMPONENTS_CDN_URL}/${appId}/draft/components/${pageId}.js`,\n filename: \"component.js\",\n },\n ];\n\n for (const file of files) {\n // Skip app.json if we have cached data\n if (file.skipIfCached && cachedAppData) {\n console.log(`Using cached ${file.filename} (skipping download)`);\n const filePath = join(tempDir, file.filename);\n await writeFile(\n filePath,\n JSON.stringify(cachedAppData, null, 2),\n \"utf-8\"\n );\n console.log(`✓ Saved ${file.filename} from cache`);\n continue;\n }\n\n try {\n console.log(`Downloading ${file.filename} from ${file.url}...`);\n const content = await downloadFile(file.url, file.headers);\n const filePath = join(tempDir, file.filename);\n await writeFile(filePath, content, \"utf-8\");\n console.log(`✓ Saved ${file.filename}`);\n } catch (error) {\n console.error(`✗ Failed to download ${file.filename}:`, error);\n throw error;\n }\n }\n\n // Read and parse page.json\n const pageJsonPath = join(tempDir, \"page.json\");\n const pageJsonContent = await readFile(pageJsonPath, \"utf-8\");\n const pageResponse = JSON.parse(pageJsonContent);\n\n // Extract page data - API response has it under 'data' field\n let pageData = pageResponse.data || pageResponse;\n\n // Debug: log structure\n console.log(\"Page response keys:\", Object.keys(pageResponse));\n if (pageResponse.data) {\n console.log(\"Page data keys:\", Object.keys(pageResponse.data));\n }\n console.log(\"Has body?\", !!pageData.body);\n console.log(\"Has data.body?\", !!(pageData as any).data?.body);\n\n // If pageData doesn't have body, try using cached app.json or downloading as fallback\n if (!pageData.body && !(pageData as any).data?.body) {\n console.log(\"Page data doesn't have body, trying app.json...\");\n try {\n let appData = cachedAppData;\n\n // If we don't have cached data, download it\n if (!appData) {\n const appUrl = `${APPS_SERVICE_URL}/devices/apps/${appId}`;\n const appContent = await downloadFile(appUrl);\n appData = JSON.parse(appContent);\n } else {\n console.log(\"Using cached app.json data\");\n }\n\n console.log(\"App data keys:\", Object.keys(appData));\n console.log(\n \"App.app keys:\",\n appData?.app ? Object.keys(appData.app) : \"N/A\"\n );\n console.log(\n \"App.app.data keys:\",\n appData?.app?.data ? Object.keys(appData.app.data) : \"N/A\"\n );\n\n // Find the page in app.data.pages\n const pages = appData?.app?.data?.pages || [];\n console.log(`Found ${pages.length} pages in app.json`);\n if (pages.length > 0) {\n console.log(\"First page ID:\", pages[0]?.id);\n }\n\n const page = pages.find((p: any) => p.id === pageId);\n if (page) {\n pageData = page;\n console.log(\"✓ Found page data in app.json\");\n console.log(\"Page from app.json has body?\", !!pageData.body);\n console.log(\n \"Page body length:\",\n Array.isArray(pageData.body) ? pageData.body.length : \"N/A\"\n );\n } else {\n console.warn(`Page ${pageId} not found in app.json`);\n console.warn(\n \"Available page IDs:\",\n pages.map((p: any) => p.id)\n );\n\n // Try using saved-apps as fallback\n const savedPagePath = join(\n process.cwd(),\n \"saved-apps\",\n appId,\n `page-${pageId}.json`\n );\n if (existsSync(savedPagePath)) {\n console.log(\"Trying saved-apps page file...\");\n try {\n const savedPageContent = await readFile(savedPagePath, \"utf-8\");\n const savedPageResponse = JSON.parse(savedPageContent);\n const savedPageData = savedPageResponse.data || savedPageResponse;\n if (savedPageData.body) {\n pageData = savedPageData;\n console.log(\"✓ Found page data in saved-apps\");\n console.log(\n \"Page body length:\",\n Array.isArray(pageData.body) ? pageData.body.length : \"N/A\"\n );\n }\n } catch (error) {\n console.warn(\"Could not load saved-apps page:\", error);\n }\n }\n }\n } catch (error) {\n console.warn(\"Could not load app.json:\", error);\n\n // Try using saved-apps as fallback\n const savedPagePath = join(\n process.cwd(),\n \"saved-apps\",\n appId,\n `page-${pageId}.json`\n );\n if (existsSync(savedPagePath)) {\n console.log(\"Trying saved-apps page file...\");\n try {\n const savedPageContent = await readFile(savedPagePath, \"utf-8\");\n const savedPageResponse = JSON.parse(savedPageContent);\n const savedPageData = savedPageResponse.data || savedPageResponse;\n if (savedPageData.body) {\n pageData = savedPageData;\n console.log(\"✓ Found page data in saved-apps\");\n console.log(\n \"Page body length:\",\n Array.isArray(pageData.body) ? pageData.body.length : \"N/A\"\n );\n }\n } catch (error) {\n console.warn(\"Could not load saved-apps page:\", error);\n }\n }\n }\n }\n\n // Find sliders and data bindings\n const sliders = findSlidersAndDataBindings(pageData);\n\n // Find standalone components with bravo:data tags\n const standaloneComponents = findStandaloneComponents(pageData);\n\n // Extract app name and page name\n let appName = \"Encore App\";\n let pageName = \"Page\";\n\n // Try to get app name from app.json (use cached data if available)\n try {\n let appDataForName = cachedAppData;\n if (!appDataForName) {\n const appJsonPath = join(tempDir, \"app.json\");\n if (existsSync(appJsonPath)) {\n const appJsonContent = await readFile(appJsonPath, \"utf-8\");\n appDataForName = JSON.parse(appJsonContent);\n }\n }\n if (appDataForName) {\n appName = appDataForName?.app?.store?.name || appName;\n console.log(`App name: ${appName}`);\n }\n } catch (error) {\n // Ignore errors, use defaults\n }\n\n // Get page name from page data\n pageName = pageData.name || pageData.id || pageName;\n console.log(`Page name: ${pageName}`);\n\n console.log(`\\nFound ${sliders.length} slider(s):`);\n sliders.forEach((slider, index) => {\n console.log(`\\n Slider ${index + 1}:`);\n console.log(` ID: ${slider.id}`);\n console.log(` Name: ${slider.name}`);\n if (slider.arrayContainer) {\n console.log(\n ` Array Container: ${slider.arrayContainer.name} (${slider.arrayContainer.id})`\n );\n console.log(` Components:`);\n slider.arrayContainer.components.forEach((comp) => {\n console.log(\n ` - ${comp.name} (${comp.id}): ${comp.type} -> prop: ${comp.propName}: ${comp.propType}`\n );\n });\n } else {\n console.log(` No array container found`);\n }\n });\n\n console.log(\n `\\nFound ${standaloneComponents.length} standalone component(s):`\n );\n standaloneComponents.forEach((comp) => {\n console.log(\n ` - ${comp.name} (${comp.id}): ${comp.type} -> prop: ${comp.propName}: ${comp.propType}`\n );\n });\n\n // Find input groups\n const inputGroups = findInputGroups(pageData);\n console.log(`\\nFound ${inputGroups.length} input group(s):`);\n inputGroups.forEach((group, index) => {\n console.log(`\\n Input Group ${index + 1}:`);\n console.log(` Name: ${group.groupName}`);\n console.log(` Type: ${group.groupType}`);\n console.log(` Elements:`);\n group.elements.forEach((el) => {\n console.log(` - ${el.name} (${el.id})`);\n });\n });\n\n // Find forms\n const forms = findForms(pageData);\n\n // Qualify form input prop names to ensure uniqueness\n qualifyFormInputs(forms);\n\n console.log(`\\nFound ${forms.length} form(s):`);\n forms.forEach((form, index) => {\n console.log(`\\n Form ${index + 1}:`);\n console.log(` Name: ${form.formName}`);\n console.log(` ID: ${form.formId}`);\n if (form.submitButtonId) {\n console.log(` Submit Button ID: ${form.submitButtonId}`);\n }\n console.log(` Inputs:`);\n form.inputs.forEach((input) => {\n console.log(` - ${input.name} (${input.id}): ${input.type}`);\n });\n });\n\n // Find standalone select inputs (not in forms)\n const selectInputs = findStandaloneSelectInputs(pageData, forms);\n\n console.log(`\\nFound ${selectInputs.length} standalone select input(s):`);\n selectInputs.forEach((input) => {\n console.log(\n ` - ${input.name} (${input.id}) -> prop: ${\n input.propName\n }, on${input.propName[0].toUpperCase()}${input.propName.slice(1)}Change`\n );\n });\n\n // Find action buttons\n const actionButtons = findActionButtons(pageData);\n\n console.log(`\\nFound ${actionButtons.length} action button(s):`);\n actionButtons.forEach((button) => {\n console.log(\n ` - ${button.name} (${\n button.id\n }) -> on${button.propName[0].toUpperCase()}${button.propName.slice(\n 1\n )}Click (action: ${button.actionType})`\n );\n });\n\n if (\n sliders.length === 0 &&\n standaloneComponents.length === 0 &&\n inputGroups.length === 0 &&\n forms.length === 0 &&\n selectInputs.length === 0 &&\n actionButtons.length === 0\n ) {\n console.warn(\n \"\\n⚠ No sliders, standalone components, input groups, forms, select inputs, or action buttons found. Generating empty wrapper.\"\n );\n }\n\n // Generate component name and directory name\n const { directoryPath, componentName } = generateNames(appName, pageName);\n const directoryName = directoryPath;\n\n // Update output path - always create a directory structure\n if (needsFilenameGeneration) {\n finalOutputPath = join(outputPath, directoryName);\n } else {\n // If a file path was provided, use its directory and create a subdirectory\n const providedDir = dirname(finalOutputPath);\n finalOutputPath = join(providedDir, directoryName);\n }\n\n console.log(`Component directory: ${directoryName}`);\n\n // Generate component code and README\n const componentCode = generateComponentCode(\n appId,\n pageId,\n componentName,\n sliders,\n standaloneComponents,\n inputGroups,\n forms,\n selectInputs,\n actionButtons,\n !!isProduction\n );\n const readmeContent = generateReadme(\n appId,\n pageId,\n appName,\n pageName,\n componentName,\n sliders,\n standaloneComponents,\n inputGroups,\n forms,\n selectInputs,\n actionButtons\n );\n\n // Ensure output directory exists\n if (!existsSync(finalOutputPath)) {\n await mkdir(finalOutputPath, { recursive: true });\n }\n\n // Write files\n if (isProduction) {\n const componentJsPath = join(tempDir, \"component.js\");\n let componentCodeContent = \"\";\n try {\n componentCodeContent = await readFile(componentJsPath, \"utf-8\");\n } catch (e) {\n console.warn(\"Could not read component.js for production build\", e);\n }\n \n let appDataForProd = cachedAppData;\n if (!appDataForProd) {\n try {\n const appJsonPath = join(tempDir, \"app.json\");\n const appJsonContent = await readFile(appJsonPath, \"utf-8\");\n appDataForProd = JSON.parse(appJsonContent);\n } catch(e) {\n console.warn(\"Could not read app.json for production build\", e);\n }\n }\n\n const productionData = {\n app: appDataForProd,\n page: pageData,\n componentCode: componentCodeContent\n };\n await writeFile(join(finalOutputPath, \"data.json\"), JSON.stringify(productionData, null, 2), \"utf-8\");\n console.log(`✓ Generated data.json for production mode`);\n }\n const indexPath = join(finalOutputPath, \"index.tsx\");\n const readmePath = join(finalOutputPath, \"README.md\");\n\n await writeFile(indexPath, componentCode, \"utf-8\");\n await writeFile(readmePath, readmeContent, \"utf-8\");\n\n console.log(`\\n✓ Generated wrapper component at: ${indexPath}`);\n console.log(`✓ Generated documentation at: ${readmePath}`);\n}\n\nfunction printUsage() {\n console.log(`\nUsage: generate-wrapper.ts <appId> [pageId] <outputPath>\n\nArguments:\n appId The Encore app ID\n pageId The Encore page ID (optional - if omitted, generates wrappers for ALL pages)\n outputPath Path where the generated TSX file(s) should be saved\n\nEnvironment variables:\n APPS_SERVICE_URL Base URL for the apps service (default: http://localhost:3000)\n\nExample:\n generate-wrapper.ts 01KA964B1T6KCKSKCNMYSTKRKZ 01KA964B2F42MN4WGCYDTG1Y70 ./src/components/MyEncoreApp.tsx\n generate-wrapper.ts 01KA964B1T6KCKSKCNMYSTKRKZ ./src/components/ (Generates all pages)\n`);\n}\n\n\nexport async function runGenerate(args: string[]) {\n const isProduction = args.includes(\"--production\");\n const cleanArgs = args.filter((arg) => arg !== \"--production\");\n\n if (cleanArgs.length < 2 || cleanArgs.includes(\"--help\") || cleanArgs.includes(\"-h\")) {\n printUsage();\n process.exit(cleanArgs.includes(\"--help\") || cleanArgs.includes(\"-h\") ? 0 : 1);\n }\n\n // Handle 2 arguments: appId, outputPath (generate for all pages)\n if (cleanArgs.length === 2) {\n const [appId, outputPath] = cleanArgs;\n\n try {\n const { pages, appData } = await getAppPages(appId);\n console.log(`Found ${pages.length} pages.`);\n\n if (pages.length === 0) {\n console.warn(\"No pages found for this app.\");\n return;\n }\n\n // Cache app.json data and reuse it for all pages\n console.log(\n `Caching app.json data for reuse across ${pages.length} page(s)...`\n );\n\n for (const page of pages) {\n if (!page.id) continue;\n console.log(`\\n----------------------------------------`);\n console.log(`Processing page: ${page.name || \"Unnamed\"} (${page.id})`);\n console.log(`----------------------------------------`);\n try { await generateWrapper({\n appId,\n pageId: page.id,\n outputPath,\n cachedAppData: appData,\n isProduction\n });\n } catch (error) {\n console.warn(`Error with page:`, error instanceof Error ? error.message : error);\n }\n }\n } catch (error) {\n console.error(\"\\nError:\", error instanceof Error ? error.message : error);\n process.exit(1);\n }\n return;\n }\n\n const [appId, pageId, outputPath] = cleanArgs;\n\n if (!appId || !pageId || !outputPath) {\n console.error(\"Error: Missing required arguments\");\n printUsage();\n process.exit(1);\n }\n\n try {\n await generateWrapper({ appId, pageId, outputPath, isProduction });\n } catch (error) {\n console.error(\"\\nError:\", error instanceof Error ? error.message : error);\n process.exit(1);\n }\n}\n\n"],"names":["dotenv","APPS_SERVICE_URL","CONST_APPS_SERVICE_URL","COMPONENTS_CDN_URL","CONST_COMPONENTS_CDN_URL","downloadFile","url","headers","response","sanitizePropName","name","cleaned","word","index","normalizedWord","firstChar","rest","generateQualifiedPropName","componentName","parentPath","baseName","validParentParts","part","findMinimalDistinguishingPath","thisPath","otherPaths","commonPrefixLength","maxCommonLength","i","thisPart","otherPath","distinguishingSuffix","suffixLength","thisSuffix","otherSuffix","arraysEqual","a","b","val","idx","getComponentPropType","componentType","_componentName","getComponentPropName","findSlidersAndDataBindings","pageData","sliders","traverse","node","path","findArrayContainer","containerNode","arrayContainer","slider","findDataComponents","comp","imageComponents","basePropName","propType","components","currentParentPath","isGenericFrame","child","container","c","imageComp","propNameGroups","compWithPath","group","_baseName","minimalPath","hasDuplicates","iteration","maxIterations","qualifiedNameGroups","dupGroup","_qualifiedName","fullPath","otherFullPaths","p","foundUnique","expandedPath","testQualifiedName","otherComp","otherFullPath","otherCommonPrefixLength","otherExpandedPath","otherQualifiedName","finalQualifiedNameGroups","finalDupGroup","finalQualifiedName","imageName","compName","body","findStandaloneComponents","sliderIds","collectSliderIds","parentId","currentId","findInputGroups","groupsMap","inputGroupTag","tag","parts","groupType","groupName","findForms","forms","parentContainer","isContainer","isNamedForm","hasSubmitAction","submitButtonId","checkForSubmitAction","n","findInputs","inputs","findStandaloneSelectInputs","selectInputs","formInputIds","form","input","qualifySelectInputs","inputWithPath","findActionButtons","buttons","hasActionTag","hasActions","actionType","actionTag","qualifyActionButtons","button","buttonWithPath","qualifyFormInputs","otherInput","generateComponentCode","appId","pageId","standaloneComponents","inputGroups","actionButtons","isProduction","propTypes","controlPropTypes","inputGroupPropTypes","formPropTypes","selectInputPropTypes","actionButtonPropTypes","propName","formDataInterfaces","formPropName","formDataTypeName","formDataProps","inputPropName","inputType","capitalizedPropName","itemTypeName","sliderPropName","allPropTypes","hasProps","propsInterface","itemTypes","s","itemProps","formDataTypes","dataMapping","controlMapping","propKey","itemMapping","controlPropName","controlEntry","repeatingContainerControlsCode","inputGroupMapping","inputGroupHandlers","handlerPropName","formDataEntries","inputGroupsCode","onActionCode","propsParameter","propsInterfaceSection","generateReadme","appName","pageName","componentDocs","controlDocs","selectInputDocs","actionButtonDocs","compDocs","dataPropsSection","controlPropsSection","inputGroupDocs","elementsList","el","inputGroupPropsSection","formDocs","inputsList","formPropsSection","optionsPropName","selectInputPropsSection","actionButtonPropsSection","propsSection","usageExample","controlExample","firstSlider","generateNames","appCamel","pageCamel","appPascal","pagePascal","join","getAppPages","content","appData","error","generateWrapper","outputPath","cachedAppData","finalOutputPath","needsFilenameGeneration","pathExt","stat","tempDir","existsSync","mkdir","files","file","filePath","writeFile","pageJsonPath","pageJsonContent","readFile","pageResponse","appUrl","appContent","pages","page","savedPagePath","savedPageContent","savedPageResponse","savedPageData","appDataForName","appJsonPath","appJsonContent","directoryPath","directoryName","providedDir","dirname","componentCode","readmeContent","componentJsPath","componentCodeContent","e","appDataForProd","productionData","indexPath","readmePath","printUsage","runGenerate","args","cleanArgs","arg"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"generate.js","sources":["../../../src/cli/commands/generate.ts"],"sourcesContent":["import { promises as fs } from \"fs\";\nimport { join, dirname } from \"path\";\nimport { existsSync } from \"fs\";\nimport * as dotenv from \"dotenv\";\nimport {\n CONST_APPS_SERVICE_URL,\n CONST_COMPONENTS_CDN_URL,\n} from \"../../../constants\";\nimport {\n findSlidersAndDataBindings,\n findStandaloneComponents,\n findInputGroups,\n findForms,\n findStandaloneSelectInputs,\n findActionButtons,\n qualifyFormInputs,\n generateComponentCode,\n generateReadme,\n sanitizePropName,\n} from \"../../codegen\";\n\nconst { writeFile, mkdir, readFile } = fs;\n\ndotenv.config();\n\n// Default apps service URL (can be overridden with APPS_SERVICE_URL env var)\nconst APPS_SERVICE_URL =\n process.env.APPS_SERVICE_URL ||\n process.env.VITE_APPS_SERVICE_URL ||\n CONST_APPS_SERVICE_URL ||\n \"https://apps-service-dev.bravostudio.app\";\nconsole.log(`Using APPS_SERVICE_URL: ${APPS_SERVICE_URL}`);\nconst COMPONENTS_CDN_URL =\n CONST_COMPONENTS_CDN_URL || \"https://apps-public-dev.bravostudio.app\";\n\nasync function downloadFile(\n url: string,\n headers?: Record<string, string>\n): Promise<string> {\n const response = await fetch(url, {\n headers: headers || {},\n });\n\n if (!response.ok) {\n throw new Error(\n `Failed to download ${url}: ${response.status} ${response.statusText}`\n );\n }\n\n return await response.text();\n}\n\nfunction generateNames(\n appName: string,\n pageName: string\n): { directoryPath: string; componentName: string } {\n const appCamel = sanitizePropName(appName);\n const pageCamel = sanitizePropName(pageName);\n // Capitalize first letter for PascalCase\n const appPascal = appCamel.charAt(0).toUpperCase() + appCamel.slice(1);\n const pagePascal = pageCamel.charAt(0).toUpperCase() + pageCamel.slice(1);\n return {\n directoryPath: join(appPascal, pagePascal),\n componentName: pagePascal,\n };\n}\n\nasync function getAppPages(\n appId: string\n): Promise<{ pages: any[]; appData: any }> {\n const url = `${APPS_SERVICE_URL}/devices/apps/${appId}`;\n console.log(`Fetching app data from ${url}...`);\n try {\n const content = await downloadFile(url);\n const appData = JSON.parse(content);\n const pages = appData?.app?.data?.pages || [];\n return { pages, appData };\n } catch (error) {\n console.error(\"Failed to fetch app data:\", error);\n throw error;\n }\n}\n\nasync function generateWrapper({\n appId,\n pageId,\n outputPath,\n cachedAppData,\n isProduction,\n}: {\n appId: string;\n pageId: string;\n outputPath: string;\n cachedAppData?: any;\n isProduction?: boolean;\n}) {\n console.log(`Generating wrapper for app: ${appId}, page: ${pageId}`);\n\n // Determine final output path - we'll update it after we get app/page names\n let finalOutputPath = outputPath;\n let needsFilenameGeneration = false;\n const pathExt = outputPath.split(\".\").pop()?.toLowerCase();\n if (\n pathExt !== \"tsx\" &&\n pathExt !== \"ts\" &&\n pathExt !== \"jsx\" &&\n pathExt !== \"js\"\n ) {\n // Path doesn't have a file extension, treat as directory\n const { stat } = await import(\"fs/promises\");\n try {\n const pathStats = await stat(outputPath);\n if (pathStats.isDirectory()) {\n needsFilenameGeneration = true;\n }\n } catch {\n // Path doesn't exist, check if it looks like a directory (no extension)\n if (!pathExt || outputPath.endsWith(\"/\")) {\n needsFilenameGeneration = true;\n }\n }\n }\n\n if (needsFilenameGeneration) {\n console.log(\n `Output path is a directory, will generate filename from app/page names`\n );\n }\n\n console.log(`Output path: ${outputPath}`);\n\n // Create temp directory for downloaded files\n const tempDir = join(process.cwd(), \".temp-bravo\", appId, pageId);\n if (!existsSync(tempDir)) {\n await mkdir(tempDir, { recursive: true });\n }\n\n // Download files (skip app.json if we have cached data)\n const files: Array<{\n url: string;\n filename: string;\n headers?: Record<string, string>;\n skipIfCached?: boolean;\n }> = [\n {\n url: `${APPS_SERVICE_URL}/devices/apps/${appId}`,\n filename: \"app.json\",\n skipIfCached: true,\n },\n {\n url: `${APPS_SERVICE_URL}/devices/apps/${appId}/node/${pageId}`,\n filename: \"page.json\",\n },\n {\n url: `${COMPONENTS_CDN_URL}/${appId}/draft/components/${pageId}.js`,\n filename: \"component.js\",\n },\n ];\n\n for (const file of files) {\n // Skip app.json if we have cached data\n if (file.skipIfCached && cachedAppData) {\n console.log(`Using cached ${file.filename} (skipping download)`);\n const filePath = join(tempDir, file.filename);\n await writeFile(\n filePath,\n JSON.stringify(cachedAppData, null, 2),\n \"utf-8\"\n );\n console.log(`✓ Saved ${file.filename} from cache`);\n continue;\n }\n\n try {\n console.log(`Downloading ${file.filename} from ${file.url}...`);\n const content = await downloadFile(file.url, file.headers);\n const filePath = join(tempDir, file.filename);\n await writeFile(filePath, content, \"utf-8\");\n console.log(`✓ Saved ${file.filename}`);\n } catch (error) {\n console.error(`✗ Failed to download ${file.filename}:`, error);\n throw error;\n }\n }\n\n // Read and parse page.json\n const pageJsonPath = join(tempDir, \"page.json\");\n const pageJsonContent = await readFile(pageJsonPath, \"utf-8\");\n const pageResponse = JSON.parse(pageJsonContent);\n\n // Extract page data - API response has it under 'data' field\n let pageData = pageResponse.data || pageResponse;\n\n // If pageData doesn't have body, try using cached app.json or downloading as fallback\n if (!pageData.body && !(pageData as any).data?.body) {\n console.log(\"Page data doesn't have body, trying app.json...\");\n try {\n let appData = cachedAppData;\n\n // If we don't have cached data, download it\n if (!appData) {\n const appUrl = `${APPS_SERVICE_URL}/devices/apps/${appId}`;\n const appContent = await downloadFile(appUrl);\n appData = JSON.parse(appContent);\n }\n\n // Find the page in app.data.pages\n const pages = appData?.app?.data?.pages || [];\n const page = pages.find((p: any) => p.id === pageId);\n if (page) {\n pageData = page;\n console.log(\"✓ Found page data in app.json\");\n }\n } catch (error) {\n console.warn(\"Could not load app.json:\", error);\n }\n }\n\n // Find components using extracted logic\n const sliders = findSlidersAndDataBindings(pageData);\n const standaloneComponents = findStandaloneComponents(pageData);\n const inputGroups = findInputGroups(pageData);\n const forms = findForms(pageData);\n\n // Qualify form input prop names\n qualifyFormInputs(forms);\n\n const selectInputs = findStandaloneSelectInputs(pageData, forms);\n const actionButtons = findActionButtons(pageData);\n\n // Extract app name and page name\n let appName = \"Encore App\";\n let pageName = \"Page\";\n\n try {\n let appDataForName = cachedAppData;\n if (!appDataForName) {\n const appJsonPath = join(tempDir, \"app.json\");\n if (existsSync(appJsonPath)) {\n const appJsonContent = await readFile(appJsonPath, \"utf-8\");\n appDataForName = JSON.parse(appJsonContent);\n }\n }\n if (appDataForName) {\n appName = appDataForName?.app?.store?.name || appName;\n }\n } catch (error) {\n // Ignore errors, use defaults\n }\n\n pageName = pageData.name || pageData.id || pageName;\n\n // Generate component name and directory name\n const { directoryPath, componentName } = generateNames(appName, pageName);\n const directoryName = directoryPath;\n\n // Update output path\n if (needsFilenameGeneration) {\n finalOutputPath = join(outputPath, directoryName);\n } else {\n const providedDir = dirname(finalOutputPath);\n finalOutputPath = join(providedDir, directoryName);\n }\n\n // Generate component code and README\n const componentCode = generateComponentCode(\n appId,\n pageId,\n componentName,\n sliders,\n standaloneComponents,\n inputGroups,\n forms,\n selectInputs,\n actionButtons,\n !!isProduction\n );\n\n const readmeContent = generateReadme(\n appId,\n pageId,\n appName,\n pageName,\n componentName,\n sliders,\n standaloneComponents,\n inputGroups,\n forms,\n selectInputs,\n actionButtons\n );\n\n // Ensure output directory exists\n if (!existsSync(finalOutputPath)) {\n await mkdir(finalOutputPath, { recursive: true });\n }\n\n // Write files\n if (isProduction) {\n const componentJsPath = join(tempDir, \"component.js\");\n let componentCodeContent = \"\";\n try {\n componentCodeContent = await readFile(componentJsPath, \"utf-8\");\n } catch (e) {}\n\n let appDataForProd = cachedAppData;\n if (!appDataForProd) {\n try {\n const appJsonPath = join(tempDir, \"app.json\");\n const appJsonContent = await readFile(appJsonPath, \"utf-8\");\n appDataForProd = JSON.parse(appJsonContent);\n } catch (e) {}\n }\n\n const productionData = {\n app: appDataForProd,\n page: pageData,\n componentCode: componentCodeContent,\n };\n await writeFile(\n join(finalOutputPath, \"data.json\"),\n JSON.stringify(productionData, null, 2),\n \"utf-8\"\n );\n }\n\n const indexPath = join(finalOutputPath, \"index.tsx\");\n const readmePath = join(finalOutputPath, \"README.md\");\n\n await writeFile(indexPath, componentCode, \"utf-8\");\n await writeFile(readmePath, readmeContent, \"utf-8\");\n\n console.log(`✓ Generated wrapper component at: ${indexPath}`);\n}\n\nfunction printUsage() {\n console.log(`\nUsage: generate-wrapper.ts <appId> [pageId] <outputPath>\n\nArguments:\n appId The Encore app ID\n pageId The Encore page ID (optional - if omitted, generates wrappers for ALL pages)\n outputPath Path where the generated TSX file(s) should be saved\n\nEnvironment variables:\n APPS_SERVICE_URL Base URL for the apps service (default: http://localhost:3000)\n\nExample:\n generate-wrapper.ts 01KA964B1T6KCKSKCNMYSTKRKZ 01KA964B2F42MN4WGCYDTG1Y70 ./src/components/MyEncoreApp.tsx\n`);\n}\n\nexport async function runGenerate(args: string[]) {\n const isProduction = args.includes(\"--production\");\n const cleanArgs = args.filter((arg) => arg !== \"--production\");\n\n if (\n cleanArgs.length < 2 ||\n cleanArgs.includes(\"--help\") ||\n cleanArgs.includes(\"-h\")\n ) {\n printUsage();\n process.exit(\n cleanArgs.includes(\"--help\") || cleanArgs.includes(\"-h\") ? 0 : 1\n );\n }\n\n if (cleanArgs.length === 2) {\n const [appId, outputPath] = cleanArgs;\n\n try {\n const { pages, appData } = await getAppPages(appId);\n if (pages.length === 0) {\n console.warn(\"No pages found for this app.\");\n return;\n }\n\n for (const page of pages) {\n if (!page.id) continue;\n try {\n await generateWrapper({\n appId,\n pageId: page.id,\n outputPath,\n cachedAppData: appData,\n isProduction,\n });\n } catch (error) {\n console.warn(\n `Error with page ${page.id}:`,\n error instanceof Error ? error.message : error\n );\n }\n }\n } catch (error) {\n console.error(\"\\nError:\", error instanceof Error ? error.message : error);\n process.exit(1);\n }\n return;\n }\n\n const [appId, pageId, outputPath] = cleanArgs;\n\n try {\n await generateWrapper({ appId, pageId, outputPath, isProduction });\n } catch (error) {\n console.error(\"\\nError:\", error instanceof Error ? error.message : error);\n process.exit(1);\n }\n}\n"],"names":["writeFile","mkdir","readFile","fs","dotenv.config","APPS_SERVICE_URL","CONST_APPS_SERVICE_URL","COMPONENTS_CDN_URL","CONST_COMPONENTS_CDN_URL","downloadFile","url","headers","response","generateNames","appName","pageName","appCamel","sanitizePropName","pageCamel","appPascal","pagePascal","join","getAppPages","appId","content","appData","error","generateWrapper","pageId","outputPath","cachedAppData","isProduction","finalOutputPath","needsFilenameGeneration","pathExt","stat","tempDir","existsSync","files","file","filePath","pageJsonPath","pageJsonContent","pageResponse","pageData","appUrl","appContent","page","p","sliders","findSlidersAndDataBindings","standaloneComponents","findStandaloneComponents","inputGroups","findInputGroups","forms","findForms","qualifyFormInputs","selectInputs","findStandaloneSelectInputs","actionButtons","findActionButtons","appDataForName","appJsonPath","appJsonContent","directoryPath","componentName","directoryName","providedDir","dirname","componentCode","generateComponentCode","readmeContent","generateReadme","componentJsPath","componentCodeContent","appDataForProd","productionData","indexPath","readmePath","printUsage","runGenerate","args","cleanArgs","arg","pages"],"mappings":"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"}
|