UNPKG

@steambrew/client

Version:
143 lines (121 loc) 4.22 kB
import Logger from './logger'; declare global { interface Window { webpackChunksteamui: any; } } const logger = new Logger('Webpack'); // In most case an object with getters for each property. Look for the first call to r.d in the module, usually near or at the top. export type Module = any; export type Export = any; type FilterFn = (module: any) => boolean; type ExportFilterFn = (moduleExport: any, exportName?: any) => boolean; type FindFn = (module: any) => any; export let modules: any = []; function initModuleCache() { const startTime = performance.now(); logger.group('Webpack Module Init'); // Webpack 5, currently on beta // Generate a fake module ID const id = Math.random(); // really should be an int and not a float but who cares let webpackRequire!: ((id: any) => Module) & { m: object }; // Insert our module in a new chunk. // The module will then be called with webpack's internal require function as its first argument window.webpackChunksteamui.push([ [id], {}, (r: any) => { webpackRequire = r; }, ]); logger.log( 'Initializing all modules. Errors here likely do not matter, as they are usually just failing module side effects.', ); // Loop over every module ID for (let i of Object.keys(webpackRequire.m)) { try { const module = webpackRequire(i); if (module) { modules.push(module); } } catch (e) { logger.debug('Ignoring require error for module', i, e); } } logger.groupEnd(`Modules initialized in ${performance.now() - startTime}ms...`); } initModuleCache(); export const findModule = (filter: FilterFn) => { for (const m of modules) { if (m.default && filter(m.default)) return m.default; if (filter(m)) return m; } }; if (typeof window.SP_REACT === 'undefined') { // @ts-ignore window.SP_REACTDOM = findModule((module) => module.createPortal && module.createRoot && module.flushSync) window.SP_REACT = findModule((module) => module.Component && module.PureComponent && module.useLayoutEffect); } export const findModuleDetailsByExport = ( filter: ExportFilterFn, minExports?: number, ): [module: Module | undefined, moduleExport: any, exportName: any] => { for (const m of modules) { if (!m) continue; for (const mod of [m.default, m]) { if (typeof mod !== 'object') continue; if (minExports && Object.keys(mod).length < minExports) continue; for (let exportName in mod) { if (mod?.[exportName]) { const filterRes = filter(mod[exportName], exportName); if (filterRes) { return [mod, mod[exportName], exportName]; } else { continue; } } } } } return [undefined, undefined, undefined]; }; export const findModuleByExport = (filter: ExportFilterFn, minExports?: number) => { return findModuleDetailsByExport(filter, minExports)?.[0]; }; export const findModuleExport = (filter: ExportFilterFn, minExports?: number) => { return findModuleDetailsByExport(filter, minExports)?.[1]; }; /** * @deprecated use findModuleExport instead */ export const findModuleChild = (filter: FindFn) => { for (const m of modules) { for (const mod of [m.default, m]) { const filterRes = filter(mod); if (filterRes) { return filterRes; } else { continue; } } } }; export const findAllModules = (filter: FilterFn) => { const out = []; for (const m of modules) { if (m.default && filter(m.default)) out.push(m.default); if (filter(m)) out.push(m); } return out; }; export const CommonUIModule = modules.find((m: Module) => { if (typeof m !== 'object') return false; for (let prop in m) { if (m[prop]?.contextType?._currentValue && Object.keys(m).length > 60) return true; } return false; }); export const IconsModule = findModuleByExport( (e) => e?.toString && /Spinner\)}\)?,.\.createElement\(\"path\",{d:\"M18 /.test(e.toString()), ); export const ReactRouter = findModuleByExport((e) => e.computeRootMatch);