diff --git a/lib/discord/src/actions.ts b/lib/discord/src/actions.ts index 20e31eb..ea78490 100644 --- a/lib/discord/src/actions.ts +++ b/lib/discord/src/actions.ts @@ -3,7 +3,6 @@ import { byProps, every, preferExports, - relativeDep, withoutProps, } from '@revenge-mod/modules/finders/filters' import { @@ -19,6 +18,8 @@ import { proxify } from '@revenge-mod/utils/proxy' import { DispatcherModuleId } from './common/flux' import type { DiscordModules } from './types' +const { relative } = byDependencies + export let ActionSheetActionCreators: DiscordModules.Actions.ActionSheetActionCreators = proxify( () => { @@ -33,8 +34,8 @@ export let ActionSheetActionCreators: DiscordModules.Actions.ActionSheetActionCr ReactModuleId, ReactJsxRuntimeModuleId, DispatcherModuleId, - relativeDep(1), - relativeDep(2), + relative(1), + relative(2), 2, ]), ), @@ -59,7 +60,7 @@ export let AlertActionCreators: DiscordModules.Actions.AlertActionCreators = 'openAlert', ), byDependencies([ - [[], relativeDep(1)], + [[], relative(1)], [ReactNativeModuleId, 2], 2, ]), diff --git a/lib/discord/src/common/flux.ts b/lib/discord/src/common/flux.ts index 330c526..17d0f14 100644 --- a/lib/discord/src/common/flux.ts +++ b/lib/discord/src/common/flux.ts @@ -3,7 +3,6 @@ import { byProps, createFilterGenerator, preferExports, - relativeDep, } from '@revenge-mod/modules/finders/filters' import { lookupModule } from '@revenge-mod/modules/finders/lookup' import { waitForModules } from '@revenge-mod/modules/finders/wait' @@ -12,13 +11,15 @@ import type { Filter } from '@revenge-mod/modules/finders/filters' import type { Metro } from '@revenge-mod/modules/types' import type { DiscordModules } from '../types' +const { relative } = byDependencies + // ../discord_common/js/packages/flux export const [Dispatcher, DispatcherModuleId] = lookupModule( preferExports( byProps('_interceptors'), byDependencies([ - relativeDep(1), + relative(1), undefined, undefined, undefined, diff --git a/lib/discord/src/common/index.ts b/lib/discord/src/common/index.ts index c3dea99..d229186 100644 --- a/lib/discord/src/common/index.ts +++ b/lib/discord/src/common/index.ts @@ -2,10 +2,7 @@ import { byDependencies, byName, byProps, - every, - looseDeps, preferExports, - relativeDep, } from '@revenge-mod/modules/finders/filters' import { lookupModule } from '@revenge-mod/modules/finders/lookup' import { proxify } from '@revenge-mod/utils/proxy' @@ -15,6 +12,8 @@ import type { DiscordModules } from '../types' export { AppStartPerformance } from '../preinit' export * as Flux from './flux' +const { loose, relative } = byDependencies + // ../discord_common/js/shared/Logger.tsx export const [Logger] = lookupModule( byName('Logger'), @@ -33,22 +32,18 @@ export let Constants: DiscordModules.Constants = proxify( const [module] = lookupModule( preferExports( byProps('ME'), - every( - // ID: 1236 - // Deps: 26, 1237, 1238, 1239, 1240, ... - // Every module has only one dependency, which is the import tracker - byDependencies( - looseDeps([ - undefined, - relativeDep(1), - relativeDep(2), - relativeDep(3), - relativeDep(4), - ]), - ), - byDependencies( - looseDeps(new Array(5).fill(OnlyImportTrackerDep)), - ), + + // ID: 1236 + // Deps: 26, 1237, 1238, 1239, 1240, ... + // Every module has only one dependency, which is the import tracker + byDependencies( + loose([ + undefined, + relative.withDependencies(OnlyImportTrackerDep, 1), + relative.withDependencies(OnlyImportTrackerDep, 2), + relative.withDependencies(OnlyImportTrackerDep, 3), + relative.withDependencies(OnlyImportTrackerDep, 4), + ]), ), ), ) diff --git a/lib/discord/src/design.ts b/lib/discord/src/design.ts index 562d2be..a6995fb 100644 --- a/lib/discord/src/design.ts +++ b/lib/discord/src/design.ts @@ -2,9 +2,7 @@ import { byDependencies, byProps, bySingleProp, - looseDeps, preferExports, - relativeDep, } from '@revenge-mod/modules/finders/filters' import { lookupModule } from '@revenge-mod/modules/finders/lookup' import { @@ -15,6 +13,8 @@ import { import { proxify } from '@revenge-mod/utils/proxy' import type { DiscordModules } from './types' +const { loose, relative } = byDependencies + // design/native.tsx export let Design: Design = proxify( () => { @@ -24,11 +24,11 @@ export let Design: Design = proxify( preferExports( byProps('TableRow', 'Button'), byDependencies( - looseDeps([ - relativeDep(1), + loose([ + relative(1), undefined, - relativeDep(2), - relativeDep(3), + relative(2), + relative(3), 2, ]), ), @@ -58,7 +58,7 @@ export let FormSwitch: DiscordModules.Components.FormSwitch = proxify(() => { 'FormSwitch', ), byDependencies([ - [relativeDep(1), relativeDep(2), undefined, relativeDep(3)], + [relative(1), relative(2), undefined, relative(3)], ReactModuleId, ReactNativeModuleId, ReactJsxRuntimeModuleId, @@ -69,8 +69,8 @@ export let FormSwitch: DiscordModules.Components.FormSwitch = proxify(() => { undefined, undefined, undefined, - relativeDep(1), - relativeDep(2), + relative(1), + relative(2), 2, ]), ), diff --git a/lib/discord/src/modules/main_tabs_v2.ts b/lib/discord/src/modules/main_tabs_v2.ts index edc9653..55dd7a8 100644 --- a/lib/discord/src/modules/main_tabs_v2.ts +++ b/lib/discord/src/modules/main_tabs_v2.ts @@ -1,15 +1,14 @@ import { byDependencies, byProps, - every, - looseDeps, preferExports, - relativeDep, } from '@revenge-mod/modules/finders/filters' import { lookupModule } from '@revenge-mod/modules/finders/lookup' import { proxify } from '@revenge-mod/utils/proxy' import type { NavigationContainerRef } from '@react-navigation/core' +const { loose, relative } = byDependencies + export interface RootNavigationRef { getRootNavigationRef< T extends object = Record, @@ -21,15 +20,10 @@ export let RootNavigationRef: RootNavigationRef = proxify( const [module] = lookupModule( preferExports( byProps('getRootNavigationRef'), - every( - byDependencies([ - looseDeps([ - [], - looseDeps([relativeDep(1), relativeDep(2)]), - ]), - 2, - ]), - ), + byDependencies([ + loose([[], loose([relative(1), relative(2)])]), + 2, + ]), ), { includeUninitialized: true, diff --git a/lib/discord/src/modules/settings/renderer.ts b/lib/discord/src/modules/settings/renderer.ts index 1b6e860..7d3cf37 100644 --- a/lib/discord/src/modules/settings/renderer.ts +++ b/lib/discord/src/modules/settings/renderer.ts @@ -1,9 +1,7 @@ import { byDependencies, byProps, - looseDeps, preferExports, - relativeDep, } from '@revenge-mod/modules/finders/filters' import { lookupModule } from '@revenge-mod/modules/finders/lookup' import { @@ -14,6 +12,8 @@ import { import { proxify } from '@revenge-mod/utils/proxy' import type { DiscordModules } from '../../types' +const { loose, relative } = byDependencies + export type SettingListRenderer = DiscordModules.Modules.Settings.SettingListRenderer @@ -23,11 +23,11 @@ export let SettingListRenderer: SettingListRenderer = proxify( preferExports( byProps('SettingsList'), byDependencies( - looseDeps([ + loose([ ReactModuleId, ReactNativeModuleId, - relativeDep(1), - relativeDep(2), + relative(1), + relative(2), undefined, ReactJsxRuntimeModuleId, ]), diff --git a/lib/discord/src/preinit.ts b/lib/discord/src/preinit.ts index 6b8ea90..b5258b9 100644 --- a/lib/discord/src/preinit.ts +++ b/lib/discord/src/preinit.ts @@ -2,17 +2,18 @@ import { byDependencies, byProps, preferExports, - relativeDep, } from '@revenge-mod/modules/finders/filters' import { lookupModule } from '@revenge-mod/modules/finders/lookup' import type { Metro } from '@revenge-mod/modules/types' import type { DiscordModules } from './types' +const { relative } = byDependencies + // ../discord_common/js/shared/AppStartPerformance.tsx export const [AppStartPerformance] = lookupModule( preferExports( byProps('markAndLog'), - byDependencies([relativeDep(-1), undefined, undefined, 2]), + byDependencies([relative(-1), undefined, undefined, 2]), ), { includeUninitialized: true, diff --git a/lib/externals/src/browserify.ts b/lib/externals/src/browserify.ts index 8903615..5d5f6b2 100644 --- a/lib/externals/src/browserify.ts +++ b/lib/externals/src/browserify.ts @@ -1,20 +1,20 @@ import { byDependencies, byProps, - looseDeps, preferExports, - relativeDep, } from '@revenge-mod/modules/finders/filters' import { lookupModule } from '@revenge-mod/modules/finders/lookup' import { proxify } from '@revenge-mod/utils/proxy' +const { loose, relative } = byDependencies + export let nodeUtil: typeof import('node:util') = proxify( () => { const [module] = lookupModule( preferExports( byProps('inspect'), byDependencies([ - looseDeps([relativeDep(2, true), relativeDep(4, true)]), + loose([relative(2, true), relative(4, true)]), [], [], ]), diff --git a/lib/externals/src/react-native-clipboard.ts b/lib/externals/src/react-native-clipboard.ts index a36281d..063fa05 100644 --- a/lib/externals/src/react-native-clipboard.ts +++ b/lib/externals/src/react-native-clipboard.ts @@ -1,14 +1,14 @@ import { byDependencies, byProps, - every, preferExports, - relativeDep, } from '@revenge-mod/modules/finders/filters' import { lookupModule } from '@revenge-mod/modules/finders/lookup' import { ReactModuleId, ReactNativeModuleId } from '@revenge-mod/react' import { destructure, proxify } from '@revenge-mod/utils/proxy' +const { relative } = byDependencies + let ClipboardModule: typeof import('@react-native-clipboard/clipboard') = proxify( () => { @@ -26,13 +26,16 @@ let ClipboardModule: typeof import('@react-native-clipboard/clipboard') = const [module] = lookupModule( preferExports( byProps('useClipboard'), - every( - byDependencies([relativeDep(1), relativeDep(2)]), - byDependencies([ - [ReactModuleId, relativeDep(2, true)], - [ReactNativeModuleId, relativeDep(3, true)], - ]), - ), + byDependencies([ + relative.withDependencies( + [ReactModuleId, relative(2, true)], + 1, + ), + relative.withDependencies( + [ReactNativeModuleId, relative(3, true)], + 2, + ), + ]), ), { includeUninitialized: true, diff --git a/lib/externals/src/react-navigation.ts b/lib/externals/src/react-navigation.ts index 4510a9d..1267e1e 100644 --- a/lib/externals/src/react-navigation.ts +++ b/lib/externals/src/react-navigation.ts @@ -2,15 +2,14 @@ import { byDependencies, byName, byProps, - every, - looseDeps, preferExports, - relativeDep, } from '@revenge-mod/modules/finders/filters' import { lookupModule } from '@revenge-mod/modules/finders/lookup' import { ReactJsxRuntimeModuleId, ReactModuleId } from '@revenge-mod/react' import { proxify } from '@revenge-mod/utils/proxy' +const { loose, relative } = byDependencies + const [, _createClassModuleId] = lookupModule(byName('_createClass')) const [, _classCallCheckModuleId] = lookupModule(byName('_classCallCheck')) @@ -21,9 +20,9 @@ export let ReactNavigationNative: typeof import('@react-navigation/native') = preferExports( byProps('useLinkTo'), byDependencies( - looseDeps([ + loose([ [], - looseDeps([ + loose([ [_createClassModuleId, _classCallCheckModuleId], ]), ]), @@ -49,23 +48,19 @@ export let ReactNavigationStack: typeof import('@react-navigation/stack') = byProps( 'createStackNavigator', ), - every( - byDependencies( - looseDeps([ - looseDeps([ + byDependencies( + loose([ + relative.withDependencies( + loose([ [[]], ReactModuleId, ReactJsxRuntimeModuleId, ]), - ]), - ), - byDependencies( - looseDeps([ - relativeDep(1), - undefined, - relativeDep(3), - ]), - ), + 1, + ), + undefined, + relative(3), + ]), ), ), { diff --git a/lib/modules/src/finders/filters.ts b/lib/modules/src/finders/filters.ts index 503f5f6..c745dcd 100644 --- a/lib/modules/src/finders/filters.ts +++ b/lib/modules/src/finders/filters.ts @@ -27,6 +27,12 @@ export interface Filter< key: string } +// @ts-expect-error: This works perfectly fine! +export interface FilterGenerator Filter> + extends G { + keyFor: (args: Parameters) => string +} + /** * Create a filter generator. * @@ -54,29 +60,33 @@ export function createFilterGenerator( exports: Metro.ModuleExports, ) => boolean, keyFor: (args: A) => string, -): (...args: A) => Filter +): FilterGenerator<(...args: A) => Filter> export function createFilterGenerator( filter: (args: A, id: Metro.ModuleID) => boolean, keyFor: (args: A) => string, -): (...args: A) => Filter +): FilterGenerator<(...args: A) => Filter> export function createFilterGenerator( f: (args: A, id: Metro.ModuleID, exports?: Metro.ModuleExports) => boolean, keyFor: (args: A) => string, -): (...args: any[]) => Filter { - return (...args: A) => { +): FilterGenerator<(...args: A) => Filter> { + const generator = (...args: A) => { const filter = (id: Metro.ModuleID, exports?: Metro.ModuleExports) => f(args, id, exports) filter.key = keyFor(args) return filter } + generator.keyFor = keyFor + return generator } -export type ByProps = = Record>( - prop: keyof T, - ...props: Array -) => Filter +export type ByProps = FilterGenerator< + = Record>( + prop: keyof T, + ...props: Array + ) => Filter +> /** * Filter modules by their exports having all of the specified properties. @@ -106,10 +116,12 @@ export const byProps = createFilterGenerator>( props => `revenge.props(${props.join(',')})`, ) as ByProps -export type WithoutProps = >( - prop: string, - ...props: string[] -) => Filter +export type WithoutProps = FilterGenerator< + >( + prop: string, + ...props: string[] + ) => Filter +> /** * Filter modules by their exports having none of the specified properties. @@ -127,9 +139,9 @@ export const withoutProps = createFilterGenerator>( props => `revenge.withoutProps(${props.join(',')})`, ) as WithoutProps -export type BySingleProp = >( - prop: keyof T, -) => Filter +export type BySingleProp = FilterGenerator< + >(prop: keyof T) => Filter +> /** * Filter modules by their exports having only the specified property. @@ -151,9 +163,9 @@ export const bySingleProp = createFilterGenerator>( ([prop]) => `revenge.singleProp(${prop})`, ) as BySingleProp -export type ByName = ( - name: string, -) => Filter +export type ByName = FilterGenerator< + (name: string) => Filter +> /** * Filter modules by their exports having the specified name. @@ -190,57 +202,63 @@ export const byName = createFilterGenerator>( ([name]) => `revenge.name(${name})`, ) as ByName -export interface RelativeDependency { - valueOf(): Metro.ModuleID - r?: boolean -} - export interface ComparableDependencyMap extends Array< - | Metro.ModuleID - | RelativeDependency - | undefined - | ComparableDependencyMap + Metro.ModuleID | number | undefined | ComparableDependencyMap > { l?: boolean + r?: number } -type ComputedComparableDependencyMap = Exclude< - ComparableDependencyMap, - Array -> - -type ByDependencies = (deps: ComparableDependencyMap) => Filter +type ByDependencies = FilterGenerator< + (deps: ComparableDependencyMap) => Filter +> & { + loose: typeof loose + relative: typeof relative +} /** * Filter modules by their dependency map. * * @param deps The dependency map to check for, can be a sparse array or have `undefined` to be any dependency ("dynamic"). **Order and size matters!** - * @see {@link looseDeps} to make comparisons less strict. + * + * To do proper fingerprinting for modules: + * @see {@link byDependencies.loose} to loosen the checks. + * @see {@link byDependencies.relative} to compare dependencies relatively. * * @example * ```ts + * const { loose, relative } = byDependencies + * + * // Logger's module ID is 5 + * // It has 3 dependencies [4, ?, 2] + * * const [Logger] = lookupModule(byDependencies([4, undefined, 2])) * // or * const [Logger] = lookupModule(byDependencies([4, , 2])) - * // or with relative dependencies - * // If Logger's module ID is 20, [19, ..., ..., 2] would match: - * const [Logger] = lookupModule(byDependencies([relativeDep(-1), , 2])) - * // or with nested dependencies - * // The last dependency would need to have zero dependencies: - * const [Logger] = lookupModule(byDependencies([4, , []])) - * // or with loose dependencies - * // Module having 4 dependencies [4, ...], [4, ..., ...], [4, ..., ..., ...] etc. would match: - * const [SomeOtherModule] = lookupModule(byDependencies(looseDeps([4, ,]))) + * + * // Relative dependencies + * const [Logger] = lookupModule(byDependencies([relative(-1), undefined, 2])) + * + * // Nested dependencies + * // The last dependency (module ID 2) would need to have zero dependencies: + * const [Logger] = lookupModule(byDependencies([4, undefined, []])) + * + * // Loose dependencies + * // Module having these dependencies: [4, ...], [4, ..., ...], [4, ..., ..., ...], etc. would match: + * const [SomeOtherModule] = lookupModule(byDependencies(loose([4]))) * ``` */ export const byDependencies = createFilterGenerator>( - ([deps], id) => compareDeps(id, deps, deps.l), - deps => `revenge.deps(${genDepsKey(deps)})`, + ([deps], id) => depCompare(getModuleDependencies(id)!, deps, id, id), + deps => `revenge.deps(${depGenFilterKey(deps)})`, ) as ByDependencies +byDependencies.loose = loose +byDependencies.relative = relative + /** - * Make this set of comparable dependencies as loose, to be used with {@link byDependencies}. + * Make this set of comparable dependencies as loose. * * Making a dependency loose skips the exact length check, but the order of the set dependencies still matters. * If you mark an index as dynamic, the same index must also be present in the other map during comparison to pass. @@ -248,93 +266,139 @@ export const byDependencies = createFilterGenerator>( * @param deps The dependency map to make loose. This permanently modifies the array. * @returns The modified dependency map. */ -export function looseDeps(deps: ComparableDependencyMap) { +function loose(deps: ComparableDependencyMap) { deps.l = true return deps } +const RelativeSignBit = 1 << 30 +const RelativeBit = 1 << 29 +const RelativeRootBit = 1 << 28 +const RelativeBitMask = ~(RelativeSignBit | RelativeBit | RelativeRootBit) + /** * Marks this dependency to compare relatively to the module ID being compared. * * @param id The dependency ID to mark as relative. - * @param root Whether this dependency should be relatively to the root module ID. Useless for single-depth comparisons. + * @param root Marks this dependency to compare relatively to the root (returning) module ID being compared. Useful for nested comparisons where you want to compare by the root module ID instead of the parent's module ID of the nested dependency. */ -export function relativeDep( - id: Metro.ModuleID, - root?: boolean, -): RelativeDependency { - const o = Object(id) as RelativeDependency - if (root) o.r = true - return o +function relative(id: Metro.ModuleID, root?: boolean) { + id = (id < 0 ? -id | RelativeSignBit : id) | RelativeBit + if (root) id |= RelativeRootBit + return id } -function compareDeps( - rootOf: Metro.ModuleID, - compare: ComparableDependencyMap, - loose = false, +/** + * Marks this dependency to compare relatively to the module ID being compared, with an additional dependencies check. + * + * @param deps The dependency map to add the relative dependency to. This permanently modifies the array. + * @param id The dependency ID to mark as relative. + * @param root Whether to use {@link relative.toRoot} instead of {@link relative}. Defaults to `false`. + * @returns The modified dependency map. + * + * @see {@link byDependencies} + * @see {@link relative} + * @see {@link relative.toRoot} + * + * @example + * ```ts + * const { relative } = byDependencies + * + * // This filter will match modules having one dependency that is its module ID + 1 + * // And module ID + 1 would have exactly two dependencies: [Any, 2] + * byDependencies( + * relative.withDependencies( + * [undefined, 2], + * 1, // Always the next module to the one being compared + * true, // The module ID being compared matches the returning (root) module ID + * ) + * ) + * ``` + */ +relative.withDependencies = ( + deps: ComparableDependencyMap, + id: Metro.ModuleID, + root?: boolean, +) => { + deps.r = relative(id, root) + return deps +} + +function depCompare( + a: Metro.ModuleID[], + b: ComparableDependencyMap, + root: Metro.ModuleID, + parent: Metro.ModuleID, ): boolean { - const stack: Array< - [ - of: Metro.ModuleID, - deps: Metro.ModuleID[], - compare: ComparableDependencyMap, - loose?: boolean, - ] - > = [] + if (b.l ? a.length < b.length : a.length !== b.length) return false - stack.push([rootOf, getModuleDependencies(rootOf)!, compare, loose]) + for (let i = 0; i < b.length; i++) { + const compare = b[i] + // Skip dynamic + if (compare === undefined) continue - while (stack.length) { - const [of, deps, compare, loose] = stack.pop()! - if ( - loose - ? deps.length < compare.length - : deps.length !== compare.length - ) - return false + const id = a[i] - const ccmp: ComputedComparableDependencyMap = [] - for (let i = 0; i < compare.length; i++) { - const cmp = compare[i] - if (cmp === undefined) continue + if (Array.isArray(compare)) { + // relative.withDependencies? + if (compare.r && !depShallowCompare(compare.r, id, root, id)) + return false - if (Array.isArray(cmp)) ccmp[i] = cmp - else if (typeof cmp === 'object') - ccmp[i] = cmp.r ? rootOf + cmp.valueOf() : of + cmp.valueOf() - else ccmp[i] = cmp - } + if (depCompare(getModuleDependencies(id)!, compare, root, id)) + continue + } else if (depShallowCompare(compare, id, root, parent)) continue - for (let i = 0; i < ccmp.length; i++) { - const orig = deps[i] - const cmp = ccmp[i] - if (cmp === undefined) continue - - if (Array.isArray(cmp)) { - const dependencies = getModuleDependencies(orig) - if (!dependencies) return false - stack.push([orig, dependencies, cmp, cmp.l]) - } else if (cmp !== orig) return false - } + return false } return true } -function genDepsKey(deps: ComparableDependencyMap): string { +function depShallowCompare( + compare: number, + id: Metro.ModuleID, + root: Metro.ModuleID, + parent: Metro.ModuleID, +) { + // relative? + if (compare & RelativeBit) + compare = + (compare & RelativeRootBit ? root : parent) + + depGetRelMagnitude(compare) + + return compare === id +} + +function depGetRelMagnitude(dep: number) { + const rootRelative = dep & RelativeSignBit + dep = dep & RelativeBitMask + if (rootRelative) dep = -dep + return dep +} + +function depGenFilterKey(deps: ComparableDependencyMap): string { let key = '' - for (const dep of deps) + for (let i = 0; i < deps.length; i++) { + const dep = deps[i] + if (dep === undefined) key += ',' else if (Array.isArray(dep)) { if (dep.l) key += '#' - key += `[${genDepsKey(dep)}],` - } else - key += `${(dep as RelativeDependency).r ? `r${dep.valueOf()}` : dep.valueOf()},` + key += `[${depGenFilterKey(dep)}],` + } else { + if (dep & RelativeBit) { + const magnitude = depGetRelMagnitude(dep) + const prefix = dep & RelativeRootBit ? '~' : '^' + key += `${prefix}${magnitude},` + } else key += `${dep},` + } + } return key.substring(0, key.length - 1) } -export type Every = { +export type Every = FilterGenerator<{ ( f1: F1, f2: F2, @@ -354,7 +418,7 @@ export type Every = { > > (...filters: Filter[]): Filter -} +}> /** * Combines multiple filters into one, returning true if **every** filter matches. @@ -382,7 +446,7 @@ export const every = createFilterGenerator<[...filters: Filter[]]>( filters => `revenge.every(${filtersToKey(filters)})`, ) as Every -export type Some = { +export type Some = FilterGenerator<{ ( f1: F1, f2: F2, @@ -401,7 +465,7 @@ export type Some = { | IsFilterWithExports > (...filters: Filter[]): Filter -} +}> /** * Combines multiple filters into one, returning true if **some** filters match. @@ -431,11 +495,13 @@ function filtersToKey(filters: Filter[]): string { return s.substring(0, s.length - 1) } -export type ModuleStateAware = ( - initializedFilter: IF, - uninitializedFilter: Filter, - strict?: boolean, -) => Filter, false> +export type ModuleStateAware = FilterGenerator< + ( + initializedFilter: IF, + uninitializedFilter: Filter, + strict?: boolean, + ) => Filter, false> +> /** * Filter modules depending on their initialized state. **Initialized modules with bad exports are skipped.** @@ -470,11 +536,13 @@ export const moduleStateAware = createFilterGenerator< ([f1, f2]) => `revenge.moduleStateAware(${f1.key},${f2.key})`, ) as ModuleStateAware -export type PreferExports = ( - withExportsFilter: WEF, - exportslessFilter: Filter, - strict?: boolean, -) => Filter, false> +export type PreferExports = FilterGenerator< + ( + withExportsFilter: WEF, + exportslessFilter: Filter, + strict?: boolean, + ) => Filter, false> +> /** * Filter modules depending on if their exports are available and filterable.