Skip to content
Snippets Groups Projects
util.js 4.2 KiB
Newer Older
david.bauer's avatar
david.bauer committed
/**
 * @copyright Copyright (c) Open-Xchange GmbH, Germany <info@open-xchange.com>
 * @license AGPL-3.0
 *
 * This code is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with OX App Suite. If not, see <https://www.gnu.org/licenses/agpl-3.0.txt>.
 *
 * Any use of the work other than as authorized under this license or copyright law is prohibited.
 */

import * as td from 'testdouble'
import { register } from 'prom-client'
import RedisMock from 'ioredis-mock'
import zlib from 'node:zlib'
richard.petersen's avatar
richard.petersen committed
import yaml from 'js-yaml'
import fastify from 'fastify'
import autoLoad from '@fastify/autoload'
import sensible from '@fastify/sensible'
import urlData from '@fastify/url-data'
import formbody from '@fastify/formbody'

import { fileURLToPath } from 'node:url'
import { dirname, join } from 'node:path'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)
richard.petersen's avatar
richard.petersen committed
export function generateSimpleViteManifest (mapping) {
  const viteManifest = {}
  for (const [file, value] of Object.entries(mapping)) {
richard.petersen's avatar
richard.petersen committed
    viteManifest[file] = {
      file,
      meta: typeof value === 'string' ? { manifests: [{ namespace: value }] } : {}
richard.petersen's avatar
richard.petersen committed
    }
    if (typeof value === 'object') Object.assign(viteManifest[file], value)
richard.petersen's avatar
richard.petersen committed
  }
  return viteManifest
}
  return td.replaceEsm('fs/promises', {}, {
richard.petersen's avatar
richard.petersen committed
      return yaml.dump(obj)
  })
}

export function mockFetch (servers = {}) {
  td.replace(global, 'fetch', async function ({ origin, pathname }, ...args) {
    const response = servers[origin]?.[pathname]
    if (response === undefined) return new Response('', { status: 404 })
    if (response instanceof Function) return response.apply(this, arguments)

    if (typeof response === 'object') {
      return new Response(JSON.stringify(response), {
        status: 200,
        headers: {
          'Content-Type': 'application/json'
        }
      })
    }
    return new Response(response, { status: 200 })
  })
}

export async function mockRedis (data = {}, isEnabled = true) {
  const mock = {
    isReady () { return Promise.resolve() },
    isEnabled () { return isEnabled },
    createClient () { return new RedisMock() },
    client: new RedisMock(data)
  await td.replaceEsm('../src/redis.js', mock)
export async function injectApp (appRoot = '/') {
  register.clear()
  process.env.APP_ROOT = appRoot
  const { configMap } = await import('../src/config_map.js')
  const { getLatestVersion } = await import('../src/version.js')

  await configMap.load()
  await getLatestVersion()
  const app = fastify({ disableRequestLogging: true })
  app.register(sensible)
  app.register(urlData)
  app.register(formbody)
  const autoLoadOptions = { dir: join(__dirname, '../src/routes'), autoHooks: true }
  if (appRoot) autoLoadOptions.options = { prefix: String(appRoot).replace(/\/$/, '') }
  app.register(autoLoad, autoLoadOptions)

export async function brotliParser (res, cb) {
  const brotli = zlib.createBrotliDecompress()
  let buffer = Buffer.from('')
  res.pipe(brotli)
  brotli.on('data', chunk => (buffer = Buffer.concat([buffer, chunk])))
  brotli.on('end', () => {
    let result = buffer.toString()
    if (res.headers['content-type'].startsWith('application/json')) {
      result = JSON.parse(result)
    }
    cb(null, result)
  })
}
export async function decompressBrotli (encodedData) {
  const compressedData = Buffer.from(encodedData)
  return new Promise((resolve, reject) => {
    zlib.brotliDecompress(compressedData, (err, data) => {
      if (err) reject(err)
      else resolve(JSON.parse(data.toString('utf8')))
    })
  })
}

export async function wait (timeout) {
  return new Promise(resolve => setTimeout(resolve, timeout))
}