clear the remaining type errors
- DiscordAccount seeded DiscordStatus without its two nullable fields. - bug-report typed reporter.name as string, but users.name is nullable; and the Discord upload wrapped a Buffer directly in a Blob. - Lucide icons take no `title` prop, so the sync spinner's tooltip moved to a wrapping span. - DesktopView cast its dynamic import to a type that included `| null`. - dock PUT cast the request body straight to string[]; it now rejects anything that is not an array of strings instead of writing it to the database. - buildZodSchema assembles a mutable record, since z.ZodRawShape is readonly in zod v4. - The dev-server proxy forwards Bun's `string | Buffer` frames through a helper that satisfies WebSocket.send without copying. bunx tsgo is now clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
0041fcbd47
commit
0d67e2af26
+57
-9
@@ -33,7 +33,16 @@ type WSData = {
|
||||
userId: number;
|
||||
email: string;
|
||||
username: string;
|
||||
provider: 'terminal' | 'chat' | 'task-runner' | 'pipeline' | 'dev-server' | 'cliamp' | 'cliamp-audio' | 'desktop' | 'sidecar';
|
||||
provider:
|
||||
| 'terminal'
|
||||
| 'chat'
|
||||
| 'task-runner'
|
||||
| 'pipeline'
|
||||
| 'dev-server'
|
||||
| 'cliamp'
|
||||
| 'cliamp-audio'
|
||||
| 'desktop'
|
||||
| 'sidecar';
|
||||
sessionId?: string;
|
||||
cwd?: string;
|
||||
command?: string;
|
||||
@@ -141,6 +150,12 @@ const handlers: Record<string, any> = {
|
||||
|
||||
// Dev-server WebSocket proxy: bridges client WS ↔ upstream dev server WS (for HMR etc.)
|
||||
type UpstreamState = { ws: WebSocket; queue: (string | Buffer)[]; ready: boolean };
|
||||
|
||||
// Bun hands WS frames over as `string | Buffer`, but the DOM WebSocket.send signature won't accept a
|
||||
// Buffer<ArrayBufferLike> (it can't rule out a SharedArrayBuffer backing). A Buffer is a Uint8Array
|
||||
// at runtime, so this forwards as-is rather than paying for a copy on every proxied frame.
|
||||
const asWsPayload = (raw: string | Buffer): string | Uint8Array<ArrayBuffer> =>
|
||||
typeof raw === 'string' ? raw : (raw as Uint8Array<ArrayBuffer>);
|
||||
const devServerUpstreams = new Map<ServerWebSocket<WSData>, UpstreamState>();
|
||||
|
||||
const devServerWebsocket = {
|
||||
@@ -154,8 +169,14 @@ const devServerWebsocket = {
|
||||
}
|
||||
try {
|
||||
const payload = await verify(wsToken);
|
||||
if (!payload) { ws.close(4001, 'Unauthorized'); return; }
|
||||
if (payload.jti && await isTokenBlacklisted(payload.jti)) { ws.close(4001, 'Unauthorized'); return; }
|
||||
if (!payload) {
|
||||
ws.close(4001, 'Unauthorized');
|
||||
return;
|
||||
}
|
||||
if (payload.jti && (await isTokenBlacklisted(payload.jti))) {
|
||||
ws.close(4001, 'Unauthorized');
|
||||
return;
|
||||
}
|
||||
} catch {
|
||||
ws.close(4001, 'Unauthorized');
|
||||
return;
|
||||
@@ -167,7 +188,7 @@ const devServerWebsocket = {
|
||||
|
||||
upstream.addEventListener('open', () => {
|
||||
state.ready = true;
|
||||
for (const msg of state.queue) upstream.send(msg);
|
||||
for (const msg of state.queue) upstream.send(asWsPayload(msg));
|
||||
state.queue.length = 0;
|
||||
});
|
||||
|
||||
@@ -189,7 +210,7 @@ const devServerWebsocket = {
|
||||
const state = devServerUpstreams.get(ws);
|
||||
if (!state) return;
|
||||
if (state.ready) {
|
||||
state.ws.send(raw);
|
||||
state.ws.send(asWsPayload(raw));
|
||||
} else {
|
||||
state.queue.push(raw);
|
||||
}
|
||||
@@ -204,7 +225,11 @@ const devServerWebsocket = {
|
||||
};
|
||||
handlers['dev-server'] = devServerWebsocket;
|
||||
|
||||
async function upgradeWs(req: Request, server: any, provider: 'terminal' | 'chat' | 'task-runner' | 'pipeline' | 'cliamp' | 'cliamp-audio' | 'desktop') {
|
||||
async function upgradeWs(
|
||||
req: Request,
|
||||
server: any,
|
||||
provider: 'terminal' | 'chat' | 'task-runner' | 'pipeline' | 'cliamp' | 'cliamp-audio' | 'desktop',
|
||||
) {
|
||||
const token = new URL(req.url).searchParams.get('token');
|
||||
if (!token) return new Response('Unauthorized', { status: 401 });
|
||||
|
||||
@@ -224,7 +249,18 @@ async function upgradeWs(req: Request, server: any, provider: 'terminal' | 'chat
|
||||
const rows = url.searchParams.get('rows') ? Number(url.searchParams.get('rows')) : undefined;
|
||||
const files = url.searchParams.get('files') ?? undefined;
|
||||
const ok = server.upgrade(req, {
|
||||
data: { userId: user.id, email: user.email, username: toShellUsername(user.username ?? '', user.email), provider, sessionId, cwd, command, cols, rows, files },
|
||||
data: {
|
||||
userId: user.id,
|
||||
email: user.email,
|
||||
username: toShellUsername(user.username ?? '', user.email),
|
||||
provider,
|
||||
sessionId,
|
||||
cwd,
|
||||
command,
|
||||
cols,
|
||||
rows,
|
||||
files,
|
||||
},
|
||||
});
|
||||
if (!ok) return new Response('Upgrade failed', { status: 500 });
|
||||
} catch {
|
||||
@@ -330,7 +366,13 @@ try {
|
||||
}
|
||||
|
||||
// Initialize queue engine in API server process
|
||||
import { initQueue, enqueueJob as queueEnqueue, cancelJob as queueCancel, listAllJobs as queueList, readJob as queueGet } from './servers/queue/init';
|
||||
import {
|
||||
initQueue,
|
||||
enqueueJob as queueEnqueue,
|
||||
cancelJob as queueCancel,
|
||||
listAllJobs as queueList,
|
||||
readJob as queueGet,
|
||||
} from './servers/queue/init';
|
||||
initQueue().catch((err) => console.error('[queue] failed to initialize:', err));
|
||||
|
||||
// Mark any orphaned pipeline jobs from previous server run
|
||||
@@ -364,7 +406,13 @@ cleanupOnStartup().catch((err) => console.error('[pipeline-jobs] startup cleanup
|
||||
const sinkList = sinks.stdout.toString();
|
||||
if (!sinkList.includes('virtual_out')) {
|
||||
const load = Bun.spawnSync({
|
||||
cmd: [pactl, 'load-module', 'module-null-sink', 'sink_name=virtual_out', 'sink_properties=device.description=Virtual_Output'],
|
||||
cmd: [
|
||||
pactl,
|
||||
'load-module',
|
||||
'module-null-sink',
|
||||
'sink_name=virtual_out',
|
||||
'sink_properties=device.description=Virtual_Output',
|
||||
],
|
||||
stdout: 'pipe',
|
||||
stderr: 'pipe',
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user