Files
Wand-Enhancer-k1tbyte/web-panel/bridge/scripts/default/installed-apps-sync/runtime.js
T

391 lines
9.1 KiB
JavaScript
Vendored

import { CONTAINER_GRAPH_MAX_DEPTH } from './constants.js';
export function isRecord(value) {
return typeof value === 'object' && value !== null;
}
export function formatError(error) {
return error?.stack || String(error);
}
export async function invokeIpc(state, channel, payload, label, level = 'warn') {
if (!state.ipcRenderer) {
return false;
}
try {
await state.ipcRenderer.invoke(channel, payload);
return true;
} catch (error) {
state.log(level, `${label} IPC failed.`, formatError(error));
return false;
}
}
export function isDiagnosticsDebugEnabled() {
return globalThis.__wandInstalledAppsSyncDebug === true;
}
let lastPredicateErrorLogAt = 0;
function logContainerGraphPredicateError(error) {
if (!isDiagnosticsDebugEnabled()) {
return;
}
const now = Date.now();
if (now - lastPredicateErrorLogAt < 1000) {
return;
}
lastPredicateErrorLogAt = now;
console.debug('[wand-installed-apps-sync] container graph predicate threw', formatError(error));
}
export function getRequire() {
return globalThis.require || (typeof window !== 'undefined' ? window.require : null);
}
export function safeString(...values) {
for (const value of values) {
if (typeof value === 'string' && value.trim()) {
return value.trim();
}
}
return '';
}
export function getWebpackRequire() {
const chunk = globalThis.webpackChunkWeMod;
if (!Array.isArray(chunk)) {
return null;
}
if (typeof chunk.__wandWebpackRequire === 'function') {
return chunk.__wandWebpackRequire;
}
let resolvedRequire = null;
chunk.push([
[`wand-enhancer-${Date.now()}`],
{},
(webpackRequire) => {
resolvedRequire = webpackRequire;
},
]);
if (typeof resolvedRequire === 'function') {
chunk.__wandWebpackRequire = resolvedRequire;
}
return resolvedRequire;
}
export function getAppRoot() {
return (
document.getElementById('root') ||
document.querySelector('[aurelia-app]') ||
document.querySelector('root')
);
}
export function hasAppRoot() {
return Boolean(getAppRoot());
}
let cachedAureliaContainer = null;
function isUsableContainer(container) {
return isRecord(container) && typeof container.get === 'function';
}
export function getAureliaContainer() {
if (isUsableContainer(cachedAureliaContainer)) {
return cachedAureliaContainer;
}
const resolved = resolveAureliaContainer();
if (resolved) {
cachedAureliaContainer = resolved;
}
return resolved;
}
function resolveAureliaContainer() {
const root = getAppRoot();
const rootContainer = getContainerFromSubtree(root);
if (rootContainer) {
return rootContainer;
}
const bodyContainer = getContainerFromElement(document.body);
if (bodyContainer) {
return bodyContainer;
}
if (isRecord(globalThis.aurelia) && globalThis.aurelia.container) {
return globalThis.aurelia.container;
}
return null;
}
export function summarizeAureliaSubtree(root) {
if (!isDiagnosticsDebugEnabled()) {
return '(debug-disabled)';
}
if (!root) {
return 'root=null';
}
let elementsWithAu = 0;
let controllerEntries = 0;
let namedAuEntries = 0;
function inspectElement(element) {
if (!isRecord(element?.au)) {
return;
}
elementsWithAu += 1;
if (element.au.controller) {
controllerEntries += 1;
}
for (const [key, value] of Object.entries(element.au)) {
if (key !== 'controller' && isRecord(value)) {
namedAuEntries += 1;
}
}
}
inspectElement(root);
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
let element = walker.nextNode();
while (element) {
inspectElement(element);
element = walker.nextNode();
}
return `elementsWithAu=${elementsWithAu}, controllerEntries=${controllerEntries}, namedAuEntries=${namedAuEntries}`;
}
export function findExportedConstructor(webpackRequire, predicate) {
const cache = webpackRequire?.c;
if (!cache || typeof cache !== 'object') {
return null;
}
for (const record of Object.values(cache)) {
const exports = record?.exports;
const candidates = [];
if (typeof exports === 'function') {
candidates.push(exports);
} else if (isRecord(exports)) {
if (typeof exports.default === 'function') {
candidates.push(exports.default);
}
for (const value of Object.values(exports)) {
if (typeof value === 'function') {
candidates.push(value);
}
}
}
for (const candidate of candidates) {
if (candidate?.prototype && predicate(candidate.prototype)) {
return candidate;
}
}
}
return null;
}
export function findInstanceInContainerGraph(
root,
predicate,
maxDepth = CONTAINER_GRAPH_MAX_DEPTH,
) {
if (!root) {
return null;
}
const seen = new Set();
const queue = [{ value: root, depth: 0 }];
while (queue.length > 0) {
const current = queue.shift();
const value = current?.value;
const depth = current?.depth ?? 0;
if (!value || seen.has(value)) {
continue;
}
seen.add(value);
try {
if (predicate(value)) {
return value;
}
} catch (error) {
logContainerGraphPredicateError(error);
}
if (depth >= maxDepth) {
continue;
}
enqueueNestedValues(queue, seen, value, depth + 1);
}
return null;
}
export function getBasename(location) {
if (typeof location !== 'string' || !location.trim()) {
return '';
}
const normalized = location.replace(/\\/g, '/').replace(/\/+$/, '');
const leaf = normalized.split('/').filter(Boolean).pop();
return leaf ? leaf.trim() : '';
}
export function toStringId(value) {
if (typeof value === 'string' && value.trim()) {
return value.trim();
}
if (typeof value === 'number' && Number.isFinite(value)) {
return String(value);
}
return null;
}
export function normalizeStringList(value) {
if (!Array.isArray(value)) {
return [];
}
return value
.filter((entry) => typeof entry === 'string' && entry.trim())
.map((entry) => entry.trim());
}
export function getPreferredLocale() {
return safeString(
document.documentElement?.lang,
Array.isArray(globalThis.navigator?.languages)
? globalThis.navigator.languages.find(
(entry) => typeof entry === 'string' && entry.trim(),
)
: '',
globalThis.navigator?.language,
'en-US',
);
}
function getContainerFromAu(au) {
if (!isRecord(au)) {
return null;
}
if (au.container) {
return au.container;
}
const directControllerContainer =
au.controller?.container || au.controller?.viewModel?.container;
if (directControllerContainer) {
return directControllerContainer;
}
for (const value of Object.values(au)) {
if (!isRecord(value)) {
continue;
}
const container =
value.container ||
value.controller?.container ||
value.viewModel?.container ||
value.controller?.viewModel?.container;
if (container) {
return container;
}
}
return null;
}
function getContainerFromElement(element) {
if (!element) {
return null;
}
if (element.__aurelia__?.container) {
return element.__aurelia__.container;
}
return getContainerFromAu(element.au);
}
function getContainerFromSubtree(root) {
if (!root) {
return null;
}
const rootContainer = getContainerFromElement(root);
if (rootContainer) {
return rootContainer;
}
const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
let element = walker.nextNode();
while (element) {
const container = getContainerFromElement(element);
if (container) {
return container;
}
element = walker.nextNode();
}
return null;
}
function enqueueNestedValues(queue, seen, value, depth) {
if (value instanceof Map) {
enqueueIterable(queue, seen, value.values(), depth);
return;
}
if (value instanceof Set || Array.isArray(value)) {
enqueueIterable(queue, seen, value.values(), depth);
return;
}
if (!isRecord(value) && typeof value !== 'function') {
return;
}
enqueueIterable(queue, seen, Object.values(value), depth);
}
function enqueueIterable(queue, seen, values, depth) {
for (const entry of values) {
if ((isRecord(entry) || typeof entry === 'function') && !seen.has(entry)) {
queue.push({ value: entry, depth });
}
}
}