import type { AppContext , Component , VNode , AsyncComponentLoader } from 'vue' ; import { h , getCurrentInstance , createApp , createSSRApp , ssrContextKey , withCtx } from 'vue' ; const newApp = import . meta . env . SSR ? createApp : createSSRApp ; export type Nodes = undefined | VNode < any , any , any > | VNode < any , any , any > [ ] ; export type VueRenderable = AsyncComponentLoader | Component | Nodes | ( ( props ? : any ) => Nodes | Promise < Nodes > ) ; export type VNodeRenderer = ( content : VueRenderable ) => Promise < string > ; export function useVueRenderer ( ) { return withCtx ( ( async ( content ) => { if ( ! content ) return '' ; const { app : _ , provides : appProvides , ... appContext } = getCurrentInstance ( ) ?. appContext || { } as AppContext ; const { [ ssrContextKey ] : ssrContext , ... provides } = appProvides ; if ( isComponent ( content ) || isAsyncComponent ( content ) ) content = h ( content ) ; else if ( isFunction ( content ) ) content = await content ( ) ; const nodes = Array . isArray ( content ) ? content : [ content ] ; const proxyApp = newApp ( { render : ( ) => nodes } ) ; Object . assign ( proxyApp . _context , { ... appContext , provides } ) ; const { renderToString } = await import ( '@vue/server-renderer' ) ; return await renderToString ( proxyApp , ssrContext ) ; } ) as VNodeRenderer , getCurrentInstance ( ) ) as VNodeRenderer ; } function isFunction ( val ) { return typeof val === 'function' ; } function isComponent ( val ) { return isFunction ( val . render ) ; } function isAsyncComponent ( val ) { return Boolean ( val ?. __asyncLoader ) ; }