mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-22 20:48:56 +01:00
Part of a series of linter auto fixes from biome. These change typescript imports to specify `type`. It's a safe fix: https://biomejs.dev/linter/rules/use-import-type/ Get [Biome](https://biomejs.dev/guides/manual-installation/) (the executable, at least) `biome lint --write --only "useImportType"` Moving us to a simple linter/formatter and shaving off a number of packages, tech debt
117 lines
2.6 KiB
TypeScript
117 lines
2.6 KiB
TypeScript
import { inspect } from 'node:util';
|
|
|
|
import type { ServerWebSocket } from 'bun';
|
|
|
|
import { createLogger, directLog } from '../logging';
|
|
import { retrace } from './retrace';
|
|
|
|
let server: Bun.Server;
|
|
const logger = createLogger('link');
|
|
const DEBUG = process.argv.includes('--debug');
|
|
|
|
export function setupLink() {
|
|
server = Bun.serve({
|
|
fetch: upgradeServer,
|
|
development: true,
|
|
hostname: '127.0.0.1',
|
|
port: 3000,
|
|
websocket: {
|
|
open(ws) {
|
|
ws.subscribe('link');
|
|
logger.log('client connected');
|
|
},
|
|
close(ws) {
|
|
ws.unsubscribe('link');
|
|
logger.log('client disconnected');
|
|
},
|
|
message: handleLinkMessage,
|
|
},
|
|
});
|
|
}
|
|
|
|
export function broadcastMessage(msg: Record<string, any>): void {
|
|
const subscribers = server.subscriberCount('link');
|
|
if (subscribers === 0) return;
|
|
|
|
server?.publish('link', JSON.stringify(msg));
|
|
}
|
|
|
|
function deserializeObject(str: any): any {
|
|
return JSON.parse(str, (_key: string, value: any) => {
|
|
if (typeof value === 'object' && value !== null) {
|
|
if (value.__undefined__) {
|
|
// NOTE: You should not rely on deserialized object's undefined,
|
|
// this is purely for inspection purposes.
|
|
return {
|
|
[inspect.custom]: () => undefined,
|
|
};
|
|
}
|
|
if (value.__number__) {
|
|
return parseFloat(value.__number__);
|
|
}
|
|
if (value.__error__) {
|
|
if (!value.stack) {
|
|
return value.string;
|
|
}
|
|
return retrace(value.stack);
|
|
}
|
|
return value;
|
|
}
|
|
return value;
|
|
});
|
|
}
|
|
|
|
function handleLinkMessage(
|
|
_ws: ServerWebSocket<unknown>,
|
|
message: string | Buffer<ArrayBufferLike>,
|
|
): void {
|
|
const deserializedMsg = deserializeObject(message);
|
|
const { type, payload } = deserializedMsg;
|
|
|
|
if (type === 'log') {
|
|
const { level, ns, args } = payload;
|
|
// Skip debug messages
|
|
if (level <= 0 && !DEBUG) return;
|
|
|
|
directLog(
|
|
ns,
|
|
...args.map((arg) => {
|
|
if (typeof arg === 'object') {
|
|
return inspect(arg, {
|
|
depth: Infinity,
|
|
colors: true,
|
|
compact: 8,
|
|
});
|
|
}
|
|
return arg;
|
|
}),
|
|
);
|
|
|
|
return;
|
|
}
|
|
if (type === 'relay') {
|
|
broadcastMessage(payload);
|
|
|
|
return;
|
|
}
|
|
|
|
logger.log('unhandled message', JSON.stringify(message));
|
|
}
|
|
|
|
function upgradeServer(req: Request, srv: Bun.Server) {
|
|
const client = crypto.randomUUID();
|
|
|
|
const upgraded = srv.upgrade(req, {
|
|
data: {
|
|
id: client,
|
|
createdAt: Date.now(),
|
|
},
|
|
});
|
|
|
|
if (upgraded) {
|
|
return new Response('Ok');
|
|
} else {
|
|
return new Response('Upgrade failed', { status: 500 });
|
|
}
|
|
}
|