this repo has no description
1import {
2 ExtensionManifest,
3 DetectedExtension,
4 ExtensionLoadSource,
5 constants
6} from "@moonlight-mod/types";
7import { readConfig } from "./config";
8import requireImport from "./util/import";
9import { getCoreExtensionsPath, getExtensionsPath } from "./util/data";
10
11function findManifests(dir: string): string[] {
12 const fs = requireImport("fs");
13 const path = requireImport("path");
14 const ret = [];
15
16 if (fs.existsSync(dir)) {
17 for (const file of fs.readdirSync(dir)) {
18 if (file === "manifest.json") {
19 ret.push(path.join(dir, file));
20 }
21
22 if (fs.statSync(path.join(dir, file)).isDirectory()) {
23 ret.push(...findManifests(path.join(dir, file)));
24 }
25 }
26 }
27
28 return ret;
29}
30
31function loadDetectedExtensions(
32 dir: string,
33 type: ExtensionLoadSource
34): DetectedExtension[] {
35 const fs = requireImport("fs");
36 const path = requireImport("path");
37 const ret: DetectedExtension[] = [];
38
39 const manifests = findManifests(dir);
40 for (const manifestPath of manifests) {
41 if (!fs.existsSync(manifestPath)) continue;
42 const dir = path.dirname(manifestPath);
43
44 const manifest: ExtensionManifest = JSON.parse(
45 fs.readFileSync(manifestPath, "utf8")
46 );
47
48 const webPath = path.join(dir, "index.js");
49 const nodePath = path.join(dir, "node.js");
50 const hostPath = path.join(dir, "host.js");
51
52 // if none exist (empty manifest) don't give a shit
53 if (
54 !fs.existsSync(webPath) &&
55 !fs.existsSync(nodePath) &&
56 !fs.existsSync(hostPath)
57 ) {
58 continue;
59 }
60
61 const web = fs.existsSync(webPath)
62 ? fs.readFileSync(webPath, "utf8")
63 : undefined;
64
65 let url: string | undefined = undefined;
66 const urlPath = path.join(dir, constants.repoUrlFile);
67 if (type === ExtensionLoadSource.Normal && fs.existsSync(urlPath)) {
68 url = fs.readFileSync(urlPath, "utf8");
69 }
70
71 const wpModules: Record<string, string> = {};
72 const wpModulesPath = path.join(dir, "webpackModules");
73 if (fs.existsSync(wpModulesPath)) {
74 const wpModulesFile = fs.readdirSync(wpModulesPath);
75
76 for (const wpModuleFile of wpModulesFile) {
77 if (wpModuleFile.endsWith(".js")) {
78 wpModules[wpModuleFile.replace(".js", "")] = fs.readFileSync(
79 path.join(wpModulesPath, wpModuleFile),
80 "utf8"
81 );
82 }
83 }
84 }
85
86 ret.push({
87 id: manifest.id,
88 manifest,
89 source: {
90 type,
91 url
92 },
93 scripts: {
94 web,
95 webPath: web != null ? webPath : undefined,
96 webpackModules: wpModules,
97 nodePath: fs.existsSync(nodePath) ? nodePath : undefined,
98 hostPath: fs.existsSync(hostPath) ? hostPath : undefined
99 }
100 });
101 }
102
103 return ret;
104}
105
106function getExtensionsNative(): DetectedExtension[] {
107 const config = readConfig();
108 const res = [];
109
110 res.push(
111 ...loadDetectedExtensions(getCoreExtensionsPath(), ExtensionLoadSource.Core)
112 );
113
114 res.push(
115 ...loadDetectedExtensions(getExtensionsPath(), ExtensionLoadSource.Normal)
116 );
117
118 for (const devSearchPath of config.devSearchPaths ?? []) {
119 res.push(
120 ...loadDetectedExtensions(devSearchPath, ExtensionLoadSource.Developer)
121 );
122 }
123
124 return res;
125}
126
127export function getExtensions(): DetectedExtension[] {
128 webPreload: {
129 return moonlightNode.extensions;
130 }
131
132 nodePreload: {
133 return getExtensionsNative();
134 }
135
136 injector: {
137 return getExtensionsNative();
138 }
139
140 throw new Error("Called getExtensions() outside of node-preload/web-preload");
141}