|
| 1 | +import { Api } from "coder/site/src/api/api" |
| 2 | +import * as vscode from "vscode" |
| 3 | +import { WebSocket } from "ws" |
| 4 | +import { errToStr } from "./api-helper" |
| 5 | +import { Storage } from "./storage" |
| 6 | + |
| 7 | +type InboxMessage = { |
| 8 | + unread_count: number |
| 9 | + notification: { |
| 10 | + id: string |
| 11 | + user_id: string |
| 12 | + template_id: string |
| 13 | + targets: string[] |
| 14 | + title: string |
| 15 | + content: string |
| 16 | + actions: { |
| 17 | + [key: string]: string |
| 18 | + } |
| 19 | + read_at: string |
| 20 | + created_at: string |
| 21 | + } |
| 22 | +} |
| 23 | + |
| 24 | +const TemplateWorkspaceOutOfMemory = "a9d027b4-ac49-4fb1-9f6d-45af15f64e7a" |
| 25 | +const TemplateWorkspaceOutOfDisk = "f047f6a3-5713-40f7-85aa-0394cce9fa3a" |
| 26 | + |
| 27 | +export class Inbox implements vscode.Disposable { |
| 28 | + private disposed = false |
| 29 | + private socket: WebSocket |
| 30 | + |
| 31 | + constructor( |
| 32 | + private readonly restClient: Api, |
| 33 | + private readonly storage: Storage, |
| 34 | + ) { |
| 35 | + // const url = this.restClient.getAxiosInstance().defaults.baseURL |
| 36 | + const token = this.restClient.getAxiosInstance().defaults.headers.common["Coder-Session-Token"] as |
| 37 | + | string |
| 38 | + | undefined |
| 39 | + // const inboxUrl = new URL(`${url}/api/v2/notifications/watch`); |
| 40 | + const inboxUrl = new URL(`ws://localhost:8080`) |
| 41 | + |
| 42 | + this.storage.writeToCoderOutputChannel("Listening to Coder Inbox") |
| 43 | + |
| 44 | + // We're gonna connect over WebSocket so replace the scheme. |
| 45 | + if (inboxUrl.protocol === "https") { |
| 46 | + inboxUrl.protocol = "wss" |
| 47 | + } else if (inboxUrl.protocol === "http") { |
| 48 | + inboxUrl.protocol = "ws" |
| 49 | + } |
| 50 | + |
| 51 | + this.socket = new WebSocket(inboxUrl, { |
| 52 | + headers: { |
| 53 | + "Coder-Session-Token": token, |
| 54 | + }, |
| 55 | + }) |
| 56 | + |
| 57 | + this.socket.on("error", (error) => { |
| 58 | + this.notifyError(error) |
| 59 | + }) |
| 60 | + |
| 61 | + this.socket.on("message", (data) => { |
| 62 | + try { |
| 63 | + const inboxMessage = JSON.parse(data.toString()) as InboxMessage |
| 64 | + |
| 65 | + if ( |
| 66 | + inboxMessage.notification.template_id === TemplateWorkspaceOutOfDisk || |
| 67 | + inboxMessage.notification.template_id === TemplateWorkspaceOutOfMemory |
| 68 | + ) { |
| 69 | + vscode.window.showWarningMessage(inboxMessage.notification.title) |
| 70 | + } |
| 71 | + } catch (error) { |
| 72 | + this.notifyError(error) |
| 73 | + } |
| 74 | + }) |
| 75 | + } |
| 76 | + |
| 77 | + dispose() { |
| 78 | + if (!this.disposed) { |
| 79 | + this.storage.writeToCoderOutputChannel("No longer listening to Coder Inbox") |
| 80 | + this.socket.close() |
| 81 | + this.disposed = true |
| 82 | + } |
| 83 | + } |
| 84 | + |
| 85 | + private notifyError(error: unknown) { |
| 86 | + const message = errToStr(error, "Got empty error while monitoring Coder Inbox") |
| 87 | + this.storage.writeToCoderOutputChannel(message) |
| 88 | + } |
| 89 | +} |
0 commit comments