diff --git a/build.mjs b/build.mjs
index 21e498e..4434039 100644
--- a/build.mjs
+++ b/build.mjs
@@ -73,16 +73,41 @@ async function build(name, entry) {
}
async function buildExt(ext, side, copyManifest, fileExt) {
- const outDir = path.join("./dist", "core-extensions", ext);
- if (!fs.existsSync(outDir)) {
- fs.mkdirSync(outDir, { recursive: true });
+ const outdir = path.join("./dist", "core-extensions", ext);
+ if (!fs.existsSync(outdir)) {
+ fs.mkdirSync(outdir, { recursive: true });
}
- const entryPoint = `packages/core-extensions/src/${ext}/${side}.${fileExt}`;
+ const entryPoints = [
+ `packages/core-extensions/src/${ext}/${side}.${fileExt}`
+ ];
+
+ const wpModulesDir = `packages/core-extensions/src/${ext}/webpackModules`;
+ if (fs.existsSync(wpModulesDir)) {
+ const wpModules = fs.readdirSync(wpModulesDir);
+ for (const wpModule of wpModules) {
+ entryPoints.push(
+ `packages/core-extensions/src/${ext}/webpackModules/${wpModule}`
+ );
+ }
+ }
+
+ const wpImportPlugin = {
+ name: "webpackImports",
+ setup(build) {
+ build.onResolve({ filter: /^@moonlight-mod\/wp\// }, (args) => {
+ const wpModule = args.path.replace(/^@moonlight-mod\/wp\//, "");
+ return {
+ path: wpModule,
+ external: true
+ };
+ });
+ }
+ };
const esbuildConfig = {
- entryPoints: [entryPoint],
- outfile: path.join(outDir, side + ".js"),
+ entryPoints,
+ outdir,
format: "cjs",
platform: "node",
@@ -98,9 +123,14 @@ async function buildExt(ext, side, copyManifest, fileExt) {
copyStaticFiles({
src: `./packages/core-extensions/src/${ext}/manifest.json`,
dest: `./dist/core-extensions/${ext}/manifest.json`
- })
+ }),
+ wpImportPlugin
]
- : []
+ : [wpImportPlugin],
+
+ logOverride: {
+ "commonjs-variable-in-esm": "verbose"
+ }
};
if (watch) {
diff --git a/env.d.ts b/env.d.ts
index df6d5da..55c16fb 100644
--- a/env.d.ts
+++ b/env.d.ts
@@ -1 +1 @@
-///
+///
diff --git a/packages/core-extensions/src/common/components.ts b/packages/core-extensions/src/common/components.ts
deleted file mode 100644
index e4f08b4..0000000
--- a/packages/core-extensions/src/common/components.ts
+++ /dev/null
@@ -1,39 +0,0 @@
-import { ExtensionWebpackModule } from "@moonlight-mod/types";
-
-export const components: ExtensionWebpackModule = {
- dependencies: [
- { ext: "spacepack", id: "spacepack" },
- "MasonryList:",
- ".flexGutterSmall,"
- //"ALWAYS_WHITE:",
- //".Messages.SWITCH_ACCOUNTS_TOAST_LOGIN_SUCCESS.format"
- ],
- run: function (module, exports, require) {
- const spacepack = require("spacepack_spacepack");
-
- const Components = spacepack.findByCode("MasonryList:function")[0].exports;
- const MarkdownParser = spacepack.findByCode(
- "parseAutoModerationSystemMessage:"
- )[0].exports.default;
- const LegacyText = spacepack.findByCode(".selectable", ".colorStandard")[0]
- .exports.default;
- const Flex = spacepack.findByCode(".flex" + "GutterSmall,")[0].exports
- .default;
- const CardClasses = spacepack.findByCode("card", "cardHeader", "inModal")[0]
- .exports;
- const ControlClasses = spacepack.findByCode(
- "title",
- "titleDefault",
- "dividerDefault"
- )[0].exports;
-
- module.exports = {
- ...Components,
- MarkdownParser,
- LegacyText,
- Flex,
- CardClasses,
- ControlClasses
- };
- }
-};
diff --git a/packages/core-extensions/src/common/flux.ts b/packages/core-extensions/src/common/flux.ts
deleted file mode 100644
index b1adf32..0000000
--- a/packages/core-extensions/src/common/flux.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { ExtensionWebpackModule } from "@moonlight-mod/types";
-import { CommonFlux } from "@moonlight-mod/types/coreExtensions";
-
-const findFlux = ["useStateFromStores:function"];
-
-export const flux: ExtensionWebpackModule = {
- dependencies: [{ ext: "spacepack", id: "spacepack" }, ...findFlux],
- run: (module, exports, require) => {
- const spacepack = require("spacepack_spacepack");
- const Flux = spacepack.findByCode(...findFlux)[0].exports;
- module.exports = Flux as CommonFlux;
- }
-};
diff --git a/packages/core-extensions/src/common/fluxDispatcher.ts b/packages/core-extensions/src/common/fluxDispatcher.ts
deleted file mode 100644
index d519eac..0000000
--- a/packages/core-extensions/src/common/fluxDispatcher.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { ExtensionWebpackModule } from "@moonlight-mod/types";
-
-export const fluxDispatcher: ExtensionWebpackModule = {
- dependencies: [
- { ext: "spacepack", id: "spacepack" },
- "isDispatching",
- "dispatch"
- ],
- run: (module, exports, require) => {
- const spacepack = require("spacepack_spacepack");
- module.exports = spacepack.findByExports(
- "isDispatching",
- "dispatch"
- )[0].exports.default;
- }
-};
diff --git a/packages/core-extensions/src/common/http.ts b/packages/core-extensions/src/common/http.ts
deleted file mode 100644
index 8722b6f..0000000
--- a/packages/core-extensions/src/common/http.ts
+++ /dev/null
@@ -1,12 +0,0 @@
-import { ExtensionWebpackModule } from "@moonlight-mod/types";
-
-const findHTTP = ["get", "put", "V8APIError"];
-
-export const http: ExtensionWebpackModule = {
- dependencies: [{ ext: "spacepack", id: "spacepack" }],
- run: (module, exports, require) => {
- const spacepack = require("spacepack_spacepack");
- const HTTP = spacepack.findByExports(...findHTTP)[0].exports;
- module.exports = HTTP.ZP ?? HTTP.Z;
- }
-};
diff --git a/packages/core-extensions/src/common/index.ts b/packages/core-extensions/src/common/index.ts
index 2aefe58..95209d6 100644
--- a/packages/core-extensions/src/common/index.ts
+++ b/packages/core-extensions/src/common/index.ts
@@ -1,17 +1,39 @@
import { ExtensionWebExports } from "@moonlight-mod/types";
-import { react } from "./react";
-import { flux } from "./flux";
-import { stores } from "./stores";
-import { http } from "./http";
-import { components } from "./components";
-import { fluxDispatcher } from "./fluxDispatcher";
-
export const webpackModules: ExtensionWebExports["webpackModules"] = {
- react,
- flux,
- stores,
- http,
- components,
- fluxDispatcher
+ components: {
+ dependencies: [
+ { ext: "spacepack", id: "spacepack" },
+ "MasonryList:",
+ ".flexGutterSmall,"
+ ]
+ },
+
+ flux: {
+ dependencies: [
+ { ext: "spacepack", id: "spacepack" },
+ "useStateFromStores:function"
+ ]
+ },
+
+ fluxDispatcher: {
+ dependencies: [
+ { ext: "spacepack", id: "spacepack" },
+ "isDispatching",
+ "dispatch"
+ ]
+ },
+
+ react: {
+ dependencies: [
+ { ext: "spacepack", id: "spacepack" },
+ "__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED",
+ /\.?version(?:=|:)/,
+ /\.?createElement(?:=|:)/
+ ]
+ },
+
+ stores: {
+ dependencies: [{ ext: "common", id: "flux" }]
+ }
};
diff --git a/packages/core-extensions/src/common/react.ts b/packages/core-extensions/src/common/react.ts
deleted file mode 100644
index 71a91a3..0000000
--- a/packages/core-extensions/src/common/react.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { ExtensionWebpackModule } from "@moonlight-mod/types";
-
-const findReact = [
- "__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED",
- /\.?version(?:=|:)/,
- /\.?createElement(?:=|:)/
-];
-
-export const react: ExtensionWebpackModule = {
- dependencies: [...findReact, { ext: "spacepack", id: "spacepack" }],
- run: (module, exports, require) => {
- const spacepack = require("spacepack_spacepack");
- module.exports = spacepack.findByCode(...findReact)[0].exports;
- }
-};
diff --git a/packages/core-extensions/src/common/stores.ts b/packages/core-extensions/src/common/stores.ts
deleted file mode 100644
index 1647502..0000000
--- a/packages/core-extensions/src/common/stores.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-import { ExtensionWebpackModule } from "@moonlight-mod/types";
-
-export const stores: ExtensionWebpackModule = {
- dependencies: [{ ext: "common", id: "flux" }],
- run: (module, exports, require) => {
- const Flux = require("common_flux");
-
- module.exports = new Proxy(
- {},
- {
- get: function (target, key, receiver) {
- const allStores = Flux.Store.getAll();
-
- let targetStore;
- for (const store of allStores) {
- const name = store.getName();
- if (name.length === 1) continue; // filter out unnamed stores
-
- if (name === key) {
- targetStore = store;
- break;
- }
- }
-
- return targetStore;
- }
- }
- );
- }
-};
diff --git a/packages/core-extensions/src/common/webpackModules/components.ts b/packages/core-extensions/src/common/webpackModules/components.ts
new file mode 100644
index 0000000..e8a0a55
--- /dev/null
+++ b/packages/core-extensions/src/common/webpackModules/components.ts
@@ -0,0 +1,26 @@
+import spacepack from "@moonlight-mod/wp/spacepack_spacepack";
+
+const Components = spacepack.findByCode("MasonryList:function")[0].exports;
+const MarkdownParser = spacepack.findByCode(
+ "parseAutoModerationSystemMessage:"
+)[0].exports.default;
+const LegacyText = spacepack.findByCode(".selectable", ".colorStandard")[0]
+ .exports.default;
+const Flex = spacepack.findByCode(".flex" + "GutterSmall,")[0].exports.default;
+const CardClasses = spacepack.findByCode("card", "cardHeader", "inModal")[0]
+ .exports;
+const ControlClasses = spacepack.findByCode(
+ "title",
+ "titleDefault",
+ "dividerDefault"
+)[0].exports;
+
+// We use CJS export here because merging the exports from Components is annoying as shit
+module.exports = {
+ ...Components,
+ MarkdownParser,
+ LegacyText,
+ Flex,
+ CardClasses,
+ ControlClasses
+};
diff --git a/packages/core-extensions/src/common/webpackModules/flux.ts b/packages/core-extensions/src/common/webpackModules/flux.ts
new file mode 100644
index 0000000..1e21d25
--- /dev/null
+++ b/packages/core-extensions/src/common/webpackModules/flux.ts
@@ -0,0 +1,5 @@
+import spacepack from "@moonlight-mod/wp/spacepack_spacepack";
+
+module.exports = spacepack.findByCode(
+ ["useStateFromStores", ":function"].join("")
+)[0].exports;
diff --git a/packages/core-extensions/src/common/webpackModules/fluxDispatcher.ts b/packages/core-extensions/src/common/webpackModules/fluxDispatcher.ts
new file mode 100644
index 0000000..964f7eb
--- /dev/null
+++ b/packages/core-extensions/src/common/webpackModules/fluxDispatcher.ts
@@ -0,0 +1,6 @@
+import spacepack from "@moonlight-mod/wp/spacepack_spacepack";
+
+module.exports = spacepack.findByExports(
+ "isDispatching",
+ "dispatch"
+)[0].exports.default;
diff --git a/packages/core-extensions/src/common/webpackModules/react.ts b/packages/core-extensions/src/common/webpackModules/react.ts
new file mode 100644
index 0000000..a89715b
--- /dev/null
+++ b/packages/core-extensions/src/common/webpackModules/react.ts
@@ -0,0 +1,7 @@
+import spacepack from "@moonlight-mod/wp/spacepack_spacepack";
+
+module.exports = spacepack.findByCode(
+ "__SECRET_INTERNALS_DO_NOT_USE" + "_OR_YOU_WILL_BE_FIRED",
+ /\.?version(?:=|:)/,
+ /\.?createElement(?:=|:)/
+)[0].exports;
diff --git a/packages/core-extensions/src/common/webpackModules/stores.ts b/packages/core-extensions/src/common/webpackModules/stores.ts
new file mode 100644
index 0000000..36bf7b9
--- /dev/null
+++ b/packages/core-extensions/src/common/webpackModules/stores.ts
@@ -0,0 +1,23 @@
+import Flux from "@moonlight-mod/wp/common_flux";
+
+module.exports = new Proxy(
+ {},
+ {
+ get: function (target, key, receiver) {
+ const allStores = Flux.Store.getAll();
+
+ let targetStore;
+ for (const store of allStores) {
+ const name = store.getName();
+ if (name.length === 1) continue; // filter out unnamed stores
+
+ if (name === key) {
+ targetStore = store;
+ break;
+ }
+ }
+
+ return targetStore;
+ }
+ }
+);
diff --git a/packages/core-extensions/src/disableSentry/index.ts b/packages/core-extensions/src/disableSentry/index.ts
index 6d43135..9d90988 100644
--- a/packages/core-extensions/src/disableSentry/index.ts
+++ b/packages/core-extensions/src/disableSentry/index.ts
@@ -7,7 +7,8 @@ export const patches: Patch[] = [
replace: {
type: PatchReplaceType.Normal,
match: /default:function\(\){return .}/,
- replacement: 'default:function(){return require("disableSentry_stub")()}'
+ replacement:
+ 'default:function(){return require("disableSentry_stub").proxy()}'
}
},
{
@@ -38,41 +39,5 @@ export const patches: Patch[] = [
];
export const webpackModules: ExtensionWebExports["webpackModules"] = {
- stub: {
- run: function (module, exports, require) {
- const logger = moonlight.getLogger("disableSentry");
-
- const keys = [
- "setUser",
- "clearUser",
- "setTags",
- "setExtra",
- "captureException",
- "captureCrash",
- "captureMessage",
- "addBreadcrumb"
- ];
-
- module.exports = () =>
- new Proxy(
- {},
- {
- get(target, prop, receiver) {
- if (prop === "profiledRootComponent") {
- return (arg: any) => arg;
- } else if (prop === "crash") {
- return () => {
- throw Error("crash");
- };
- } else if (keys.includes(prop.toString())) {
- return (...args: any[]) =>
- logger.debug(`Sentry calling "${prop.toString()}":`, ...args);
- } else {
- return undefined;
- }
- }
- }
- );
- }
- }
+ stub: {}
};
diff --git a/packages/core-extensions/src/disableSentry/webpackModules/stub.ts b/packages/core-extensions/src/disableSentry/webpackModules/stub.ts
new file mode 100644
index 0000000..f766777
--- /dev/null
+++ b/packages/core-extensions/src/disableSentry/webpackModules/stub.ts
@@ -0,0 +1,33 @@
+const logger = moonlight.getLogger("disableSentry");
+
+const keys = [
+ "setUser",
+ "clearUser",
+ "setTags",
+ "setExtra",
+ "captureException",
+ "captureCrash",
+ "captureMessage",
+ "addBreadcrumb"
+];
+
+export const proxy = () =>
+ new Proxy(
+ {},
+ {
+ get(target, prop, receiver) {
+ if (prop === "profiledRootComponent") {
+ return (arg: any) => arg;
+ } else if (prop === "crash") {
+ return () => {
+ throw Error("crash");
+ };
+ } else if (keys.includes(prop.toString())) {
+ return (...args: any[]) =>
+ logger.debug(`Sentry calling "${prop.toString()}":`, ...args);
+ } else {
+ return undefined;
+ }
+ }
+ }
+ );
diff --git a/packages/core-extensions/src/moonbase/index.tsx b/packages/core-extensions/src/moonbase/index.tsx
index 151882c..a00ad26 100644
--- a/packages/core-extensions/src/moonbase/index.tsx
+++ b/packages/core-extensions/src/moonbase/index.tsx
@@ -1,6 +1,5 @@
import { ExtensionWebExports } from "@moonlight-mod/types";
import ui from "./ui";
-import { stores } from "./stores";
import { DownloadIconSVG, TrashIconSVG } from "./types";
export const webpackModules: ExtensionWebExports["webpackModules"] = {
@@ -8,10 +7,7 @@ export const webpackModules: ExtensionWebExports["webpackModules"] = {
dependencies: [
{ ext: "common", id: "flux" },
{ ext: "common", id: "fluxDispatcher" }
- ],
- run: (module, exports, require) => {
- module.exports = stores(require);
- }
+ ]
},
moonbase: {
@@ -26,13 +22,11 @@ export const webpackModules: ExtensionWebExports["webpackModules"] = {
],
entrypoint: true,
run: (module, exports, require) => {
- const settings = require("settings_settings");
+ const settings = require("settings_settings").Settings;
const React = require("common_react");
- const spacepack = require("spacepack_spacepack");
+ const spacepack = require("spacepack_spacepack").spacepack;
const { MoonbaseSettingsStore } =
- require("moonbase_stores") as ReturnType<
- (typeof import("./stores"))["stores"]
- >;
+ require("moonbase_stores") as typeof import("./webpackModules/stores");
settings.addSection("Moonbase", "Moonbase", ui(require), null, -2, {
stores: [MoonbaseSettingsStore],
diff --git a/packages/core-extensions/src/moonbase/stores.ts b/packages/core-extensions/src/moonbase/stores.ts
deleted file mode 100644
index aa7c95b..0000000
--- a/packages/core-extensions/src/moonbase/stores.ts
+++ /dev/null
@@ -1,257 +0,0 @@
-import WebpackRequire from "@moonlight-mod/types/discord/require";
-import { Config, ExtensionLoadSource } from "@moonlight-mod/types";
-import {
- ExtensionState,
- MoonbaseExtension,
- MoonbaseNatives,
- RepositoryManifest
-} from "./types";
-
-export const stores = (require: typeof WebpackRequire) => {
- const Flux = require("common_flux");
- const Dispatcher = require("common_fluxDispatcher");
- const natives: MoonbaseNatives = moonlight.getNatives("moonbase");
-
- const logger = moonlight.getLogger("moonbase");
-
- class MoonbaseSettingsStore extends Flux.Store {
- private origConfig: Config;
- private config: Config;
-
- modified: boolean;
- submitting: boolean;
- installing: boolean;
-
- extensions: { [id: string]: MoonbaseExtension };
- updates: { [id: string]: { version: string; download: string } };
-
- constructor() {
- super(Dispatcher);
-
- // Fucking Electron making it immutable
- this.origConfig = moonlightNode.config;
- this.config = JSON.parse(JSON.stringify(this.origConfig));
-
- this.modified = false;
- this.submitting = false;
- this.installing = false;
-
- this.extensions = {};
- this.updates = {};
- for (const ext of moonlightNode.extensions) {
- const existingExtension = this.extensions[ext.id];
- if (existingExtension != null) continue;
-
- this.extensions[ext.id] = {
- ...ext,
- state: moonlight.enabledExtensions.has(ext.id)
- ? ExtensionState.Enabled
- : ExtensionState.Disabled
- };
- }
-
- natives.fetchRepositories(this.config.repositories).then((ret) => {
- for (const [repo, exts] of Object.entries(ret)) {
- try {
- for (const ext of exts) {
- try {
- const existingExtension = this.extensions[ext.id];
- if (existingExtension !== null) {
- if (this.hasUpdate(repo, ext, existingExtension)) {
- this.updates[ext.id] = {
- version: ext.version!,
- download: ext.download
- };
- }
- continue;
- }
-
- this.extensions[ext.id] = {
- id: ext.id,
- manifest: ext,
- source: { type: ExtensionLoadSource.Normal, url: repo },
- state: ExtensionState.NotDownloaded
- };
- } catch (e) {
- logger.error(`Error processing extension ${ext.id}`, e);
- }
- }
- } catch (e) {
- logger.error(`Error processing repository ${repo}`, e);
- }
- }
-
- this.emitChange();
- });
- }
-
- // this logic sucks so bad lol
- private hasUpdate(
- repo: string,
- repoExt: RepositoryManifest,
- existing: MoonbaseExtension
- ) {
- return (
- existing.source.type === ExtensionLoadSource.Normal &&
- existing.source.url != null &&
- existing.source.url === repo &&
- repoExt.version != null &&
- existing.manifest.version !== repoExt.version
- );
- }
-
- // Jank
- private isModified() {
- const orig = JSON.stringify(this.origConfig);
- const curr = JSON.stringify(this.config);
- return orig !== curr;
- }
-
- get busy() {
- return this.submitting || this.installing;
- }
-
- showNotice() {
- return this.modified;
- }
-
- getExtension(id: string) {
- return this.extensions[id];
- }
-
- getExtensionName(id: string) {
- return Object.prototype.hasOwnProperty.call(this.extensions, id)
- ? this.extensions[id].manifest.meta?.name ?? id
- : id;
- }
-
- getExtensionUpdate(id: string) {
- return Object.prototype.hasOwnProperty.call(this.updates, id)
- ? this.updates[id]
- : null;
- }
-
- getExtensionEnabled(id: string) {
- const val = this.config.extensions[id];
- if (val == null) return false;
- return typeof val === "boolean" ? val : val.enabled;
- }
-
- getExtensionConfig(id: string, key: string): T | undefined {
- const defaultValue =
- this.extensions[id].manifest.settings?.[key]?.default;
- const cfg = this.config.extensions[id];
-
- if (cfg == null || typeof cfg === "boolean") return defaultValue;
- return cfg.config?.[key] ?? defaultValue;
- }
-
- getExtensionConfigName(id: string, key: string) {
- return this.extensions[id].manifest.settings?.[key]?.displayName ?? key;
- }
-
- setExtensionConfig(id: string, key: string, value: any) {
- const oldConfig = this.config.extensions[id];
- const newConfig =
- typeof oldConfig === "boolean"
- ? {
- enabled: oldConfig,
- config: { [key]: value }
- }
- : {
- ...oldConfig,
- config: { ...(oldConfig?.config ?? {}), [key]: value }
- };
-
- this.config.extensions[id] = newConfig;
- this.modified = this.isModified();
- this.emitChange();
- }
-
- setExtensionEnabled(id: string, enabled: boolean) {
- let val = this.config.extensions[id];
-
- if (val == null) {
- this.config.extensions[id] = { enabled };
- this.emitChange();
- return;
- }
-
- if (typeof val === "boolean") {
- val = enabled;
- } else {
- val.enabled = enabled;
- }
-
- this.config.extensions[id] = val;
- this.modified = this.isModified();
- this.emitChange();
- }
-
- async installExtension(id: string) {
- const ext = this.getExtension(id);
- if (!("download" in ext.manifest)) {
- throw new Error("Extension has no download URL");
- }
-
- this.installing = true;
- try {
- const url = this.updates[id]?.download ?? ext.manifest.download;
- await natives.installExtension(ext.manifest, url, ext.source.url!);
- if (ext.state === ExtensionState.NotDownloaded) {
- this.extensions[id].state = ExtensionState.Disabled;
- }
-
- delete this.updates[id];
- } catch (e) {
- logger.error("Error installing extension:", e);
- }
-
- this.installing = false;
- this.emitChange();
- }
-
- async deleteExtension(id: string) {
- const ext = this.getExtension(id);
- if (ext == null) return;
-
- this.installing = true;
- try {
- await natives.deleteExtension(ext.id);
- this.extensions[id].state = ExtensionState.NotDownloaded;
- } catch (e) {
- logger.error("Error deleting extension:", e);
- }
-
- this.installing = false;
- this.emitChange();
- }
-
- writeConfig() {
- this.submitting = true;
-
- try {
- moonlightNode.writeConfig(this.config);
- // I love jank cloning
- this.origConfig = JSON.parse(JSON.stringify(this.config));
- } catch (e) {
- logger.error("Error writing config", e);
- }
-
- this.submitting = false;
- this.modified = false;
- this.emitChange();
- }
-
- reset() {
- this.submitting = false;
- this.modified = false;
- this.config = JSON.parse(JSON.stringify(this.origConfig));
- this.emitChange();
- }
- }
-
- return {
- MoonbaseSettingsStore: new MoonbaseSettingsStore()
- };
-};
diff --git a/packages/core-extensions/src/moonbase/ui/index.tsx b/packages/core-extensions/src/moonbase/ui/index.tsx
index 83bc092..b12f7cc 100644
--- a/packages/core-extensions/src/moonbase/ui/index.tsx
+++ b/packages/core-extensions/src/moonbase/ui/index.tsx
@@ -12,15 +12,14 @@ export enum ExtensionPage {
export default (require: typeof WebpackRequire) => {
const React = require("common_react");
- const spacepack = require("spacepack_spacepack");
+ const spacepack = require("spacepack_spacepack").spacepack;
const CommonComponents = require("common_components");
const Flux = require("common_flux");
const { ExtensionInfo } = info(require);
const { Settings } = settings(require);
- const { MoonbaseSettingsStore } = require("moonbase_stores") as ReturnType<
- (typeof import("../stores"))["stores"]
- >;
+ const { MoonbaseSettingsStore } =
+ require("moonbase_stores") as typeof import("../webpackModules/stores");
const UserProfileClasses = spacepack.findByCode(
"tabBarContainer",
diff --git a/packages/core-extensions/src/moonbase/ui/info.tsx b/packages/core-extensions/src/moonbase/ui/info.tsx
index 1813964..dfd5a2c 100644
--- a/packages/core-extensions/src/moonbase/ui/info.tsx
+++ b/packages/core-extensions/src/moonbase/ui/info.tsx
@@ -15,7 +15,7 @@ enum DependencyType {
export default (require: typeof WebpackRequire) => {
const React = require("common_react");
- const spacepack = require("spacepack_spacepack");
+ const spacepack = require("spacepack_spacepack").spacepack;
const CommonComponents = require("common_components");
const UserInfoClasses = spacepack.findByCode(
@@ -24,9 +24,8 @@ export default (require: typeof WebpackRequire) => {
"userInfoSectionHeader"
)[0].exports;
- const { MoonbaseSettingsStore } = require("moonbase_stores") as ReturnType<
- (typeof import("../stores"))["stores"]
- >;
+ const { MoonbaseSettingsStore } =
+ require("moonbase_stores") as typeof import("../webpackModules/stores");
function InfoSection({
title,
diff --git a/packages/core-extensions/src/moonbase/ui/settings.tsx b/packages/core-extensions/src/moonbase/ui/settings.tsx
index 5dba53c..c624c99 100644
--- a/packages/core-extensions/src/moonbase/ui/settings.tsx
+++ b/packages/core-extensions/src/moonbase/ui/settings.tsx
@@ -20,9 +20,8 @@ export default (require: typeof WebpackRequire) => {
const CommonComponents = require("common_components");
const Flux = require("common_flux");
- const { MoonbaseSettingsStore } = require("moonbase_stores") as ReturnType<
- (typeof import("../stores"))["stores"]
- >;
+ const { MoonbaseSettingsStore } =
+ require("moonbase_stores") as typeof import("../webpackModules/stores");
function Boolean({ ext, name, setting }: SettingsProps) {
const { FormSwitch } = CommonComponents;
diff --git a/packages/core-extensions/src/moonbase/webpackModules/stores.ts b/packages/core-extensions/src/moonbase/webpackModules/stores.ts
new file mode 100644
index 0000000..b1c729a
--- /dev/null
+++ b/packages/core-extensions/src/moonbase/webpackModules/stores.ts
@@ -0,0 +1,251 @@
+import { Config, ExtensionLoadSource } from "@moonlight-mod/types";
+import {
+ ExtensionState,
+ MoonbaseExtension,
+ MoonbaseNatives,
+ RepositoryManifest
+} from "../types";
+import Flux from "@moonlight-mod/wp/common_flux";
+import Dispatcher from "@moonlight-mod/wp/common_fluxDispatcher";
+
+const natives: MoonbaseNatives = moonlight.getNatives("moonbase");
+const logger = moonlight.getLogger("moonbase");
+
+class MoonbaseSettingsStore extends Flux.Store {
+ private origConfig: Config;
+ private config: Config;
+
+ modified: boolean;
+ submitting: boolean;
+ installing: boolean;
+
+ extensions: { [id: string]: MoonbaseExtension };
+ updates: { [id: string]: { version: string; download: string } };
+
+ constructor() {
+ super(Dispatcher);
+
+ // Fucking Electron making it immutable
+ this.origConfig = moonlightNode.config;
+ this.config = JSON.parse(JSON.stringify(this.origConfig));
+
+ this.modified = false;
+ this.submitting = false;
+ this.installing = false;
+
+ this.extensions = {};
+ this.updates = {};
+ for (const ext of moonlightNode.extensions) {
+ const existingExtension = this.extensions[ext.id];
+ if (existingExtension != null) continue;
+
+ this.extensions[ext.id] = {
+ ...ext,
+ state: moonlight.enabledExtensions.has(ext.id)
+ ? ExtensionState.Enabled
+ : ExtensionState.Disabled
+ };
+ }
+
+ natives.fetchRepositories(this.config.repositories).then((ret) => {
+ for (const [repo, exts] of Object.entries(ret)) {
+ try {
+ for (const ext of exts) {
+ try {
+ const existingExtension = this.extensions[ext.id];
+ if (existingExtension !== null) {
+ if (this.hasUpdate(repo, ext, existingExtension)) {
+ this.updates[ext.id] = {
+ version: ext.version!,
+ download: ext.download
+ };
+ }
+ continue;
+ }
+
+ this.extensions[ext.id] = {
+ id: ext.id,
+ manifest: ext,
+ source: { type: ExtensionLoadSource.Normal, url: repo },
+ state: ExtensionState.NotDownloaded
+ };
+ } catch (e) {
+ logger.error(`Error processing extension ${ext.id}`, e);
+ }
+ }
+ } catch (e) {
+ logger.error(`Error processing repository ${repo}`, e);
+ }
+ }
+
+ this.emitChange();
+ });
+ }
+
+ // this logic sucks so bad lol
+ private hasUpdate(
+ repo: string,
+ repoExt: RepositoryManifest,
+ existing: MoonbaseExtension
+ ) {
+ return (
+ existing.source.type === ExtensionLoadSource.Normal &&
+ existing.source.url != null &&
+ existing.source.url === repo &&
+ repoExt.version != null &&
+ existing.manifest.version !== repoExt.version
+ );
+ }
+
+ // Jank
+ private isModified() {
+ const orig = JSON.stringify(this.origConfig);
+ const curr = JSON.stringify(this.config);
+ return orig !== curr;
+ }
+
+ get busy() {
+ return this.submitting || this.installing;
+ }
+
+ showNotice() {
+ return this.modified;
+ }
+
+ getExtension(id: string) {
+ return this.extensions[id];
+ }
+
+ getExtensionName(id: string) {
+ return Object.prototype.hasOwnProperty.call(this.extensions, id)
+ ? this.extensions[id].manifest.meta?.name ?? id
+ : id;
+ }
+
+ getExtensionUpdate(id: string) {
+ return Object.prototype.hasOwnProperty.call(this.updates, id)
+ ? this.updates[id]
+ : null;
+ }
+
+ getExtensionEnabled(id: string) {
+ const val = this.config.extensions[id];
+ if (val == null) return false;
+ return typeof val === "boolean" ? val : val.enabled;
+ }
+
+ getExtensionConfig(id: string, key: string): T | undefined {
+ const defaultValue = this.extensions[id].manifest.settings?.[key]?.default;
+ const cfg = this.config.extensions[id];
+
+ if (cfg == null || typeof cfg === "boolean") return defaultValue;
+ return cfg.config?.[key] ?? defaultValue;
+ }
+
+ getExtensionConfigName(id: string, key: string) {
+ return this.extensions[id].manifest.settings?.[key]?.displayName ?? key;
+ }
+
+ setExtensionConfig(id: string, key: string, value: any) {
+ const oldConfig = this.config.extensions[id];
+ const newConfig =
+ typeof oldConfig === "boolean"
+ ? {
+ enabled: oldConfig,
+ config: { [key]: value }
+ }
+ : {
+ ...oldConfig,
+ config: { ...(oldConfig?.config ?? {}), [key]: value }
+ };
+
+ this.config.extensions[id] = newConfig;
+ this.modified = this.isModified();
+ this.emitChange();
+ }
+
+ setExtensionEnabled(id: string, enabled: boolean) {
+ let val = this.config.extensions[id];
+
+ if (val == null) {
+ this.config.extensions[id] = { enabled };
+ this.emitChange();
+ return;
+ }
+
+ if (typeof val === "boolean") {
+ val = enabled;
+ } else {
+ val.enabled = enabled;
+ }
+
+ this.config.extensions[id] = val;
+ this.modified = this.isModified();
+ this.emitChange();
+ }
+
+ async installExtension(id: string) {
+ const ext = this.getExtension(id);
+ if (!("download" in ext.manifest)) {
+ throw new Error("Extension has no download URL");
+ }
+
+ this.installing = true;
+ try {
+ const url = this.updates[id]?.download ?? ext.manifest.download;
+ await natives.installExtension(ext.manifest, url, ext.source.url!);
+ if (ext.state === ExtensionState.NotDownloaded) {
+ this.extensions[id].state = ExtensionState.Disabled;
+ }
+
+ delete this.updates[id];
+ } catch (e) {
+ logger.error("Error installing extension:", e);
+ }
+
+ this.installing = false;
+ this.emitChange();
+ }
+
+ async deleteExtension(id: string) {
+ const ext = this.getExtension(id);
+ if (ext == null) return;
+
+ this.installing = true;
+ try {
+ await natives.deleteExtension(ext.id);
+ this.extensions[id].state = ExtensionState.NotDownloaded;
+ } catch (e) {
+ logger.error("Error deleting extension:", e);
+ }
+
+ this.installing = false;
+ this.emitChange();
+ }
+
+ writeConfig() {
+ this.submitting = true;
+
+ try {
+ moonlightNode.writeConfig(this.config);
+ // I love jank cloning
+ this.origConfig = JSON.parse(JSON.stringify(this.config));
+ } catch (e) {
+ logger.error("Error writing config", e);
+ }
+
+ this.submitting = false;
+ this.modified = false;
+ this.emitChange();
+ }
+
+ reset() {
+ this.submitting = false;
+ this.modified = false;
+ this.config = JSON.parse(JSON.stringify(this.origConfig));
+ this.emitChange();
+ }
+}
+
+const settingsStore = new MoonbaseSettingsStore();
+export { settingsStore as MoonbaseSettingsStore };
diff --git a/packages/core-extensions/src/settings/index.ts b/packages/core-extensions/src/settings/index.ts
index f3fe5b5..c98f56a 100644
--- a/packages/core-extensions/src/settings/index.ts
+++ b/packages/core-extensions/src/settings/index.ts
@@ -1,8 +1,4 @@
import { Patch } from "@moonlight-mod/types";
-import {
- SettingsSection,
- Settings as SettingsType
-} from "@moonlight-mod/types/coreExtensions";
import { ExtensionWebExports } from "@moonlight-mod/types";
export const patches: Patch[] = [
@@ -11,7 +7,7 @@ export const patches: Patch[] = [
replace: {
match: /\.CUSTOM,element:(.+?)}\];return (.{1,2})/,
replacement: (_, lastElement, sections) =>
- `.CUSTOM,element:${lastElement}}];return require("settings_settings")._mutateSections(${sections})`
+ `.CUSTOM,element:${lastElement}}];return require("settings_settings").Settings._mutateSections(${sections})`
}
},
{
@@ -21,63 +17,13 @@ export const patches: Patch[] = [
replacement: (orig, sections, section) =>
`${orig.replace(
/Object\.values\(.\.UserSettingsSections\)/,
- (orig) => `[...require("settings_settings").sectionNames,...${orig}]`
+ (orig) =>
+ `[...require("settings_settings").Settings.sectionNames,...${orig}]`
)}??${sections}.find(x=>x.section==${section})?._moonlight_submenu?.()`
}
}
];
export const webpackModules: ExtensionWebExports["webpackModules"] = {
- settings: {
- run: (module, exports, require) => {
- const Settings: SettingsType = {
- ourSections: [],
- sectionNames: [],
-
- addSection: (section, label, element, color = null, pos, notice) => {
- const data: SettingsSection = {
- section,
- label,
- color,
- element,
- pos: pos ?? -4,
- notice: notice
- };
-
- Settings.ourSections.push(data);
- Settings.sectionNames.push(label);
- return data;
- },
-
- addDivider: (pos = null) => {
- Settings.ourSections.push({
- section: "DIVIDER",
- pos: pos === null ? -4 : pos
- });
- },
-
- addHeader: function (label, pos = null) {
- Settings.ourSections.push({
- section: "HEADER",
- label: label,
- pos: pos === null ? -4 : pos
- });
- },
-
- _mutateSections: (sections) => {
- for (const section of Settings.ourSections) {
- sections.splice(
- section.pos < 0 ? sections.length + section.pos : section.pos,
- 0,
- section
- );
- }
-
- return sections;
- }
- };
-
- module.exports = Settings;
- }
- }
+ settings: {}
};
diff --git a/packages/core-extensions/src/settings/webpackModules/settings.ts b/packages/core-extensions/src/settings/webpackModules/settings.ts
new file mode 100644
index 0000000..09ef6fd
--- /dev/null
+++ b/packages/core-extensions/src/settings/webpackModules/settings.ts
@@ -0,0 +1,53 @@
+import {
+ SettingsSection,
+ Settings as SettingsType
+} from "@moonlight-mod/types/coreExtensions";
+
+export const Settings: SettingsType = {
+ ourSections: [],
+ sectionNames: [],
+
+ addSection: (section, label, element, color = null, pos, notice) => {
+ const data: SettingsSection = {
+ section,
+ label,
+ color,
+ element,
+ pos: pos ?? -4,
+ notice: notice
+ };
+
+ Settings.ourSections.push(data);
+ Settings.sectionNames.push(label);
+ return data;
+ },
+
+ addDivider: (pos = null) => {
+ Settings.ourSections.push({
+ section: "DIVIDER",
+ pos: pos === null ? -4 : pos
+ });
+ },
+
+ addHeader: function (label, pos = null) {
+ Settings.ourSections.push({
+ section: "HEADER",
+ label: label,
+ pos: pos === null ? -4 : pos
+ });
+ },
+
+ _mutateSections: (sections) => {
+ for (const section of Settings.ourSections) {
+ sections.splice(
+ section.pos < 0 ? sections.length + section.pos : section.pos,
+ 0,
+ section
+ );
+ }
+
+ return sections;
+ }
+};
+
+export default Settings;
diff --git a/packages/core-extensions/src/spacepack/index.ts b/packages/core-extensions/src/spacepack/index.ts
index c406cce..3fd3b96 100644
--- a/packages/core-extensions/src/spacepack/index.ts
+++ b/packages/core-extensions/src/spacepack/index.ts
@@ -1,10 +1,14 @@
-import { ExtensionWebExports, WebpackModuleFunc } from "@moonlight-mod/types";
-import webpackModule from "./webpackModule";
+import { ExtensionWebExports } from "@moonlight-mod/types";
+import { Spacepack } from "@moonlight-mod/types/coreExtensions";
+
+declare global {
+ interface Window {
+ spacepack: Spacepack;
+ }
+}
export const webpackModules: ExtensionWebExports["webpackModules"] = {
spacepack: {
- entrypoint: true,
- // Assert the type because we're adding extra fields to require
- run: webpackModule as WebpackModuleFunc
+ entrypoint: true
}
};
diff --git a/packages/core-extensions/src/spacepack/webpackModule.ts b/packages/core-extensions/src/spacepack/webpackModule.ts
deleted file mode 100644
index 50bef29..0000000
--- a/packages/core-extensions/src/spacepack/webpackModule.ts
+++ /dev/null
@@ -1,176 +0,0 @@
-import { WebpackModuleFunc, WebpackModule } from "@moonlight-mod/types";
-import { Spacepack } from "@moonlight-mod/types/coreExtensions";
-import { WebpackRequireType } from "@moonlight-mod/types/discord/webpack";
-
-declare global {
- interface Window {
- spacepack: Spacepack;
- }
-}
-
-export default (module: any, exports: any, require: WebpackRequireType) => {
- const cache = require.c;
- const modules = require.m;
-
- const logger = moonlight.getLogger("spacepack");
-
- const spacepack: Spacepack = {
- require,
- modules,
- cache,
-
- inspect: (module: number | string) => {
- if (typeof module === "number") {
- module = module.toString();
- }
-
- if (!(module in modules)) {
- return null;
- }
-
- const func = modules[module];
- if (func.__moonlight === true) {
- return func;
- }
-
- const funcStr = func.toString();
-
- return new Function(
- "module",
- "exports",
- "require",
- `(${funcStr}).apply(this, arguments)\n` +
- `//# sourceURL=Webpack-Module-${module}`
- ) as WebpackModuleFunc;
- },
-
- findByCode: (...args: (string | RegExp)[]) => {
- return Object.entries(modules)
- .filter(
- ([id, mod]) =>
- !args.some(
- (item) =>
- !(item instanceof RegExp
- ? item.test(mod.toString())
- : mod.toString().indexOf(item) !== -1)
- )
- )
- .map(([id]) => {
- //if (!(id in cache)) require(id);
- //return cache[id];
-
- let exports;
- try {
- exports = require(id);
- } catch (e) {
- logger.error(`Error requiring module "${id}": `, e);
- }
-
- return {
- id,
- exports
- };
- })
- .filter((item) => item !== null);
- },
-
- findByExports: (...args: string[]) => {
- return Object.entries(cache)
- .filter(
- ([id, { exports }]) =>
- !args.some(
- (item) =>
- !(
- exports !== undefined &&
- exports !== window &&
- (exports?.[item] ||
- exports?.default?.[item] ||
- exports?.Z?.[item] ||
- exports?.ZP?.[item])
- )
- )
- )
- .map((item) => item[1])
- .reduce((prev, curr) => {
- if (!prev.includes(curr)) prev.push(curr);
- return prev;
- }, []);
- },
-
- findObjectFromKey: (exports: Record, key: string) => {
- let subKey;
- if (key.indexOf(".") > -1) {
- const splitKey = key.split(".");
- key = splitKey[0];
- subKey = splitKey[1];
- }
- for (const exportKey in exports) {
- const obj = exports[exportKey];
- if (obj && obj[key] !== undefined) {
- if (subKey) {
- if (obj[key][subKey]) return obj;
- } else {
- return obj;
- }
- }
- }
- return null;
- },
-
- findObjectFromValue: (exports: Record, value: any) => {
- for (const exportKey in exports) {
- const obj = exports[exportKey];
- // eslint-disable-next-line eqeqeq
- if (obj == value) return obj;
- for (const subKey in obj) {
- // eslint-disable-next-line eqeqeq
- if (obj && obj[subKey] == value) {
- return obj;
- }
- }
- }
- return null;
- },
-
- findObjectFromKeyValuePair: (
- exports: Record,
- key: string,
- value: any
- ) => {
- for (const exportKey in exports) {
- const obj = exports[exportKey];
- // eslint-disable-next-line eqeqeq
- if (obj && obj[key] == value) {
- return obj;
- }
- }
- return null;
- },
-
- findFunctionByStrings: (
- exports: Record,
- ...strings: (string | RegExp)[]
- ) => {
- return (
- Object.entries(exports).filter(
- ([index, func]) =>
- typeof func === "function" &&
- !strings.some(
- (query) =>
- !(query instanceof RegExp
- ? func.toString().match(query)
- : func.toString().includes(query))
- )
- )?.[0]?.[1] ?? null
- );
- }
- };
-
- module.exports = spacepack;
-
- if (
- moonlight.getConfigOption("spacepack", "addToGlobalScope") === true
- ) {
- window.spacepack = spacepack;
- }
-};
diff --git a/packages/core-extensions/src/spacepack/webpackModules/spacepack.ts b/packages/core-extensions/src/spacepack/webpackModules/spacepack.ts
new file mode 100644
index 0000000..f6369cd
--- /dev/null
+++ b/packages/core-extensions/src/spacepack/webpackModules/spacepack.ts
@@ -0,0 +1,172 @@
+import {
+ WebpackModule,
+ WebpackModuleFunc,
+ WebpackRequireType
+} from "@moonlight-mod/types";
+import { Spacepack } from "@moonlight-mod/types/coreExtensions";
+
+const webpackRequire = require as unknown as WebpackRequireType;
+const cache = webpackRequire.c;
+const modules = webpackRequire.m;
+
+const logger = moonlight.getLogger("spacepack");
+
+export const spacepack: Spacepack = {
+ require: webpackRequire,
+ modules,
+ cache,
+
+ inspect: (module: number | string) => {
+ if (typeof module === "number") {
+ module = module.toString();
+ }
+
+ if (!(module in modules)) {
+ return null;
+ }
+
+ const func = modules[module];
+ if (func.__moonlight === true) {
+ return func;
+ }
+
+ const funcStr = func.toString();
+
+ return new Function(
+ "module",
+ "exports",
+ "require",
+ `(${funcStr}).apply(this, arguments)\n` +
+ `//# sourceURL=Webpack-Module-${module}`
+ ) as WebpackModuleFunc;
+ },
+
+ findByCode: (...args: (string | RegExp)[]) => {
+ return Object.entries(modules)
+ .filter(
+ ([id, mod]) =>
+ !args.some(
+ (item) =>
+ !(item instanceof RegExp
+ ? item.test(mod.toString())
+ : mod.toString().indexOf(item) !== -1)
+ )
+ )
+ .map(([id]) => {
+ //if (!(id in cache)) require(id);
+ //return cache[id];
+
+ let exports;
+ try {
+ exports = require(id);
+ } catch (e) {
+ logger.error(`Error requiring module "${id}": `, e);
+ }
+
+ return {
+ id,
+ exports
+ };
+ })
+ .filter((item) => item !== null);
+ },
+
+ findByExports: (...args: string[]) => {
+ return Object.entries(cache)
+ .filter(
+ ([id, { exports }]) =>
+ !args.some(
+ (item) =>
+ !(
+ exports !== undefined &&
+ exports !== window &&
+ (exports?.[item] ||
+ exports?.default?.[item] ||
+ exports?.Z?.[item] ||
+ exports?.ZP?.[item])
+ )
+ )
+ )
+ .map((item) => item[1])
+ .reduce((prev, curr) => {
+ if (!prev.includes(curr)) prev.push(curr);
+ return prev;
+ }, []);
+ },
+
+ findObjectFromKey: (exports: Record, key: string) => {
+ let subKey;
+ if (key.indexOf(".") > -1) {
+ const splitKey = key.split(".");
+ key = splitKey[0];
+ subKey = splitKey[1];
+ }
+ for (const exportKey in exports) {
+ const obj = exports[exportKey];
+ if (obj && obj[key] !== undefined) {
+ if (subKey) {
+ if (obj[key][subKey]) return obj;
+ } else {
+ return obj;
+ }
+ }
+ }
+ return null;
+ },
+
+ findObjectFromValue: (exports: Record, value: any) => {
+ for (const exportKey in exports) {
+ const obj = exports[exportKey];
+ // eslint-disable-next-line eqeqeq
+ if (obj == value) return obj;
+ for (const subKey in obj) {
+ // eslint-disable-next-line eqeqeq
+ if (obj && obj[subKey] == value) {
+ return obj;
+ }
+ }
+ }
+ return null;
+ },
+
+ findObjectFromKeyValuePair: (
+ exports: Record,
+ key: string,
+ value: any
+ ) => {
+ for (const exportKey in exports) {
+ const obj = exports[exportKey];
+ // eslint-disable-next-line eqeqeq
+ if (obj && obj[key] == value) {
+ return obj;
+ }
+ }
+ return null;
+ },
+
+ findFunctionByStrings: (
+ exports: Record,
+ ...strings: (string | RegExp)[]
+ ) => {
+ return (
+ Object.entries(exports).filter(
+ ([index, func]) =>
+ typeof func === "function" &&
+ !strings.some(
+ (query) =>
+ !(query instanceof RegExp
+ ? func.toString().match(query)
+ : func.toString().includes(query))
+ )
+ )?.[0]?.[1] ?? null
+ );
+ }
+};
+
+if (
+ moonlight.getConfigOption("spacepack", "addToGlobalScope") === true
+) {
+ window.spacepack = spacepack;
+}
+
+export default spacepack;
diff --git a/packages/core/src/extension.ts b/packages/core/src/extension.ts
index 320f161..3a7553b 100644
--- a/packages/core/src/extension.ts
+++ b/packages/core/src/extension.ts
@@ -66,6 +66,21 @@ function loadDetectedExtensions(
url = fs.readFileSync(urlPath, "utf8");
}
+ const wpModules: Record = {};
+ const wpModulesPath = path.join(dir, "webpackModules");
+ if (fs.existsSync(wpModulesPath)) {
+ const wpModulesFile = fs.readdirSync(wpModulesPath);
+
+ for (const wpModuleFile of wpModulesFile) {
+ if (wpModuleFile.endsWith(".js")) {
+ wpModules[wpModuleFile.replace(".js", "")] = fs.readFileSync(
+ path.join(wpModulesPath, wpModuleFile),
+ "utf8"
+ );
+ }
+ }
+ }
+
ret.push({
id: manifest.id,
manifest,
@@ -76,6 +91,7 @@ function loadDetectedExtensions(
scripts: {
web,
webPath: web != null ? webPath : undefined,
+ webpackModules: wpModules,
nodePath: fs.existsSync(nodePath) ? nodePath : undefined,
hostPath: fs.existsSync(hostPath) ? hostPath : undefined
}
diff --git a/packages/core/src/extension/loader.ts b/packages/core/src/extension/loader.ts
index 495b500..8c41f36 100644
--- a/packages/core/src/extension/loader.ts
+++ b/packages/core/src/extension/loader.ts
@@ -1,7 +1,8 @@
import {
ExtensionWebExports,
DetectedExtension,
- ProcessedExtensions
+ ProcessedExtensions,
+ WebpackModuleFunc
} from "@moonlight-mod/types";
import { readConfig } from "../config";
import Logger from "../util/logger";
@@ -49,7 +50,22 @@ async function loadExt(ext: DetectedExtension) {
if (exports.webpackModules != null) {
for (const [name, wp] of Object.entries(exports.webpackModules)) {
- registerWebpackModule({ ...wp, ext: ext.id, id: name });
+ if (wp.run == null && ext.scripts.webpackModules?.[name] != null) {
+ const func = new Function(
+ "module",
+ "exports",
+ "require",
+ ext.scripts.webpackModules[name]!
+ ) as WebpackModuleFunc;
+ registerWebpackModule({
+ ...wp,
+ ext: ext.id,
+ id: name,
+ run: func
+ });
+ } else {
+ registerWebpackModule({ ...wp, ext: ext.id, id: name });
+ }
}
}
}
diff --git a/packages/types/package.json b/packages/types/package.json
index 30d164f..7ee5fd2 100644
--- a/packages/types/package.json
+++ b/packages/types/package.json
@@ -5,6 +5,7 @@
"types": "./src/index.ts",
"exports": {
".": "./src/index.ts",
+ "./import": "./src/import.d.ts",
"./*": "./src/*.ts"
},
"dependencies": {
diff --git a/packages/types/src/coreExtensions.ts b/packages/types/src/coreExtensions.ts
index 8c65de2..8ac4c47 100644
--- a/packages/types/src/coreExtensions.ts
+++ b/packages/types/src/coreExtensions.ts
@@ -1,9 +1,9 @@
import { FluxDefault, Store } from "./discord/common/Flux";
-import WebpackRequire from "./discord/require";
-import { WebpackModuleFunc } from "./discord/webpack";
import { CommonComponents as CommonComponents_ } from "./coreExtensions/components";
import { Dispatcher } from "flux";
import React from "react";
+import { WebpackModuleFunc } from "./discord";
+import WebpackRequire from "./discord/require";
export type Spacepack = {
inspect: (module: number | string) => WebpackModuleFunc | null;
diff --git a/packages/types/src/discord/require.ts b/packages/types/src/discord/require.ts
index 056dc96..4b918e1 100644
--- a/packages/types/src/discord/require.ts
+++ b/packages/types/src/discord/require.ts
@@ -8,13 +8,21 @@ import {
} from "../coreExtensions";
declare function WebpackRequire(id: string): any;
-declare function WebpackRequire(id: "spacepack_spacepack"): Spacepack;
-declare function WebpackRequire(id: "common_react"): CommonReact;
+declare function WebpackRequire(id: "spacepack_spacepack"): {
+ default: Spacepack;
+ spacepack: Spacepack;
+};
+
+declare function WebpackRequire(id: "common_components"): CommonComponents;
declare function WebpackRequire(id: "common_flux"): CommonFlux;
declare function WebpackRequire(
id: "common_fluxDispatcher"
): CommonFluxDispatcher;
-declare function WebpackRequire(id: "settings_settings"): Settings;
-declare function WebpackRequire(id: "common_components"): CommonComponents;
+declare function WebpackRequire(id: "common_react"): CommonReact;
+
+declare function WebpackRequire(id: "settings_settings"): {
+ Settings: Settings;
+ default: Settings;
+};
export default WebpackRequire;
diff --git a/packages/types/src/extension.ts b/packages/types/src/extension.ts
index 1c7560f..7fc1e95 100644
--- a/packages/types/src/extension.ts
+++ b/packages/types/src/extension.ts
@@ -62,6 +62,7 @@ export type DetectedExtension = {
scripts: {
web?: string;
webPath?: string;
+ webpackModules?: Record;
nodePath?: string;
hostPath?: string;
};
@@ -108,7 +109,7 @@ export type ExtensionDependency = string | RegExp | ExplicitExtensionDependency;
export type ExtensionWebpackModule = {
entrypoint?: boolean;
dependencies?: ExtensionDependency[];
- run: WebpackModuleFunc;
+ run?: WebpackModuleFunc;
};
export type ExtensionWebExports = {
diff --git a/packages/types/src/import.d.ts b/packages/types/src/import.d.ts
new file mode 100644
index 0000000..b87e1da
--- /dev/null
+++ b/packages/types/src/import.d.ts
@@ -0,0 +1,23 @@
+declare module "@moonlight-mod/wp/spacepack_spacepack" {
+ import { Spacepack } from "@moonlight-mod/types/coreExtensions";
+ export const spacepack: Spacepack;
+ export default spacepack;
+}
+
+declare module "@moonlight-mod/wp/common_components" {
+ import { CommonComponents } from "@moonlight-mod/types/coreExtensions";
+ const components: CommonComponents;
+ export default components;
+}
+
+declare module "@moonlight-mod/wp/common_flux" {
+ import { CommonFlux } from "@moonlight-mod/types/coreExtensions";
+ const Flux: CommonFlux;
+ export default Flux;
+}
+
+declare module "@moonlight-mod/wp/common_fluxDispatcher" {
+ import { CommonFluxDispatcher } from "@moonlight-mod/types/coreExtensions";
+ const Dispatcher: CommonFluxDispatcher;
+ export default Dispatcher;
+}
diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts
index 15477be..ba2f7d7 100644
--- a/packages/types/src/index.ts
+++ b/packages/types/src/index.ts
@@ -2,6 +2,7 @@
///
///
///
+///
/* eslint-disable no-var */
import {
diff --git a/packages/types/tsconfig.json b/packages/types/tsconfig.json
index 80ec4b5..40dd733 100644
--- a/packages/types/tsconfig.json
+++ b/packages/types/tsconfig.json
@@ -10,5 +10,5 @@
"jsx": "react",
"declaration": true
},
- "include": ["./src/**/*", "src/index.ts"]
+ "include": ["./src/**/*", "src/index.ts", "./src/import.d.ts"]
}