Skip to content
Snippets Groups Projects
Commit 7f8077d8 authored by richard.petersen's avatar richard.petersen :sailboat:
Browse files

Feature: JS Files will trigger custom events to make sure, css is loaded

parent 9b33933e
No related branches found
No related tags found
No related merge requests found
import { describe, it, expect, beforeAll, afterAll, beforeEach, afterEach } from '@jest/globals'
import mockfs from 'mock-fs'
import request from 'supertest'
import { createApp } from '../src/createApp'
import { createMockServer, generateSimpleViteManifest, getRandomPort } from './util.js'
describe('JS files with dependencies contain events', () => {
let app
let mockserver
const port = getRandomPort()
beforeAll(() => {
mockfs({
'./config/manifests': {
'urls.yaml': `manifests:
- http://localhost:${port}/api/manifest.json`
}
})
app = createApp()
})
afterAll(() => {
mockfs.restore()
})
beforeEach(async () => {
mockserver = await createMockServer({ port })
mockserver.respondWith({
'/api/manifest.json': generateSimpleViteManifest({
'example.js': {},
'main.css': {},
'index.html': {
file: 'index.html.js',
isEntry: true,
imports: ['example.js'],
css: ['main.css']
}
}),
'/example.js': (req, res) => res.setHeader('content-type', 'application/javascript').status(200).send('this is example'),
'/index.html.js': (req, res) => res.setHeader('content-type', 'application/javascript').status(200).send('console.log("this is index.html.js")'),
'/main.css': (req, res) => res.setHeader('content-type', 'text/css').status(200).send('.foo { color: #000; }'),
'/index.html': (req, res) => res.setHeader('content-type', 'text/html').status(200).send('<html><head></head><body>it\'s me</body></html>')
})
await request(app).get('/ready')
})
afterEach(() => {
mockserver.close()
process.env.CACHE_TTL = 30000
})
it('javascript file contains dispatcher for dependencies', async () => {
const response = await request(app).get('/index.html.js')
expect(response.statusCode).toBe(200)
expect(response.headers.dependencies).toEqual('main.css')
expect(response.text).toEqual('console.log("this is index.html.js")\n/*injected by manifest-service*/document.dispatchEvent(new CustomEvent("load-css",{detail:{css:["main.css"]}}))')
})
})
......@@ -3,13 +3,20 @@ import crypto from 'crypto'
import { config } from './config.js'
import promClient from 'prom-client'
import { getLogger } from '@open-xchange/logging'
import { isJSFile } from './util.js'
const logger = getLogger()
async function fetchData (path, baseUrl) {
async function fetchData (path, baseUrl, appendix) {
const response = await fetch(new URL(path, baseUrl))
if (!response.ok) throw new Error(`Error fetching file: ${path}`)
const content = Buffer.from(await response.arrayBuffer())
const resBuffer = await response.arrayBuffer()
const appendixLength = appendix?.length || 0
const content = Buffer.alloc(resBuffer.byteLength + appendixLength)
content.fill(Buffer.from(resBuffer), 0, resBuffer.byteLength)
if (appendix) content.write(appendix, resBuffer.byteLength)
const sha256Sum = crypto.createHash('sha256').update(content).digest('base64')
return [path, {
'content-type': response.headers.get('content-type'),
......@@ -49,7 +56,12 @@ class FileCache {
logger.error(`could not find manifest for "${file}"`)
return null
}
return await fetchData(file, manifest.meta.baseUrl)
let appendix
if (manifest.css && isJSFile(file)) {
const cssString = manifest.css.map(file => `"${file}"`).join(',')
appendix = `\n/*injected by manifest-service*/document.dispatchEvent(new CustomEvent("load-css",{detail:{css:[${cssString}]}}))`
}
return await fetchData(file, manifest.meta.baseUrl, appendix)
} catch (e) {
fileErrorCounter.inc()
logger.error(e)
......
import path from 'path'
// totaly awesome hash function. Do not use this for encryption (crypto.subtle.digest etc would be overkill for this)
export function hash (array) {
const string = JSON.stringify(array)
......@@ -14,3 +16,8 @@ export function hash (array) {
return new Uint32Array([hash]).toString()
}
export function isJSFile (name) {
const extname = path.extname(name)
return extname === '.js'
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment