import { InkscapeRasterizer } from '@swirly/rasterizer-inkscape' ; import { PuppeteerRasterizer } from '@swirly/rasterizer-puppeteer' ; import { IRasterizer , RasterizationRequest , RasterizerName } from '@swirly/types' ; import fastify , { FastifyInstance , FastifyReply , FastifyRequest } from 'fastify' ; import pMemoize from 'p-memoize' ; const rasterizerImpls = { puppeteer : PuppeteerRasterizer , inkscape : InkscapeRasterizer } ; export class RasterizationServer { static readonly RASTERIZER_NAMES = Object . keys ( rasterizerImpls ) as RasterizerName [ ] ; private _port : number ; private _address : string ; private _fastify ? : FastifyInstance ; private _rasterizers : Map < RasterizerName , IRasterizer > ; constructor ( port = 0 , address = null ) { this . _port = port ; this . _address = address != null ? address : '0.0.0.0' ; this . _rasterizers = new Map < RasterizerName , IRasterizer > ( ) ; this . _createRasterizer = pMemoize ( this . _createRasterizer . bind ( this ) , { cachePromiseRejection : true } ) ; } get url ( ) : string { const { address , port } = this . _fastify ! . server . address ( ) as { address : string ; port : number ; } ; return `http://${ address }:${ port }` ; } async start ( ) { this . _fastify = fastify ( ) ; this . _registerRoutes ( ) ; await this . _fastify ! . listen ( this . _port , this . _address ) ; } async stop ( ) { await this . _fastify ! . close ( ) ; const rasterizers = Array . from ( this . _rasterizers . values ( ) ) ; await Promise . all ( rasterizers . map ( async ( rasterizer ) => { await rasterizer . dispose ( ) ; } ) ) ; } _registerRoutes ( ) { this . _fastify ! . get ( '/' , ( request , reply ) => { reply . send ( { } ) ; } ) ; this . _fastify ! . post ( '/rasterize' , async ( request , reply ) => { const { rasterizer , svgXml , width , height , format } = request . body as RasterizationRequest ; const rasterizerImpl = await this . _createRasterizer ( rasterizer ) ; const output = await rasterizerImpl . rasterize ( svgXml , width , height , format ) ; reply . header ( 'content-type' , `image/${ format }` ) ; return output ; } ) ; } async _createRasterizer ( name ) { const RasterizerImpl = rasterizerImpls [ name ] ; const rasterizer = new RasterizerImpl ( ) ; await rasterizer . init ( ) ; this . _rasterizers . set ( name , rasterizer ) ; return rasterizer ; } }