- Default to a nice `[matrix]` banner
- There is room for improvement here when the Matrix Public Archive gets it's own logo (https://github.com/matrix-org/matrix-public-archive/issues/94) and maybe says "Matrix Public Archive" somewhere in the banner.
- This is good enough for now (and certainly better than downstream previews using the first image on the page).
- For rooms, it will use the room avatar
Part of https://github.com/matrix-org/matrix-public-archive/issues/202
Image is sized to 1200x630 to match conventions of `og:image`.
Crafted the banner image by modifying the header on the room directory homepage and taking a node screenshot. Page zoom @ 175%
- Like getting all of the dependencies for a given entry point
- And the favicons
Also fix the problem where `server/hydrogen-render/render-page-html.js` was calling `getFaviconAssetUrls()` right away before the client build had a chance to generate `dist/manifest.json` and result in `Error: Cannot find module '../../dist/manifest.json'`
- Rename `public` -> `client` so it doesn't get copied automagically as-is (without hashes which we want for cache busting), https://vitejs.dev/guide/assets.html#the-public-directory
- We still build the version files to `public/` so their copied as-is and Vite handles it for us (so we can use `emptyOutDir`)
- Use a multiple entrypoint `.js` Vite build so things can be more intelligently bundled and take less time
- We aren't using library mode because it doesn't minify or bundle assets
- Using hash asset tags for cache busting. Hash of the file included in the file name
- We lookup these hashed assets from `manifest.json` that Vite builds (https://vitejs.dev/guide/backend-integration.html) to serve and preload
- In terms of optimized bundles, I know the current output isn't great now but will have to opt to fix that up separately in the future. Tracked by https://github.com/matrix-org/matrix-public-archive/issues/176
Fixes https://github.com/matrix-org/matrix-public-archive/issues/141
Node.js v19 has `crypto` set on the global already, so this change causes `vmContext.global.crypto` to be assigned only if `vmContext.global.crypto` isn’t already defined.
Otherwise, without this change, the room directory fails to render in Node.js v19+, and instead _"TypeError: Cannot set property crypto of `#<Object>` which has only a getter"_ gets thrown.
This isn't spawning from any previous security issue. Just adding an extra check to help ensure we don't ever regress this in the future.
```
AssertionError [ERR_ASSERTION]: We should not be leaking the `config.matrixAccessToken` to the Hydrogen render function because this will reach the client!
at renderHydrogenToString (matrix-public-archive\server\hydrogen-render\render-hydrogen-to-string.js:24:3)
at renderHydrogenVmRenderScriptToPageHtml (matrix-public-archive\server\hydrogen-render\render-hydrogen-vm-render-script-to-page-html.js:22:36)
at matrix-public-archive\server\routes\room-directory-routes.js:53:28
at processTicksAndRejections (node:internal/process/task_queues:96:5)
```
1. Add surrounding messages to the given messages so we have a full screen of content to make it feel lively even in quiet rooms
- As you scroll around the timeline across different days, the date changes in the URL, calendar, etc
2. Add summary item to the bottom of the timeline that explains if we couldn't find any messages in the specific day requested
- Also allows you to the jump to the next activity in the room. Adds `/:roomId/jump?ts=xxx&dir=[f|b]` to facilitate this.
- Part of https://github.com/matrix-org/matrix-public-archive/issues/46
3. Add developer options modal which is linked from the bottom of the right-panel
- Adds an option so you can debug the `IntersectionObserver` and how it's selecting the active day from the top-edge of the scroll viewport.
- In the future, this will also include a nice little visualization of the backend timing traces
Follow-up to https://github.com/matrix-org/matrix-public-archive/pull/36
Render pipeline separation of concerns:
1. Run in `child_process`
2. Hydrogen render
It's now just a generic `child_process` runner that runs the Hydrogen render in it. This eliminates the windy path of the 1-4 steps that was only held together by the file names themselves.
Follow-up to https://github.com/matrix-org/matrix-public-archive/pull/51
Better `child_process` error handling for a couple scenarios with the finger pointing at it 👉
Also make sure we handle all of these scenarios:
1. Child process fork script throws an `uncaughtException` or `unhandledRejection`
- These are captured and serialized back to the parent and stored in `childErrors` and exposed if we never get a successful rendered HTML response.
2. Child process fails to startup
- Render process is rejected in the `child.on('error', ...` callback
3. 👉 Child process times out and is aborted
- Render process is rejected in the `child.on('error', ...` callback and any `childErrors` encountered are logged
4. 👉 Child process fork script throws an error in scope of in `process.on('message', async (renderOptions) => {`
- Child exits with code 1 and we reject the render process with the error
5. Child process exits with code 1 (error)
- Render process is rejected with any `childError` info
6. Child process exits with code 0 (success) but never sends back any HTML
- We have a `returnedData` data check and any child errors encountered are logged
Add test to make sure the archive doesn't fail when event for event relation is missing and not included in list of provided events. Like if someone is replying to an event that was from long ago out of our range.
In the case of missing relations, Hydrogen does `_loadContextEntryNotInTimeline` because it can't find the event locally which throws an `uncaughtException`. Before https://github.com/matrix-org/matrix-public-archive/pull/51, the `uncaughtException` killed the Hydrogen `child_process` before it could pass back the HTML. Now this PR mainly just adds a test to make sure it works.
```
TypeError: Cannot read properties of undefined (reading 'storeNames')
at TimelineReader.readById (hydrogen-web\target\lib-build\hydrogen.cjs.js:12483:33)
at Timeline._getEventFromStorage (hydrogen-web\target\lib-build\hydrogen.cjs.js:12762:46)
at Timeline._loadContextEntryNotInTimeline (hydrogen-web\target\lib-build\hydrogen.cjs.js:12747:35)
at Timeline._loadContextEntriesWhereNeeded (hydrogen-web\target\lib-build\hydrogen.cjs.js:12741:14)
at Timeline.addEntries (hydrogen-web\target\lib-build\hydrogen.cjs.js:12699:10)
at mountHydrogen (4-hydrogen-vm-render-script.js:204:12)
at 4-hydrogen-vm-render-script.js:353:1
at Script.runInContext (node:vm:139:12)
at _renderHydrogenToStringUnsafe (matrix-public-archive\server\hydrogen-render\3-render-hydrogen-to-string-unsafe.js:102:41)
at async process.<anonymous> (matrix-public-archive\server\hydrogen-render\2-render-hydrogen-to-string-fork-script.js:18:27)
```
Split off from https://github.com/matrix-org/matrix-public-archive/pull/43
Listen to `process.on('uncaughtException', ...)` and handle the async errors ourselves so it no longer fails the child process.
And if the process does exit with status code 1 (error), we have those underlying errors serialized and shown.
We now run the Hydrogen render in a `child_process` so we can exit the whole render process. We still use the `vm` to setup the browser-like globals. With a `vm`, everything continues to run even after it returns and there isn't a way to clean up, stop, kill, terminate the vm script or context so we need this extra `child_process` now to clean up. I don't like the complexity necessary for this though. I wish the `vm` API allowed for this use case. The only way to stop a `vm` is the `timeout` and we want to stop as soon as we return.
Fix https://github.com/matrix-org/matrix-public-archive/issues/34