this repo has no description
1import "@moonlight-mod/web-preload";
2import { readConfig, writeConfig } from "@moonlight-mod/core/config";
3import Logger, { initLogger } from "@moonlight-mod/core/util/logger";
4import { getExtensions } from "@moonlight-mod/core/extension";
5import { loadExtensions } from "@moonlight-mod/core/extension/loader";
6import { MoonlightBranch, MoonlightNode } from "@moonlight-mod/types";
7import { getConfig, getConfigOption, getManifest, setConfigOption } from "@moonlight-mod/core/util/config";
8import { IndexedDB } from "@zenfs/dom";
9import { configureSingle } from "@zenfs/core";
10import * as fs from "@zenfs/core/promises";
11import { NodeEventPayloads, NodeEventType } from "@moonlight-mod/types/core/event";
12import { createEventEmitter } from "@moonlight-mod/core/util/event";
13
14function getParts(path: string) {
15 if (path.startsWith("/")) path = path.substring(1);
16 return path.split("/");
17}
18
19window._moonlightBrowserInit = async () => {
20 delete window._moonlightBrowserInit;
21
22 // Set up a virtual filesystem with IndexedDB
23 await configureSingle({
24 backend: IndexedDB,
25 storeName: "moonlight-fs"
26 });
27
28 window.moonlightNodeSandboxed = {
29 fs: {
30 async readFile(path) {
31 return new Uint8Array(await fs.readFile(path));
32 },
33 async readFileString(path) {
34 const file = await this.readFile(path);
35 return new TextDecoder().decode(file);
36 },
37 async writeFile(path, data) {
38 await fs.writeFile(path, data);
39 },
40 async writeFileString(path, data) {
41 const file = new TextEncoder().encode(data);
42 await this.writeFile(path, file);
43 },
44 async unlink(path) {
45 await fs.unlink(path);
46 },
47
48 async readdir(path) {
49 return await fs.readdir(path);
50 },
51 async mkdir(path) {
52 const parts = getParts(path);
53 for (let i = 0; i < parts.length; i++) {
54 const path = this.join(...parts.slice(0, i + 1));
55 if (!(await this.exists(path))) await fs.mkdir(path);
56 }
57 },
58
59 async rmdir(path) {
60 const entries = await this.readdir(path);
61
62 for (const entry of entries) {
63 const fullPath = this.join(path, entry);
64 const isFile = await this.isFile(fullPath);
65 if (isFile) {
66 await this.unlink(fullPath);
67 } else {
68 await this.rmdir(fullPath);
69 }
70 }
71
72 await fs.rmdir(path);
73 },
74
75 async exists(path) {
76 return await fs.exists(path);
77 },
78 async isFile(path) {
79 return (await fs.stat(path)).isFile();
80 },
81 async isDir(path) {
82 return (await fs.stat(path)).isDirectory();
83 },
84
85 join(...parts) {
86 let str = parts.join("/");
87 if (!str.startsWith("/")) str = "/" + str;
88 return str;
89 },
90 dirname(path) {
91 const parts = getParts(path);
92 return "/" + parts.slice(0, parts.length - 1).join("/");
93 },
94 basename(path) {
95 const parts = getParts(path);
96 return parts[parts.length - 1];
97 }
98 },
99 // TODO
100 addCors(url) {},
101 addBlocked(url) {}
102 };
103
104 // Actual loading begins here
105 let config = await readConfig();
106 initLogger(config);
107
108 const extensions = await getExtensions();
109 const processedExtensions = await loadExtensions(extensions);
110
111 const moonlightNode: MoonlightNode = {
112 get config() {
113 return config;
114 },
115 extensions,
116 processedExtensions,
117 nativesCache: {},
118 isBrowser: true,
119 events: createEventEmitter<NodeEventType, NodeEventPayloads>(),
120
121 version: MOONLIGHT_VERSION,
122 branch: MOONLIGHT_BRANCH as MoonlightBranch,
123
124 getConfig(ext) {
125 return getConfig(ext, config);
126 },
127 getConfigOption(ext, name) {
128 const manifest = getManifest(extensions, ext);
129 return getConfigOption(ext, name, config, manifest?.settings);
130 },
131 async setConfigOption(ext, name, value) {
132 setConfigOption(config, ext, name, value);
133 await this.writeConfig(config);
134 },
135
136 getNatives: () => {},
137 getLogger: (id: string) => {
138 return new Logger(id);
139 },
140
141 getMoonlightDir() {
142 return "/";
143 },
144 getExtensionDir: (ext: string) => {
145 return `/extensions/${ext}`;
146 },
147
148 async writeConfig(newConfig) {
149 await writeConfig(newConfig);
150 config = newConfig;
151 this.events.dispatchEvent(NodeEventType.ConfigSaved, newConfig);
152 }
153 };
154
155 Object.assign(window, {
156 moonlightNode
157 });
158
159 // This is set by web-preload for us
160 await window._moonlightWebLoad!();
161};