import camelcase from "camelcase" ; import { Manifest , loadString , getResourceModule } from "@kosko/yaml" ; export type { Manifest } ; interface Component { readonly name : string ; readonly text : string ; readonly imports : readonly Import [ ] ; } interface Import { readonly names : readonly string [ ] ; readonly path : string ; } function jsonStringify ( data ) { return JSON . stringify ( data , null , "  " ) ; } async function generateComponent ( manifest ) { const { apiVersion , kind , ... data } = manifest ; const name = camelcase ( kind ) ; const mod = await getResourceModule ( manifest ) ; if ( ! mod ) { return { name , text : jsonStringify ( manifest ) , imports : [ ] } ; } return { name , text : `new ${ mod . export }(${ jsonStringify ( data ) })` , imports : [ { path : mod . path , names : [ mod . export ] } ] } ; } async function generateForList ( items ) { const result = [ ] ; for ( const data of items ) { if ( data . apiVersion === "v1" && data . kind === "List" ) { result . push ( ... ( await generateForList ( data . items as any ) ) ) ; } else { result . push ( await generateComponent ( data ) ) ; } } return result ; } function uniqComponentName ( components ) { const nameMap = { } ; return components . map ( ( component ) => { let name = component . name ; const idx = nameMap [ name ] ; if ( idx ) { nameMap [ name ] ++ ; name += idx ; } else { nameMap [ name ] = 1 ; } return { ... component , name } ; } ) ; } function collectImports ( components ) { const importMap = { } ; for ( const component of components ) { for ( const { path , names } of component . imports ) { if ( ! importMap [ path ] ) importMap [ path ] = new Set ( ) ; for ( const name of names ) { importMap [ path ] . add ( name ) ; } } } return Object . keys ( importMap ) . map ( ( path ) => ( { path , names : [ ... importMap [ path ] . values ( ) ] } ) ) ; } param data export async function migrate ( data ) { const components = uniqComponentName ( await generateForList ( data ) ) ; let output = `"use strict";\n\n` ; for ( const { path , names } of collectImports ( components ) ) { output += `const { ${ names . join ( ", " ) } } = require("${ path }");\n` ; } for ( const { name , text } of components ) { output += `\nconst ${ name } = ${ text };\n` ; } output += `\nmodule.exports = [${ components . map ( ( c ) => c . name ) . join ( ", " ) }];\n` ; return output ; } param input export async function migrateString ( input ) { return migrate ( await loadString ( input ) ) ; }