feat: Initial commit

This commit is contained in:
2026-06-27 23:25:12 +07:00
commit c8317eb02a
189 changed files with 20068 additions and 0 deletions
+4
View File
@@ -0,0 +1,4 @@
export interface AppConfig {
version: string;
gamePath: string | null;
}
+34
View File
@@ -0,0 +1,34 @@
export type TwoFactorMethod = "totp" | "emailOtp";
export type AuthStatus =
| { state: "unauthenticated" }
| { state: "awaiting2fa"; methods: TwoFactorMethod[] }
| { state: "authenticated"; user: CurrentUserSummary };
export interface CurrentUserSummary {
id: string;
displayName: string;
userIcon: string;
currentAvatarThumbnailImageUrl: string;
}
export interface Account {
id: string;
displayName: string;
userIcon: string;
}
export interface AccountsState {
accounts: Account[];
activeId: string | null;
}
export interface LoginCredentials {
username: string;
password: string;
}
export interface TwoFactorPayload {
method: TwoFactorMethod;
code: string;
}
+14
View File
@@ -0,0 +1,14 @@
export interface Avatar {
id: string;
name: string;
authorId: string;
authorName: string;
description: string;
imageUrl: string;
thumbnailImageUrl: string;
releaseStatus: string;
tags: string[];
favorites: number;
createdAt?: string;
updatedAt?: string;
}
+59
View File
@@ -0,0 +1,59 @@
import type { RepoStats } from "./repository";
export type LogLevel = "debug" | "info" | "warn" | "error";
export interface LogEntry {
id: number;
ts: number;
level: LogLevel;
scope: string;
message: string;
data?: unknown;
}
export type CacheStatus = "fresh" | "stale" | "expired";
export interface CacheEntryInfo {
key: string;
createdAt: number;
expiresAt: number;
hardExpiresAt: number;
hits: number;
lastAccess: number;
size: number;
value: unknown;
}
export interface CacheStats {
entries: number;
inflight: number;
totalSize: number;
fresh: number;
stale: number;
expired: number;
hits: number;
misses: number;
sets: number;
patches: number;
revalidations: number;
invalidations: number;
clears: number;
persisted: boolean;
persistFile: string | null;
}
export interface WsEvent {
id: number;
ts: number;
type: string;
handled: boolean;
content: unknown;
}
export interface DebugSnapshot {
cache: CacheEntryInfo[];
stats: CacheStats;
logs: LogEntry[];
ws: WsEvent[];
repos: RepoStats[];
}
+20
View File
@@ -0,0 +1,20 @@
export type EnhancementId = "linux-screenshot-symlink";
export type OsPlatform = "linux" | "win32" | "darwin";
export interface EnhancementDetail {
key: string;
path?: string;
}
export interface EnhancementState {
id: EnhancementId;
enabled: boolean;
detail?: EnhancementDetail;
resolvedPath?: string;
}
export interface EnhancementsSnapshot {
platform: OsPlatform;
states: EnhancementState[];
}
+32
View File
@@ -0,0 +1,32 @@
export interface PhotoMetadata {
author?: string;
authorId?: string;
worldId?: string;
worldName?: string;
takenAt?: string;
width?: number;
height?: number;
}
export interface Photo {
id: string;
fileName: string;
bucket: string;
src: string;
thumb: string;
sizeBytes: number;
modifiedAt: string;
metadata: PhotoMetadata;
}
export interface ThumbCacheStats {
count: number;
totalBytes: number;
dir: string;
}
export interface GallerySnapshot {
roots: string[];
empty: boolean;
photos: Photo[];
}
+4
View File
@@ -0,0 +1,4 @@
export interface GameStatus {
running: boolean;
supported: boolean;
}
+12
View File
@@ -0,0 +1,12 @@
export interface Group {
id: string;
name: string;
shortCode?: string;
description?: string;
iconUrl?: string;
bannerUrl?: string;
ownerId?: string;
memberCount?: number;
privacy?: string;
isRepresenting?: boolean;
}
+28
View File
@@ -0,0 +1,28 @@
export type FieldSource = "ws" | "rest:detail" | "rest:list" | "rest:search" | "seed";
export interface FieldMeta {
at: number;
src: FieldSource;
}
export interface EntityMeta {
fields: Record<string, FieldMeta>;
firstSeen: number;
lastRead: number;
lastFetch: number;
}
export interface StoredEntity<T> {
data: T;
meta: EntityMeta;
}
export interface RepoStats {
name: string;
count: number;
totalSize: number;
oldestRead: number | null;
newestFetch: number | null;
pendingWrites: number;
backendFile: string | null;
}
+17
View File
@@ -0,0 +1,17 @@
export type ApiErrorCode =
| "unauthorized"
| "requires_2fa"
| "invalid_2fa"
| "rate_limited"
| "not_found"
| "network"
| "unknown";
export interface ApiError {
code: ApiErrorCode;
message: string;
retryAfter?: number;
methods?: ("totp" | "emailOtp")[];
}
export type IpcResult<T> = { ok: true; data: T } | { ok: false; error: ApiError };
+46
View File
@@ -0,0 +1,46 @@
export type ContentFilterKey =
| "content_sex"
| "content_adult"
| "content_violence"
| "content_gore"
| "content_horror";
export interface AccountLink {
linked: boolean;
label?: string;
}
export interface AccountSettings {
id: string;
displayName: string;
displayNameChangedAt?: string;
previousDisplayName?: string;
supporter: boolean;
pronouns: string;
email: string;
emailVerified: boolean;
pendingEmail?: string;
twoFactorEnabled: boolean;
twoFactorEnabledDate?: string;
usesGeneratedPassword: boolean;
ageVerificationStatus: "18+" | "hidden" | "verified";
ageVerified: boolean;
isAdult: boolean;
contentFilters: ContentFilterKey[];
contentFiltersLocked: boolean;
sharedConnectionsHidden: boolean;
discordFriendsHidden: boolean;
discord: AccountLink;
google: AccountLink;
accountDeletionDate?: string | null;
}
export interface Pending2Fa {
secret: string;
qrCodeDataUrl: string;
}
export interface RecoveryCode {
code: string;
used: boolean;
}
+83
View File
@@ -0,0 +1,83 @@
export type TrustRank =
| "visitor"
| "new"
| "user"
| "known"
| "trusted"
| "veteran"
| "nuisance"
| "troll";
export type UserStatus = "active" | "join me" | "ask me" | "busy" | "offline";
export type Platform = "standalonewindows" | "android" | "web" | "offline" | string;
export type Location = "offline" | "private" | "traveling" | "" | string;
export interface ParsedLocation {
worldId: string;
instanceId: string;
region?: string;
}
export function parseLocation(loc?: string): ParsedLocation | null {
if (!loc || loc === "offline" || loc === "private" || loc === "traveling") return null;
const [worldId, rest] = loc.split(":");
if (!worldId?.startsWith("wrld_") || !rest) return null;
const instanceId = rest.split("~")[0];
const region = /~region\(([^)]+)\)/.exec(rest)?.[1];
return { worldId, instanceId, region };
}
export interface Badge {
id: string;
name: string;
description: string;
imageUrl: string;
showcased: boolean;
}
export interface UserProfile {
id: string;
displayName: string;
bio: string;
bioLinks: string[];
statusDescription: string;
status: UserStatus;
trustRank: TrustRank;
tags: string[];
userIcon: string;
profilePicOverride: string;
profilePicOverrideThumbnail: string;
currentAvatarImageUrl: string;
currentAvatarThumbnailImageUrl: string;
currentAvatarTags: string[];
location?: Location;
lastPlatform?: Platform;
lastLogin?: string;
lastActivity?: string;
state?: "online" | "active" | "offline";
platform?: Platform;
isFriend: boolean;
friendKey?: string;
developerType?: "none" | "trusted" | "internal" | "moderator" | string;
ageVerificationStatus?: string;
ageVerified?: boolean;
pronouns?: string;
languages?: string[];
dateJoined?: string;
pastDisplayNames?: { displayName: string; updatedAt?: string }[];
note?: string;
badges: Badge[];
isSelf: boolean;
}
export interface SocialSnapshot {
selfId: string | null;
users: UserProfile[];
}
+47
View File
@@ -0,0 +1,47 @@
export type ReleaseStatus = "public" | "private" | "hidden" | "all";
export interface WorldPlatforms {
pc: boolean;
android: boolean;
}
export interface World {
id: string;
detailed: boolean;
name: string;
authorId: string;
authorName: string;
description: string;
imageUrl: string;
thumbnailImageUrl: string;
releaseStatus: ReleaseStatus;
capacity: number;
favorites: number;
visits: number;
occupants: number;
heat: number;
tags: string[];
createdAt?: string;
updatedAt?: string;
recommendedCapacity?: number;
popularity?: number;
version?: number;
publishedAt?: string;
labsPublishedAt?: string;
previewYoutubeId?: string;
platforms?: WorldPlatforms;
publicOccupants?: number;
privateOccupants?: number;
}
export interface WorldSnapshot {
worlds: World[];
byAuthor: Record<string, string[]>;
}
export interface FavoriteWorldFolder {
name: string;
displayName: string;
worldIds: string[];
}