remove projects and apps end to end
deletes the last of the projects/apps cluster: the published-app store (/api/apps + /api/app-serve), the project dev-server and its websocket proxy (/api/dev-server + /api/dev-server-proxy), the shared html-rewrite they were the only consumers of, and their frontend — the Preview panel, the UserApp panel/header, useUserApps and the /settings/apps screen. also drops getUserProjectsDir and getUserAppsDir, the ProjectType and ProjectDefinition types, and the 'dev-server' websocket provider from server.tsx. nothing on disk is touched. 1440 deletions, 31 insertions. tsgo clean.
This commit is contained in:
-116
@@ -11,7 +11,6 @@ import { pipelineWebsocket } from './servers/api/tasks/pipeline-executor';
|
||||
import { cliampWebsocket, cliampAudioWebsocket } from './servers/api/cliamp/relay';
|
||||
import { desktopWebsocket } from './servers/api/desktop/websocket';
|
||||
import { vaultWebsocket, upgradeVaultWs } from './servers/api/vault/websocket';
|
||||
import { findEntryByProxyId, touchEntry } from './servers/api/dev-server/router';
|
||||
import officerWeb from './apps/officer-web/index.gen.html';
|
||||
import { startBrowserRelay } from './servers/api/browser/relay';
|
||||
import { registerSidecar, unregisterSidecar, handleSidecarMessage } from './servers/sidecar-registry';
|
||||
@@ -38,7 +37,6 @@ type WSData = {
|
||||
| 'chat'
|
||||
| 'task-runner'
|
||||
| 'pipeline'
|
||||
| 'dev-server'
|
||||
| 'cliamp'
|
||||
| 'cliamp-audio'
|
||||
| 'desktop'
|
||||
@@ -50,10 +48,6 @@ type WSData = {
|
||||
cols?: number;
|
||||
rows?: number;
|
||||
search?: string; // raw query string, for providers that relay it to a sidecar
|
||||
devServerPort?: number;
|
||||
devServerSlug?: string;
|
||||
wsProxyPath?: string;
|
||||
wsToken?: string;
|
||||
};
|
||||
|
||||
// Sidecar registration WebSocket handler
|
||||
@@ -150,83 +144,6 @@ const handlers: Record<string, any> = {
|
||||
sidecar: sidecarWebsocket,
|
||||
};
|
||||
|
||||
// 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 = {
|
||||
async open(ws: ServerWebSocket<WSData>) {
|
||||
const { devServerPort, wsProxyPath, wsToken } = ws.data;
|
||||
|
||||
// Validate JWT (deferred from upgrade which must be synchronous in Bun)
|
||||
if (!wsToken) {
|
||||
ws.close(4001, 'Unauthorized');
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
} catch {
|
||||
ws.close(4001, 'Unauthorized');
|
||||
return;
|
||||
}
|
||||
|
||||
const upstream = new WebSocket(`ws://localhost:${devServerPort}${wsProxyPath}`);
|
||||
const state: UpstreamState = { ws: upstream, queue: [], ready: false };
|
||||
devServerUpstreams.set(ws, state);
|
||||
|
||||
upstream.addEventListener('open', () => {
|
||||
state.ready = true;
|
||||
for (const msg of state.queue) upstream.send(asWsPayload(msg));
|
||||
state.queue.length = 0;
|
||||
});
|
||||
|
||||
upstream.addEventListener('message', (event) => {
|
||||
ws.send(event.data as string | ArrayBuffer);
|
||||
});
|
||||
|
||||
upstream.addEventListener('close', () => {
|
||||
devServerUpstreams.delete(ws);
|
||||
ws.close();
|
||||
});
|
||||
|
||||
upstream.addEventListener('error', () => {
|
||||
devServerUpstreams.delete(ws);
|
||||
ws.close();
|
||||
});
|
||||
},
|
||||
message(ws: ServerWebSocket<WSData>, raw: string | Buffer) {
|
||||
const state = devServerUpstreams.get(ws);
|
||||
if (!state) return;
|
||||
if (state.ready) {
|
||||
state.ws.send(asWsPayload(raw));
|
||||
} else {
|
||||
state.queue.push(raw);
|
||||
}
|
||||
},
|
||||
close(ws: ServerWebSocket<WSData>) {
|
||||
const state = devServerUpstreams.get(ws);
|
||||
if (state) {
|
||||
state.ws.close();
|
||||
devServerUpstreams.delete(ws);
|
||||
}
|
||||
},
|
||||
};
|
||||
handlers['dev-server'] = devServerWebsocket;
|
||||
|
||||
async function upgradeWs(
|
||||
req: Request,
|
||||
server: any,
|
||||
@@ -269,35 +186,6 @@ async function upgradeWs(
|
||||
}
|
||||
}
|
||||
|
||||
function upgradeDevServerWs(req: Request, server: any) {
|
||||
const url = new URL(req.url);
|
||||
const match = url.pathname.match(/^\/api\/dev-server-proxy\/([^/]+)(\/.*)?$/);
|
||||
if (!match) return new Response('Not found', { status: 404 });
|
||||
|
||||
const proxyId = match[1]!;
|
||||
const entry = findEntryByProxyId(proxyId);
|
||||
if (!entry) return new Response('No dev server running', { status: 404 });
|
||||
|
||||
const wsToken = url.searchParams.get('token');
|
||||
if (!wsToken) return new Response('Unauthorized', { status: 401 });
|
||||
|
||||
touchEntry(entry);
|
||||
|
||||
const wsProxyPath = match[2] || '/';
|
||||
const ok = server.upgrade(req, {
|
||||
data: {
|
||||
userId: 0,
|
||||
email: '',
|
||||
provider: 'dev-server' as const,
|
||||
devServerPort: entry.port,
|
||||
devServerSlug: proxyId,
|
||||
wsProxyPath,
|
||||
wsToken,
|
||||
},
|
||||
});
|
||||
if (!ok) return new Response('Upgrade failed', { status: 500 });
|
||||
}
|
||||
|
||||
const server = serve({
|
||||
port: Number(PORT),
|
||||
idleTimeout: 60,
|
||||
@@ -312,10 +200,6 @@ const server = serve({
|
||||
const file = Bun.file(`public${new URL(req.url).pathname}`);
|
||||
return new Response(file);
|
||||
},
|
||||
'/api/dev-server-proxy/*': (req, server) => {
|
||||
if (req.headers.get('upgrade') === 'websocket') return upgradeDevServerWs(req, server);
|
||||
return honoServer.fetch(req, server);
|
||||
},
|
||||
// Vaultwarden notifications hub: upgrade the WebSocket here (proxied to upstream by vaultWebsocket);
|
||||
// everything else on this path (SignalR long-poll negotiate/poll) falls through to the HTTP proxy.
|
||||
'/api/vault/notifications/*': (req, server) => {
|
||||
|
||||
Reference in New Issue
Block a user