mirror of
https://github.com/modrinth/code.git
synced 2026-08-25 00:55:25 +00:00
feat: hosting access tab (#5995)
* feat: implement access tab with dummy data * fix: spacing * feat: qa * feat: implement backend * qa: qa pass * feat: fix user "search" * fix: lint * feat: change to bitfield * feat: fix fields * fix: lint * fix: lint * feat: hook up api * feat: fix permissions * feat: audit log table event start * feat: better mobile mode for audit log table * feat: i18n * feat: qa * feat: enforce permissions * feat: email template start * feat: qa * fix: tooltip bug * feat: qa * impl: sse support in api-client * feat: sse impl * fix: desync path * feat: time frame picker from analytics * feat: QA * fix: spacing * fix: permisison audit log entries * fix: hosting manage page shared server detection * fix: lint * feat: qa + lint * feat: audit log table sort by time * feat: finish frontend panel stuff * fix: lint * fix: backend alignment * fix: lint * fix: supress friend errors * feat: qa * fix: qa * fix: lint * fix: utils barrel * fix: safari cookies in dev * fix: pin nuxt * feat: fixes + notif fix * fix: notifications * feat: qa * fix: notification sync not happening immediately * fix: qa * fix: qa * feat: qa * blog + prepr * feat: toast shit * blog images * thumbnail update one last time * prepr * feat: use reinvite route * update images * fix: reinvite stuff * fix: lint * fix: alignment of save bar * fix: notif sizing * fix: split up access * fix: lint * fix: lint * fix: link --------- Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
This commit is contained in:
@@ -3,7 +3,6 @@ export * from './highlightjs'
|
||||
export * from './licenses'
|
||||
export * from './parse'
|
||||
export * from './projects'
|
||||
export * from './servers'
|
||||
export * from './types'
|
||||
export * from './users'
|
||||
export * from './utils'
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export * from './modrinth-server-error'
|
||||
export * from './modrinth-servers-fetch-error'
|
||||
export * from './modrinth-servers-multi-error'
|
||||
@@ -1,61 +0,0 @@
|
||||
import { FetchError } from 'ofetch'
|
||||
|
||||
import type { V1ErrorInfo } from '../types'
|
||||
|
||||
export class ModrinthServerError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
public readonly statusCode?: number,
|
||||
public readonly originalError?: Error,
|
||||
public readonly module?: string,
|
||||
public readonly v1Error?: V1ErrorInfo,
|
||||
public readonly responseData?: unknown,
|
||||
) {
|
||||
let errorMessage = message
|
||||
let method = 'GET'
|
||||
let path = ''
|
||||
|
||||
if (originalError instanceof FetchError) {
|
||||
const matches = message.match(/\[([A-Z]+)\]\s+"([^"]+)":/)
|
||||
if (matches) {
|
||||
method = matches[1]
|
||||
path = matches[2].replace(/https?:\/\/[^/]+\/[^/]+\/v\d+\//, '')
|
||||
}
|
||||
|
||||
const statusMessage = (() => {
|
||||
if (!statusCode) return 'Unknown Error'
|
||||
switch (statusCode) {
|
||||
case 400:
|
||||
return 'Bad Request'
|
||||
case 401:
|
||||
return 'Unauthorized'
|
||||
case 403:
|
||||
return 'Forbidden'
|
||||
case 404:
|
||||
return 'Not Found'
|
||||
case 408:
|
||||
return 'Request Timeout'
|
||||
case 429:
|
||||
return 'Too Many Requests'
|
||||
case 500:
|
||||
return 'Internal Server Error'
|
||||
case 502:
|
||||
return 'Bad Gateway'
|
||||
case 503:
|
||||
return 'Service Unavailable'
|
||||
case 504:
|
||||
return 'Gateway Timeout'
|
||||
default:
|
||||
return `HTTP ${statusCode}`
|
||||
}
|
||||
})()
|
||||
|
||||
errorMessage = `[${method}] ${statusMessage} (${statusCode}) while fetching ${path}${module ? ` in ${module}` : ''}`
|
||||
} else {
|
||||
errorMessage = `${message}${statusCode ? ` (${statusCode})` : ''}${module ? ` in ${module}` : ''}`
|
||||
}
|
||||
|
||||
super(errorMessage)
|
||||
this.name = 'ModrinthServersFetchError'
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
export class ModrinthServersFetchError extends Error {
|
||||
constructor(
|
||||
message: string,
|
||||
public statusCode?: number,
|
||||
public originalError?: Error,
|
||||
) {
|
||||
super(message)
|
||||
this.name = 'ModrinthFetchError'
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
export class ModrinthServersMultiError extends Error {
|
||||
public readonly errors: Map<string, Error> = new Map()
|
||||
public readonly timestamp: number = Date.now()
|
||||
|
||||
constructor(message?: string) {
|
||||
super(message || 'Multiple errors occurred')
|
||||
this.name = 'MultipleErrors'
|
||||
}
|
||||
|
||||
addError(module: string, error: Error) {
|
||||
this.errors.set(module, error)
|
||||
this.message = this.buildErrorMessage()
|
||||
}
|
||||
|
||||
hasErrors() {
|
||||
return this.errors.size > 0
|
||||
}
|
||||
|
||||
private buildErrorMessage(): string {
|
||||
return Array.from(this.errors.entries())
|
||||
|
||||
.map(([_module, error]) => error.message)
|
||||
.join('\n')
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
export * from './errors'
|
||||
export * from './types'
|
||||
@@ -1,19 +0,0 @@
|
||||
import type { ModrinthServerError } from '../errors'
|
||||
|
||||
export interface V1ErrorInfo {
|
||||
context?: string
|
||||
error: string
|
||||
description: string
|
||||
}
|
||||
|
||||
export interface JWTAuth {
|
||||
url: string
|
||||
token: string
|
||||
}
|
||||
|
||||
export interface ModuleError {
|
||||
error: ModrinthServerError
|
||||
timestamp: number
|
||||
}
|
||||
|
||||
export type ModuleName = 'general' | 'network' | 'startup'
|
||||
@@ -1,18 +0,0 @@
|
||||
export type ServerNotice = {
|
||||
id: number
|
||||
message: string
|
||||
title?: string
|
||||
level: 'info' | 'warn' | 'critical' | 'survey'
|
||||
dismissable: boolean
|
||||
announce_at: string
|
||||
expires: string
|
||||
assigned: {
|
||||
kind: 'server' | 'node'
|
||||
id: string
|
||||
name: string
|
||||
}[]
|
||||
dismissed_by: {
|
||||
server: string
|
||||
dismissed_on: string
|
||||
}[]
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
export interface Mod {
|
||||
filename: string
|
||||
project_id: string | undefined
|
||||
version_id: string | undefined
|
||||
name: string | undefined
|
||||
version_number: string | undefined
|
||||
icon_url: string | undefined
|
||||
owner: string | undefined
|
||||
disabled: boolean
|
||||
installing: boolean
|
||||
}
|
||||
|
||||
export type ContentType = 'mod' | 'plugin'
|
||||
@@ -1,33 +0,0 @@
|
||||
import type { JWTAuth } from './api'
|
||||
import type { FilesystemOp, FSQueuedOp } from './websocket'
|
||||
|
||||
export interface DirectoryItem {
|
||||
name: string
|
||||
type: 'directory' | 'file'
|
||||
count?: number
|
||||
modified: number
|
||||
created: number
|
||||
path: string
|
||||
}
|
||||
|
||||
export interface FileUploadQuery {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
promise: Promise<any>
|
||||
onProgress: (
|
||||
callback: (progress: { loaded: number; total: number; progress: number }) => void,
|
||||
) => void
|
||||
cancel: () => void
|
||||
}
|
||||
|
||||
export interface DirectoryResponse {
|
||||
items: DirectoryItem[]
|
||||
total: number
|
||||
current?: number
|
||||
}
|
||||
|
||||
export interface FSModule {
|
||||
auth: JWTAuth
|
||||
ops: FilesystemOp[]
|
||||
queuedOps: FSQueuedOp[]
|
||||
opsQueuedForModification: string[]
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
export * from './api'
|
||||
export * from './common'
|
||||
export * from './content'
|
||||
export * from './filesystem'
|
||||
export * from './server'
|
||||
export * from './stats'
|
||||
export * from './websocket'
|
||||
@@ -1,77 +0,0 @@
|
||||
import type { Project } from '../../types'
|
||||
import type { ServerNotice } from './common'
|
||||
|
||||
export interface ServerGeneral {
|
||||
server_id: string
|
||||
name: string
|
||||
net: {
|
||||
ip: string
|
||||
port: number
|
||||
domain: string
|
||||
}
|
||||
game: string
|
||||
backup_quota: number
|
||||
used_backup_quota: number
|
||||
status: string
|
||||
suspension_reason: 'moderated' | 'paymentfailed' | 'cancelled' | 'upgrading' | 'other' | string
|
||||
loader: string
|
||||
loader_version: string
|
||||
mc_version: string
|
||||
upstream: {
|
||||
kind: 'modpack' | 'mod' | 'resourcepack'
|
||||
version_id: string
|
||||
project_id: string
|
||||
} | null
|
||||
motd?: string
|
||||
image?: string
|
||||
project?: Project
|
||||
sftp_username: string
|
||||
sftp_password: string
|
||||
sftp_host: string
|
||||
datacenter?: string
|
||||
notices?: ServerNotice[]
|
||||
node: {
|
||||
token: string
|
||||
instance: string
|
||||
}
|
||||
flows?: {
|
||||
intro?: boolean
|
||||
}
|
||||
is_medal?: boolean
|
||||
}
|
||||
|
||||
export interface Allocation {
|
||||
port: number
|
||||
name: string
|
||||
}
|
||||
|
||||
export interface Startup {
|
||||
invocation: string
|
||||
original_invocation: string
|
||||
jdk_version: 'lts8' | 'lts11' | 'lts17' | 'lts21'
|
||||
jdk_build: 'corretto' | 'temurin' | 'graal'
|
||||
}
|
||||
|
||||
export type PowerAction = 'Start' | 'Stop' | 'Restart' | 'Kill'
|
||||
export type JDKVersion = 'lts8' | 'lts11' | 'lts17' | 'lts21'
|
||||
export type JDKBuild = 'corretto' | 'temurin' | 'graal'
|
||||
|
||||
export type Loaders =
|
||||
| 'Fabric'
|
||||
| 'Quilt'
|
||||
| 'Forge'
|
||||
| 'NeoForge'
|
||||
| 'Paper'
|
||||
| 'Spigot'
|
||||
| 'Bukkit'
|
||||
| 'Vanilla'
|
||||
| 'Purpur'
|
||||
|
||||
export type ServerState =
|
||||
| 'starting'
|
||||
| 'running'
|
||||
| 'restarting'
|
||||
| 'stopping'
|
||||
| 'stopped'
|
||||
| 'crashed'
|
||||
| 'unknown'
|
||||
@@ -1,20 +0,0 @@
|
||||
export interface Stats {
|
||||
current: {
|
||||
cpu_percent: number
|
||||
ram_usage_bytes: number
|
||||
ram_total_bytes: number
|
||||
storage_usage_bytes: number
|
||||
storage_total_bytes: number
|
||||
}
|
||||
past: {
|
||||
cpu_percent: number
|
||||
ram_usage_bytes: number
|
||||
ram_total_bytes: number
|
||||
storage_usage_bytes: number
|
||||
storage_total_bytes: number
|
||||
}
|
||||
graph: {
|
||||
cpu: number[]
|
||||
ram: number[]
|
||||
}
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
import type { ServerState } from './server'
|
||||
import type { Stats } from './stats'
|
||||
|
||||
export interface WSAuth {
|
||||
url: string
|
||||
token: string
|
||||
}
|
||||
|
||||
export interface WSLogEvent {
|
||||
event: 'log'
|
||||
message: string
|
||||
}
|
||||
|
||||
type CurrentStats = Stats['current']
|
||||
|
||||
export interface WSStatsEvent extends CurrentStats {
|
||||
event: 'stats'
|
||||
}
|
||||
|
||||
export interface WSAuthExpiringEvent {
|
||||
event: 'auth-expiring'
|
||||
}
|
||||
|
||||
export interface WSPowerStateEvent {
|
||||
event: 'power-state'
|
||||
state: ServerState
|
||||
// if state "crashed"
|
||||
oom_killed?: boolean
|
||||
exit_code?: number
|
||||
}
|
||||
|
||||
export interface WSAuthIncorrectEvent {
|
||||
event: 'auth-incorrect'
|
||||
}
|
||||
|
||||
export interface WSInstallationResultOkEvent {
|
||||
event: 'installation-result'
|
||||
result: 'ok'
|
||||
}
|
||||
|
||||
export interface WSInstallationResultErrEvent {
|
||||
event: 'installation-result'
|
||||
result: 'err'
|
||||
reason: string
|
||||
}
|
||||
|
||||
export type WSInstallationResultEvent = WSInstallationResultOkEvent | WSInstallationResultErrEvent
|
||||
|
||||
export interface WSAuthOkEvent {
|
||||
event: 'auth-ok'
|
||||
}
|
||||
|
||||
export interface WSUptimeEvent {
|
||||
event: 'uptime'
|
||||
uptime: number // seconds
|
||||
}
|
||||
|
||||
export interface WSNewModEvent {
|
||||
event: 'new-mod'
|
||||
}
|
||||
|
||||
export type FSQueuedOpUnarchive = {
|
||||
op: 'unarchive'
|
||||
src: string
|
||||
}
|
||||
|
||||
export type FSQueuedOp = FSQueuedOpUnarchive
|
||||
|
||||
export type FSOpUnarchive = {
|
||||
op: 'unarchive'
|
||||
progress: number // Note: 1 does not mean it's done
|
||||
id: string // UUID
|
||||
|
||||
mime: string
|
||||
src: string
|
||||
state:
|
||||
| 'queued'
|
||||
| 'ongoing'
|
||||
| 'cancelled'
|
||||
| 'done'
|
||||
| 'failed-corrupted'
|
||||
| 'failed-invalid-path'
|
||||
| 'failed-cf-no-serverpack'
|
||||
| 'failed-cf-not-available'
|
||||
| 'failed-not-reachable'
|
||||
|
||||
current_file: string | null
|
||||
failed_path?: string
|
||||
bytes_processed: number
|
||||
files_processed: number
|
||||
started: string
|
||||
}
|
||||
|
||||
export type FilesystemOp = FSOpUnarchive
|
||||
|
||||
export interface WSFilesystemOpsEvent {
|
||||
event: 'filesystem-ops'
|
||||
all: FilesystemOp[]
|
||||
}
|
||||
Reference in New Issue
Block a user