elite-dangerous-local-journal-reader¶
Audience: Agent
Purpose¶
Desktop (Tauri 2) application that watches Elite Dangerous journal *.log lines and sidecar JSON on disk, wraps each update in a BridgeEnvelope, and streams it to an embedded web UI over Tauri IPC edos:file:event. An injected bridge script re-emits the same payload as browser postMessage / CustomEvent using IFM outer name edos-file-event (plus legacy elite-event / elite-status shorthands). Complements the hosted elite-dangerous-remote-journal-reader popup: same shared types and message strings, different host (native shell vs browser + File System Access API).
Tech stack¶
- Shell: Rust, Tauri 2 (
src-tauri/) - Bridge helpers (published patterns): TypeScript
src/edosBridge.ts— depends on@howfe/elite-dangerous-event-typesand@tauri-apps/apionly inside this repo; copied or imported bridge listeners in other web apps must not bundle Tauri (see contract doc). - Optional tooling: Node
build-service/— seeelite-dangerous-local-journal-reader/docs/build-service.md.
Layout¶
| Path | Role |
|---|---|
src-tauri/src/bridge.rs |
EVENT_NAME = edos:file:event; string constants aligned with MessageTypeEnum (elite-event, elite-status) |
src/edosBridge.ts |
listenEliteEventFromBridge, listenEdosFileEventFromBridge, debug helpers; re-exports envelope types/constants |
elite-dangerous-local-journal-reader/docs/bridge-contract.md |
Contract for embedded apps (event names, payloads, security) |
Integration points¶
@howfe/elite-dangerous-event-types—EdosFileEventEnvelope,EDOS_FILE_EVENT_MESSAGE(edos-file-event),TAURI_EDOS_FILE_EVENT_CHANNEL(edos:file:event).@howfe/inter-frame-messenger— same outereventstrings for parity with remote reader / surface map IPC (IPC.md).- Embedded URL — which web app loads inside the webview is a product/host choice; TODO: Verify
src-tauri/tauri.conf.json/ capabilities for allowedremote.urlswhen documenting a specific pairing.
URL-wired “install on desktop” (build service)¶
The Node build-service/ is a small HTTP API that produces a single Windows .exe with your hosted web app URL embedded in a PE trailer (after marker <<<EDOS_BRIDGE_TAIL_V1>>>), so the Tauri shell opens that URL in the webview without extra config files. Full contract, cache keys, env vars, and Docker build context are in elite-dangerous-local-journal-reader/docs/build-service.md; machine-readable API in elite-dangerous-local-journal-reader/build-service/api/openapi.yaml; URL resolution order (CLI, env, tail, compile-time) in elite-dangerous-local-journal-reader/README.md.
Typical “Get desktop bridge” flow for a hosted web UI
- Choose
appUrl= the canonical HTTPS URL of the web app you want inside the bridge (the same deployment users already open in the browser). - Call
POST /buildwith JSON{ "appUrl": "<that url>", "targetPlatform": "windows-x64" }on the build-service host, orGET /build?appUrl=…(query form is bookmark-friendly; GET still performs build or cache lookup — do not treat it as a safe prefetch). - Read JSON: use
artifactDownloadPath(path only) on the same host as the API — production deployment for this repo’s build-service:https://app.edos.howfe.org${artifactDownloadPath}— to download the wired executable (Content-Disposition: attachmentonGET /artifacts/<file>). - In the UI, start the download from the hosted app (see Download filename below). Avoid sending users straight to the artifact URL with
location.hrefor a plain<a href>if you want a short, product-specific save name.
Download filename (hosted “Get desktop bridge” buttons)¶
GET /artifacts/<file> always uses a deterministic server file name (for example edos-local-journal-bridge-0.1.0-012d749e40c3.exe). That string is the on-disk cache key, not a product marketing name. Each hosted app chooses the name shown in the user’s Downloads folder when implementing its download button.
Recommended (works cross-origin): after step 2–3, fetch the artifact bytes from the build-service origin, then trigger save with a programmatic link and download:
const BUILD_SERVICE_ORIGIN = 'https://app.edos.howfe.org';
/** Per-app: e.g. `edam.exe` (surface map), `edjev.exe` (EDJEV). */
const DESKTOP_BRIDGE_FILENAME = 'edjev.exe';
async function downloadDesktopBridge(appUrl: string): Promise<void> {
const buildRes = await fetch(
`${BUILD_SERVICE_ORIGIN}/build?${new URLSearchParams({
appUrl,
targetPlatform: 'windows-x64',
})}`,
{ headers: { Accept: 'application/json' }, cache: 'no-store' },
);
const build = (await buildRes.json()) as { artifactDownloadPath?: string };
if (!buildRes.ok || !build.artifactDownloadPath?.startsWith('/')) {
throw new Error('Build request failed or missing artifactDownloadPath');
}
const artifactUrl = `${BUILD_SERVICE_ORIGIN}${build.artifactDownloadPath}`;
const fileRes = await fetch(artifactUrl);
if (!fileRes.ok) {
throw new Error(`Artifact download failed (${fileRes.status})`);
}
const blob = await fileRes.blob();
const objectUrl = URL.createObjectURL(blob);
const anchor = document.createElement('a');
anchor.href = objectUrl;
anchor.download = DESKTOP_BRIDGE_FILENAME;
anchor.click();
URL.revokeObjectURL(objectUrl);
}
Why not only <a download="edjev.exe" href="…/artifacts/…">? The HTML download attribute is often ignored for cross-origin URLs (hosted app on edjev.howfe.org, artifacts on app.edos.howfe.org). Navigating to the artifact URL directly uses the server’s Content-Disposition file name (the long cache key). The blob + download pattern avoids both issues.
Not required in build-service: the API does not need a per-app file name parameter; cache entries stay keyed by appUrl + version metadata. Optional future enhancement: GET /artifacts/...?filename=edjev.exe to override Content-Disposition for bookmark-only flows without JavaScript — TODO: Verify if implemented before relying on it.
Browser / CORS: the Node app (build-service/src/server.ts) does not set CORS. For the public https://app.edos.howfe.org deployment, Traefik (reverse proxy in front of the build-service container) adds CORS headers for browser fetch to /build and /artifacts; change policy there if a hosted SPA’s preflight still fails.
Extension points¶
- Add or adjust watched sources in Rust (
source_registry, watchers) and keepSourceType/EdosBridgeSourceKindaligned (elite-dangerous-event-types/edosEnvelope.ts). build-service/— OpenAPI-driven packaging flow per project-local docs.
Pitfalls / checks¶
- Do not require
@tauri-apps/apiin generic web apps; only the shell uses invoke/listen — see bridge-contract.md. - Origin filtering — embedded listeners should pass
expectedOrigin: window.location.originwhere applicable (edosBridge.ts). - Rust ↔ TypeScript —
BridgeEnvelopeuses camelCase JSON (serde(rename_all = "camelCase")); matchEdosFileEventEnvelopefields.
Related docs¶
- elite-dangerous-journal-event-viewer — example webview
appUrl(edjev); installer/buildcalls go tohttps://app.edos.howfe.org(this repo’s build-service deployment — REPOS.md) - bridge-contract.md — authoritative wire contract
- build-service.md —
/build, caching, PE tail splice, env vars - REPOS.md — run commands
- ARCHITECTURE.md — desktop bridge + sidecars
- IPC.md —
MessageTypeEnumtable