Initial
This commit is contained in:
commit
b43955e0d9
162 changed files with 15425 additions and 0 deletions
83
mocks/plugin.ts
Normal file
83
mocks/plugin.ts
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
import type { Plugin } from 'vite';
|
||||
import { WebSocketServer } from 'ws';
|
||||
import { handle, synthTelemetryHistory } from './handlers';
|
||||
|
||||
const COOKIE = 'mocksid';
|
||||
const WS_PATH = /^\/api\/ws\/satellite\/([0-9a-f-]{36})\/telemetry\/$/i;
|
||||
|
||||
function readCookie(header: string | undefined, name: string): string | null {
|
||||
if (!header) return null;
|
||||
for (const part of header.split(';')) {
|
||||
const [k, ...v] = part.trim().split('=');
|
||||
if (k === name) return decodeURIComponent(v.join('='));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Dev-only middleware that answers /api/* from the in-memory mock backend. */
|
||||
export function mockApi(): Plugin {
|
||||
return {
|
||||
name: 'mock-api',
|
||||
configureServer(server) {
|
||||
// Live telemetry: a real WebSocket so the tracking flow is exercised
|
||||
// end-to-end (the read-only satellite consumer in the real backend).
|
||||
const wss = new WebSocketServer({ noServer: true });
|
||||
server.httpServer?.on('upgrade', (req, socket, head) => {
|
||||
const url = req.url ?? '';
|
||||
const match = url.split('?')[0].match(WS_PATH);
|
||||
if (!match) return; // let Vite's own HMR socket handle it
|
||||
wss.handleUpgrade(req, socket as never, head, (ws) => {
|
||||
// Continue the satellite's synthetic track from where history ended.
|
||||
const history = synthTelemetryHistory(match[1]);
|
||||
let next = history.length;
|
||||
const first = history[0] as { timestamp: number; lat: number; lon: number };
|
||||
const timer = setInterval(() => {
|
||||
ws.send(
|
||||
JSON.stringify({
|
||||
id: `${match[1]}-live-${next}`,
|
||||
timestamp: first.timestamp + (next - history.length + 1) * 60,
|
||||
lat: first.lat + (next - history.length + 1) * 0.004,
|
||||
lon: first.lon + (next - history.length + 1) * 0.01,
|
||||
alt: 18000 + (next - history.length + 1) * 900,
|
||||
payload: { live: true },
|
||||
raw_data: {}
|
||||
})
|
||||
);
|
||||
next += 1;
|
||||
}, 1000);
|
||||
ws.on('close', () => clearInterval(timer));
|
||||
});
|
||||
});
|
||||
|
||||
server.middlewares.use((req, res, next) => {
|
||||
if (!req.url?.startsWith('/api/')) return next();
|
||||
let raw = '';
|
||||
req.on('data', (c) => (raw += c));
|
||||
req.on('end', () => {
|
||||
const body = raw ? JSON.parse(raw) : {};
|
||||
const sessionUser = readCookie(req.headers.cookie, COOKIE);
|
||||
const [pathname, search = ''] = req.url!.split('?');
|
||||
const result = handle(
|
||||
req.method ?? 'GET',
|
||||
pathname,
|
||||
body,
|
||||
sessionUser,
|
||||
new URLSearchParams(search)
|
||||
);
|
||||
res.statusCode = result.status;
|
||||
res.setHeader('content-type', 'application/json');
|
||||
res.setHeader('x-csrftoken', 'mock-csrf');
|
||||
if (result.session !== undefined) {
|
||||
res.setHeader(
|
||||
'set-cookie',
|
||||
result.session === null
|
||||
? `${COOKIE}=; Path=/; Max-Age=0; SameSite=Lax`
|
||||
: `${COOKIE}=${encodeURIComponent(result.session)}; Path=/; SameSite=Lax`
|
||||
);
|
||||
}
|
||||
res.end(JSON.stringify(result.body));
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue