web.service.ts raw

   1  import { TWebMetadata } from '@/types'
   2  import DataLoader from 'dataloader'
   3  
   4  class WebService {
   5    static instance: WebService
   6  
   7    private proxyUrl(url: string): string {
   8      const proxyServer = import.meta.env.VITE_PROXY_SERVER
   9      if (proxyServer) {
  10        return `${proxyServer}/sites/${encodeURIComponent(url)}`
  11      }
  12      return url
  13    }
  14  
  15    private webMetadataDataLoader = new DataLoader<string, TWebMetadata>(
  16      async (urls) => {
  17        return await Promise.all(
  18          urls.map(async (url) => {
  19            try {
  20              const res = await fetch(this.proxyUrl(url))
  21              const html = await res.text()
  22              const parser = new DOMParser()
  23              const doc = parser.parseFromString(html, 'text/html')
  24  
  25              const title =
  26                doc.querySelector('meta[property="og:title"]')?.getAttribute('content') ||
  27                doc.querySelector('title')?.textContent
  28              const description =
  29                doc.querySelector('meta[property="og:description"]')?.getAttribute('content') ||
  30                (doc.querySelector('meta[name="description"]') as HTMLMetaElement | null)?.content
  31              const image = (doc.querySelector('meta[property="og:image"]') as HTMLMetaElement | null)
  32                ?.content
  33  
  34              return { title, description, image }
  35            } catch {
  36              return {}
  37            }
  38          })
  39        )
  40      },
  41      { maxBatchSize: 1 }
  42    )
  43  
  44    constructor() {
  45      if (!WebService.instance) {
  46        WebService.instance = this
  47      }
  48      return WebService.instance
  49    }
  50  
  51    async fetchWebMetadata(url: string) {
  52      return await this.webMetadataDataLoader.load(url)
  53    }
  54  }
  55  
  56  const instance = new WebService()
  57  
  58  export default instance
  59