From 5c892bb8a175f9067c6dbd0b3be982851b8248dc Mon Sep 17 00:00:00 2001 From: PalmDevs Date: Tue, 7 Apr 2026 22:01:49 +0700 Subject: [PATCH] fix(lib/plugins/apis): set most APIs during pre-init phase --- lib/discord/package.json | 3 - lib/discord/src/types/api.ts | 35 ---------- lib/externals/package.json | 3 - lib/externals/src/types.ts | 13 ---- lib/plugins/src/apis/discord.ts | 85 ++++++++++++++++++++++++ lib/plugins/src/apis/externals.ts | 35 ++++++++++ lib/plugins/src/apis/index.ts | 28 ++++++++ lib/plugins/src/types.ts | 12 ++-- lib/utils/src/types.ts | 2 +- src/plugins/init/api.assets/index.ts | 23 ------- src/plugins/init/api.components/index.ts | 28 -------- src/plugins/init/api.discord/index.ts | 81 ---------------------- src/plugins/init/api.externals/index.ts | 48 ------------- src/plugins/preinit/api.discord/index.ts | 37 +++++++++++ src/plugins/preinit/api.utils/index.ts | 2 +- 15 files changed, 194 insertions(+), 241 deletions(-) delete mode 100644 lib/externals/src/types.ts create mode 100644 lib/plugins/src/apis/discord.ts create mode 100644 lib/plugins/src/apis/externals.ts delete mode 100644 src/plugins/init/api.assets/index.ts delete mode 100644 src/plugins/init/api.components/index.ts delete mode 100644 src/plugins/init/api.discord/index.ts delete mode 100644 src/plugins/init/api.externals/index.ts create mode 100644 src/plugins/preinit/api.discord/index.ts diff --git a/lib/discord/package.json b/lib/discord/package.json index 67ccbda..132e12b 100644 --- a/lib/discord/package.json +++ b/lib/discord/package.json @@ -48,9 +48,6 @@ "./types": { "types": "./src/types/index.ts" }, - "./types/api": { - "types": "./src/types/api.ts" - }, "./_/modules/settings": { "default": "./src/modules/settings/_internal.ts" } diff --git a/lib/discord/src/types/api.ts b/lib/discord/src/types/api.ts index 5c684eb..58ca768 100644 --- a/lib/discord/src/types/api.ts +++ b/lib/discord/src/types/api.ts @@ -1,41 +1,6 @@ import type { DiscordModules } from '.' -export interface PluginApiDiscord { - actions: PluginApiDiscord.Actions - common: PluginApiDiscord.Common - design: PluginApiDiscord.Design - flux: PluginApiDiscord.Flux - modules: PluginApiDiscord.Modules - native: PluginApiDiscord.Native - utils: PluginApiDiscord.Utils -} - -export namespace PluginApiDiscord { - export type Actions = typeof import('@revenge-mod/discord/actions') - export type Common = typeof import('@revenge-mod/discord/common') - export type Design = typeof import('@revenge-mod/discord/design') - export type Flux = typeof import('@revenge-mod/discord/flux') - export type Native = typeof import('@revenge-mod/discord/native') - - export interface Utils { - finders: typeof import('@revenge-mod/discord/utils/modules/finders') - metro: { - subscriptions: typeof import('@revenge-mod/discord/utils/modules/metro/subscriptions') - } - } - - export interface Modules { - mainTabsV2: typeof import('@revenge-mod/discord/modules/main_tabs_v2') - settings: typeof import('@revenge-mod/discord/modules/settings') & - typeof import('@revenge-mod/discord/modules/settings/renderer') - } -} - declare module '@revenge-mod/plugins/types' { - export interface UnscopedInitPluginApi { - discord: PluginApiDiscord - } - export interface InitPluginApi { logger: DiscordModules.Logger } diff --git a/lib/externals/package.json b/lib/externals/package.json index a44e4bf..7ec2cad 100644 --- a/lib/externals/package.json +++ b/lib/externals/package.json @@ -17,9 +17,6 @@ }, "./shopify": { "default": "./src/shopify.ts" - }, - "./types": { - "types": "./src/types.ts" } } } diff --git a/lib/externals/src/types.ts b/lib/externals/src/types.ts deleted file mode 100644 index f5d95f2..0000000 --- a/lib/externals/src/types.ts +++ /dev/null @@ -1,13 +0,0 @@ -export interface PluginApiExternals { - Browserify: typeof import('@revenge-mod/externals/browserify') - ReactNativeClipboard: typeof import('@revenge-mod/externals/react-native-clipboard') - ReactNativeSafeAreaContext: typeof import('@revenge-mod/externals/react-native-safe-area-context') - ReactNavigation: typeof import('@revenge-mod/externals/react-navigation') - Shopify: typeof import('@revenge-mod/externals/shopify') -} - -declare module '@revenge-mod/plugins/types' { - export interface UnscopedInitPluginApi { - externals: PluginApiExternals - } -} diff --git a/lib/plugins/src/apis/discord.ts b/lib/plugins/src/apis/discord.ts new file mode 100644 index 0000000..396284f --- /dev/null +++ b/lib/plugins/src/apis/discord.ts @@ -0,0 +1,85 @@ +import defer * as DiscordActions from '@revenge-mod/discord/actions' +import defer * as DiscordCommon from '@revenge-mod/discord/common' +import defer * as DiscordDesign from '@revenge-mod/discord/design' +import defer * as DiscordFlux from '@revenge-mod/discord/flux' +import defer * as DiscordModulesMainTabsV2 from '@revenge-mod/discord/modules/main_tabs_v2' +import defer * as DiscordNative from '@revenge-mod/discord/native' +import defer * as DiscordUtilsFinders from '@revenge-mod/discord/utils/modules/finders' +import defer * as DiscordUtilsMetroSubscriptions from '@revenge-mod/discord/utils/modules/metro/subscriptions' +import { defineLazyProperties } from '@revenge-mod/utils/object' +import { guardIndexInitialized } from '.' + +export interface PluginApiDiscord { + actions: PluginApiDiscord.Actions + /** + * This submodule is only available after the index module (ID 0) is initialized. + * Attempting to access it before then will throw an error. + */ + common: PluginApiDiscord.Common + design: PluginApiDiscord.Design + flux: PluginApiDiscord.Flux + modules: PluginApiDiscord.Modules + native: PluginApiDiscord.Native + utils: PluginApiDiscord.Utils +} + +export namespace PluginApiDiscord { + export type Actions = typeof import('@revenge-mod/discord/actions') + export type Common = typeof import('@revenge-mod/discord/common') + export type Design = typeof import('@revenge-mod/discord/design') + export type Flux = typeof import('@revenge-mod/discord/flux') + export type Native = typeof import('@revenge-mod/discord/native') + + export interface Utils { + finders: typeof import('@revenge-mod/discord/utils/modules/finders') + metro: { + subscriptions: typeof import('@revenge-mod/discord/utils/modules/metro/subscriptions') + } + } + + export interface Modules { + mainTabsV2: typeof import('@revenge-mod/discord/modules/main_tabs_v2') + settings: typeof import('@revenge-mod/discord/modules/settings') & + typeof import('@revenge-mod/discord/modules/settings/renderer') + } +} + +export const discord = defineLazyProperties( + { + modules: defineLazyProperties({} as PluginApiDiscord.Modules, { + mainTabsV2: () => { + return DiscordModulesMainTabsV2 + }, + settings: () => ({ + ...require('@revenge-mod/discord/modules/settings'), + ...require('@revenge-mod/discord/modules/settings/renderer'), + }), + }), + utils: defineLazyProperties({} as PluginApiDiscord.Utils, { + finders: () => { + return DiscordUtilsFinders + }, + metro: () => ({ + subscriptions: DiscordUtilsMetroSubscriptions, + }), + }), + } as PluginApiDiscord, + { + actions: () => { + return DiscordActions + }, + common: () => { + guardIndexInitialized('Discord.common') + return DiscordCommon + }, + flux: () => { + return DiscordFlux + }, + design: () => { + return DiscordDesign + }, + native: () => { + return DiscordNative + }, + }, +) diff --git a/lib/plugins/src/apis/externals.ts b/lib/plugins/src/apis/externals.ts new file mode 100644 index 0000000..eb2b9e8 --- /dev/null +++ b/lib/plugins/src/apis/externals.ts @@ -0,0 +1,35 @@ +import defer * as Browserify from '@revenge-mod/externals/browserify' +import defer * as ReactNativeClipboard from '@revenge-mod/externals/react-native-clipboard' +import defer * as ReactNativeSafeAreaContext from '@revenge-mod/externals/react-native-safe-area-context' +import defer * as ReactNavigation from '@revenge-mod/externals/react-navigation' +import defer * as Shopify from '@revenge-mod/externals/shopify' +import { defineLazyProperties } from '@revenge-mod/utils/object' + +export interface PluginApiExternals { + Browserify: typeof import('@revenge-mod/externals/browserify') + ReactNativeClipboard: typeof import('@revenge-mod/externals/react-native-clipboard') + ReactNativeSafeAreaContext: typeof import('@revenge-mod/externals/react-native-safe-area-context') + ReactNavigation: typeof import('@revenge-mod/externals/react-navigation') + Shopify: typeof import('@revenge-mod/externals/shopify') +} + +export const externals: PluginApiExternals = defineLazyProperties( + {} as PluginApiExternals, + { + Browserify: () => { + return Browserify + }, + ReactNativeClipboard: () => { + return ReactNativeClipboard + }, + ReactNativeSafeAreaContext: () => { + return ReactNativeSafeAreaContext + }, + ReactNavigation: () => { + return ReactNavigation + }, + Shopify: () => { + return Shopify + }, + }, +) diff --git a/lib/plugins/src/apis/index.ts b/lib/plugins/src/apis/index.ts index 5768fe9..6f8d097 100644 --- a/lib/plugins/src/apis/index.ts +++ b/lib/plugins/src/apis/index.ts @@ -1,4 +1,10 @@ +import * as assets from '@revenge-mod/assets' +import defer * as Components from '@revenge-mod/components' +import { isModuleInitialized } from '@revenge-mod/modules/metro/utils' import * as patcher from '@revenge-mod/patcher' +import { defineLazyProperties } from '@revenge-mod/utils/object' +import defer * as Discord from './discord' +import { externals } from './externals' import { modules } from './modules' import { plugins } from './plugins' import { react } from './react' @@ -17,6 +23,28 @@ export const pUnscopedApi: patcher, plugins, react, + assets, + externals, +} + +defineLazyProperties(pUnscopedApi, { + components: () => { + guardIndexInitialized('Components') + return Components + }, +}) + +defineLazyProperties(pUnscopedApi, { + discord: () => { + return Discord.discord + }, +}) + +export function guardIndexInitialized(name: string) { + if (!isModuleInitialized(0)) + throw new Error( + `Cannot access ${name} API before index module (ID 0) is initialized`, + ) } export function spreadDescriptors( diff --git a/lib/plugins/src/types.ts b/lib/plugins/src/types.ts index 7948bd9..9ad9c01 100644 --- a/lib/plugins/src/types.ts +++ b/lib/plugins/src/types.ts @@ -1,4 +1,6 @@ import type { FunctionComponent } from 'react' +import type { PluginApiDiscord } from './apis/discord' +import type { PluginApiExternals } from './apis/externals' import type { PluginApiModules } from './apis/modules' import type { PluginApiPlugins } from './apis/plugins' import type { PluginApiReact } from './apis/react' @@ -19,6 +21,10 @@ export interface UnscopedPreInitPluginApi< patcher: typeof import('@revenge-mod/patcher') plugins: PluginApiPlugins react: PluginApiReact + assets: typeof import('@revenge-mod/assets') + externals: PluginApiExternals + components: typeof import('@revenge-mod/components') + discord: PluginApiDiscord } /** @@ -27,9 +33,7 @@ export interface UnscopedPreInitPluginApi< */ export interface UnscopedInitPluginApi< O extends PluginApiExtensionsOptions = PluginApiExtensionsOptions, -> extends UnscopedPreInitPluginApi { - assets: typeof import('@revenge-mod/assets') -} +> extends UnscopedPreInitPluginApi {} /** * The unscoped plugin API. This API is available as a global for plugins. @@ -112,7 +116,6 @@ export interface PreInitPluginApi< * The plugin API (limited). * Available in the `init` phase. */ -// @ts-expect-error export interface InitPluginApi< O extends PluginApiExtensionsOptions = PluginApiExtensionsOptions, > extends PreInitPluginApi { @@ -125,7 +128,6 @@ export interface InitPluginApi< * The plugin API. * Available in the `start` and `stop` phase. */ -// @ts-expect-error export interface PluginApi< O extends PluginApiExtensionsOptions = PluginApiExtensionsOptions, > extends InitPluginApi { diff --git a/lib/utils/src/types.ts b/lib/utils/src/types.ts index 7844d10..07f171d 100644 --- a/lib/utils/src/types.ts +++ b/lib/utils/src/types.ts @@ -28,10 +28,10 @@ export interface PreInitPluginApiUtils { promise: typeof import('@revenge-mod/utils/promise') proxy: typeof import('@revenge-mod/utils/proxy') tree: typeof import('@revenge-mod/utils/tree') + react: typeof import('@revenge-mod/utils/react') } export interface PluginApiUtils extends PreInitPluginApiUtils { - react: typeof import('@revenge-mod/utils/react') discord: typeof import('@revenge-mod/utils/discord') } diff --git a/src/plugins/init/api.assets/index.ts b/src/plugins/init/api.assets/index.ts deleted file mode 100644 index cf0e118..0000000 --- a/src/plugins/init/api.assets/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -import * as assets from '@revenge-mod/assets' -import { InternalPluginFlags, registerPlugin } from '@revenge-mod/plugins/_' -import { PluginFlags } from '@revenge-mod/plugins/constants' - -registerPlugin( - { - id: 'revenge.api.assets', - name: 'Assets API', - description: '@revenge-mod/assets API for plugins.', - author: 'Revenge', - icon: 'PollsIcon', - }, - { - init({ unscoped }) { - unscoped.assets = assets - }, - }, - PluginFlags.Enabled, - // biome-ignore format: Don't format this - InternalPluginFlags.Internal | - InternalPluginFlags.Essential | - InternalPluginFlags.API, -) diff --git a/src/plugins/init/api.components/index.ts b/src/plugins/init/api.components/index.ts deleted file mode 100644 index 028e12e..0000000 --- a/src/plugins/init/api.components/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -import defer * as Components from '@revenge-mod/components' -import { InternalPluginFlags, registerPlugin } from '@revenge-mod/plugins/_' -import { PluginFlags } from '@revenge-mod/plugins/constants' -import { defineLazyProperties } from '@revenge-mod/utils/object' - -registerPlugin( - { - id: 'revenge.api.components', - name: 'Components API', - description: '@revenge-mod/components API for plugins.', - author: 'Revenge', - icon: 'PollsIcon', - }, - { - init({ unscoped }) { - defineLazyProperties(unscoped, { - components: () => { - return Components - }, - }) - }, - }, - PluginFlags.Enabled, - // biome-ignore format: Don't format this - InternalPluginFlags.Internal | - InternalPluginFlags.Essential | - InternalPluginFlags.API, -) diff --git a/src/plugins/init/api.discord/index.ts b/src/plugins/init/api.discord/index.ts deleted file mode 100644 index b953944..0000000 --- a/src/plugins/init/api.discord/index.ts +++ /dev/null @@ -1,81 +0,0 @@ -import defer * as DiscordActions from '@revenge-mod/discord/actions' -import defer * as DiscordCommon from '@revenge-mod/discord/common' -import { Logger } from '@revenge-mod/discord/common' -import defer * as DiscordDesign from '@revenge-mod/discord/design' -import defer * as DiscordFlux from '@revenge-mod/discord/flux' -import defer * as DiscordModulesMainTabsV2 from '@revenge-mod/discord/modules/main_tabs_v2' -import defer * as DiscordNative from '@revenge-mod/discord/native' -import { InternalPluginFlags, registerPlugin } from '@revenge-mod/plugins/_' -import { PluginFlags } from '@revenge-mod/plugins/constants' -import { - defineLazyProperties, - defineLazyProperty, -} from '@revenge-mod/utils/object' -import type { PluginApiDiscord } from '@revenge-mod/discord/types/api' - -registerPlugin( - { - id: 'revenge.api.discord', - name: 'Discord API', - description: '@revenge-mod/discord API for plugins.', - author: 'Revenge', - icon: 'PollsIcon', - }, - { - init({ unscoped, decorate }) { - decorate(plugin => { - defineLazyProperty( - plugin.api, - 'logger', - () => - new Logger(`Revenge > Plugins (${plugin.manifest.id})`), - ) - }) - - defineLazyProperties( - (unscoped.discord = { - modules: defineLazyProperties( - {} as PluginApiDiscord.Modules, - { - mainTabsV2: () => { - return DiscordModulesMainTabsV2 - }, - settings: () => ({ - ...require('@revenge-mod/discord/modules/settings'), - ...require('@revenge-mod/discord/modules/settings/renderer'), - }), - }, - ), - utils: { - finders: require('@revenge-mod/discord/utils/modules/finders'), - metro: { - subscriptions: require('@revenge-mod/discord/utils/modules/metro/subscriptions'), - }, - }, - } as PluginApiDiscord), - { - actions: () => { - return DiscordActions - }, - common: () => { - return DiscordCommon - }, - flux: () => { - return DiscordFlux - }, - design: () => { - return DiscordDesign - }, - native: () => { - return DiscordNative - }, - }, - ) - }, - }, - PluginFlags.Enabled, - // biome-ignore format: Don't format this - InternalPluginFlags.Internal | - InternalPluginFlags.Essential | - InternalPluginFlags.API, -) diff --git a/src/plugins/init/api.externals/index.ts b/src/plugins/init/api.externals/index.ts deleted file mode 100644 index d10f470..0000000 --- a/src/plugins/init/api.externals/index.ts +++ /dev/null @@ -1,48 +0,0 @@ -import defer * as Browserify from '@revenge-mod/externals/browserify' -import defer * as ReactNativeClipboard from '@revenge-mod/externals/react-native-clipboard' -import defer * as ReactNativeSafeAreaContext from '@revenge-mod/externals/react-native-safe-area-context' -import defer * as ReactNavigation from '@revenge-mod/externals/react-navigation' -import defer * as Shopify from '@revenge-mod/externals/shopify' -import { InternalPluginFlags, registerPlugin } from '@revenge-mod/plugins/_' -import { PluginFlags } from '@revenge-mod/plugins/constants' -import { defineLazyProperties } from '@revenge-mod/utils/object' -import type { PluginApiExternals } from '@revenge-mod/externals/types' - -registerPlugin( - { - id: 'revenge.api.externals', - name: 'Externals API', - description: '@revenge-mod/externals API for plugins.', - author: 'Revenge', - icon: 'PollsIcon', - }, - { - init({ unscoped }) { - defineLazyProperties( - (unscoped.externals = {} as PluginApiExternals), - { - Browserify: () => { - return Browserify - }, - ReactNativeClipboard: () => { - return ReactNativeClipboard - }, - ReactNativeSafeAreaContext: () => { - return ReactNativeSafeAreaContext - }, - ReactNavigation: () => { - return ReactNavigation - }, - Shopify: () => { - return Shopify - }, - }, - ) - }, - }, - PluginFlags.Enabled, - // biome-ignore format: Don't format this - InternalPluginFlags.Internal | - InternalPluginFlags.Essential | - InternalPluginFlags.API, -) diff --git a/src/plugins/preinit/api.discord/index.ts b/src/plugins/preinit/api.discord/index.ts new file mode 100644 index 0000000..3e37558 --- /dev/null +++ b/src/plugins/preinit/api.discord/index.ts @@ -0,0 +1,37 @@ +import { InternalPluginFlags, registerPlugin } from '@revenge-mod/plugins/_' +import { PluginFlags } from '@revenge-mod/plugins/constants' +import { defineLazyProperty } from '@revenge-mod/utils/object' + +registerPlugin( + { + id: 'revenge.api.discord', + name: 'Discord API', + description: '@revenge-mod/discord API for plugins.', + author: 'Revenge', + icon: 'PollsIcon', + }, + { + init({ + decorate, + unscoped: { + discord: { + common: { Logger }, + }, + }, + }) { + decorate(plugin => { + defineLazyProperty( + plugin.api, + 'logger', + () => + new Logger(`Revenge > Plugins (${plugin.manifest.id})`), + ) + }) + }, + }, + PluginFlags.Enabled, + // biome-ignore format: Don't format this + InternalPluginFlags.Internal | + InternalPluginFlags.Essential | + InternalPluginFlags.API, +) diff --git a/src/plugins/preinit/api.utils/index.ts b/src/plugins/preinit/api.utils/index.ts index ca9a4ea..46137df 100644 --- a/src/plugins/preinit/api.utils/index.ts +++ b/src/plugins/preinit/api.utils/index.ts @@ -26,11 +26,11 @@ registerPlugin( promise: UtilsPromise, proxy: UtilsProxy, tree: UtilsTree, + react: UtilsReact, } }, init({ unscoped: { utils } }) { utils.discord = UtilsDiscord - utils.react = UtilsReact }, }, PluginFlags.Enabled,