This commit is contained in:
ryan-0324 2024-05-31 23:24:14 -04:00 committed by GitHub
parent fa252b5146
commit f183b773af
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 303 additions and 59 deletions

View file

@ -159,7 +159,11 @@ export default tseslint.config(
}],
"import/no-default-export": "error",
"import/no-unused-modules": "error",
"no-restricted-syntax": ["error", "TSEnumDeclaration[const=false]"],
"no-restricted-syntax": [
"error",
"ImportDeclaration[importKind=value]",
"TSEnumDeclaration[const=false]",
],
}
},
);

View file

@ -21,7 +21,7 @@
"devDependencies": {
"@eslint-types/unicorn": "^52.0.0",
"@stylistic/eslint-plugin": "^2.1.0",
"eslint": "^9.3.0",
"eslint": "^9.4.0",
"eslint-plugin-headers": "^1.1.2",
"eslint-plugin-import-x": "^0.5.1",
"eslint-plugin-simple-import-sort": "^12.1.0",

File diff suppressed because one or more lines are too long

View file

@ -18,6 +18,8 @@ export type ChannelRecord = GuildChannelRecord | PrivateChannelRecord | ThreadCh
export type GuildChannelRecord = GuildTextualChannelRecord | GuildVocalChannelRecord | ForumChannelRecord;
export type GuildSelectableChannelRecord = Exclude<GuildChannelRecord, GuildCategoryChannelRecord>;
type ChannelRecordOwnPropertyKeys = "application_id" | "appliedTags" | "availableTags" | "bitrate_" | "defaultAutoArchiveDuration" | "defaultForumLayout" | "defaultReactionEmoji" | "defaultSortOrder" | "defaultThreadRateLimitPerUser" | "flags_" | "guild_id" | "icon" | "iconEmoji" | "id" | "isMessageRequest" | "isMessageRequestTimestamp" | "isSpam" | "lastMessageId" | "lastPinTimestamp" | "member" | "memberCount" | "memberIdsPreview" | "memberListId" | "messageCount" | "name" | "nicks" | "nsfw_" | "originChannelId" | "ownerId" | "parentChannelThreadType" | "parent_id" | "permissionOverwrites_" | "position_" | "rateLimitPerUser_" | "rawRecipients" | "recipients" | "rtcRegion" | "safetyWarnings" | "template" | "themeColor" | "threadMetadata" | "topic_" | "totalMessageSent" | "type" | "userLimit_" | "version" | "videoQualityMode";
export type ChannelRecordOwnProperties<ChannelRecord extends ChannelRecordBase> = Pick<ChannelRecord, ChannelRecordOwnPropertyKeys>;

View file

@ -8,7 +8,7 @@
export type Defined<T> = Exclude<T, undefined>;
/** @internal */
export type GenericConstructor = new (...args: any[]) => any;
export type GenericConstructor = new (...args: any[]) => unknown;
/** @internal */
export type Nullish = null | undefined;

View file

@ -21,7 +21,6 @@ export class DraftStore<
Action extends FluxAction = DraftStoreAction
> extends FluxPersistedStore<Constructor, State, Action> {
static displayName: "DraftStore";
static migrations: any; // TEMP
static persistKey: "DraftStore";
getDraft(channelId: string, draftType: DraftType): string;

View file

@ -0,0 +1,88 @@
/*
* discord-types
* Copyright (C) 2024 Vencord project contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import type { ExtractAction, FluxAction } from "../flux/fluxActions";
import type { ChannelType, GuildChannelRecord, GuildSelectableChannelRecord } from "../general/channels/ChannelRecord";
import type { GuildCategoryChannelRecord } from "../general/channels/GuildTextualChannelRecord";
import type { GuildVocalChannelRecord } from "../general/channels/GuildVocalChannelRecord";
import type { Nullish } from "../internal";
import type { FluxStore } from "./abstract/FluxStore";
export type GuildChannelStoreAction = ExtractAction<FluxAction, "BACKGROUND_SYNC" | "CACHE_LOADED_LAZY" | "CHANNEL_CREATE" | "CHANNEL_DELETE" | "CHANNEL_SELECT" | "CHANNEL_UPDATES" | "CONNECTION_OPEN" | "GUILD_CREATE" | "GUILD_DELETE" | "GUILD_MEMBER_UPDATE" | "GUILD_ROLE_CREATE" | "GUILD_ROLE_DELETE" | "GUILD_ROLE_UPDATE" | "GUILD_UPDATE" | "IMPERSONATE_STOP" | "IMPERSONATE_UPDATE" | "OVERLAY_INITIALIZE" | "VOICE_CHANNEL_SELECT" | "VOICE_CHANNEL_STATUS_UPDATE" | "VOICE_STATE_UPDATES">;
export class GuildChannelStore<Action extends FluxAction = GuildChannelStoreAction> extends FluxStore<Action> {
static displayName: "GuildChannelStore";
getAllGuilds(): { [guildId: string]: GuildChannels | undefined; };
getChannels(guildId?: string | Nullish): GuildChannels;
getDefaultChannel<SearchVocal extends boolean | undefined = undefined>(
guild: string,
searchVocal?: SearchVocal, /* = false */
permissions?: /* Permissions */ bigint | undefined /* = Permissions.VIEW_CHANNEL */
): GuildChannelFromSearchVocal<SearchVocal>;
getDirectoryChannelIds(guildId: string): string[];
getFirstChannel<SearchVocal extends boolean | undefined = undefined>(
guildId: string,
predicate: (
value: GuildChannelFromSearchVocal<SearchVocal>,
index: number,
array: GuildChannelFromSearchVocal<SearchVocal>[]
) => unknown,
searchVocal?: SearchVocal /* = false */
): GuildChannelFromSearchVocal<SearchVocal> | null;
getFirstChannelOfType<Type extends GuildChannelType>(
guildId: string,
predicate: (
value: GuildChannelFromType<Type>,
index: number,
array: GuildChannelFromType<Type>[]
) => unknown,
type: Type
): GuildChannelFromType<Type> | null;
getSelectableChannelIds(guildId: string): string[];
getSelectableChannels(guildId: string): GuildChannel<GuildSelectableChannelRecord>[];
getSFWDefaultChannel<SearchVocal extends boolean | undefined = undefined>(
guild: string,
searchVocal?: SearchVocal, /* = false */
permissions?: /* Permissions */ bigint | undefined /* = Permissions.VIEW_CHANNEL */
): GuildChannelFromSearchVocal<SearchVocal>;
getTextChannelNameDisambiguations(guildId?: string | Nullish): {
[channelId: string]: { id: string; name: string; };
};
getVocalChannelIds(guildId: string): string[];
hasCategories(guildId: string): boolean;
hasChannels(guildId: string): boolean;
hasElevatedPermissions(guildId: string): boolean;
hasSelectableChannel(guildId: string, channelId: string): boolean;
}
export interface GuildChannels {
count: number;
[GuildChannelType.CATEGORY]: GuildChannel<GuildCategoryChannelRecord>[];
[GuildChannelType.SELECTABLE]: GuildChannel<GuildSelectableChannelRecord>[];
[GuildChannelType.VOCAL]: GuildChannel<GuildVocalChannelRecord>[];
id: string; // guildId
}
// Does not actually exist.
export const enum GuildChannelType {
CATEGORY = ChannelType.GUILD_CATEGORY,
SELECTABLE = "SELECTABLE",
VOCAL = "VOCAL",
}
export interface GuildChannel<Channel extends GuildChannelRecord = GuildChannelRecord> {
channel: Channel;
comparator: number;
}
type GuildChannelFromSearchVocal<SearchVocal extends boolean | undefined>
= GuildChannel<GuildSelectableChannelRecord> | (SearchVocal extends true
? GuildChannel<GuildVocalChannelRecord>
: never);
type GuildChannelFromType<Type extends GuildChannelType>
= GuildChannels[Type] extends (infer Channel)[] ? Channel : never;

View file

@ -0,0 +1,55 @@
/*
* discord-types
* Copyright (C) 2024 Vencord project contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import type { ExtractAction, FluxAction } from "../flux/fluxActions";
import type { ChannelRecord } from "../general/channels/ChannelRecord";
import type { GuildRecord } from "../general/GuildRecord";
import type { Role } from "../general/Role";
import type { UserRecord } from "../general/UserRecord";
import type { FluxStore } from "./abstract/FluxStore";
export type PermissionStoreAction = ExtractAction<FluxAction, "BACKGROUND_SYNC" | "CACHE_LOADED" | "CACHE_LOADED_LAZY" | "CHANNEL_CREATE" | "CHANNEL_DELETE" | "CHANNEL_UPDATES" | "CONNECTION_CLOSED" | "CONNECTION_OPEN" | "CURRENT_USER_UPDATE" | "GUILD_CREATE" | "GUILD_DELETE" | "GUILD_FEED_FETCH_SUCCESS" | "GUILD_MEMBER_ADD" | "GUILD_MEMBER_UPDATE" | "GUILD_ROLE_CREATE" | "GUILD_ROLE_DELETE" | "GUILD_ROLE_UPDATE" | "GUILD_UPDATE" | "IMPERSONATE_STOP" | "IMPERSONATE_UPDATE" | "LOAD_ARCHIVED_THREADS_SUCCESS" | "LOAD_MESSAGES_SUCCESS" | "LOAD_THREADS_SUCCESS" | "LOGOUT" | "MOD_VIEW_SEARCH_FINISH" | "OVERLAY_INITIALIZE" | "SEARCH_FINISH" | "STAGE_INSTANCE_CREATE" | "STAGE_INSTANCE_DELETE" | "STAGE_INSTANCE_UPDATE" | "THREAD_CREATE" | "THREAD_LIST_SYNC" | "THREAD_MEMBERS_UPDATE" | "THREAD_MEMBER_UPDATE" | "THREAD_UPDATE">;
export class PermissionStore<Action extends FluxAction = PermissionStoreAction> extends FluxStore<Action> {
static displayName: "PermissionStore";
can(e?: any, t?: any, n?: any, i?: any, r?: any): boolean; // TEMP
canAccessGuildSettings(guild: GuildRecord): boolean;
canAccessMemberSafetyPage(guild: GuildRecord): boolean;
canBasicChannel(e?: any, t?: any, n?: any, i?: any, r?: any): boolean; // TEMP
canImpersonateRole(guild: GuildRecord, role: Role): boolean;
canManageUser(
permissions: /* Permissions */ bigint,
userOrUserId: UserRecord | string,
guild: GuildRecord
): boolean;
canWithPartialContext(e?: any, t?: any): boolean; // TEMP
computeBasicPermissions(arg: Record<string, any>): /* Permissions */ bigint; // TEMP
computePermissions(guildOrChannel: GuildRecord | ChannelRecord, t?: any, n?: any, i?: any): any; // TEMP
getChannelPermissions(channel: ChannelRecord): /* Permissions */ bigint;
getChannelsVersion(): number;
getGuildPermissionProps(guild: GuildRecord): {
canAccessMembersPage: boolean;
canManageBans: boolean;
canManageChannels: boolean;
canManageGuild: boolean;
canManageGuildExpressions: boolean;
canManageNicknames: boolean;
canManageRoles: boolean;
canManageWebhooks: boolean;
canViewAuditLog: boolean;
canViewAuditLogV2: boolean;
canViewGuildAnalytics: boolean;
guild: GuildRecord;
isGuildAdmin: boolean;
isOwner: boolean;
isOwnerWithRequiredMfaLevel: boolean;
};
getGuildPermissions(guild: GuildRecord): /* Permissions */ bigint;
getGuildVersion(guildId: string): number;
getHighestRole(guild: GuildRecord): Role;
isRoleHigher(guild: GuildRecord, roleA: Role, roleB: Role): boolean;
}

View file

@ -0,0 +1,36 @@
/*
* discord-types
* Copyright (C) 2024 Vencord project contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import type { ExtractAction, FluxAction } from "../flux/fluxActions";
import type { FluxStore } from "./abstract/FluxStore";
export type PresenceStoreAction = ExtractAction<FluxAction, "ACTIVITY_METADATA_UPDATE" | "CONNECTION_OPEN" | "CONNECTION_OPEN_SUPPLEMENTAL" | "GUILD_CREATE" | "GUILD_DELETE" | "GUILD_MEMBER_REMOVE" | "OVERLAY_INITIALIZE" | "PRESENCES_REPLACE" | "PRESENCE_UPDATES" | "SELF_PRESENCE_STORE_UPDATE" | "THREAD_MEMBERS_UPDATE" | "THREAD_MEMBER_LIST_UPDATE">;
// Does not extend PersistedStore.
export class PresenceStore<Action extends FluxAction = PresenceStoreAction> extends FluxStore<Action> {
static displayName: "PresenceStore";
findActivity(e?: any, t?: any): any; // TEMP
getActivities(e?: any): any; // TEMP
getActivityMetadata(e?: any): any; // TEMP
getAllApplicationActivities(e?: any): any; // TEMP
getApplicationActivity(e?: any, t?: any): any; // TEMP
getClientStatus(e?: any): any; // TEMP
getLastOnlineTimestamp(e?: any): any; // TEMP
getPrimaryActivity(e?: any): any; // TEMP
getState(): {
activities: any; // TEMP
activityMetadata: any; // TEMP
clientStatuses: any; // TEMP
lastOnlineTimestamps: any; // TEMP
presencesForGuilds: any; // TEMP
statuses: any; // TEMP
}; // TEMP
getStatus(e?: any): any; // TEMP
getUserIds(): any; // TEMP
isMobileOnline(e?: any): any; // TEMP
setCurrentUserOnConnectionOpen(e?: any, t?: any): any; // TEMP
}

View file

@ -0,0 +1,41 @@
/*
* discord-types
* Copyright (C) 2024 Vencord project contributors
* SPDX-License-Identifier: GPL-3.0-or-later
*/
import type { ExtractAction, FluxAction } from "../flux/fluxActions";
import type { FluxStore } from "./abstract/FluxStore";
export type ReadStateStoreAction = ExtractAction<FluxAction, "BACKGROUND_SYNC_CHANNEL_MESSAGES" | "BULK_ACK" | "CACHE_LOADED" | "CHANNEL_ACK" | "CHANNEL_CREATE" | "CHANNEL_DELETE" | "CHANNEL_LOCAL_ACK" | "CHANNEL_PINS_ACK" | "CHANNEL_PINS_UPDATE" | "CHANNEL_RTC_UPDATE_CHAT_OPEN" | "CHANNEL_SELECT" | "CLEAR_OLDEST_UNREAD_MESSAGE" | "CONNECTION_OPEN" | "CONNECTION_OPEN_SUPPLEMENTAL" | "CURRENT_USER_UPDATE" | "DECAY_READ_STATES" | "DISABLE_AUTOMATIC_ACK" | "DRAWER_CLOSE" | "DRAWER_OPEN" | "ENABLE_AUTOMATIC_ACK" | "GUILD_CREATE" | "GUILD_DELETE" | "GUILD_FEATURE_ACK" | "GUILD_SCHEDULED_EVENT_CREATE" | "GUILD_SCHEDULED_EVENT_DELETE" | "GUILD_SCHEDULED_EVENT_UPDATE" | "GUILD_UPDATE" | "LOAD_ARCHIVED_THREADS_SUCCESS" | "LOAD_MESSAGES_SUCCESS" | "LOAD_THREADS_SUCCESS" | "LOGOUT" | "MESSAGE_ACK" | "MESSAGE_CREATE" | "MESSAGE_DELETE" | "MESSAGE_DELETE_BULK" | "MESSAGE_REQUEST_ACK" | "MESSAGE_REQUEST_CLEAR_ACK" | "MOD_VIEW_SEARCH_FINISH" | "NOTIFICATION_CENTER_ITEMS_ACK" | "NOTIFICATION_CENTER_ITEM_CREATE" | "OVERLAY_INITIALIZE" | "PASSIVE_UPDATE_V2" | "RELATIONSHIP_ADD" | "RELATIONSHIP_REMOVE" | "RESORT_THREADS" | "SEARCH_FINISH" | "THREAD_CREATE" | "THREAD_DELETE" | "THREAD_LIST_SYNC" | "THREAD_MEMBERS_UPDATE" | "THREAD_MEMBER_UPDATE" | "THREAD_UPDATE" | "TRY_ACK" | "UPDATE_CHANNEL_DIMENSIONS" | "USER_NON_CHANNEL_ACK" | "VOICE_CHANNEL_SELECT" | "WINDOW_FOCUS">;
export class ReadStateStore<Action extends FluxAction = ReadStateStoreAction> extends FluxStore<Action> {
static displayName: "ReadStateStore";
ackMessageId(e?: any): any; // TEMP
getAllReadStates(e?: any): any; // TEMP
getForDebugging(e?: any): any; // TEMP
getGuildChannelUnreadState(e?: any, t?: any, n?: any, i?: any, r?: any): any; // TEMP
getGuildUnreadsSentinel(e?: any): any; // TEMP
getMentionChannelIds(): any; // TEMP
getMentionCount(e?: any): any; // TEMP
getNonChannelAckId(e?: any): any; // TEMP
getNotifCenterReadState(e?: any): any; // TEMP
getOldestUnreadMessageId(e?: any): any; // TEMP
getOldestUnreadTimestamp(e?: any): any; // TEMP
getReadStatesByChannel(): any; // TEMP
getSnapshot(e?: any, t?: any): any; // TEMP
getTrackedAckMessageId(e?: any): any; // TEMP
getUnreadCount(e?: any): any; // TEMP
hasOpenedThread(e?: any): any; // TEMP
hasRecentlyVisitedAndRead(e?: any): any; // TEMP
hasTrackedUnread(e?: any): any; // TEMP
hasUnread(e?: any): any; // TEMP
hasUnreadPins(e?: any): any; // TEMP
isEstimated(e?: any): any; // TEMP
isForumPostUnread(e?: any): any; // TEMP
isNewForumThread(e?: any, t?: any, n?: any): any; // TEMP
lastMessageId(e?: any): any; // TEMP
lastMessageTimestamp(e?: any): any; // TEMP
lastPinTimestamp(e?: any): any; // TEMP
}

View file

@ -17,15 +17,5 @@ export class WindowStore<Action extends FluxAction = WindowStoreAction> extends
isElementFullScreen(windowId?: string | undefined): boolean;
isFocused(windowId?: string | undefined): boolean;
isVisible(windowId?: string | undefined): boolean;
windowSize(windowId?: string | undefined): Window["windowSize"];
}
export interface Window {
focused: boolean;
isElementFullscreen: boolean;
visible: boolean;
windowSize: {
height: number;
width: number;
};
windowSize(windowId?: string | undefined): { height: number; width: number; };
}

View file

@ -13,37 +13,40 @@ import type { FluxStore } from "./FluxStore";
// Original name: PersistedStore
export abstract class FluxPersistedStore<
Constructor extends GenericConstructor = GenericConstructor,
State = any,
State = unknown,
Action extends FluxAction = FluxAction
> extends FluxStore<Action> {
constructor(dispatcher: FluxDispatcher, actionHandlers: FluxActionHandlerMap<Action>);
static _clearAllPromise: Promise<void> | Nullish;
static _writePromises: Map<any, any>; // TEMP
static _writeResolvers: Map<any, any>; // TEMP
static _writePromises: Map</* persistKey: */string, Promise<void>>;
static _writeResolvers: Map</* persistKey: */string, [resolver: () => void, callbackId: number]>;
static allPersistKeys: Set<string>;
static clearAll(e: any): Promise<void>; // TEMP
static clearPersistQueue(e: any): void; // TEMP
static clearAll(options: FluxPersistedStoreClearOptions): Promise<void>;
static clearPersistQueue(options: FluxPersistedStoreClearOptions): void;
static disableWrite: boolean;
static disableWrites: boolean;
static getAllStates(): Promise<any>; // TEMP
static initializeAll(stateMap: Record<string, any>): void; // TEMP
static migrateAndReadStoreState(e: any, t: any): { // TEMP
requiresPersist: boolean;
state: any /* | undefined */; // TEMP
};
static migrations: ((...args: any[]) => any)[] | undefined;
static persistKey: string; // not actually defined on PersistedStore's constructor, but all subclasses are required to have it
static shouldClear(e: any, t: any): boolean; // TEMP
static getAllStates(): Promise<{ [persistKey: string]: unknown; }>;
static initializeAll(stateMap: { [persistKey: string]: unknown; }): void;
/**
* If {@link clearAll} has been called for the specified persist key, state in the returned object will be undefined.
*/
static migrateAndReadStoreState<NewestState = unknown, OldStates extends unknown[] = unknown[]>(
persistKey: string,
migrations?: FluxPersistedStoreMigrations<[...OldStates, NewestState]> | Nullish
): { requiresPersist: boolean; state: NewestState; } | { requiresPersist: false; state: undefined; };
static migrations: ((oldState: any) => unknown)[] | undefined;
static persistKey: string; // abstract
static shouldClear(options: FluxPersistedStoreClearOptions, persistKey: string): boolean;
static throttleDelay: number;
static userAgnosticPersistKeys: Set<string>;
asyncPersist(): Promise<boolean | undefined>;
clear(): void;
getClass(): Constructor;
abstract getState(): State; // TEMP
abstract initialize(state: State): void; // TEMP
initializeFromState(state: State): void; // TEMP
abstract getState(): State;
abstract initialize(state: State): void;
initializeFromState(state: State): void;
persist(): void;
_version: number;
@ -54,3 +57,23 @@ export abstract class FluxPersistedStore<
flush: () => () => void;
};
}
export interface FluxPersistedStoreClearOptions {
/** Array of persist keys. */
omit?: string[] | Nullish;
type: "all" | "user-data-only";
}
type MigrationsFromTuple<States extends unknown[]>
= States extends [infer OldState, infer NewState, ...infer NewerStates]
? [(oldState: OldState) => NewState, ...MigrationsFromTuple<[NewState, ...NewerStates]>]
: [];
export type FluxPersistedStoreMigrations<States extends unknown[] = unknown[]>
= States extends [infer OldState, ...infer NewerStates]
? NewerStates extends []
? [(oldState: OldState) => unknown]
: MigrationsFromTuple<States>
: States extends (infer T)[]
? ((oldState: T) => T)[]
: never;

View file

@ -5,7 +5,7 @@
*/
import type { FluxActionHandlerMap } from "../../flux/fluxActionHandlers";
import type { ExcludeAction, FluxAction } from "../../flux/fluxActions";
import type { ExcludeAction, ExtractAction, FluxAction } from "../../flux/fluxActions";
import type { GenericConstructor } from "../../internal";
import type { FluxStore } from "./FluxStore";
@ -14,19 +14,21 @@ export interface FluxSnapshot<SnapshotData = any> {
version: number;
}
export type FluxSnapshotStoreAction = ExcludeAction<FluxAction, "CLEAR_CACHES" | "WRITE_CACHES">;
type CacheActionType = "CLEAR_CACHES" | "WRITE_CACHES";
export type FluxSnapshotStoreAction = ExcludeAction<FluxAction, CacheActionType>;
// Original name: SnapshotStore
export abstract class FluxSnapshotStore<
Constructor extends GenericConstructor = GenericConstructor,
SnapshotData = any,
SnapshotData = unknown,
Action extends FluxSnapshotStoreAction = FluxSnapshotStoreAction
> extends FluxStore<Action & Exclude<FluxAction, FluxSnapshotStoreAction>> {
> extends FluxStore<Action & ExtractAction<FluxAction, CacheActionType>> {
constructor(actionHandlers: FluxActionHandlerMap<Action>);
static allStores: FluxSnapshotStore[];
static clearAll(): void;
static displayName: string; // not actually defined on SnapshotStore's constructor, but all subclasses are required to have it
static displayName: string; // abstract
clear(): void;
getClass(): Constructor;

View file

@ -21,7 +21,7 @@ export abstract class FluxStore<Action extends FluxAction = FluxAction> {
static displayName: string | undefined; // undefined on FluxStore's constructor
static getAll(): FluxStore[];
static initialize(): void;
static initialized: Promise<undefined>;
static initialized: Promise<void>;
emitChange(): void;
getDispatchToken(): string;

View file

@ -9,9 +9,13 @@ export * from "./ApplicationStore";
export * from "./ChannelStore";
export * from "./DraftStore";
export * from "./EmojiStore";
export * from "./GuildChannelStore";
export * from "./GuildMemberStore";
export * from "./GuildStore";
export * from "./MessageStore";
export * from "./PermissionStore";
export * from "./PresenceStore";
export * from "./ReadStateStore";
export * from "./RelationshipStore";
export * from "./SelectedChannelStore";
export * from "./SelectedGuildStore";