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