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