import { Sink } from './Sink' import { ClientConfig } from '@rondo.dev/client' import { apiLogger } from '../logger' export type GetHeader = (config: Config) => string export type GetFooter = ( config: ClientConfig, stateJSON: string) => string const getHeaderDefault: GetHeader = config => ` ${config.appName}
` const getFooterDefault: GetFooter = (config, state) => `
` export class HTMLSink implements Sink { constructor( protected readonly getHeader: GetHeader = getHeaderDefault, protected readonly getFooter: GetFooter = getFooterDefault, ) { } protected stringifyState(state: State): string { // TODO figure out a better way to escape state JSON return JSON .stringify(state) .replace(/( reactStream: NodeJS.ReadableStream, htmlStream: NodeJS.WritableStream, config: Config, state: State, ): Promise { return new Promise((resolve, reject) => { htmlStream.write(this.getHeader(config)) reactStream.on('error', (err: Error) => { apiLogger.error('Error in React SSR: %s', err.stack) reject(err) }) reactStream.pipe(htmlStream, { end: false }) reactStream.on('end', () => { htmlStream.write(this.getFooter(config, this.stringifyState(state))) htmlStream.end() resolve() }) }) } }