mirror of
https://github.com/modrinth/code.git
synced 2026-08-25 00:55:25 +00:00
Revert "feat: sync individual content installation states on panel" (#7154)
Revert "feat: sync individual content installation states on panel (#6909)"
This reverts commit 9628b4c269.
This commit is contained in:
@@ -9,7 +9,6 @@ export type WebSocketEventHandler<
|
||||
export interface WebSocketConnection {
|
||||
serverId: string
|
||||
socket: WebSocket
|
||||
authenticated: boolean
|
||||
reconnectAttempts: number
|
||||
reconnectTimer?: ReturnType<typeof setTimeout>
|
||||
isReconnecting: boolean
|
||||
@@ -32,7 +31,6 @@ export abstract class AbstractWebSocketClient {
|
||||
protected readonly MAX_RECONNECT_ATTEMPTS = 10
|
||||
protected readonly RECONNECT_BASE_DELAY = 1000
|
||||
protected readonly RECONNECT_MAX_DELAY = 30000
|
||||
protected readonly AUTHENTICATION_TIMEOUT = 30000
|
||||
|
||||
constructor(
|
||||
protected client: {
|
||||
@@ -60,7 +58,6 @@ export abstract class AbstractWebSocketClient {
|
||||
}
|
||||
|
||||
if (status && !status.connected && !options?.force) {
|
||||
await this.waitForAuthentication(serverId)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -72,28 +69,6 @@ export abstract class AbstractWebSocketClient {
|
||||
await this.connect(serverId, auth)
|
||||
}
|
||||
|
||||
protected async waitForAuthentication(serverId: string): Promise<void> {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
let unsubscribe = () => {}
|
||||
const timeout = setTimeout(() => {
|
||||
unsubscribe()
|
||||
reject(new Error(`WebSocket authentication timed out for server ${serverId}`))
|
||||
}, this.AUTHENTICATION_TIMEOUT)
|
||||
|
||||
unsubscribe = this.on(serverId, 'auth-ok', () => {
|
||||
clearTimeout(timeout)
|
||||
unsubscribe()
|
||||
resolve()
|
||||
})
|
||||
|
||||
if (this.getStatus(serverId)?.connected) {
|
||||
clearTimeout(timeout)
|
||||
unsubscribe()
|
||||
resolve()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
on<E extends Archon.Websocket.v0.WSEventType>(
|
||||
serverId: string,
|
||||
eventType: E,
|
||||
@@ -113,7 +88,7 @@ export abstract class AbstractWebSocketClient {
|
||||
if (!connection) return null
|
||||
|
||||
return {
|
||||
connected: connection.socket.readyState === WebSocket.OPEN && connection.authenticated,
|
||||
connected: connection.socket.readyState === WebSocket.OPEN,
|
||||
reconnecting: connection.isReconnecting,
|
||||
reconnectAttempts: connection.reconnectAttempts,
|
||||
}
|
||||
|
||||
@@ -301,24 +301,13 @@ export namespace Archon {
|
||||
environment?: Labrinth.Projects.v3.Environment | null
|
||||
}
|
||||
|
||||
export type AddonStatus =
|
||||
| 'pending'
|
||||
| 'installed'
|
||||
| {
|
||||
failed: {
|
||||
error: string
|
||||
}
|
||||
}
|
||||
|
||||
export type Addon = {
|
||||
id: string
|
||||
filename: string
|
||||
filesize: number
|
||||
btime?: string
|
||||
disabled: boolean
|
||||
kind: AddonKind
|
||||
from_modpack: boolean
|
||||
status: AddonStatus
|
||||
pack_client_retained: boolean
|
||||
pack_client_depends: boolean
|
||||
has_update: string | null
|
||||
@@ -334,10 +323,6 @@ export namespace Archon {
|
||||
modloader_version: string | null
|
||||
game_version: string | null
|
||||
modpack: ModpackFields | null
|
||||
installing?: 'loader' | 'modpack'
|
||||
error?: {
|
||||
message: string
|
||||
}
|
||||
addons: Addon[] | null
|
||||
}
|
||||
|
||||
@@ -1004,78 +989,6 @@ export namespace Archon {
|
||||
world_id: string
|
||||
spec: Archon.Content.v1.Addons
|
||||
}
|
||||
export type WorldContentPlatform =
|
||||
| 'forge'
|
||||
| 'neoforge'
|
||||
| 'fabric'
|
||||
| 'quilt'
|
||||
| 'paper'
|
||||
| 'purpur'
|
||||
| 'vanilla'
|
||||
export type WorldContentPlatformData = {
|
||||
platform: WorldContentPlatform
|
||||
game_version: string
|
||||
platform_version: string | null
|
||||
}
|
||||
export type WorldContentModpackSource =
|
||||
| 'CurseForge'
|
||||
| {
|
||||
Modrinth: {
|
||||
version_id: string
|
||||
project_id: string
|
||||
mrpack_sha1: string | null
|
||||
}
|
||||
}
|
||||
| {
|
||||
LocalMrPackFile: {
|
||||
path: string
|
||||
name: string
|
||||
description: string | null
|
||||
version_name: string | null
|
||||
}
|
||||
}
|
||||
export type WorldContentModpack = {
|
||||
spec: WorldContentModpackSource
|
||||
downloads: number | null
|
||||
followers: number | null
|
||||
icon_url: string | null
|
||||
owner: Archon.Content.v1.ContentOwner | null
|
||||
title: string | null
|
||||
description: string | null
|
||||
version_number: string | null
|
||||
date_published: string | null
|
||||
environment: Labrinth.Projects.v3.Environment | null
|
||||
has_update: string | null
|
||||
}
|
||||
export type WorldContentItem = {
|
||||
parent_directory: string
|
||||
file_sha1: string | null
|
||||
filename: string
|
||||
btime?: string
|
||||
from_modpack: boolean
|
||||
version_id: string | null
|
||||
project_id: string | null
|
||||
pack_client_retained: boolean
|
||||
pack_client_depends: boolean
|
||||
status: Archon.Content.v1.AddonStatus
|
||||
filesize: number | null
|
||||
name: string | null
|
||||
version: Archon.Content.v1.AddonVersion | null
|
||||
owner: Archon.Content.v1.ContentOwner | null
|
||||
has_update: string | null
|
||||
icon_url: string | null
|
||||
}
|
||||
export type WorldContentUpdateEvent = {
|
||||
type: 'world.content.update'
|
||||
world_id: string
|
||||
platform_data: WorldContentPlatformData | null
|
||||
linked_modpack: WorldContentModpack | null
|
||||
installing?: 'loader' | 'modpack'
|
||||
error?: {
|
||||
message: string
|
||||
}
|
||||
content: WorldContentItem[]
|
||||
}
|
||||
|
||||
export type SyncEvent =
|
||||
| ProtocolResetEvent
|
||||
@@ -1094,7 +1007,6 @@ export namespace Archon {
|
||||
| WorldStartupPatchEvent
|
||||
| WorldContentAddonPatchEvent
|
||||
| WorldContentBaseUpdateEvent
|
||||
| WorldContentUpdateEvent
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1199,53 +1111,6 @@ export namespace Archon {
|
||||
version_id: string
|
||||
}
|
||||
|
||||
export type InstallProgressFileKey = {
|
||||
type: 'file'
|
||||
install_type: 'install' | 'update'
|
||||
project_id: string
|
||||
version_id: string
|
||||
parent_directory: string
|
||||
source_filename: string | null
|
||||
target_filename?: string | null
|
||||
}
|
||||
|
||||
export type InstallProgressModrinthModpackKey = {
|
||||
type: 'modrinth_modpack'
|
||||
project_id: string
|
||||
version_id: string
|
||||
}
|
||||
|
||||
export type InstallProgressLocalModpackKey = {
|
||||
type: 'local_modpack'
|
||||
filename: string
|
||||
}
|
||||
|
||||
export type InstallProgressPlatformKey = {
|
||||
type: 'platform'
|
||||
platform: 'forge' | 'neoforge' | 'fabric' | 'quilt' | 'paper' | 'purpur' | 'vanilla'
|
||||
platform_version: string
|
||||
game_version: string
|
||||
}
|
||||
|
||||
export type InstallProgressKey =
|
||||
| InstallProgressFileKey
|
||||
| InstallProgressModrinthModpackKey
|
||||
| InstallProgressLocalModpackKey
|
||||
| InstallProgressPlatformKey
|
||||
|
||||
export type InstallProgressItem = {
|
||||
world_id: string
|
||||
key: InstallProgressKey
|
||||
id: string
|
||||
progress: number | null
|
||||
error: string | null
|
||||
}
|
||||
|
||||
export type WSInstallProgressEvent = {
|
||||
event: 'install-progress'
|
||||
items: InstallProgressItem[]
|
||||
}
|
||||
|
||||
export type FilesystemOpKind = 'unarchive'
|
||||
|
||||
export type FilesystemOpState =
|
||||
@@ -1343,7 +1208,6 @@ export namespace Archon {
|
||||
| WSInstallationResultEvent
|
||||
| WSUptimeEvent
|
||||
| WSNewModEvent
|
||||
| WSInstallProgressEvent
|
||||
| WSFilesystemOpsEvent
|
||||
|
||||
export type WSEventType = WSEvent['event']
|
||||
|
||||
@@ -19,60 +19,36 @@ export class GenericWebSocketClient extends AbstractWebSocketClient {
|
||||
}
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let settled = false
|
||||
let authenticationTimeout: ReturnType<typeof setTimeout> | null = null
|
||||
const resolveConnection = () => {
|
||||
if (settled) return
|
||||
settled = true
|
||||
if (authenticationTimeout) clearTimeout(authenticationTimeout)
|
||||
resolve()
|
||||
}
|
||||
const rejectConnection = (error: unknown) => {
|
||||
if (settled) return
|
||||
settled = true
|
||||
if (authenticationTimeout) clearTimeout(authenticationTimeout)
|
||||
reject(error)
|
||||
}
|
||||
try {
|
||||
const ws = new WebSocket(getNodeWebSocketUrl(auth.url))
|
||||
|
||||
const connection: WebSocketConnection = {
|
||||
serverId,
|
||||
socket: ws,
|
||||
authenticated: false,
|
||||
reconnectAttempts: 0,
|
||||
reconnectTimer: undefined,
|
||||
isReconnecting: false,
|
||||
}
|
||||
|
||||
this.connections.set(serverId, connection)
|
||||
authenticationTimeout = setTimeout(() => {
|
||||
rejectConnection(new Error(`WebSocket authentication timed out for server ${serverId}`))
|
||||
if (this.connections.get(serverId) === connection) this.closeConnection(serverId)
|
||||
}, this.AUTHENTICATION_TIMEOUT)
|
||||
|
||||
ws.onopen = () => {
|
||||
ws.send(JSON.stringify({ event: 'auth', jwt: auth.token }))
|
||||
|
||||
connection.reconnectAttempts = 0
|
||||
connection.isReconnecting = false
|
||||
|
||||
resolve()
|
||||
}
|
||||
|
||||
ws.onmessage = (messageEvent) => {
|
||||
try {
|
||||
const data = JSON.parse(messageEvent.data) as Archon.Websocket.v0.WSEvent
|
||||
if (data.event === 'auth-ok') {
|
||||
connection.authenticated = true
|
||||
} else if (data.event === 'auth-incorrect') {
|
||||
connection.authenticated = false
|
||||
}
|
||||
|
||||
const eventKey = `${serverId}:${data.event}` as keyof WSEventMap
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
this.emitter.emit(eventKey, data as any)
|
||||
|
||||
if (data.event === 'auth-ok') resolveConnection()
|
||||
|
||||
if (data.event === 'auth-expiring' || data.event === 'auth-incorrect') {
|
||||
this.handleAuthExpiring(serverId).catch(console.error)
|
||||
}
|
||||
@@ -82,17 +58,11 @@ export class GenericWebSocketClient extends AbstractWebSocketClient {
|
||||
}
|
||||
|
||||
ws.onclose = (event) => {
|
||||
connection.authenticated = false
|
||||
console.debug(`[WebSocket] Closed for server ${serverId}:`, {
|
||||
code: event.code,
|
||||
reason: event.reason,
|
||||
wasClean: event.wasClean,
|
||||
})
|
||||
rejectConnection(
|
||||
new Error(
|
||||
`WebSocket closed before authentication for server ${serverId} (code: ${event.code})`,
|
||||
),
|
||||
)
|
||||
if (event.code !== NORMAL_CLOSURE) {
|
||||
this.scheduleReconnect(serverId, auth)
|
||||
}
|
||||
@@ -107,14 +77,14 @@ export class GenericWebSocketClient extends AbstractWebSocketClient {
|
||||
readyStateLabel: ['CONNECTING', 'OPEN', 'CLOSING', 'CLOSED'][readyState],
|
||||
type: (event as Event).type,
|
||||
})
|
||||
rejectConnection(
|
||||
reject(
|
||||
new Error(
|
||||
`WebSocket connection failed for server ${serverId} (readyState: ${readyState})`,
|
||||
),
|
||||
)
|
||||
}
|
||||
} catch (error) {
|
||||
rejectConnection(error)
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user