Files
worldmonitor/scripts/build-sidecar-handlers.mjs
Elie Habib 651cd3d08b feat(desktop): sidecar cloud proxy, domain handlers, and panel fixes (#1454)
* feat(desktop): compile domain handlers + add in-memory sidecar cache

The sidecar was broken for all 23 sebuf/RPC domain routes because
the build script (build-sidecar-handlers.mjs) never existed on main
while package.json already referenced it. This adds the missing script
and an in-memory TTL+LRU cache so the sidecar doesn't need Upstash Redis.

- Add scripts/build-sidecar-handlers.mjs (esbuild multi-entry, 23 domains)
- Add server/_shared/sidecar-cache.ts (500 entries, 50MB max, lazy sweep)
- Modify redis.ts getCachedJson/setCachedJson to use dynamic import for
  sidecar cache when LOCAL_API_MODE=tauri-sidecar (zero cost on Vercel Edge)
- Update tauri.conf.json beforeDevCommand to compile handlers
- Add gitignore pattern for compiled api/*/v1/[rpc].js

* fix(desktop): gate premium panel fetches and open footer links in browser

Skip oref-sirens and telegram-intel HTTP requests on desktop when
WORLDMONITOR_API_KEY is not present. Use absolute URLs for footer
links on desktop so the Tauri external link handler opens them in
the system browser instead of navigating within the webview.

* fix(desktop): cloud proxy, bootstrap timeouts, and panel data fixes

- Set Origin header on cloud proxy requests (fixes 401 from API key validator)
- Strip If-None-Match/If-Modified-Since headers (fixes stale 304 responses)
- Add cloud-preferred routing for market/economic/news/infrastructure/research
- Enable cloud fallback via LOCAL_API_CLOUD_FALLBACK env var in main.rs
- Increase bootstrap timeouts on desktop (8s/12s vs 3s/5s) for sidecar proxy hops
- Force per-feed RSS fallback on desktop (server digest has fewer categories)
- Add finance feeds to commodity variant (client + server)
- Remove desktop diagnostics from ServiceStatusPanel (show cloud statuses only)
- Restore DeductionPanel CSS from PR #1162
- Deduplicate repeated sidecar error logs
2026-03-12 06:50:30 +04:00

65 lines
1.8 KiB
JavaScript

/**
* Compiles per-domain RPC handlers (api/{domain}/v1/[rpc].ts) into bundled
* ESM .js files so the Tauri sidecar's buildRouteTable() can load them.
*
* Run: node scripts/build-sidecar-handlers.mjs
*/
import { build } from 'esbuild';
import { readdir, stat } from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
import path from 'node:path';
import { existsSync } from 'node:fs';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const ROOT = path.resolve(__dirname, '..');
const apiDir = path.join(ROOT, 'api');
// Skip the catch-all [domain] directory (handled by build-sidecar-sebuf.mjs)
const SKIP_DIRS = new Set(['[domain]', '[[...path]]']);
// Discover all api/{domain}/v1/[rpc].ts entry points
const entries = [];
const dirs = await readdir(apiDir, { withFileTypes: true });
for (const d of dirs) {
if (!d.isDirectory() || SKIP_DIRS.has(d.name)) continue;
const tsFile = path.join(apiDir, d.name, 'v1', '[rpc].ts');
if (existsSync(tsFile)) {
entries.push(tsFile);
}
}
if (entries.length === 0) {
console.log('build:sidecar-handlers no domain handlers found, skipping');
process.exit(0);
}
try {
await build({
entryPoints: entries,
outdir: ROOT,
outbase: ROOT,
bundle: true,
format: 'esm',
platform: 'node',
target: 'node20',
treeShaking: true,
// Resolve @/ alias to src/
alias: { '@': path.join(ROOT, 'src') },
});
// Report results
let totalKB = 0;
for (const entry of entries) {
const jsFile = entry.replace(/\.ts$/, '.js');
if (existsSync(jsFile)) {
const { size } = await stat(jsFile);
totalKB += size / 1024;
}
}
console.log(`build:sidecar-handlers ${entries.length} domains ${totalKB.toFixed(0)} KB total`);
} catch (err) {
console.error('build:sidecar-handlers failed:', err.message);
process.exit(1);
}