[Init] First production version

This commit is contained in:
Minoricew
2024-11-28 01:47:04 +08:00
parent fd0eb0c0c4
commit d976184e42
27 changed files with 2707 additions and 0 deletions

View File

@@ -0,0 +1,135 @@
const fs = require("fs");
const path = require("path");
class HooksManager {
loadHooks() {
if (global.__HUGO_AURA__.hooks) {
return global.__HUGO_AURA__.hooks;
}
const hooksPath = path.join(__dirname, "../../../aura/ui/hooks");
const hooks = new Map();
try {
const files = fs.readdirSync(hooksPath);
files.forEach((file) => {
if (!file.endsWith(".js")) return;
try {
const hook = require(path.join(hooksPath, file));
const targetWindow = hook.windowName || path.basename(file, ".js");
hooks.set(targetWindow, hook);
console.log(
`[HugoAura / Init] Loaded hook for window: ${targetWindow}`
);
} catch (err) {
console.error(
`[HugoAura / Init / Error] Failed to load hook ${file}:`,
err
);
}
});
} catch (err) {
console.error(
"[HugoAura / Init / Error] Failed to read hooks directory:",
err
);
}
global.__HUGO_AURA__.hooks = hooks;
return hooks;
}
cleanupWindow(windowKey, listeners) {
console.log(
`[HugoAura / Cleanup / ${windowKey}] Window destroyed, cleaning up...`
);
if (listeners) {
const { webContents, domReadyListener, destroyedListener } = listeners;
webContents.removeListener("dom-ready", domReadyListener);
webContents.removeListener("destroyed", destroyedListener);
}
global.__HUGO_AURA__.hookedWindows.delete(windowKey);
}
handleWindowHook(webContents, hookConfig, windowName) {
if (!hookConfig) return;
const windowKey = `${hookConfig.windowName || windowName}`;
if (global.__HUGO_AURA__.hookedWindows.has(windowKey)) {
console.log(
`[HugoAura / Init] Duplicate hook for ${windowKey}, ignoring...`
);
return;
}
console.log(`[HugoAura / Init] Hook is initializing for ${windowKey}...`);
console.log(
`[HugoAura / Init] Hook loaded at: ${new Date().toISOString()}`
);
const domReadyListener = () => {
try {
console.log(
`[HugoAura / UI / Verb / ${windowKey}] Loading injection script...`
);
const injectionScript = fs
.readFileSync(path.join(__dirname, "./injection.js"), "utf8")
.replace('"__TEMPLATE_TARGETS__"', JSON.stringify(hookConfig.targets))
.replace(
'"__TEMPLATE_GLOBAL_STYLES__"',
JSON.stringify(hookConfig.globalStyles || [])
)
.replace(
'"__TEMPLATE_GLOBAL_JS__"',
JSON.stringify(hookConfig.globalJS || [])
)
.replace("__TEMPLATE_ON_LOADED__", hookConfig.onLoaded || "");
webContents
.executeJavaScript(injectionScript, true)
.then(() =>
console.log(
`[HugoAura / UI / Done / ${windowKey}] Injection script executed`
)
)
.catch((err) =>
console.error(
`[HugoAura / UI / Error / ${windowKey}] Failed to execute injection script:`,
err
)
);
} catch (err) {
console.error(
`[HugoAura / UI / Error / ${windowKey}] Failed to load UI hook:`,
err
);
}
};
const destroyedListener = () => {
this.cleanupWindow(
windowKey,
global.__HUGO_AURA__.hookedWindows.get(windowKey)
);
};
webContents.on("dom-ready", domReadyListener);
webContents.on("destroyed", destroyedListener);
global.__HUGO_AURA__.hookedWindows.set(windowKey, {
webContents,
domReadyListener,
destroyedListener,
});
console.log(
`[HugoAura / Init / Success / ${windowKey}] Hook initialized successfully!`
);
}
}
module.exports = HooksManager;

View File

@@ -0,0 +1,337 @@
(() => {
const waitForElement = (selector, timeout = 5000) => {
return new Promise((resolve, reject) => {
if (document.querySelector(selector)) {
return resolve(document.querySelector(selector));
}
const observer = new MutationObserver((mutations) => {
if (document.querySelector(selector)) {
observer.disconnect();
resolve(document.querySelector(selector));
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
setTimeout(() => {
observer.disconnect();
reject("[HugoAura / UI / Injection] Timeout waiting for element");
}, timeout);
});
};
const createStore = () => {
const store = {
router: "/",
};
const internal = {
get: (key) => store[key],
set: (key, value) => {
store[key] = value;
return true;
},
};
window.$store = {
get: (key) => {
const stack = new Error().stack;
if (stack.includes("aura/ui/pages/")) {
return internal.get(key);
}
return undefined;
},
set: (key, value) => {
const stack = new Error().stack;
if (stack.includes("aura/ui/pages/")) {
return internal.set(key, value);
}
return false;
},
};
return internal;
};
const store = createStore();
const createUILoader = () => {
const modules = "__TEMPLATE_TARGETS__";
const containers = new Map();
const observers = new Map();
const moduleResources = new Map();
const globalScripts = new Set();
const insertElement = (target, element, mode = "appendChild") => {
const elementId = element.id;
if (document.getElementById(elementId)) {
console.log(
`[HugoAura / UI / Warning] Element ${elementId} already exists, skipping insertion`
);
return;
}
switch (mode) {
case "insertBefore":
target.parentNode.insertBefore(element, target);
break;
case "insertAfter":
target.parentNode.insertBefore(element, target.nextSibling);
break;
case "appendChild":
default:
target.appendChild(element);
}
};
const loadGlobalJS = async () => {
const scripts = "__TEMPLATE_GLOBAL_JS__";
for (const scriptPath of scripts) {
try {
const script = document.createElement("script");
script.src = `../../aura/${scriptPath}`;
document.body.appendChild(script);
globalScripts.add(script);
await new Promise((resolve, reject) => {
script.onload = resolve;
script.onerror = reject;
});
console.log(
`[HugoAura / UI / Global] Loaded global script: ${scriptPath}`
);
} catch (err) {
console.error(
`[HugoAura / UI / Error] Failed to load global script ${scriptPath}:`,
err
);
}
}
};
const monitorParent = (moduleKey, target, _mode) => {
if (observers.has(moduleKey)) {
observers.get(moduleKey).disconnect();
}
const elementId = `aura-container-${moduleKey.replace(/\./g, "-")}`;
const observer = new MutationObserver((_mutations) => {
if (!document.getElementById(elementId)) {
let targetElement = document.querySelector(
modules[moduleKey].pageSelector
);
if (
targetElement &&
modules[moduleKey].active &&
modules[moduleKey].revive
) {
if (!document.getElementById(elementId)) {
console.log(
`[HugoAura / UI / Revival] Reviving module ${moduleKey}`
);
this.loadModule(moduleKey, true);
}
}
}
});
observer.observe(target.parentNode, {
childList: true,
subtree: false,
});
observers.set(moduleKey, observer);
};
const loader = {
async loadModule(moduleKey, isRevive = false) {
if (!modules[moduleKey]?.active) return;
try {
const config = modules[moduleKey];
const target = await waitForElement(config.pageSelector);
const elementId = `aura-container-${moduleKey.replace(/\./g, "-")}`;
if (document.getElementById(elementId)) {
console.log(
`[HugoAura / UI / Warning] Module ${moduleKey} already loaded, skipping`
);
return;
}
const container = document.createElement("div");
container.id = elementId;
containers.set(moduleKey, container);
const resources = new Set();
moduleResources.set(moduleKey, resources);
if (config.pageCSS && !isRevive) {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = `../../aura/${config.pageCSS}`;
document.head.appendChild(link);
resources.add(link);
}
const html = await fetch(`../../aura/${config.pageURI}`).then((r) =>
r.text()
);
container.innerHTML = html;
insertElement(target, container, config.selectorMode);
monitorParent(moduleKey, target, container, config.selectorMode);
if (config.pageScript && !isRevive) {
const script = document.createElement("script");
script.src = `../../aura/${config.pageScript}`;
document.body.appendChild(script);
resources.add(script);
}
const observer = new MutationObserver(() => {
if (
!document.contains(container) &&
modules[moduleKey].active &&
modules[moduleKey].revive
) {
this.loadModule(moduleKey, true);
}
});
observer.observe(document.body, {
childList: true,
subtree: true,
});
observers.set(moduleKey, observer);
} catch (err) {
console.error(
`[HugoAura / UI / Error] Failed to load module ${moduleKey}:`,
err
);
}
},
unloadModule(moduleKey) {
const container = containers.get(moduleKey);
const observer = observers.get(moduleKey);
const resources = moduleResources.get(moduleKey);
if (observer) {
observer.disconnect();
observers.delete(moduleKey);
}
if (container) {
container.remove();
containers.delete(moduleKey);
}
if (resources) {
resources.forEach((element) => element.remove());
moduleResources.delete(moduleKey);
}
},
handleModuleChange(moduleKey, path = []) {
const fullPath = [...path, moduleKey].join(".");
if (path.length === 0 && modules[moduleKey].active) {
this.loadModule(moduleKey);
} else if (path.length === 0) {
this.unloadModule(moduleKey);
} else {
if (moduleKey === "active") {
if (modules[path[0]].active) {
this.loadModule(path[0]);
} else {
this.unloadModule(path[0]);
}
} else {
this.unloadModule(path[0]);
this.loadModule(path[0]);
}
}
},
};
const createDeepProxy = (target, handler, path = []) => {
return new Proxy(target, {
get(target, prop) {
const value = Reflect.get(target, prop);
if (typeof value === "object" && value !== null) {
return createDeepProxy(value, handler, [...path, prop]);
}
return value;
},
set(target, prop, value) {
console.debug(
`[HugoAura / UI / Debug] Setting property: ${[...path, prop].join(
"."
)}`
);
const result = Reflect.set(target, prop, value);
if (result) {
handler([...path], prop, value);
}
return result;
},
deleteProperty(target, prop) {
console.debug(
`[HugoAura / UI / Debug] Deleting property: ${[...path, prop].join(
"."
)}`
);
const result = Reflect.deleteProperty(target, prop);
if (result) {
handler([...path], prop, undefined);
}
return result;
},
});
};
const initialLoad = async () => {
try {
await loadGlobalJS();
for (const [key, config] of Object.entries(modules)) {
if (config.active) {
await loader.loadModule(key);
}
}
} catch (err) {
console.error("[HugoAura / UI / Error] Initial load failed:", err);
}
};
initialLoad();
return createDeepProxy(modules, (path, prop, value) => {
loader.handleModuleChange(prop, path);
});
};
window.__HUGO_AURA_LOADER__ = createUILoader();
const loadGlobalStyles = async () => {
const styles = "__TEMPLATE_GLOBAL_STYLES__";
styles.forEach((style) => {
const link = document.createElement("link");
link.rel = "stylesheet";
link.href = `../../aura/${style}`;
document.head.appendChild(link);
});
};
const init = async () => {
await loadGlobalStyles();
__TEMPLATE_ON_LOADED__;
};
init().catch((err) =>
console.error("[HugoAura / UI / Error] Initialization failed:", err)
);
})();

View File

@@ -0,0 +1,141 @@
const path = require('path');
class WebpackHook {
#ruleCache = new Map();
loadRewriteRules(config) {
const rewriteConfig = config.rewrite || {};
const rules = [];
Object.entries(rewriteConfig).forEach(([rulePath, ruleConfig]) => {
if (this.#ruleCache.has(rulePath) && !ruleConfig.enabled) {
console.log(`[HugoAura / AppHook] Skipping disabled rule: ${rulePath}`);
return;
}
try {
let rule = this.#ruleCache.get(rulePath);
if (!rule) {
rule = require(path.join(
__dirname,
'../../../aura/jsRewrite/',
rulePath
));
this.#ruleCache.set(rulePath, rule);
}
if (ruleConfig.enabled) {
rules.push({
id: rulePath,
feature: rule.feature,
method: rule.method,
methodArg: rule.methodArg,
preHook: rule.preHook || null,
newFunction: rule.newFunction,
});
console.log(`[HugoAura / AppHook] Loaded rule: ${rulePath}`);
}
} catch (err) {
console.error(
`[HugoAura / AppHook] Failed to load rule ${rulePath}:`,
err
);
}
});
return rules;
}
patchModules(modules, rewrites) {
modules.forEach((mod, index) => {
if (typeof mod !== 'function') return;
const stringifyFunc = mod.toString();
rewrites.forEach((rewrite) => {
const ruleId = rewrite.id;
const method = rewrite.method;
try {
if (eval(`(stringifyFunc) => ${rewrite.feature}`)(stringifyFunc)) {
console.log(
`[HugoAura / AppHook] Found target function for rule ${ruleId} at index ${index}, engaging hook...`
);
console.log(`[HugoAura / AppHook] Using hook method: ${method}`);
let rewrittenFunction = mod;
switch (method) {
case 'reactComponent':
window.__HUGO_AURA_HOOK__[ruleId] = {
feature: rewrite.feature,
newFunction: rewrite.newFunction
}
rewrittenFunction = rewrite.preHook(mod);
break;
case 'legacy':
default:
rewrittenFunction = rewrite.newFunction;
break;
}
modules[index] = rewrittenFunction;
console.log(
`[HugoAura / AppHook] Successfully patched function for rule ${ruleId}`
);
}
} catch (err) {
console.error(
`[HugoAura / AppHook] Error evaluating feature for rule ${ruleId}:`,
err
);
}
});
});
if (typeof window !== 'undefined') {
window.__HUGO_AURA_DEBUG__ = {
getRuleCache: () => Array.from(this.#ruleCache.keys()),
};
}
}
installHook(window, config) {
let realWebpackJsonp = window.webpackJsonp;
Object.defineProperty(window, 'webpackJsonp', {
get: () => realWebpackJsonp,
set: (value) => {
console.log(
`[HugoAura / AppHook] Intercepted webpackJsonp initialization`
);
if (!realWebpackJsonp && Array.isArray(value)) {
const originalPush = value.push.bind(value);
value.push = (...args) => {
if (args[0] && Array.isArray(args[0][1])) {
const [chunkIds, modules] = args[0];
console.log(
`[HugoAura / AppHook] Intercepting chunk ${chunkIds.join(', ')}`
);
const rewrites = this.loadRewriteRules(config);
if (rewrites.length > 0) {
this.patchModules(modules, rewrites);
}
}
return originalPush.apply(value, args);
};
}
realWebpackJsonp = value;
},
configurable: true,
});
}
}
module.exports = WebpackHook;

View File

@@ -0,0 +1,137 @@
const fs = require('fs');
const path = require('path');
const os = require('os');
const deepMerge = (target, source) => {
const result = JSON.parse(JSON.stringify(target));
if (!source || typeof source !== 'object') {
return {};
}
const keysToDelete = [];
Object.keys(result).forEach((key) => {
if (!(key in source)) {
keysToDelete.push(key);
} else if (
typeof result[key] === 'object' &&
result[key] !== null &&
typeof source[key] === 'object' &&
source[key] !== null
) {
result[key] = deepMerge(result[key], source[key]);
if (Object.keys(result[key]).length === 0) {
keysToDelete.push(key);
}
}
});
keysToDelete.forEach((key) => {
delete result[key];
});
Object.keys(source).forEach((key) => {
if (!(key in result)) {
result[key] = JSON.parse(JSON.stringify(source[key]));
}
});
return result;
};
class ConfigManager {
constructor() {
this.configPath = path.join(
os.homedir(),
'Documents',
'HugoAura',
'config.json'
);
this.defaultConfigPath = path.join(__dirname, 'default.json');
}
getHugoAuraConfigPath() {
return path.dirname(this.configPath);
}
getConfigPath() {
return this.configPath;
}
getDefaultConfig() {
try {
return JSON.parse(fs.readFileSync(this.defaultConfigPath, 'utf8'));
} catch (err) {
console.warn(
'[HugoAura / Config] No default config found, using empty config'
);
return { rewrite: {} };
}
}
ensureConfigExists() {
if (global.__HUGO_AURA__.configInit) return;
const hugoAuraPath = this.getHugoAuraConfigPath();
if (!fs.existsSync(hugoAuraPath)) {
console.log('[HugoAura / Config] Creating HugoAura directory');
fs.mkdirSync(hugoAuraPath, { recursive: true });
}
if (!fs.existsSync(this.configPath)) {
console.log('[HugoAura / Config] Creating default config file');
const defaultConfig = this.getDefaultConfig();
this.writeConfig(defaultConfig);
}
}
readConfig() {
try {
const config = JSON.parse(fs.readFileSync(this.configPath, 'utf8'));
console.log('[HugoAura / Config] Successfully loaded config:', config);
return config;
} catch (err) {
console.error('[HugoAura / Config] Failed to read config:', err);
return this.getDefaultConfig();
}
}
writeConfig(config) {
try {
fs.writeFileSync(
this.configPath,
JSON.stringify(config, null, 2),
'utf8'
);
return true;
} catch (err) {
console.error('[HugoAura / Config] Failed to write config:', err);
return false;
}
}
loadConfig() {
let defaultConfig = this.getDefaultConfig();
let config = {};
try {
if (fs.existsSync(this.configPath)) {
const userConfig = JSON.parse(fs.readFileSync(this.configPath, 'utf8'));
if (global.__HUGO_AURA__.configInit) {
config = userConfig;
return userConfig;
} else {
config = deepMerge(userConfig, defaultConfig);
console.log('[HugoAura / Config] Merged with user config');
this.writeConfig(config);
}
}
} catch (err) {
console.error('[HugoAura / Config] Failed to load user config:', err);
config = defaultConfig;
}
return config;
}
}
module.exports = new ConfigManager();

View File

@@ -0,0 +1,13 @@
{
"rewrite": {
"vendor/passwordValidation": {
"enabled": true,
"type": "customPassword",
"customPassword": {
"passwordWithSalt": "770f27b0379ee6ba0f11731e49aa7af1",
"salt": "aura"
}
}
},
"devTools": false
}