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
+131
View File
@@ -0,0 +1,131 @@
import type {
AccountsState,
AuthStatus,
LoginCredentials,
TwoFactorMethod,
TwoFactorPayload,
} from "./types/auth";
import type { SocialSnapshot, UserProfile, UserStatus } from "./types/user";
import type { FavoriteWorldFolder, World, WorldSnapshot } from "./types/world";
import type { Avatar } from "./types/avatar";
import type { RepoStats, StoredEntity } from "./types/repository";
import type { AccountSettings, ContentFilterKey, Pending2Fa, RecoveryCode } from "./types/settings";
import type { Group } from "./types/group";
import type { EnhancementId, EnhancementsSnapshot } from "./types/enhancements";
import type { GallerySnapshot, Photo, ThumbCacheStats } from "./types/gallery";
import type { AppConfig } from "./types/appConfig";
import type { GameStatus } from "./types/game";
import type { IpcResult } from "./types/result";
import type { CacheEntryInfo, CacheStats, DebugSnapshot, LogEntry, WsEvent } from "./types/debug";
export interface CacheUpdate {
cache: CacheEntryInfo[];
stats: CacheStats;
}
export interface IpcRequests {
"auth:status": () => IpcResult<AuthStatus>;
"auth:login": (creds: LoginCredentials) => IpcResult<AuthStatus>;
"auth:verify2fa": (payload: TwoFactorPayload) => IpcResult<AuthStatus>;
"auth:logout": () => IpcResult<void>;
"accounts:list": () => IpcResult<AccountsState>;
"accounts:switch": (id: string) => IpcResult<AuthStatus>;
"accounts:remove": (id: string) => IpcResult<AccountsState>;
"user:me": () => IpcResult<UserProfile>;
"user:get": (userId: string) => IpcResult<UserProfile>;
"user:getByName": (username: string) => IpcResult<UserProfile>;
"user:search": (query: string) => IpcResult<UserProfile[]>;
"friends:list": () => IpcResult<UserProfile[]>;
"world:byUser": (userId: string) => IpcResult<World[]>;
"world:search": (query: string) => IpcResult<World[]>;
"world:favorites": (userId: string) => IpcResult<FavoriteWorldFolder[]>;
"world:get": (worldId: string) => IpcResult<World>;
"world:snapshot": () => IpcResult<WorldSnapshot>;
"avatar:get": (avatarId: string) => IpcResult<Avatar>;
"avatar:favorites": () => IpcResult<Avatar[]>;
"group:byUser": (userId: string) => IpcResult<Group[]>;
"group:represented": (userId: string) => IpcResult<Group | null>;
"social:snapshot": () => IpcResult<SocialSnapshot>;
"settings:get": () => IpcResult<AccountSettings>;
"settings:displayName": (p: {
displayName: string;
currentPassword: string;
}) => IpcResult<AccountSettings>;
"settings:revertDisplayName": (p: { currentPassword: string }) => IpcResult<AccountSettings>;
"settings:email": (p: { email: string; currentPassword: string }) => IpcResult<AccountSettings>;
"settings:password": (p: {
currentPassword: string;
newPassword: string;
}) => IpcResult<AccountSettings>;
"settings:privacy": (p: {
sharedConnectionsHidden?: boolean;
discordFriendsHidden?: boolean;
}) => IpcResult<AccountSettings>;
"settings:status": (p: { status: UserStatus; statusDescription: string }) => IpcResult<void>;
"settings:contentFilters": (filters: ContentFilterKey[]) => IpcResult<AccountSettings>;
"settings:enable2fa": () => IpcResult<Pending2Fa>;
"settings:verify2fa": (code: string) => IpcResult<{ verified: boolean }>;
"settings:disable2fa": () => IpcResult<AccountSettings>;
"settings:recoveryCodes": () => IpcResult<RecoveryCode[]>;
"settings:reverify2fa": (p: {
method: TwoFactorMethod;
code: string;
}) => IpcResult<{ verified: boolean }>;
"settings:resetUserData": () => IpcResult<void>;
"settings:deleteAccount": () => IpcResult<AccountSettings>;
"config:get": () => IpcResult<AppConfig>;
"config:setGamePath": (p: { gamePath: string | null }) => IpcResult<AppConfig>;
"config:pickGamePath": () => IpcResult<AppConfig>;
"game:status": () => IpcResult<GameStatus>;
"game:launch": () => IpcResult<GameStatus>;
"gallery:snapshot": () => IpcResult<GallerySnapshot>;
"gallery:reveal": (path: string) => IpcResult<void>;
"gallery:openExternal": (path: string) => IpcResult<void>;
"gallery:delete": (paths: string[]) => IpcResult<void>;
"gallery:thumbStats": () => IpcResult<ThumbCacheStats>;
"gallery:thumbClear": () => IpcResult<ThumbCacheStats>;
"enhancements:snapshot": () => IpcResult<EnhancementsSnapshot>;
"enhancements:setEnabled": (p: {
id: EnhancementId;
enabled: boolean;
}) => IpcResult<EnhancementsSnapshot>;
"debug:snapshot": () => IpcResult<DebugSnapshot>;
"debug:cacheInvalidate": (key: string) => IpcResult<CacheUpdate>;
"debug:cacheClear": () => IpcResult<CacheUpdate>;
"debug:repoStats": () => IpcResult<RepoStats[]>;
"debug:repoInspect": (name: string) => IpcResult<StoredEntity<{ id: string }>[]>;
"debug:repoClear": (name: string) => IpcResult<RepoStats[]>;
"debug:repoFlush": (name: string) => IpcResult<RepoStats[]>;
"debug:openWindow": () => IpcResult<void>;
}
export interface IpcEvents {
"auth:changed": AuthStatus;
"accounts:changed": AccountsState;
"social:seed": SocialSnapshot;
"social:upsert": UserProfile;
"world:seed": WorldSnapshot;
"world:upsert": World;
"world:favoriteFolders": { userId: string; folders: FavoriteWorldFolder[]; done: boolean };
"game:changed": GameStatus;
"gallery:added": Photo;
"debug:log": LogEntry;
"debug:cache": CacheUpdate;
"ws:event": WsEvent;
}
export type IpcRequestChannel = keyof IpcRequests;
export type IpcEventChannel = keyof IpcEvents;
+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[];
}
+6
View File
@@ -0,0 +1,6 @@
export const TRAFFIC_LIGHT_INSET = 16;
const TRAFFIC_LIGHT_CLUSTER_WIDTH = 52;
const TRAFFIC_LIGHT_GUTTER = -8;
export const MAC_CONTENT_INSET =
TRAFFIC_LIGHT_INSET + TRAFFIC_LIGHT_CLUSTER_WIDTH + TRAFFIC_LIGHT_GUTTER;